]> git.sur5r.net Git - u-boot/blob - board/ocotea/flash.c
Patch by Scott McNutt, 25 Apr 2004:
[u-boot] / board / ocotea / flash.c
1 /*
2  * (C) Copyright 2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2002 Jun Gu <jung@artesyncp.com>
6  * Add support for Am29F016D and dynamic switch setting.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 /*
28  * Modified 4/5/2001
29  * Wait for completion of each sector erase command issued
30  * 4/5/2001
31  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
32  */
33
34 #include <common.h>
35 #include <ppc4xx.h>
36 #include <asm/processor.h>
37
38 #undef DEBUG
39
40 #ifdef DEBUG
41 #define DEBUGF(x...) printf(x)
42 #else
43 #define DEBUGF(x...)
44 #endif                          /* DEBUG */
45
46 #define     BOOT_SMALL_FLASH        32  /* 00100000 */
47 #define     FLASH_ONBD_N            2   /* 00000010 */
48 #define     FLASH_SRAM_SEL          1   /* 00000001 */
49
50 #define     BOOT_SMALL_FLASH_VAL    4
51 #define     FLASH_ONBD_N_VAL        2
52 #define     FLASH_SRAM_SEL_VAL      1
53
54
55 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips        */
56
57 static unsigned long flash_addr_table[8][CFG_MAX_FLASH_BANKS] = {
58         {0xFF800000, 0xFF900000, 0xFFC00000},   /* 0:000: configuraton 4 */
59         {0xFF900000, 0xFF800000, 0xFFC00000},   /* 1:001: configuraton 3 */
60         {0x00000000, 0x00000000, 0x00000000},   /* 2:010: configuraton 8 */
61         {0x00000000, 0x00000000, 0x00000000},   /* 3:011: configuraton 7 */
62         {0xFFE00000, 0xFFF00000, 0xFF800000},   /* 4:100: configuraton 2 */
63         {0xFFF00000, 0xFFF80000, 0xFF800000},   /* 5:101: configuraton 1 */
64         {0x00000000, 0x00000000, 0x00000000},   /* 6:110: configuraton 6 */
65         {0x00000000, 0x00000000, 0x00000000}    /* 7:111: configuraton 5 */
66 };
67
68 /*-----------------------------------------------------------------------
69  * Functions
70  */
71 static ulong flash_get_size(vu_long * addr, flash_info_t * info);
72 static int write_word(flash_info_t * info, ulong dest, ulong data);
73
74
75 #ifdef CONFIG_OCOTEA
76 #define ADDR0           0x5555
77 #define ADDR1           0x2aaa
78 #define FLASH_WORD_SIZE unsigned char
79 #endif
80
81 /*-----------------------------------------------------------------------
82  */
83
84 unsigned long flash_init(void)
85 {
86         unsigned long total_b = 0;
87         unsigned long size_b[CFG_MAX_FLASH_BANKS];
88         unsigned char *fpga_base = (unsigned char *) CFG_FPGA_BASE;
89         unsigned char switch_status;
90         unsigned short index = 0;
91         int i;
92
93         /* read FPGA base register FPGA_REG0 */
94         switch_status = *fpga_base;
95
96         /* check the bitmap of switch status */
97         if (switch_status & BOOT_SMALL_FLASH) {
98                 index += BOOT_SMALL_FLASH_VAL;
99         }
100         if (switch_status & FLASH_ONBD_N) {
101                 index += FLASH_ONBD_N_VAL;
102         }
103         if (switch_status & FLASH_SRAM_SEL) {
104                 index += FLASH_SRAM_SEL_VAL;
105         }
106
107         DEBUGF("\n");
108         DEBUGF("FLASH: Index: %d\n", index);
109
110         /* Init: no FLASHes known */
111         for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
112                 flash_info[i].flash_id = FLASH_UNKNOWN;
113                 flash_info[i].sector_count = -1;
114                 flash_info[i].size = 0;
115
116                 /* check whether the address is 0 */
117                 if (flash_addr_table[index][i] == 0) {
118                         continue;
119                 }
120
121                 /* call flash_get_size() to initialize sector address */
122                 size_b[i] = flash_get_size((vu_long *) flash_addr_table[index][i], &flash_info[i]);
123                 flash_info[i].size = size_b[i];
124                 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
125                         printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
126                                 i, size_b[i], size_b[i] << 20);
127                         flash_info[i].sector_count = -1;
128                         flash_info[i].size = 0;
129                 }
130
131                 total_b += flash_info[i].size;
132         }
133
134         return total_b;
135 }
136
137 /*-----------------------------------------------------------------------
138  */
139 void flash_print_info(flash_info_t * info)
140 {
141         int i;
142         int k;
143         int size;
144         int erased;
145         volatile unsigned long *flash;
146
147         if (info->flash_id == FLASH_UNKNOWN) {
148                 printf("missing or unknown FLASH type\n");
149                 return;
150         }
151
152         switch (info->flash_id & FLASH_VENDMASK) {
153         case FLASH_MAN_AMD:
154                 printf("AMD ");
155                 break;
156         case FLASH_MAN_FUJ:
157                 printf("FUJITSU ");
158                 break;
159         case FLASH_MAN_SST:
160                 printf("SST ");
161                 break;
162         default:
163                 printf("Unknown Vendor ");
164                 break;
165         }
166
167         switch (info->flash_id & FLASH_TYPEMASK) {
168         case FLASH_AM040:
169                 printf("AM29F040 (512 Kbit, uniform sector size)\n");
170                 break;
171         case FLASH_AM400B:
172                 printf("AM29LV400B (4 Mbit, bottom boot sect)\n");
173                 break;
174         case FLASH_AM400T:
175                 printf("AM29LV400T (4 Mbit, top boot sector)\n");
176                 break;
177         case FLASH_AM800B:
178                 printf("AM29LV800B (8 Mbit, bottom boot sect)\n");
179                 break;
180         case FLASH_AM800T:
181                 printf("AM29LV800T (8 Mbit, top boot sector)\n");
182                 break;
183         case FLASH_AM160B:
184                 printf("AM29LV160B (16 Mbit, bottom boot sect)\n");
185                 break;
186         case FLASH_AM160T:
187                 printf("AM29LV160T (16 Mbit, top boot sector)\n");
188                 break;
189         case FLASH_AM320B:
190                 printf("AM29LV320B (32 Mbit, bottom boot sect)\n");
191                 break;
192         case FLASH_AM320T:
193                 printf("AM29LV320T (32 Mbit, top boot sector)\n");
194                 break;
195         case FLASH_AMDLV033C:
196                 printf("AM29LV033C (32 Mbit, top boot sector)\n");
197                 break;
198         case FLASH_SST800A:
199                 printf("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
200                 break;
201         case FLASH_SST160A:
202                 printf("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
203                 break;
204         default:
205                 printf("Unknown Chip Type\n");
206                 break;
207         }
208
209         printf("  Size: %ld KB in %d Sectors\n",
210                info->size >> 10, info->sector_count);
211
212         printf("  Sector Start Addresses:");
213         for (i = 0; i < info->sector_count; ++i) {
214                 /*
215                  * Check if whole sector is erased
216                  */
217                 if (i != (info->sector_count - 1))
218                         size = info->start[i + 1] - info->start[i];
219                 else
220                         size = info->start[0] + info->size - info->start[i];
221                 erased = 1;
222                 flash = (volatile unsigned long *) info->start[i];
223                 size = size >> 2;       /* divide by 4 for longword access */
224                 for (k = 0; k < size; k++) {
225                         if (*flash++ != 0xffffffff) {
226                                 erased = 0;
227                                 break;
228                         }
229                 }
230
231                 if ((i % 5) == 0)
232                         printf("\n   ");
233                 printf(" %08lX%s%s",
234                        info->start[i],
235                        erased ? " E" : "  ", info->protect[i] ? "RO " : "   ");
236         }
237         printf("\n");
238         return;
239 }
240
241 /*-----------------------------------------------------------------------
242  */
243
244 /*
245  * The following code cannot be run from FLASH!
246  */
247 static ulong flash_get_size(vu_long * addr, flash_info_t * info)
248 {
249         short i;
250         FLASH_WORD_SIZE value;
251         ulong base = (ulong) addr;
252         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
253
254         DEBUGF("FLASH ADDR: %08x\n", (unsigned) addr);
255
256         /* Write auto select command: read Manufacturer ID */
257         udelay(10000);
258         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
259         udelay(1000);
260         addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
261         udelay(1000);
262         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00900090;
263         udelay(1000);
264
265         value = addr2[0];
266         DEBUGF("FLASH MANUFACT: %x\n", value);
267
268         switch (value) {
269         case (FLASH_WORD_SIZE) AMD_MANUFACT:
270                 info->flash_id = FLASH_MAN_AMD;
271                 break;
272         case (FLASH_WORD_SIZE) FUJ_MANUFACT:
273                 info->flash_id = FLASH_MAN_FUJ;
274                 break;
275         case (FLASH_WORD_SIZE) SST_MANUFACT:
276                 info->flash_id = FLASH_MAN_SST;
277                 break;
278         case (FLASH_WORD_SIZE) STM_MANUFACT:
279                 info->flash_id = FLASH_MAN_STM;
280                 break;
281         default:
282                 info->flash_id = FLASH_UNKNOWN;
283                 info->sector_count = 0;
284                 info->size = 0;
285                 return (0);             /* no or unknown flash  */
286         }
287
288         value = addr2[1];               /* device ID            */
289
290         DEBUGF("\nFLASH DEVICEID: %x\n", value);
291
292         switch (value) {
293         case (FLASH_WORD_SIZE) AMD_ID_LV040B:
294                 info->flash_id += FLASH_AM040;
295                 info->sector_count = 8;
296                 info->size = 0x0080000; /* => 512 ko */
297                 break;
298         case (FLASH_WORD_SIZE) AMD_ID_F040B:
299                 info->flash_id += FLASH_AM040;
300                 info->sector_count = 8;
301                 info->size = 0x0080000; /* => 512 ko */
302                 break;
303         case (FLASH_WORD_SIZE) AMD_ID_LV033C:
304                 info->flash_id += FLASH_AMDLV033C;
305                 info->sector_count = 64;
306                 info->size = 0x00400000;
307                 break;                  /* => 4 MB              */
308         default:
309                 info->flash_id = FLASH_UNKNOWN;
310                 return (0);             /* => no or unknown flash */
311         }
312
313         /* set up sector start address table */
314         if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
315             (info->flash_id == FLASH_AM040) ||
316             (info->flash_id == FLASH_AMD016)) {
317                 for (i = 0; i < info->sector_count; i++)
318                         info->start[i] = base + (i * 0x00010000);
319         } else {
320                 if (info->flash_id & FLASH_BTYPE) {
321                         /* set sector offsets for bottom boot block type        */
322                         info->start[0] = base + 0x00000000;
323                         info->start[1] = base + 0x00004000;
324                         info->start[2] = base + 0x00006000;
325                         info->start[3] = base + 0x00008000;
326                         for (i = 4; i < info->sector_count; i++) {
327                                 info->start[i] = base + (i * 0x00010000) - 0x00030000;
328                         }
329                 } else {
330                         /* set sector offsets for top boot block type           */
331                         i = info->sector_count - 1;
332                         info->start[i--] = base + info->size - 0x00004000;
333                         info->start[i--] = base + info->size - 0x00006000;
334                         info->start[i--] = base + info->size - 0x00008000;
335                         for (; i >= 0; i--) {
336                                 info->start[i] = base + i * 0x00010000;
337                         }
338                 }
339         }
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                 addr2 = (volatile FLASH_WORD_SIZE *) (info->start[i]);
346                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
347                         info->protect[i] = 0;
348                 else
349                         info->protect[i] = addr2[2] & 1;
350         }
351
352         /*
353          * Prevent writes to uninitialized FLASH.
354          */
355         if (info->flash_id != FLASH_UNKNOWN) {
356         }
357
358         return (info->size);
359 }
360
361 int wait_for_DQ7(flash_info_t * info, int sect)
362 {
363         ulong start, now, last;
364         volatile FLASH_WORD_SIZE *addr =
365                 (FLASH_WORD_SIZE *) (info->start[sect]);
366
367         start = get_timer(0);
368         last = start;
369         while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
370                (FLASH_WORD_SIZE) 0x00800080) {
371                 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
372                         printf("Timeout\n");
373                         return -1;
374                 }
375                 /* show that we're waiting */
376                 if ((now - last) > 1000) {      /* every second */
377                         putc('.');
378                         last = now;
379                 }
380         }
381         return 0;
382 }
383
384 /*-----------------------------------------------------------------------
385  */
386
387 int flash_erase(flash_info_t * info, int s_first, int s_last)
388 {
389         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
390         volatile FLASH_WORD_SIZE *addr2;
391         int flag, prot, sect, l_sect;
392         int i;
393
394         if ((s_first < 0) || (s_first > s_last)) {
395                 if (info->flash_id == FLASH_UNKNOWN) {
396                         printf("- missing\n");
397                 } else {
398                         printf("- no sectors to erase\n");
399                 }
400                 return 1;
401         }
402
403         if (info->flash_id == FLASH_UNKNOWN) {
404                 printf("Can't erase unknown flash type - aborted\n");
405                 return 1;
406         }
407
408         prot = 0;
409         for (sect = s_first; sect <= s_last; ++sect) {
410                 if (info->protect[sect]) {
411                         prot++;
412                 }
413         }
414
415         if (prot) {
416                 printf("- Warning: %d protected sectors will not be erased!\n",
417                        prot);
418         } else {
419                 printf("\n");
420         }
421
422         l_sect = -1;
423
424         /* Disable interrupts which might cause a timeout here */
425         flag = disable_interrupts();
426
427         /* Start erase on unprotected sectors */
428         for (sect = s_first; sect <= s_last; sect++) {
429                 if (info->protect[sect] == 0) { /* not protected */
430                         addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
431                         printf("Erasing sector %p\n", addr2);
432
433                         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
434                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
435                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
436                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
437                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
438                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
439                                 addr2[0] = (FLASH_WORD_SIZE) 0x00500050;        /* block erase */
440                                 for (i = 0; i < 50; i++)
441                                         udelay(1000);   /* wait 1 ms */
442                         } else {
443                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
444                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
445                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
446                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
447                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
448                                 addr2[0] = (FLASH_WORD_SIZE) 0x00300030;        /* sector erase */
449                         }
450                         l_sect = sect;
451                         /*
452                          * Wait for each sector to complete, it's more
453                          * reliable.  According to AMD Spec, you must
454                          * issue all erase commands within a specified
455                          * timeout.  This has been seen to fail, especially
456                          * if printf()s are included (for debug)!!
457                          */
458                         wait_for_DQ7(info, sect);
459                 }
460         }
461
462         /* re-enable interrupts if necessary */
463         if (flag)
464                 enable_interrupts();
465
466         /* wait at least 80us - let's wait 1 ms */
467         udelay(1000);
468
469         /* reset to read mode */
470         addr = (FLASH_WORD_SIZE *) info->start[0];
471         addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
472
473         printf(" done\n");
474         return 0;
475 }
476
477 /*-----------------------------------------------------------------------
478  * Copy memory to flash, returns:
479  * 0 - OK
480  * 1 - write timeout
481  * 2 - Flash not erased
482  */
483 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
484 {
485         ulong cp, wp, data;
486         int i, l, rc;
487
488         wp = (addr & ~3);               /* get lower word aligned address */
489
490         /*
491          * handle unaligned start bytes
492          */
493         if ((l = addr - wp) != 0) {
494                 data = 0;
495             for (i = 0, cp = wp; i < l; ++i, ++cp) {
496                     data = (data << 8) | (*(uchar *) cp);
497             }
498             for (; i < 4 && cnt > 0; ++i) {
499                     data = (data << 8) | *src++;
500                     --cnt;
501                     ++cp;
502             }
503             for (; cnt == 0 && i < 4; ++i, ++cp) {
504                     data = (data << 8) | (*(uchar *) cp);
505             }
506
507             if ((rc = write_word(info, wp, data)) != 0) {
508                     return (rc);
509             }
510             wp += 4;
511         }
512
513         /*
514          * handle word aligned part
515          */
516         while (cnt >= 4) {
517                 data = 0;
518                 for (i = 0; i < 4; ++i) {
519                         data = (data << 8) | *src++;
520                 }
521                 if ((rc = write_word(info, wp, data)) != 0) {
522                         return (rc);
523                 }
524                 wp += 4;
525                 cnt -= 4;
526         }
527
528         if (cnt == 0) {
529                 return (0);
530         }
531
532         /*
533          * handle unaligned tail bytes
534          */
535         data = 0;
536         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
537                 data = (data << 8) | *src++;
538                 --cnt;
539         }
540         for (; i < 4; ++i, ++cp) {
541                 data = (data << 8) | (*(uchar *) cp);
542         }
543
544         return (write_word(info, wp, data));
545 }
546
547 /*-----------------------------------------------------------------------
548  * Write a word to Flash, returns:
549  * 0 - OK
550  * 1 - write timeout
551  * 2 - Flash not erased
552  */
553 static int write_word(flash_info_t * info, ulong dest, ulong data)
554 {
555         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]);
556         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
557         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
558         ulong start;
559         int i;
560
561         /* Check if Flash is (sufficiently) erased */
562         if ((*((volatile FLASH_WORD_SIZE *) dest) &
563              (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
564                 return (2);
565         }
566
567         for (i = 0; i < 4 / sizeof(FLASH_WORD_SIZE); i++) {
568                 int flag;
569
570                 /* Disable interrupts which might cause a timeout here */
571                 flag = disable_interrupts();
572
573                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
574                 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
575                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
576
577                 dest2[i] = data2[i];
578
579                 /* re-enable interrupts if necessary */
580                 if (flag)
581                         enable_interrupts();
582
583                 /* data polling for D7 */
584                 start = get_timer(0);
585                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
586                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
587
588                         if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
589                                 return (1);
590                         }
591                 }
592         }
593
594         return (0);
595 }