]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/prodrive/common/flash.c
Merge branch 'mpc86xx'
[karo-tx-uboot.git] / board / prodrive / common / flash.c
1 /*
2  * (C) Copyright 2006
3  * Stefan Roese, DENX Software Engineering, sr@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 <asm/processor.h>
26
27 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
28
29 /*
30  * Functions
31  */
32 static int write_word(flash_info_t *info, ulong dest, ulong data);
33
34 void flash_print_info(flash_info_t *info)
35 {
36         int i;
37         int k;
38         int size;
39         int erased;
40         volatile unsigned long *flash;
41
42         if (info->flash_id == FLASH_UNKNOWN) {
43                 printf ("missing or unknown FLASH type\n");
44                 return;
45         }
46
47         switch (info->flash_id & FLASH_VENDMASK) {
48         case FLASH_MAN_AMD:     printf ("AMD ");                break;
49         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
50         case FLASH_MAN_SST:     printf ("SST ");                break;
51         case FLASH_MAN_EXCEL:   printf ("Excel Semiconductor "); break;
52         default:                printf ("Unknown Vendor ");     break;
53         }
54
55         switch (info->flash_id & FLASH_TYPEMASK) {
56         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
57                 break;
58         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
59                 break;
60         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
61                 break;
62         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
63                 break;
64         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
65                 break;
66         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
67                 break;
68         case FLASH_AM320T:      printf ("AM29LV320T (32 M, top sector)\n");
69                 break;
70         case FLASH_AM320B:      printf ("AM29LV320B (32 M, bottom sector)\n");
71                 break;
72         case FLASH_AMDL322T:    printf ("AM29DL322T (32 M, top sector)\n");
73                 break;
74         case FLASH_AMDL322B:    printf ("AM29DL322B (32 M, bottom sector)\n");
75                 break;
76         case FLASH_AMDL323T:    printf ("AM29DL323T (32 M, top sector)\n");
77                 break;
78         case FLASH_AMDL323B:    printf ("AM29DL323B (32 M, bottom sector)\n");
79                 break;
80         case FLASH_SST020:      printf ("SST39LF/VF020 (2 Mbit, uniform sector size)\n");
81                 break;
82         case FLASH_SST040:      printf ("SST39LF/VF040 (4 Mbit, uniform sector size)\n");
83                 break;
84         default:                printf ("Unknown Chip Type\n");
85                 break;
86         }
87
88         printf ("  Size: %ld MB in %d Sectors\n",
89                 info->size >> 20, info->sector_count);
90
91         printf ("  Sector Start Addresses:");
92         for (i=0; i<info->sector_count; ++i) {
93 #ifdef CFG_FLASH_EMPTY_INFO
94                 /*
95                  * Check if whole sector is erased
96                  */
97                 if (i != (info->sector_count-1))
98                         size = info->start[i+1] - info->start[i];
99                 else
100                         size = info->start[0] + info->size - info->start[i];
101                 erased = 1;
102                 flash = (volatile unsigned long *)info->start[i];
103                 size = size >> 2;        /* divide by 4 for longword access */
104                 for (k=0; k<size; k++) {
105                         if (*flash++ != 0xffffffff) {
106                                 erased = 0;
107                                 break;
108                         }
109                 }
110
111                 if ((i % 5) == 0)
112                         printf ("\n   ");
113                 /* print empty and read-only info */
114                 printf (" %08lX%s%s",
115                         info->start[i],
116                         erased ? " E" : "  ",
117                         info->protect[i] ? "RO " : "   ");
118 #else
119                 if ((i % 5) == 0)
120                         printf ("\n   ");
121                 printf (" %08lX%s",
122                         info->start[i],
123                         info->protect[i] ? " (RO)" : "     ");
124 #endif
125
126         }
127         printf ("\n");
128         return;
129 }
130
131 /*
132  * The following code cannot be run from FLASH!
133  */
134 static ulong flash_get_size(vu_long *addr, flash_info_t *info)
135 {
136         short i;
137         short n;
138         CFG_FLASH_WORD_SIZE value;
139         ulong base = (ulong)addr;
140         volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr;
141
142         /* Write auto select command: read Manufacturer ID */
143         addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
144         addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
145         addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
146
147         value = addr2[CFG_FLASH_READ0];
148
149         switch (value) {
150         case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
151                 info->flash_id = FLASH_MAN_AMD;
152                 break;
153         case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT:
154                 info->flash_id = FLASH_MAN_FUJ;
155                 break;
156         case (CFG_FLASH_WORD_SIZE)SST_MANUFACT:
157                 info->flash_id = FLASH_MAN_SST;
158                 break;
159         case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT:
160                 info->flash_id = FLASH_MAN_EXCEL;
161                 break;
162         default:
163                 info->flash_id = FLASH_UNKNOWN;
164                 info->sector_count = 0;
165                 info->size = 0;
166                 return (0);                     /* no or unknown flash  */
167         }
168
169         value = addr2[CFG_FLASH_READ1];         /* device ID            */
170
171         switch (value) {
172         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T:
173                 info->flash_id += FLASH_AM400T;
174                 info->sector_count = 11;
175                 info->size = 0x00080000;
176                 break;                          /* => 0.5 MB            */
177
178         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B:
179                 info->flash_id += FLASH_AM400B;
180                 info->sector_count = 11;
181                 info->size = 0x00080000;
182                 break;                          /* => 0.5 MB            */
183
184         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T:
185                 info->flash_id += FLASH_AM800T;
186                 info->sector_count = 19;
187                 info->size = 0x00100000;
188                 break;                          /* => 1 MB              */
189
190         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B:
191                 info->flash_id += FLASH_AM800B;
192                 info->sector_count = 19;
193                 info->size = 0x00100000;
194                 break;                          /* => 1 MB              */
195
196         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T:
197                 info->flash_id += FLASH_AM160T;
198                 info->sector_count = 35;
199                 info->size = 0x00200000;
200                 break;                          /* => 2 MB              */
201
202         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B:
203                 info->flash_id += FLASH_AM160B;
204                 info->sector_count = 35;
205                 info->size = 0x00200000;
206                 break;                          /* => 2 MB              */
207
208         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T:
209                 info->flash_id += FLASH_AM320T;
210                 info->sector_count = 71;
211                 info->size = 0x00400000;  break;        /* => 4 MB      */
212
213         case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B:
214                 info->flash_id += FLASH_AM320B;
215                 info->sector_count = 71;
216                 info->size = 0x00400000;  break;        /* => 4 MB      */
217
218         case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T:
219                 info->flash_id += FLASH_AMDL322T;
220                 info->sector_count = 71;
221                 info->size = 0x00400000;  break;        /* => 4 MB      */
222
223         case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B:
224                 info->flash_id += FLASH_AMDL322B;
225                 info->sector_count = 71;
226                 info->size = 0x00400000;  break;        /* => 4 MB      */
227
228         case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T:
229                 info->flash_id += FLASH_AMDL323T;
230                 info->sector_count = 71;
231                 info->size = 0x00400000;  break;        /* => 4 MB      */
232
233         case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B:
234                 info->flash_id += FLASH_AMDL323B;
235                 info->sector_count = 71;
236                 info->size = 0x00400000;  break;        /* => 4 MB      */
237
238         case (CFG_FLASH_WORD_SIZE)SST_ID_xF020:
239                 info->flash_id += FLASH_SST020;
240                 info->sector_count = 64;
241                 info->size = 0x00040000;
242                 break;                          /* => 256 kB            */
243
244         case (CFG_FLASH_WORD_SIZE)SST_ID_xF040:
245                 info->flash_id += FLASH_SST040;
246                 info->sector_count = 128;
247                 info->size = 0x00080000;
248                 break;                          /* => 512 kB            */
249
250         default:
251                 info->flash_id = FLASH_UNKNOWN;
252                 return (0);                     /* => no or unknown flash */
253
254         }
255
256         /* set up sector start address table */
257         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
258                 for (i = 0; i < info->sector_count; i++)
259                         info->start[i] = base + (i * 0x00001000);
260         } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
261                    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
262                    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
263                    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
264                 /* set sector offsets for bottom boot block type        */
265                 for (i=0; i<8; ++i) {           /*  8 x 8k boot sectors */
266                         info->start[i] = base;
267                         base += 8 << 10;
268                 }
269                 while (i < info->sector_count) {        /* 64k regular sectors  */
270                         info->start[i] = base;
271                         base += 64 << 10;
272                         ++i;
273                 }
274         } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
275                    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
276                    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
277                    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
278                 /* set sector offsets for top boot block type           */
279                 base += info->size;
280                 i = info->sector_count;
281                 for (n=0; n<8; ++n) {           /*  8 x 8k boot sectors */
282                         base -= 8 << 10;
283                         --i;
284                         info->start[i] = base;
285                 }
286                 while (i > 0) {                 /* 64k regular sectors  */
287                         base -= 64 << 10;
288                         --i;
289                         info->start[i] = base;
290                 }
291         } else {
292                 if (info->flash_id & FLASH_BTYPE) {
293                         /* set sector offsets for bottom boot block type        */
294                         info->start[0] = base + 0x00000000;
295                         info->start[1] = base + 0x00004000;
296                         info->start[2] = base + 0x00006000;
297                         info->start[3] = base + 0x00008000;
298                         for (i = 4; i < info->sector_count; i++) {
299                                 info->start[i] = base + (i * 0x00010000) - 0x00030000;
300                         }
301                 } else {
302                         /* set sector offsets for top boot block type           */
303                         i = info->sector_count - 1;
304                         info->start[i--] = base + info->size - 0x00004000;
305                         info->start[i--] = base + info->size - 0x00006000;
306                         info->start[i--] = base + info->size - 0x00008000;
307                         for (; i >= 0; i--) {
308                                 info->start[i] = base + i * 0x00010000;
309                         }
310                 }
311         }
312
313         /* check for protected sectors */
314         for (i = 0; i < info->sector_count; i++) {
315                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
316                 /* D0 = 1 if protected */
317                 addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]);
318                 if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD)
319                         info->protect[i] = 0;
320                 else
321                         info->protect[i] = addr2[CFG_FLASH_READ2] & 1;
322         }
323
324         /*
325          * Prevent writes to uninitialized FLASH.
326          */
327         if (info->flash_id != FLASH_UNKNOWN) {
328                 addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0];
329                 *addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0;       /* reset bank */
330         }
331
332         return (info->size);
333 }
334
335
336 int flash_erase(flash_info_t *info, int s_first, int s_last)
337 {
338         volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
339         volatile CFG_FLASH_WORD_SIZE *addr2;
340         int flag, prot, sect, l_sect;
341         ulong start, now, last;
342
343         if ((s_first < 0) || (s_first > s_last)) {
344                 if (info->flash_id == FLASH_UNKNOWN)
345                         printf ("- missing\n");
346                 else
347                         printf ("- no sectors to erase\n");
348                 return 1;
349         }
350
351         if (info->flash_id == FLASH_UNKNOWN) {
352                 printf ("Can't erase unknown flash type - aborted\n");
353                 return 1;
354         }
355
356         prot = 0;
357         for (sect=s_first; sect<=s_last; ++sect)
358                 if (info->protect[sect])
359                         prot++;
360
361         if (prot)
362                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
363         else
364                 printf ("\n");
365
366         l_sect = -1;
367
368         /* Disable interrupts which might cause a timeout here */
369         flag = disable_interrupts();
370
371         /* Start erase on unprotected sectors */
372         for (sect = s_first; sect<=s_last; sect++) {
373                 if (info->protect[sect] == 0) { /* not protected */
374                         addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
375                         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
376                                 addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
377                                 addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
378                                 addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
379                                 addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
380                                 addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
381                                 addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030;  /* sector erase */
382
383                                 /* re-enable interrupts if necessary */
384                                 if (flag) {
385                                         enable_interrupts();
386                                         flag = 0;
387                                 }
388
389                                 /* data polling for D7 */
390                                 start = get_timer (0);
391                                 while ((addr2[0] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
392                                        (CFG_FLASH_WORD_SIZE)0x00800080) {
393                                         if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
394                                                 return (1);
395                                 }
396                         } else {
397                                 if (sect == s_first) {
398                                         addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
399                                         addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
400                                         addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
401                                         addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
402                                         addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
403                                 }
404                                 addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030;  /* sector erase */
405                         }
406                         l_sect = sect;
407                 }
408         }
409
410         /* re-enable interrupts if necessary */
411         if (flag)
412                 enable_interrupts();
413
414         /* wait at least 80us - let's wait 1 ms */
415         udelay (1000);
416
417         /*
418          * We wait for the last triggered sector
419          */
420         if (l_sect < 0)
421                 goto DONE;
422
423         start = get_timer (0);
424         last  = start;
425         addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
426         while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
427                 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
428                         printf ("Timeout\n");
429                         return 1;
430                 }
431                 /* show that we're waiting */
432                 if ((now - last) > 1000) {      /* every second */
433                         putc ('.');
434                         last = now;
435                 }
436         }
437
438 DONE:
439         /* reset to read mode */
440         addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
441         addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0;      /* reset bank */
442
443         printf (" done\n");
444         return 0;
445 }
446
447 /*
448  * Copy memory to flash, returns:
449  * 0 - OK
450  * 1 - write timeout
451  * 2 - Flash not erased
452  */
453 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
454 {
455         ulong cp, wp, data;
456         int i, l, rc;
457
458         wp = (addr & ~3);       /* get lower word aligned address */
459
460         /*
461          * handle unaligned start bytes
462          */
463         if ((l = addr - wp) != 0) {
464                 data = 0;
465                 for (i=0, cp=wp; i<l; ++i, ++cp) {
466                         data = (data << 8) | (*(uchar *)cp);
467                 }
468                 for (; i<4 && cnt>0; ++i) {
469                         data = (data << 8) | *src++;
470                         --cnt;
471                         ++cp;
472                 }
473                 for (; cnt==0 && i<4; ++i, ++cp) {
474                         data = (data << 8) | (*(uchar *)cp);
475                 }
476
477                 if ((rc = write_word(info, wp, data)) != 0) {
478                         return (rc);
479                 }
480                 wp += 4;
481         }
482
483         /*
484          * handle word aligned part
485          */
486         while (cnt >= 4) {
487                 data = 0;
488                 for (i=0; i<4; ++i)
489                         data = (data << 8) | *src++;
490                 if ((rc = write_word(info, wp, data)) != 0)
491                         return (rc);
492                 wp  += 4;
493                 cnt -= 4;
494         }
495
496         if (cnt == 0)
497                 return (0);
498
499         /*
500          * handle unaligned tail bytes
501          */
502         data = 0;
503         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
504                 data = (data << 8) | *src++;
505                 --cnt;
506         }
507         for (; i<4; ++i, ++cp)
508                 data = (data << 8) | (*(uchar *)cp);
509
510         return (write_word(info, wp, data));
511 }
512
513 /*
514  * Write a word to Flash, returns:
515  * 0 - OK
516  * 1 - write timeout
517  * 2 - Flash not erased
518  */
519 static int write_word(flash_info_t *info, ulong dest, ulong data)
520 {
521         volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
522         volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
523         volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
524         ulong start;
525         int flag;
526         int i;
527
528         /* Check if Flash is (sufficiently) erased */
529         if ((*((vu_long *)dest) & data) != data)
530                 return (2);
531
532         /* Disable interrupts which might cause a timeout here */
533         flag = disable_interrupts();
534
535         for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++) {
536                 addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
537                 addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
538                 addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;
539
540                 dest2[i] = data2[i];
541
542                 /* re-enable interrupts if necessary */
543                 if (flag)
544                         enable_interrupts();
545
546                 /* data polling for D7 */
547                 start = get_timer (0);
548                 while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
549                        (data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
550                         if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
551                                 return (1);
552                 }
553         }
554
555         return (0);
556 }