source: SVN/rincon/u-boot/board/fads/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: 13.2 KB
Line 
1/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <mpc8xx.h>
26
27flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips */
28
29#if defined(CONFIG_ENV_IS_IN_FLASH)
30# ifndef  CONFIG_ENV_ADDR
31#  define CONFIG_ENV_ADDR       (CFG_FLASH_BASE + CONFIG_ENV_OFFSET)
32# endif
33# ifndef  CONFIG_ENV_SIZE
34#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
35# endif
36# ifndef  CONFIG_ENV_SECT_SIZE
37#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
38# endif
39#endif
40
41#define QUAD_ID(id)     ((((ulong)(id) & 0xFF) << 24) | \
42                         (((ulong)(id) & 0xFF) << 16) | \
43                         (((ulong)(id) & 0xFF) << 8)  | \
44                         (((ulong)(id) & 0xFF) << 0)    \
45                        )
46
47/*-----------------------------------------------------------------------
48 * Functions
49 */
50static ulong flash_get_size (vu_long * addr, flash_info_t * info);
51static int write_word (flash_info_t * info, ulong dest, ulong data);
52
53/*-----------------------------------------------------------------------
54 */
55unsigned long flash_init (void)
56{
57        volatile immap_t *immap = (immap_t *) CFG_IMMR;
58        volatile memctl8xx_t *memctl = &immap->im_memctl;
59        vu_long *bcsr = (vu_long *)BCSR_ADDR;
60        unsigned long pd_size, total_size, bsize, or_am;
61        int i;
62
63        /* Init: no FLASHes known */
64        for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
65                flash_info[i].flash_id = FLASH_UNKNOWN;
66                flash_info[i].size = 0;
67                flash_info[i].sector_count = 0;
68                flash_info[i].start[0] = 0xFFFFFFFF; /* For TFTP */
69        }
70
71        switch ((bcsr[2] & BCSR2_FLASH_PD_MASK) >> BCSR2_FLASH_PD_SHIFT) {
72        case 2:
73        case 4:
74        case 6:
75                pd_size = 0x800000;
76                or_am = 0xFF800000;
77                break;
78
79        case 5:
80        case 7:
81                pd_size = 0x400000;
82                or_am = 0xFFC00000;
83                break;
84
85        case 8:
86                pd_size = 0x200000;
87                or_am = 0xFFE00000;
88                break;
89
90        default:
91                pd_size = 0;
92                or_am = 0xFFE00000;
93                printf("## Unsupported flash detected by BCSR: 0x%08lX\n", bcsr[2]);
94        }
95
96        total_size = 0;
97        for (i = 0; i < CFG_MAX_FLASH_BANKS && total_size < pd_size; ++i) {
98                bsize = flash_get_size((vu_long *)(CFG_FLASH_BASE + total_size),
99                                       &flash_info[i]);
100
101                if (flash_info[i].flash_id == FLASH_UNKNOWN) {
102                        printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
103                                i, bsize, bsize >> 20);
104                }
105
106                total_size += bsize;
107        }
108
109        if (total_size != pd_size) {
110                printf("## Detected flash size %lu conflicts with PD data %lu\n",
111                       total_size, pd_size);
112        }
113
114        /* Remap FLASH according to real size */
115        memctl->memc_or0 = or_am | CFG_OR_TIMING_FLASH;
116
117        for (i = 0; i < CFG_MAX_FLASH_BANKS && flash_info[i].size != 0; ++i) {
118#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
119                /* monitor protection ON by default */
120                if (CFG_MONITOR_BASE >= flash_info[i].start[0])
121                        flash_protect (FLAG_PROTECT_SET,
122                                       CFG_MONITOR_BASE,
123                                       CFG_MONITOR_BASE + monitor_flash_len - 1,
124                                       &flash_info[i]);
125#endif
126
127#ifdef  CONFIG_ENV_IS_IN_FLASH
128                /* ENV protection ON by default */
129                if (CONFIG_ENV_ADDR >= flash_info[i].start[0])
130                        flash_protect (FLAG_PROTECT_SET,
131                                       CONFIG_ENV_ADDR,
132                                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
133                                       &flash_info[i]);
134#endif
135        }
136
137        return total_size;
138}
139
140/*-----------------------------------------------------------------------
141 */
142void flash_print_info (flash_info_t * info)
143{
144        int i;
145
146        if (info->flash_id == FLASH_UNKNOWN) {
147                printf ("missing or unknown FLASH type\n");
148                return;
149        }
150
151        switch (info->flash_id & FLASH_VENDMASK) {
152        case FLASH_MAN_AMD:
153                printf ("AMD ");
154                break;
155        case FLASH_MAN_FUJ:
156                printf ("FUJITSU ");
157                break;
158        case FLASH_MAN_BM:
159                printf ("BRIGHT MICRO ");
160                break;
161        default:
162                printf ("Unknown Vendor ");
163                break;
164        }
165
166        switch (info->flash_id & FLASH_TYPEMASK) {
167        case FLASH_AM040:
168                printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
169                break;
170        case FLASH_AM080:
171                printf ("29F080 or 29LV080 (8 Mbit, uniform sectors)\n");
172                break;
173        case FLASH_AM400B:
174                printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
175                break;
176        case FLASH_AM400T:
177                printf ("AM29LV400T (4 Mbit, top boot sector)\n");
178                break;
179        case FLASH_AM800B:
180                printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
181                break;
182        case FLASH_AM800T:
183                printf ("AM29LV800T (8 Mbit, top boot sector)\n");
184                break;
185        case FLASH_AM160B:
186                printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
187                break;
188        case FLASH_AM160T:
189                printf ("AM29LV160T (16 Mbit, top boot sector)\n");
190                break;
191        case FLASH_AM320B:
192                printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
193                break;
194        case FLASH_AM320T:
195                printf ("AM29LV320T (32 Mbit, top boot sector)\n");
196                break;
197        default:
198                printf ("Unknown Chip Type\n");
199                break;
200        }
201
202        printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20,
203                info->sector_count);
204
205        printf ("  Sector Start Addresses:");
206
207        for (i = 0; i < info->sector_count; ++i) {
208                if ((i % 5) == 0) {
209                        printf ("\n   ");
210                }
211
212                printf (" %08lX%s",
213                        info->start[i], info->protect[i] ? " (RO)" : "     ");
214        }
215
216        printf ("\n");
217}
218
219/*-----------------------------------------------------------------------
220 * The following code can not run from flash!
221 */
222static ulong flash_get_size (vu_long * addr, flash_info_t * info)
223{
224        short i;
225
226        /* Write auto select command: read Manufacturer ID */
227        addr[0x0555] = 0xAAAAAAAA;
228        addr[0x02AA] = 0x55555555;
229        addr[0x0555] = 0x90909090;
230
231        switch (addr[0]) {
232        case QUAD_ID(AMD_MANUFACT):
233                info->flash_id = FLASH_MAN_AMD;
234                break;
235
236        case QUAD_ID(FUJ_MANUFACT):
237                info->flash_id = FLASH_MAN_FUJ;
238                break;
239
240        default:
241                info->flash_id = FLASH_UNKNOWN;
242                info->sector_count = 0;
243                info->size = 0;
244                break;
245        }
246
247        switch (addr[1]) {      /* device ID            */
248        case QUAD_ID(AMD_ID_F040B):
249        case QUAD_ID(AMD_ID_LV040B):
250                info->flash_id += FLASH_AM040;
251                info->sector_count = 8;
252                info->size = 0x00200000;
253                break;          /* => 2 MB              */
254
255        case QUAD_ID(AMD_ID_F080B):
256                info->flash_id += FLASH_AM080;
257                info->sector_count = 16;
258                info->size = 0x00400000;
259                break;          /* => 4 MB              */
260#if 0
261        case AMD_ID_LV400T:
262                info->flash_id += FLASH_AM400T;
263                info->sector_count = 11;
264                info->size = 0x00100000;
265                break;          /* => 1 MB              */
266
267        case AMD_ID_LV400B:
268                info->flash_id += FLASH_AM400B;
269                info->sector_count = 11;
270                info->size = 0x00100000;
271                break;          /* => 1 MB              */
272
273        case AMD_ID_LV800T:
274                info->flash_id += FLASH_AM800T;
275                info->sector_count = 19;
276                info->size = 0x00200000;
277                break;          /* => 2 MB              */
278
279        case AMD_ID_LV800B:
280                info->flash_id += FLASH_AM800B;
281                info->sector_count = 19;
282                info->size = 0x00200000;
283                break;          /* => 2 MB              */
284
285        case AMD_ID_LV160T:
286                info->flash_id += FLASH_AM160T;
287                info->sector_count = 35;
288                info->size = 0x00400000;
289                break;          /* => 4 MB              */
290
291        case AMD_ID_LV160B:
292                info->flash_id += FLASH_AM160B;
293                info->sector_count = 35;
294                info->size = 0x00400000;
295                break;          /* => 4 MB              */
296
297        case AMD_ID_LV320T:
298                info->flash_id += FLASH_AM320T;
299                info->sector_count = 67;
300                info->size = 0x00800000;
301                break;          /* => 8 MB              */
302
303        case AMD_ID_LV320B:
304                info->flash_id += FLASH_AM320B;
305                info->sector_count = 67;
306                info->size = 0x00800000;
307                break;          /* => 8 MB              */
308#endif /* 0 */
309        default:
310                info->flash_id = FLASH_UNKNOWN;
311                return (0);     /* => no or unknown flash */
312        }
313
314#if 0
315        /* set up sector start address table */
316        if (info->flash_id & FLASH_BTYPE) {
317                /* set sector offsets for bottom boot block type        */
318                info->start[0] = base + 0x00000000;
319                info->start[1] = base + 0x00008000;
320                info->start[2] = base + 0x0000C000;
321                info->start[3] = base + 0x00010000;
322                for (i = 4; i < info->sector_count; i++) {
323                        info->start[i] = base + (i * 0x00020000) - 0x00060000;
324                }
325        } else {
326                /* set sector offsets for top boot block type           */
327                i = info->sector_count - 1;
328                info->start[i--] = base + info->size - 0x00008000;
329                info->start[i--] = base + info->size - 0x0000C000;
330                info->start[i--] = base + info->size - 0x00010000;
331                for (; i >= 0; i--) {
332                        info->start[i] = base + i * 0x00020000;
333                }
334        }
335#else
336        /* set sector offsets for uniform sector type */
337        for (i = 0; i < info->sector_count; i++)
338                info->start[i] = (ulong)addr + (i * 0x00040000);
339#endif
340
341        /* check for protected sectors */
342        for (i = 0; i < info->sector_count; i++) {
343                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
344                /* D0 = 1 if protected */
345                addr = (volatile unsigned long *) (info->start[i]);
346                info->protect[i] = addr[2] & 1;
347        }
348
349        if (info->flash_id != FLASH_UNKNOWN) {
350                addr = (volatile unsigned long *) info->start[0];
351                *addr = 0xF0F0F0F0;     /* reset bank */
352        }
353
354        return (info->size);
355}
356
357/*-----------------------------------------------------------------------
358 */
359int flash_erase (flash_info_t * info, int s_first, int s_last)
360{
361        vu_long *addr = (vu_long *) (info->start[0]);
362        int flag, prot, sect, l_sect;
363        ulong start, now, last;
364
365        if ((s_first < 0) || (s_first > s_last)) {
366                if (info->flash_id == FLASH_UNKNOWN) {
367                        printf ("- missing\n");
368                } else {
369                        printf ("- no sectors to erase\n");
370                }
371                return ERR_INVAL;
372        }
373
374        if ((info->flash_id == FLASH_UNKNOWN) ||
375            (info->flash_id > FLASH_AMD_COMP)) {
376                printf ("Can't erase unknown flash type - aborted\n");
377                return ERR_UNKNOWN_FLASH_TYPE;
378        }
379
380        prot = 0;
381        for (sect = s_first; sect <= s_last; ++sect) {
382                if (info->protect[sect]) {
383                        prot++;
384                }
385        }
386
387        if (prot) {
388                printf ("- Warning: %d protected sectors will not be erased!\n", prot);
389        } else {
390                printf ("\n");
391        }
392
393        l_sect = -1;
394
395        /* Disable interrupts which might cause a timeout here */
396        flag = disable_interrupts ();
397
398        addr[0x0555] = 0xAAAAAAAA;
399        addr[0x02AA] = 0x55555555;
400        addr[0x0555] = 0x80808080;
401        addr[0x0555] = 0xAAAAAAAA;
402        addr[0x02AA] = 0x55555555;
403
404        /* Start erase on unprotected sectors */
405        for (sect = s_first; sect <= s_last; sect++) {
406                if (info->protect[sect] == 0) { /* not protected */
407                        addr = (vu_long *) (info->start[sect]);
408                        addr[0] = 0x30303030;
409                        l_sect = sect;
410                }
411        }
412
413        /* re-enable interrupts if necessary */
414        if (flag)
415                enable_interrupts ();
416
417        /* wait at least 80us - let's wait 1 ms */
418        udelay (1000);
419
420        /*
421         * We wait for the last triggered sector
422         */
423        if (l_sect < 0)
424                goto DONE;
425
426        start = get_timer (0);
427        last = start;
428        addr = (vu_long *) (info->start[l_sect]);
429        while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF)
430        {
431                if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
432                        printf ("Timeout\n");
433                        return ERR_TIMOUT;
434                }
435                /* show that we're waiting */
436                if ((now - last) > 1000) {      /* every second */
437                        putc ('.');
438                        last = now;
439                }
440        }
441
442      DONE:
443        /* reset to read mode */
444        addr = (volatile unsigned long *) info->start[0];
445        addr[0] = 0xF0F0F0F0;   /* reset bank */
446
447        printf (" done\n");
448
449        return 0;
450}
451
452/*-----------------------------------------------------------------------
453 * Copy memory to flash, returns:
454 * 0 - OK
455 * 1 - write timeout
456 * 2 - Flash not erased
457 */
458int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
459{
460        ulong cp, wp, data;
461        int i, l, rc;
462
463        wp = (addr & ~3);       /* get lower word aligned address */
464
465        /*
466         * handle unaligned start bytes
467         */
468        if ((l = addr - wp) != 0) {
469                data = 0;
470                for (i = 0, cp = wp; i < l; ++i, ++cp) {
471                        data = (data << 8) | (*(uchar *) cp);
472                }
473                for (; i < 4 && cnt > 0; ++i) {
474                        data = (data << 8) | *src++;
475                        --cnt;
476                        ++cp;
477                }
478                for (; cnt == 0 && i < 4; ++i, ++cp) {
479                        data = (data << 8) | (*(uchar *) cp);
480                }
481
482                if ((rc = write_word (info, wp, data)) != 0) {
483                        return (rc);
484                }
485                wp += 4;
486        }
487
488        /*
489         * handle word aligned part
490         */
491        while (cnt >= 4) {
492                data = 0;
493                for (i = 0; i < 4; ++i) {
494                        data = (data << 8) | *src++;
495                }
496                if ((rc = write_word (info, wp, data)) != 0) {
497                        return (rc);
498                }
499                wp += 4;
500                cnt -= 4;
501        }
502
503        if (cnt == 0) {
504                return (0);
505        }
506
507        /*
508         * handle unaligned tail bytes
509         */
510        data = 0;
511        for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
512                data = (data << 8) | *src++;
513                --cnt;
514        }
515        for (; i < 4; ++i, ++cp) {
516                data = (data << 8) | (*(uchar *) cp);
517        }
518
519        return (write_word (info, wp, data));
520}
521
522/*-----------------------------------------------------------------------
523 * Write a word to Flash, returns:
524 * 0 - OK
525 * 1 - write timeout
526 * 2 - Flash not erased
527 */
528static int write_word (flash_info_t * info, ulong dest, ulong data)
529{
530        vu_long *addr = (vu_long *) (info->start[0]);
531        ulong start;
532        int flag;
533
534        /* Check if Flash is (sufficiently) erased */
535        if ((*((vu_long *) dest) & data) != data) {
536                return ERR_NOT_ERASED;
537        }
538        /* Disable interrupts which might cause a timeout here */
539        flag = disable_interrupts ();
540
541        addr[0x0555] = 0xAAAAAAAA;
542        addr[0x02AA] = 0x55555555;
543        addr[0x0555] = 0xA0A0A0A0;
544
545        *((vu_long *) dest) = data;
546
547        /* re-enable interrupts if necessary */
548        if (flag)
549                enable_interrupts ();
550
551        /* data polling for D7 */
552        start = get_timer (0);
553        while ((*((vu_long *) dest) & 0x80808080) != (data & 0x80808080))
554        {
555                if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
556                        return ERR_TIMOUT;
557                }
558        }
559        return (0);
560}
Note: See TracBrowser for help on using the repository browser.