Merge with rsync://git-user@source.denx.net/git/u-boot.git
[platform/kernel/u-boot.git] / board / amcc / yosemite / flash.c
1 /*
2  * (C) Copyright 2002-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 /*
35  * Ported to XPedite1000, 1/2 mb boot flash only
36  * Travis B. Sawyer, <travis.sawyer@sandburst.com>
37  */
38
39 #include <common.h>
40 #include <ppc4xx.h>
41 #include <asm/processor.h>
42
43 #undef DEBUG
44 #ifdef DEBUG
45 #define DEBUGF(x...) printf(x)
46 #else
47 #define DEBUGF(x...)
48 #endif                          /* DEBUG */
49
50 #define BOOT_SMALL_FLASH        32      /* 00100000 */
51 #define FLASH_ONBD_N            2       /* 00000010 */
52 #define FLASH_SRAM_SEL          1       /* 00000001 */
53
54 #define BOOT_SMALL_FLASH_VAL    4
55 #define FLASH_ONBD_N_VAL        2
56 #define FLASH_SRAM_SEL_VAL      1
57
58 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips   */
59
60 unsigned long flash_addr_table[512][CFG_MAX_FLASH_BANKS] = {
61         {0xfe000000}
62
63 };
64
65 /*-----------------------------------------------------------------------
66  * Functions
67  */
68 static ulong flash_get_size(vu_long * addr, flash_info_t * info);
69 static int write_word(flash_info_t * info, ulong dest, ulong data);
70
71 #define ADDR0           0xaaaa
72 #define ADDR1           0x5554
73 #define FLASH_WORD_SIZE unsigned short
74
75 /*-----------------------------------------------------------------------
76  */
77
78 unsigned long flash_init(void)
79 {
80         unsigned long total_b = 0;
81         unsigned long size_b[CFG_MAX_FLASH_BANKS];
82         unsigned short index = 0;
83         int i;
84
85         DEBUGF("\n");
86         DEBUGF("FLASH: Index: %d\n", index);
87
88         /* Init: no FLASHes known */
89         for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
90                 flash_info[i].flash_id = FLASH_UNKNOWN;
91                 flash_info[i].sector_count = -1;
92                 flash_info[i].size = 0;
93
94                 /* check whether the address is 0 */
95                 if (flash_addr_table[index][i] == 0) {
96                         continue;
97                 }
98
99                 /* call flash_get_size() to initialize sector address */
100                 size_b[i] = flash_get_size((vu_long *)
101                                            flash_addr_table[index][i],
102                                            &flash_info[i]);
103                 flash_info[i].size = size_b[i];
104                 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
105                         printf
106                             ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
107                              i, size_b[i], size_b[i] << 20);
108                         flash_info[i].sector_count = -1;
109                         flash_info[i].size = 0;
110                 }
111
112                 total_b += flash_info[i].size;
113         }
114
115         /* FLASH protect Monitor */
116         flash_protect(FLAG_PROTECT_SET,
117                       CFG_MONITOR_BASE, 0xFFFFFFFF, &flash_info[0]);
118
119         return total_b;
120 }
121
122 /*-----------------------------------------------------------------------
123  */
124 void flash_print_info(flash_info_t * info)
125 {
126         int i;
127         int k;
128         int size;
129         int erased;
130         volatile unsigned long *flash;
131
132         if (info->flash_id == FLASH_UNKNOWN) {
133                 printf("missing or unknown FLASH type\n");
134                 return;
135         }
136
137         switch (info->flash_id & FLASH_VENDMASK) {
138         case FLASH_MAN_AMD:
139                 printf("AMD ");
140                 break;
141         case FLASH_MAN_FUJ:
142                 printf("FUJITSU ");
143                 break;
144         case FLASH_MAN_SST:
145                 printf("SST ");
146                 break;
147         default:
148                 printf("Unknown Vendor ");
149                 break;
150         }
151
152         switch (info->flash_id & FLASH_TYPEMASK) {
153         case FLASH_AMD016:
154                 printf("AM29F016D (16 Mbit, uniform sector size)\n");
155                 break;
156         case FLASH_AM040:
157                 printf("AM29F040 (512 Kbit, uniform sector size)\n");
158                 break;
159         case FLASH_AM400B:
160                 printf("AM29LV400B (4 Mbit, bottom boot sect)\n");
161                 break;
162         case FLASH_AM400T:
163                 printf("AM29LV400T (4 Mbit, top boot sector)\n");
164                 break;
165         case FLASH_AM800B:
166                 printf("AM29LV800B (8 Mbit, bottom boot sect)\n");
167                 break;
168         case FLASH_AM800T:
169                 printf("AM29LV800T (8 Mbit, top boot sector)\n");
170                 break;
171         case FLASH_AM160B:
172                 printf("AM29LV160B (16 Mbit, bottom boot sect)\n");
173                 break;
174         case FLASH_AM160T:
175                 printf("AM29LV160T (16 Mbit, top boot sector)\n");
176                 break;
177         case FLASH_AM320B:
178                 printf("AM29LV320B (32 Mbit, bottom boot sect)\n");
179                 break;
180         case FLASH_AM320T:
181                 printf("AM29LV320T (32 Mbit, top boot sector)\n");
182                 break;
183         case FLASH_SST800A:
184                 printf("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
185                 break;
186         case FLASH_SST160A:
187                 printf("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
188                 break;
189         default:
190                 printf("Unknown Chip Type\n");
191                 break;
192         }
193
194         printf("  Size: %ld KB in %d Sectors\n",
195                info->size >> 10, info->sector_count);
196
197         printf("  Sector Start Addresses:");
198         for (i = 0; i < info->sector_count; ++i) {
199                 /*
200                  * Check if whole sector is erased
201                  */
202                 if (i != (info->sector_count - 1))
203                         size = info->start[i + 1] - info->start[i];
204                 else
205                         size = info->start[0] + info->size - info->start[i];
206                 erased = 1;
207                 flash = (volatile unsigned long *)info->start[i];
208                 size = size >> 2;       /* divide by 4 for longword access */
209                 for (k = 0; k < size; k++) {
210                         if (*flash++ != 0xffffffff) {
211                                 erased = 0;
212                                 break;
213                         }
214                 }
215
216                 if ((i % 5) == 0)
217                         printf("\n   ");
218                 printf(" %08lX%s%s",
219                        info->start[i],
220                        erased ? " E" : "  ", info->protect[i] ? "RO " : "   ");
221         }
222         printf("\n");
223         return;
224 }
225
226 /*-----------------------------------------------------------------------
227  */
228
229 /*-----------------------------------------------------------------------
230  */
231
232 /*
233  * The following code cannot be run from FLASH!
234  */
235 static ulong flash_get_size(vu_long * addr, flash_info_t * info)
236 {
237         short i;
238         FLASH_WORD_SIZE value;
239         ulong base = (ulong) addr;
240         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
241
242         DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr);
243
244         /* Write auto select command: read Manufacturer ID */
245         udelay(10000);
246         *(FLASH_WORD_SIZE *) ((int)addr + ADDR0) = (FLASH_WORD_SIZE) 0x00AA;
247         udelay(1000);
248         *(FLASH_WORD_SIZE *) ((int)addr + ADDR1) = (FLASH_WORD_SIZE) 0x0055;
249         udelay(1000);
250         *(FLASH_WORD_SIZE *) ((int)addr + ADDR0) = (FLASH_WORD_SIZE) 0x0090;
251         udelay(1000);
252
253         value = addr2[0];
254
255         DEBUGF("FLASH MANUFACT: %x\n", value);
256
257         switch (value) {
258         case (FLASH_WORD_SIZE) AMD_MANUFACT:
259                 info->flash_id = FLASH_MAN_AMD;
260                 break;
261         case (FLASH_WORD_SIZE) FUJ_MANUFACT:
262                 info->flash_id = FLASH_MAN_FUJ;
263                 break;
264         case (FLASH_WORD_SIZE) SST_MANUFACT:
265                 info->flash_id = FLASH_MAN_SST;
266                 break;
267         case (FLASH_WORD_SIZE) STM_MANUFACT:
268                 info->flash_id = FLASH_MAN_STM;
269                 break;
270         default:
271                 info->flash_id = FLASH_UNKNOWN;
272                 info->sector_count = 0;
273                 info->size = 0;
274                 return (0);     /* no or unknown flash  */
275         }
276
277 #ifdef CONFIG_ADCIOP
278         value = addr2[0];       /* device ID            */
279         debug("\ndev_code=%x\n", value);
280 #else
281         value = addr2[1];       /* device ID            */
282 #endif
283
284         DEBUGF("\nFLASH DEVICEID: %x\n", value);
285
286         info->flash_id = 0;
287         info->sector_count = CFG_MAX_FLASH_SECT;
288         info->size = 0x02000000;
289
290         /* set up sector start address table */
291         for (i = 0; i < info->sector_count; i++) {
292                 info->start[i] = (int)base + (i * 0x00020000);
293                 info->protect[i] = 0;
294         }
295
296         *(FLASH_WORD_SIZE *) ((int)addr) = (FLASH_WORD_SIZE) 0x00F0;    /* reset bank */
297
298         return (info->size);
299 }
300
301 int wait_for_DQ7(flash_info_t * info, int sect)
302 {
303         ulong start, now, last;
304         volatile FLASH_WORD_SIZE *addr =
305             (FLASH_WORD_SIZE *) (info->start[sect]);
306
307         start = get_timer(0);
308         last = start;
309         while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
310                (FLASH_WORD_SIZE) 0x00800080) {
311                 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
312                         printf("Timeout\n");
313                         return -1;
314                 }
315                 /* show that we're waiting */
316                 if ((now - last) > 1000) {      /* every second */
317                         putc('.');
318                         last = now;
319                 }
320         }
321         return 0;
322 }
323
324 /*-----------------------------------------------------------------------
325  */
326
327 int flash_erase(flash_info_t * info, int s_first, int s_last)
328 {
329         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
330         volatile FLASH_WORD_SIZE *addr2;
331         int flag, prot, sect, l_sect;
332
333         if ((s_first < 0) || (s_first > s_last)) {
334                 if (info->flash_id == FLASH_UNKNOWN) {
335                         printf("- missing\n");
336                 } else {
337                         printf("- no sectors to erase\n");
338                 }
339                 return 1;
340         }
341
342         if (info->flash_id == FLASH_UNKNOWN) {
343                 printf("Can't erase unknown flash type - aborted\n");
344                 return 1;
345         }
346
347         prot = 0;
348         for (sect = s_first; sect <= s_last; ++sect) {
349                 if (info->protect[sect]) {
350                         prot++;
351                 }
352         }
353
354         if (prot) {
355                 printf("- Warning: %d protected sectors will not be erased!\n",
356                        prot);
357         } else {
358                 printf("\n");
359         }
360
361         l_sect = -1;
362
363         /* Disable interrupts which might cause a timeout here */
364         flag = disable_interrupts();
365
366         /* Start erase on unprotected sectors */
367         for (sect = s_first; sect <= s_last; sect++) {
368                 if (info->protect[sect] == 0) { /* not protected */
369                         addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
370                         printf("Erasing sector %p\n", addr2);
371                         *(FLASH_WORD_SIZE *) ((int)addr + ADDR0) =
372                             (FLASH_WORD_SIZE) 0x00AA;
373                         asm("sync");
374                         asm("isync");
375                         *(FLASH_WORD_SIZE *) ((int)addr + ADDR1) =
376                             (FLASH_WORD_SIZE) 0x0055;
377                         asm("sync");
378                         asm("isync");
379                         *(FLASH_WORD_SIZE *) ((int)addr + ADDR0) =
380                             (FLASH_WORD_SIZE) 0x0080;
381                         asm("sync");
382                         asm("isync");
383                         *(FLASH_WORD_SIZE *) ((int)addr + ADDR0) =
384                             (FLASH_WORD_SIZE) 0x00AA;
385                         asm("sync");
386                         asm("isync");
387                         *(FLASH_WORD_SIZE *) ((int)addr + ADDR1) =
388                             (FLASH_WORD_SIZE) 0x0055;
389                         asm("sync");
390                         asm("isync");
391                         addr2[0] = (FLASH_WORD_SIZE) 0x00300030;        /* sector erase */
392                         asm("sync");
393                         asm("isync");
394
395                         l_sect = sect;
396                         /*
397                          * Wait for each sector to complete, it's more
398                          * reliable.  According to AMD Spec, you must
399                          * issue all erase commands within a specified
400                          * timeout.  This has been seen to fail, especially
401                          * if printf()s are included (for debug)!!
402                          */
403                         wait_for_DQ7(info, sect);
404                 }
405         }
406
407         /* re-enable interrupts if necessary */
408         if (flag)
409                 enable_interrupts();
410
411         /* wait at least 80us - let's wait 1 ms */
412         udelay(1000);
413
414 #if 0
415         /*
416          * We wait for the last triggered sector
417          */
418         if (l_sect < 0)
419                 goto DONE;
420         wait_for_DQ7(info, l_sect);
421
422       DONE:
423 #endif
424         /* reset to read mode */
425         addr = (FLASH_WORD_SIZE *) info->start[0];
426         addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
427
428         printf(" done\n");
429         return 0;
430 }
431
432 /*-----------------------------------------------------------------------
433  * Copy memory to flash, returns:
434  * 0 - OK
435  * 1 - write timeout
436  * 2 - Flash not erased
437  */
438 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
439 {
440         ulong cp, wp, data;
441         int i, l, rc;
442         ulong status_value = 0;
443
444         wp = (addr & ~3);       /* get lower word aligned address */
445
446         /*
447          * handle unaligned start bytes
448          */
449         if ((l = addr - wp) != 0) {
450                 data = 0;
451                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
452                         data = (data << 8) | (*(uchar *) cp);
453                 }
454                 for (; i < 4 && cnt > 0; ++i) {
455                         data = (data << 8) | *src++;
456                         --cnt;
457                         ++cp;
458                 }
459                 for (; cnt == 0 && i < 4; ++i, ++cp) {
460                         data = (data << 8) | (*(uchar *) cp);
461                 }
462
463                 if ((rc = write_word(info, wp, data)) != 0) {
464                         return (rc);
465                 }
466                 wp += 4;
467         }
468
469         /*
470          * handle word aligned part
471          */
472         while (cnt >= 4) {
473
474                 /*print status if needed */
475                 if ((wp >= (status_value + 0x20000))
476                     && (status_value < 0xFFFE0000)) {
477                         status_value = wp;
478                         printf("writing to sector 0x%X\n", status_value);
479                 }
480
481                 data = 0;
482                 for (i = 0; i < 4; ++i) {
483                         data = (data << 8) | *src++;
484                 }
485                 if ((rc = write_word(info, wp, data)) != 0) {
486                         return (rc);
487                 }
488                 wp += 4;
489                 cnt -= 4;
490         }
491
492         if (cnt == 0) {
493                 return (0);
494         }
495
496         /*
497          * handle unaligned tail bytes
498          */
499         data = 0;
500         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
501                 data = (data << 8) | *src++;
502                 --cnt;
503         }
504         for (; i < 4; ++i, ++cp) {
505                 data = (data << 8) | (*(uchar *) cp);
506         }
507
508         return (write_word(info, wp, data));
509 }
510
511 /*-----------------------------------------------------------------------
512  * Write a word to Flash, returns:
513  * 0 - OK
514  * 1 - write timeout
515  * 2 - Flash not erased
516  */
517 static int write_word(flash_info_t * info, ulong dest, ulong data)
518 {
519         vu_long *addr2 = (vu_long *) (info->start[0]);
520         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
521         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
522         ulong start;
523         int i;
524
525         /* Check if Flash is (sufficiently) erased */
526         if ((*((volatile FLASH_WORD_SIZE *)dest) &
527              (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
528                 return (2);
529         }
530
531         for (i = 0; i < 4 / sizeof(FLASH_WORD_SIZE); i++) {
532                 int flag;
533
534                 /* Disable interrupts which might cause a timeout here */
535                 flag = disable_interrupts();
536
537                 *(FLASH_WORD_SIZE *) ((int)addr2 + ADDR0) =
538                     (FLASH_WORD_SIZE) 0x00AA;
539                 asm("sync");
540                 asm("isync");
541                 *(FLASH_WORD_SIZE *) ((int)addr2 + ADDR1) =
542                     (FLASH_WORD_SIZE) 0x0055;
543                 asm("sync");
544                 asm("isync");
545                 *(FLASH_WORD_SIZE *) ((int)addr2 + ADDR0) =
546                     (FLASH_WORD_SIZE) 0x00A0;
547                 asm("sync");
548                 asm("isync");
549
550                 dest2[i] = data2[i];
551
552                 /* re-enable interrupts if necessary */
553                 if (flag)
554                         enable_interrupts();
555
556                 /* data polling for D7 */
557                 start = get_timer(0);
558                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
559                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
560
561                         if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
562                                 return (1);
563                         }
564                 }
565         }
566
567         return (0);
568 }
569
570 /*-----------------------------------------------------------------------
571  */