]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/jse/flash.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / board / jse / flash.c
1 /*
2  * (C) Copyright 2000-2004
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 /*
25  * Modified 4/5/2001
26  * Wait for completion of each sector erase command issued
27  * 4/5/2001
28  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
29  */
30
31 #include <common.h>
32 #include <ppc4xx.h>
33 #include <asm/processor.h>
34
35 #if CONFIG_SYS_MAX_FLASH_BANKS != 1
36 #error "CONFIG_SYS_MAX_FLASH_BANKS must be 1"
37 #endif
38 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips */
39
40 /*-----------------------------------------------------------------------
41  * Functions
42  */
43 static ulong flash_get_size (vu_long * addr, flash_info_t * info);
44 static int write_word (flash_info_t * info, ulong dest, ulong data);
45 static void flash_get_offsets (ulong base, flash_info_t * info);
46
47 #define ADDR0           0x5555
48 #define ADDR1           0x2aaa
49 #define FLASH_WORD_SIZE unsigned char
50
51 /*-----------------------------------------------------------------------
52  */
53
54 unsigned long flash_init (void)
55 {
56         unsigned long size_b0;
57
58         /* Init: no FLASHes known */
59         flash_info[0].flash_id = FLASH_UNKNOWN;
60
61         /* Static FLASH Bank configuration here - FIXME XXX */
62
63         size_b0 = flash_get_size ((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
64
65         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
66                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
67                         size_b0, size_b0 << 20);
68         }
69
70         /* Only one bank */
71         /* Setup offsets */
72         flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
73
74         /* Monitor protection ON by default */
75         (void) flash_protect (FLAG_PROTECT_SET,
76                               FLASH_BASE0_PRELIM,
77                               FLASH_BASE0_PRELIM + monitor_flash_len - 1,
78                               &flash_info[0]);
79         flash_info[0].size = size_b0;
80
81         return size_b0;
82 }
83
84
85 /*-----------------------------------------------------------------------
86  */
87 /*
88  * This implementation assumes that the flash chips are uniform sector
89  * devices. This is true for all likely JSE devices.
90  */
91 static void flash_get_offsets (ulong base, flash_info_t * info)
92 {
93         unsigned idx;
94         unsigned long sector_size = info->size / info->sector_count;
95
96         for (idx = 0; idx < info->sector_count; idx += 1) {
97                 info->start[idx] = base + (idx * sector_size);
98         }
99 }
100
101 /*-----------------------------------------------------------------------
102  */
103 void flash_print_info (flash_info_t * info)
104 {
105         int i;
106         int k;
107         int size;
108         int erased;
109         volatile unsigned long *flash;
110
111         if (info->flash_id == FLASH_UNKNOWN) {
112                 printf ("missing or unknown FLASH type\n");
113                 return;
114         }
115
116         switch (info->flash_id & FLASH_VENDMASK) {
117         case FLASH_MAN_AMD:
118                 printf ("AMD ");
119                 break;
120         case FLASH_MAN_FUJ:
121                 printf ("FUJITSU ");
122                 break;
123         case FLASH_MAN_SST:
124                 printf ("SST ");
125                 break;
126         case FLASH_MAN_STM:
127                 printf ("ST Micro ");
128                 break;
129         default:
130                 printf ("Unknown Vendor ");
131                 break;
132         }
133
134           /* (Reduced table of only parts expected in JSE boards.) */
135         switch (info->flash_id) {
136         case FLASH_MAN_AMD | FLASH_AM040:
137                 printf ("AM29F040 (512 Kbit, uniform sector size)\n");
138                 break;
139         case FLASH_MAN_STM | FLASH_AM040:
140                 printf ("MM29W040W (512 Kbit, uniform sector size)\n");
141                 break;
142         default:
143                 printf ("Unknown Chip Type\n");
144                 break;
145         }
146
147         printf ("  Size: %ld KB in %d Sectors\n",
148                 info->size >> 10, info->sector_count);
149
150         printf ("  Sector Start Addresses:");
151         for (i = 0; i < info->sector_count; ++i) {
152                 /*
153                  * Check if whole sector is erased
154                  */
155                 if (i != (info->sector_count - 1))
156                         size = info->start[i + 1] - info->start[i];
157                 else
158                         size = info->start[0] + info->size - info->start[i];
159                 erased = 1;
160                 flash = (volatile unsigned long *) info->start[i];
161                 size = size >> 2;       /* divide by 4 for longword access */
162                 for (k = 0; k < size; k++) {
163                         if (*flash++ != 0xffffffff) {
164                                 erased = 0;
165                                 break;
166                         }
167                 }
168
169                 if ((i % 5) == 0)
170                         printf ("\n   ");
171                 printf (" %08lX%s%s",
172                         info->start[i],
173                         erased ? " E" : "  ", info->protect[i] ? "RO " : "   "
174                 );
175         }
176         printf ("\n");
177         return;
178 }
179
180 /*-----------------------------------------------------------------------
181  */
182
183
184 /*-----------------------------------------------------------------------
185  */
186
187 /*
188  * The following code cannot be run from FLASH!
189  */
190 static ulong flash_get_size (vu_long * addr, flash_info_t * info)
191 {
192         short i;
193         FLASH_WORD_SIZE value;
194         ulong base = (ulong) addr;
195         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
196
197         /* Write auto select command: read Manufacturer ID */
198         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
199         addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
200         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00900090;
201
202         value = addr2[0];
203
204         switch (value) {
205         case (FLASH_WORD_SIZE) AMD_MANUFACT:
206                 info->flash_id = FLASH_MAN_AMD;
207                 break;
208         case (FLASH_WORD_SIZE) FUJ_MANUFACT:
209                 info->flash_id = FLASH_MAN_FUJ;
210                 break;
211         case (FLASH_WORD_SIZE) SST_MANUFACT:
212                 info->flash_id = FLASH_MAN_SST;
213                 break;
214         case (FLASH_WORD_SIZE)STM_MANUFACT:
215                 info->flash_id = FLASH_MAN_STM;
216                 break;
217         default:
218                 info->flash_id = FLASH_UNKNOWN;
219                 info->sector_count = 0;
220                 info->size = 0;
221                 printf("Unknown flash manufacturer code: 0x%x\n", value);
222                 return (0);     /* no or unknown flash  */
223         }
224
225         value = addr2[1];       /* device ID            */
226
227         switch (value) {
228         case (FLASH_WORD_SIZE) AMD_ID_F040B:
229                 info->flash_id += FLASH_AM040;
230                 info->sector_count = 8;
231                 info->size = 0x0080000; /* => 512 ko */
232                 break;
233         case (FLASH_WORD_SIZE) AMD_ID_LV040B:
234                 info->flash_id += FLASH_AM040;
235                 info->sector_count = 8;
236                 info->size = 0x0080000; /* => 512 ko */
237                 break;
238         case (FLASH_WORD_SIZE)STM_ID_M29W040B: /* most likele JSE chip */
239                 info->flash_id += FLASH_AM040;
240                 info->sector_count = 8;
241                 info->size = 0x0080000; /* => 512 ko */
242                 break;
243         default:
244                 info->flash_id = FLASH_UNKNOWN;
245                 return (0);     /* => no or unknown flash */
246
247         }
248
249           /* Calculate the sector offsets (Use JSE Optimized code). */
250         flash_get_offsets(base, info);
251
252         /* check for protected sectors */
253         for (i = 0; i < info->sector_count; i++) {
254                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
255                 /* D0 = 1 if protected */
256                 addr2 = (volatile FLASH_WORD_SIZE *) (info->start[i]);
257                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
258                         info->protect[i] = 0;
259                 else
260                         info->protect[i] = addr2[2] & 1;
261         }
262
263         /*
264          * Prevent writes to uninitialized FLASH.
265          */
266         if (info->flash_id != FLASH_UNKNOWN) {
267                 addr2 = (FLASH_WORD_SIZE *) info->start[0];
268                 *addr2 = (FLASH_WORD_SIZE) 0x00F000F0;  /* reset bank */
269         }
270
271         return (info->size);
272 }
273
274 int wait_for_DQ7 (flash_info_t * info, int sect)
275 {
276         ulong start, now, last;
277         volatile FLASH_WORD_SIZE *addr =
278                 (FLASH_WORD_SIZE *) (info->start[sect]);
279
280         start = get_timer (0);
281         last = start;
282         while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
283                (FLASH_WORD_SIZE) 0x00800080) {
284                 if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
285                         printf ("Timeout\n");
286                         return -1;
287                 }
288                 /* show that we're waiting */
289                 if ((now - last) > 1000) {      /* every second */
290                         putc ('.');
291                         last = now;
292                 }
293         }
294         return 0;
295 }
296
297 /*-----------------------------------------------------------------------
298  */
299
300 int flash_erase (flash_info_t * info, int s_first, int s_last)
301 {
302         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
303         volatile FLASH_WORD_SIZE *addr2;
304         int flag, prot, sect, l_sect;
305         int i;
306
307         if ((s_first < 0) || (s_first > s_last)) {
308                 if (info->flash_id == FLASH_UNKNOWN) {
309                         printf ("- missing\n");
310                 } else {
311                         printf ("- no sectors to erase\n");
312                 }
313                 return 1;
314         }
315
316         if (info->flash_id == FLASH_UNKNOWN) {
317                 printf ("Can't erase unknown flash type - aborted\n");
318                 return 1;
319         }
320
321         prot = 0;
322         for (sect = s_first; sect <= s_last; ++sect) {
323                 if (info->protect[sect]) {
324                         prot++;
325                 }
326         }
327
328         if (prot) {
329                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
330         } else {
331                 printf ("\n");
332         }
333
334         l_sect = -1;
335
336         /* Disable interrupts which might cause a timeout here */
337         flag = disable_interrupts ();
338
339         /* Start erase on unprotected sectors */
340         for (sect = s_first; sect <= s_last; sect++) {
341                 if (info->protect[sect] == 0) { /* not protected */
342                         addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
343                         printf ("Erasing sector %p\n", addr2);  /* CLH */
344
345                         if ((info->flash_id & FLASH_VENDMASK) ==
346                             FLASH_MAN_SST) {
347                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
348                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
349                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
350                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
351                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
352                                 addr2[0] = (FLASH_WORD_SIZE) 0x00500050;        /* block erase */
353                                 for (i = 0; i < 50; i++)
354                                         udelay (1000);  /* wait 1 ms */
355                         } else {
356                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
357                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
358                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
359                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
360                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
361                                 addr2[0] = (FLASH_WORD_SIZE) 0x00300030;        /* sector erase */
362                         }
363                         l_sect = sect;
364                         /*
365                          * Wait for each sector to complete, it's more
366                          * reliable.  According to AMD Spec, you must
367                          * issue all erase commands within a specified
368                          * timeout.  This has been seen to fail, especially
369                          * if printf()s are included (for debug)!!
370                          */
371                         wait_for_DQ7 (info, sect);
372                 }
373         }
374
375         /* re-enable interrupts if necessary */
376         if (flag)
377                 enable_interrupts ();
378
379         /* wait at least 80us - let's wait 1 ms */
380         udelay (1000);
381
382 #if 0
383         /*
384          * We wait for the last triggered sector
385          */
386         if (l_sect < 0)
387                 goto DONE;
388         wait_for_DQ7 (info, l_sect);
389
390 DONE:
391 #endif
392         /* reset to read mode */
393         addr = (FLASH_WORD_SIZE *) info->start[0];
394         addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
395
396         printf (" done\n");
397         return 0;
398 }
399
400 /*-----------------------------------------------------------------------
401  * Copy memory to flash, returns:
402  * 0 - OK
403  * 1 - write timeout
404  * 2 - Flash not erased
405  */
406
407 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
408 {
409         ulong cp, wp, data;
410         int i, l, rc;
411
412         wp = (addr & ~3);       /* get lower word aligned address */
413
414         /*
415          * handle unaligned start bytes
416          */
417         if ((l = addr - wp) != 0) {
418                 data = 0;
419                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
420                         data = (data << 8) | (*(uchar *) cp);
421                 }
422                 for (; i < 4 && cnt > 0; ++i) {
423                         data = (data << 8) | *src++;
424                         --cnt;
425                         ++cp;
426                 }
427                 for (; cnt == 0 && i < 4; ++i, ++cp) {
428                         data = (data << 8) | (*(uchar *) cp);
429                 }
430
431                 if ((rc = write_word (info, wp, data)) != 0) {
432                         return (rc);
433                 }
434                 wp += 4;
435         }
436
437         /*
438          * handle word aligned part
439          */
440         while (cnt >= 4) {
441                 data = 0;
442                 for (i = 0; i < 4; ++i) {
443                         data = (data << 8) | *src++;
444                 }
445                 if ((rc = write_word (info, wp, data)) != 0) {
446                         return (rc);
447                 }
448                 wp += 4;
449                 cnt -= 4;
450         }
451
452         if (cnt == 0) {
453                 return (0);
454         }
455
456         /*
457          * handle unaligned tail bytes
458          */
459         data = 0;
460         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
461                 data = (data << 8) | *src++;
462                 --cnt;
463         }
464         for (; i < 4; ++i, ++cp) {
465                 data = (data << 8) | (*(uchar *) cp);
466         }
467
468         return (write_word (info, wp, data));
469 }
470
471 /*-----------------------------------------------------------------------
472  * Write a word to Flash, returns:
473  * 0 - OK
474  * 1 - write timeout
475  * 2 - Flash not erased
476  */
477 static int write_word (flash_info_t * info, ulong dest, ulong data)
478 {
479         volatile FLASH_WORD_SIZE *addr2 =
480                 (FLASH_WORD_SIZE *) (info->start[0]);
481         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
482         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
483         ulong start;
484         int i;
485
486         /* Check if Flash is (sufficiently) erased */
487         if ((*((volatile FLASH_WORD_SIZE *) dest) &
488             (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
489                 return (2);
490         }
491
492         for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
493                 int flag;
494
495                 /* Disable interrupts which might cause a timeout here */
496                 flag = disable_interrupts ();
497
498                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
499                 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
500                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
501
502                 dest2[i] = data2[i];
503
504                 /* re-enable interrupts if necessary */
505                 if (flag)
506                         enable_interrupts ();
507
508                 /* data polling for D7 */
509                 start = get_timer (0);
510                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
511                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
512
513                         if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
514                                 return (1);
515                         }
516                 }
517         }
518
519         return (0);
520 }