source: SVN/rincon/u-boot/board/funkwerk/vovpn-gw/flash.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 10.2 KB
Line 
1/*
2 * (C) Copyright 2004
3 * Elmeg Communications Systems GmbH, Juergen Selent (j.selent@elmeg.de)
4 *
5 * Support for the Elmeg VoVPN Gateway Module
6 * ------------------------------------------
7 * This is a signle bank flashdriver for INTEL 28F320J3, 28F640J3
8 * and 28F128J3A flashs working in 8 Bit mode.
9 *
10 * Most of this code is taken from existing u-boot source code.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29
30flash_info_t                            flash_info[CFG_MAX_FLASH_BANKS];
31
32#define FLASH_CMD_READ_ID               0x90
33#define FLASH_CMD_READ_STATUS           0x70
34#define FLASH_CMD_RESET                 0xff
35#define FLASH_CMD_BLOCK_ERASE           0x20
36#define FLASH_CMD_ERASE_CONFIRM         0xd0
37#define FLASH_CMD_CLEAR_STATUS          0x50
38#define FLASH_CMD_SUSPEND_ERASE         0xb0
39#define FLASH_CMD_WRITE                 0x40
40#define FLASH_CMD_WRITE_BUFF            0xe8
41#define FLASH_CMD_PROG_RESUME           0xd0
42#define FLASH_CMD_PROTECT               0x60
43#define FLASH_CMD_PROTECT_SET           0x01
44#define FLASH_CMD_PROTECT_CLEAR         0xd0
45#define FLASH_STATUS_DONE               0x80
46
47#define FLASH_WRITE_BUFFER_SIZE         32
48
49#ifdef CFG_FLASH_16BIT
50#define FLASH_WORD_SIZE                 unsigned short
51#define FLASH_ID_MASK                   0xffff
52#define FLASH_CMD_ADDR_SHIFT            0
53#else
54#define FLASH_WORD_SIZE                 unsigned char
55#define FLASH_ID_MASK                   0xff
56/* A0 is not used in either 8x or 16x for READ ID */
57#define FLASH_CMD_ADDR_SHIFT            1
58#endif
59
60
61static unsigned long
62flash_get(volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
63{
64        volatile FLASH_WORD_SIZE *p;
65        FLASH_WORD_SIZE value;
66        int i;
67
68        addr[0] = FLASH_CMD_READ_ID;
69
70        /* manufactor */
71        value = addr[0 << FLASH_CMD_ADDR_SHIFT];
72        switch (value) {
73        case (INTEL_MANUFACT & FLASH_ID_MASK):
74                info->flash_id = FLASH_MAN_INTEL;
75                break;
76        default:
77                info->flash_id = FLASH_UNKNOWN;
78                info->sector_count = 0;
79                info->size = 0;
80                *addr = FLASH_CMD_RESET;
81                return (0);
82
83        }
84
85        /* device */
86        value = addr[1 << FLASH_CMD_ADDR_SHIFT];
87        switch (value) {
88        case (INTEL_ID_28F320J3A & FLASH_ID_MASK):
89                info->flash_id += FLASH_28F320J3A;
90                info->sector_count = 32;
91                info->size = 0x00400000;
92                break;
93        case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
94                info->flash_id += FLASH_28F640J3A;
95                info->sector_count = 64;
96                info->size = 0x00800000;
97                break;
98        case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
99                info->flash_id += FLASH_28F128J3A;
100                info->sector_count = 128;
101                info->size = 0x01000000;
102                break;
103        default:
104                info->flash_id = FLASH_UNKNOWN;
105                info->sector_count = 0;
106                info->size = 0;
107                *addr = FLASH_CMD_RESET;
108                return (0);
109        }
110
111        /* setup sectors */
112        for (i = 0; i < info->sector_count; i++) {
113                info->start[i] = (unsigned long)addr + (i * info->size/info->sector_count);
114        }
115
116        /* check protected sectors */
117        for (i = 0; i < info->sector_count; i++) {
118                p = (volatile FLASH_WORD_SIZE *)(info->start[i]);
119                info->protect[i] = p[2 << FLASH_CMD_ADDR_SHIFT] & 1;
120        }
121
122        /* reset bank */
123        *addr = FLASH_CMD_RESET;
124        return (info->size);
125}
126
127unsigned long
128flash_init(void)
129{
130        unsigned long   size;
131        int             i;
132
133        for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
134                flash_info[i].flash_id = FLASH_UNKNOWN;
135        }
136        size = flash_get((volatile FLASH_WORD_SIZE *)CFG_FLASH_BASE, &flash_info[0]);
137        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
138                printf ("## Unknown FLASH Size=0x%08lx\n", size);
139                return (0);
140        }
141
142        /* always protect 1 sector containing the HRCW */
143        flash_protect(FLAG_PROTECT_SET,
144                      flash_info[0].start[0],
145                      flash_info[0].start[1] - 1,
146                      &flash_info[0]);
147
148#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
149        flash_protect(FLAG_PROTECT_SET,
150                      CFG_MONITOR_FLASH,
151                      CFG_MONITOR_FLASH+CFG_MONITOR_LEN-1,
152                      &flash_info[0]);
153#endif
154#ifdef  CONFIG_ENV_IS_IN_FLASH
155        flash_protect(FLAG_PROTECT_SET,
156                      CONFIG_ENV_ADDR,
157                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
158                      &flash_info[0]);
159#endif
160        return (size);
161}
162
163void
164flash_print_info(flash_info_t *info)
165{
166        int i;
167
168        if (info->flash_id == FLASH_UNKNOWN) {
169                printf ("missing or unknown FLASH type\n");
170                return;
171        }
172
173        switch (info->flash_id & FLASH_VENDMASK) {
174        case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
175        default:                printf ("Unknown Vendor ");     break;
176        }
177
178        switch (info->flash_id & FLASH_TYPEMASK) {
179        case FLASH_28F320J3A:   printf ("28F320JA3 (32 Mbit)\n");
180                                break;
181        case FLASH_28F640J3A:   printf ("28F640JA3 (64 Mbit)\n");
182                                break;
183        case FLASH_28F128J3A:   printf ("28F128JA3 (128 Mbit)\n");
184                                break;
185        default:                printf ("Unknown Chip Type");
186                                break;
187        }
188
189        printf ("  Size: %ld MB in %d Sectors\n",
190                info->size >> 20, info->sector_count);
191
192        printf ("  Sector Start Addresses:");
193        for (i=0; i<info->sector_count; ++i) {
194                if ((i % 5) == 0)
195                        printf ("\n   ");
196                printf (" %08lX%s",
197                        info->start[i],
198                        info->protect[i] ? " (RO)" : "     "
199                );
200        }
201        printf ("\n");
202}
203
204int
205flash_erase(flash_info_t *info, int s_first, int s_last)
206{
207        unsigned long start, now, last;
208        int flag, prot, sect;
209        volatile FLASH_WORD_SIZE *addr;
210        FLASH_WORD_SIZE status;
211
212        if ((s_first < 0) || (s_first > s_last)) {
213                if (info->flash_id == FLASH_UNKNOWN) {
214                        printf ("- missing\n");
215                } else {
216                        printf ("- no sectors to erase\n");
217                }
218                return (1);
219        }
220
221        if (info->flash_id == FLASH_UNKNOWN) {
222                printf ("Cannot erase unknown flash - aborted\n");
223                return (1);
224        }
225
226        prot = 0;
227        for (sect=s_first; sect<=s_last; ++sect) {
228                if (info->protect[sect]) {
229                        prot++;
230                }
231        }
232
233        if (prot) {
234                printf ("- Warning: %d protected sectors will not be erased!\n", prot);
235        } else {
236                printf ("\n");
237        }
238
239        start = get_timer (0);
240        last  = start;
241
242        for (sect = s_first; sect<=s_last; sect++) {
243                if (info->protect[sect]) {
244                        continue;
245                }
246
247                addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
248                /* Disable interrupts which might cause a timeout here */
249                flag = disable_interrupts();
250
251#ifdef DEBUG
252                printf("Erase sector %d at start addr 0x%08X", sect, (unsigned int)info->start[sect]);
253#endif
254
255                *addr = FLASH_CMD_CLEAR_STATUS;
256                *addr = FLASH_CMD_BLOCK_ERASE;
257                *addr = FLASH_CMD_ERASE_CONFIRM;
258
259                /* re-enable interrupts if necessary */
260                if (flag) {
261                        enable_interrupts();
262                }
263
264                /* wait at least 80us - let's wait 1 ms */
265                udelay (1000);
266
267                while (((status = *addr) & FLASH_STATUS_DONE) != FLASH_STATUS_DONE) {
268                        if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
269                                printf("Flash erase timeout at address %lx\n", info->start[sect]);
270                                *addr = FLASH_CMD_SUSPEND_ERASE;
271                                *addr = FLASH_CMD_RESET;
272                                return (1);
273                        }
274
275                        /* show that we're waiting */
276                        if ((now - last) > 1000) {      /* every second */
277                                putc ('.');
278                                last = now;
279                        }
280                }
281                *addr = FLASH_CMD_RESET;
282        }
283        printf (" done\n");
284        return (0);
285}
286
287static int
288write_buff2( volatile FLASH_WORD_SIZE *dst,
289             volatile FLASH_WORD_SIZE *src,
290             unsigned long cnt )
291{
292        unsigned long start;
293        FLASH_WORD_SIZE status;
294        int flag, i;
295
296        start = get_timer (0);
297        while (1) {
298                /* Disable interrupts which might cause a timeout here */
299                flag = disable_interrupts();
300                dst[0] = FLASH_CMD_WRITE_BUFF;
301                if ((status = *dst) & FLASH_STATUS_DONE) {
302                        break;
303                }
304
305                /* re-enable interrupts if necessary */
306                if (flag) {
307                        enable_interrupts();
308                }
309
310                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
311                        return (-1);
312                }
313        }
314        dst[0] = (FLASH_WORD_SIZE)(cnt - 1);
315        for (i=0; i<cnt; i++) {
316                dst[i] = src[i];
317        }
318        dst[0] = FLASH_CMD_PROG_RESUME;
319
320        if (flag) {
321                enable_interrupts();
322        }
323
324        return( 0 );
325}
326
327static int
328poll_status( volatile FLASH_WORD_SIZE *addr )
329{
330        unsigned long start;
331
332        start = get_timer (0);
333        /* wait for error or finish */
334        while (1) {
335                if (*addr == FLASH_STATUS_DONE) {
336                        if (*addr == FLASH_STATUS_DONE) {
337                                break;
338                        }
339                }
340                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
341                        *addr = FLASH_CMD_RESET;
342                        return (-1);
343                }
344        }
345        *addr = FLASH_CMD_RESET;
346        return (0);
347}
348
349/*
350 * write_buff return values:
351 * 0 - OK
352 * 1 - write timeout
353 * 2 - Flash not erased
354 * 4 - Flash not identified
355 */
356int
357write_buff(flash_info_t *info, uchar *src, ulong udst, ulong cnt)
358{
359        volatile FLASH_WORD_SIZE *addr, *dst;
360        unsigned long bcnt;
361        int flag, i;
362
363        if (info->flash_id == FLASH_UNKNOWN) {
364                return (4);
365        }
366
367        addr = (volatile FLASH_WORD_SIZE *)(info->start[0]);
368        dst = (volatile FLASH_WORD_SIZE *) udst;
369
370#ifdef CFG_FLASH_16BIT
371#error NYI
372#else
373        while (cnt > 0) {
374                /* Check if buffer write is possible */
375                if (cnt > 1 && (((unsigned long)dst & (FLASH_WRITE_BUFFER_SIZE - 1)) == 0)) {
376                        bcnt = cnt > FLASH_WRITE_BUFFER_SIZE ? FLASH_WRITE_BUFFER_SIZE : cnt;
377                        /* Check if Flash is (sufficiently) erased */
378                        for (i=0; i<bcnt; i++) {
379                                if ((dst[i] & src[i]) != src[i]) {
380                                        return (2);
381                                }
382                        }
383                        if (write_buff2( dst,src,bcnt ) != 0) {
384                                addr[0] = FLASH_CMD_READ_STATUS;
385                        }
386                        if (poll_status( dst ) != 0) {
387                                return (1);
388                        }
389                        cnt -= bcnt;
390                        dst += bcnt;
391                        src += bcnt;
392                        continue;
393                }
394
395                /* Check if Flash is (sufficiently) erased */
396                if ((*dst & *src) != *src) {
397                        return (2);
398                }
399
400                /* Disable interrupts which might cause a timeout here */
401                flag = disable_interrupts();
402                addr[0] = FLASH_CMD_ERASE_CONFIRM;
403                addr[0] = FLASH_CMD_WRITE;
404                *dst++ = *src++;
405                /* re-enable interrupts if necessary */
406                if (flag) {
407                        enable_interrupts();
408                }
409
410                if (poll_status( dst ) != 0) {
411                        return (1);
412                }
413                cnt --;
414        }
415#endif
416        return (0);
417}
418
419int
420flash_real_protect(flash_info_t *info, long sector, int prot)
421{
422        volatile FLASH_WORD_SIZE *addr;
423        unsigned long start;
424
425        addr = (volatile FLASH_WORD_SIZE *)(info->start[sector]);
426        *addr = FLASH_CMD_CLEAR_STATUS;
427        *addr = FLASH_CMD_PROTECT;
428
429        if(prot) {
430                *addr = FLASH_CMD_PROTECT_SET;
431        } else {
432                *addr = FLASH_CMD_PROTECT_CLEAR;
433        }
434
435        /* wait for error or finish */
436        start = get_timer (0);
437        while(!(addr[0] & FLASH_STATUS_DONE)){
438                if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
439                        printf("Flash protect timeout at address %lx\n",  info->start[sector]);
440                        addr[0] = FLASH_CMD_RESET;
441                        return (1);
442                }
443        }
444
445        /* Set software protect flag */
446        info->protect[sector] = prot;
447        *addr = FLASH_CMD_RESET;
448        return (0);
449}
Note: See TracBrowser for help on using the repository browser.