]> git.sur5r.net Git - u-boot/blob - board/trab/flash.c
* Patch by Gleb Natapov, 19 Sep 2003:
[u-boot] / board / trab / flash.c
1 /*
2  * (C) Copyright 2002
3  * Gary Jennejohn, DENX Software Engineering, <gj@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 /* #define DEBUG */
25
26 #include <common.h>
27 #include <environment.h>
28
29 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
30
31 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
32
33
34 #define CMD_READ_ARRAY          0x00F000F0
35 #define CMD_UNLOCK1             0x00AA00AA
36 #define CMD_UNLOCK2             0x00550055
37 #define CMD_ERASE_SETUP         0x00800080
38 #define CMD_ERASE_CONFIRM       0x00300030
39 #define CMD_PROGRAM             0x00A000A0
40 #define CMD_UNLOCK_BYPASS       0x00200020
41 #define CMD_READ_MANF_ID        0x00900090
42 #define CMD_UNLOCK_BYPASS_RES1  0x00900090
43 #define CMD_UNLOCK_BYPASS_RES2  0x00000000
44
45 #define MEM_FLASH_ADDR          (*(volatile u32 *)CFG_FLASH_BASE)
46 #define MEM_FLASH_ADDR1         (*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))
47 #define MEM_FLASH_ADDR2         (*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2)))
48
49 #define BIT_ERASE_DONE          0x00800080
50 #define BIT_RDY_MASK            0x00800080
51 #define BIT_PROGRAM_ERROR       0x00200020
52 #define BIT_TIMEOUT             0x80000000      /* our flag */
53
54 #define READY 1
55 #define ERR   2
56 #define TMO   4
57
58 /*-----------------------------------------------------------------------
59  */
60
61 ulong flash_init (void)
62 {
63         int i, j;
64         ulong size = 0;
65
66         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
67                 ulong flashbase = 0;
68                 flash_info_t *info = &flash_info[i];
69
70                 /* Init: no FLASHes known */
71                 info->flash_id = FLASH_UNKNOWN;
72
73                 size += flash_get_size (CFG_FLASH_BASE, info);
74
75                 if (i == 0)
76                         flashbase = CFG_FLASH_BASE;
77                 else
78                         panic ("configured too many flash banks!\n");
79                 for (j = 0; j < info->sector_count; j++) {
80
81                         info->protect[j] = 0;
82                         info->start[j] = flashbase;
83
84                         switch (info->flash_id & FLASH_TYPEMASK) {
85                         case (FLASH_AM320B & FLASH_TYPEMASK):
86                                 /* Boot sector type: 8 x 8 + N x 128 kB */
87                                 flashbase += (j < 8) ? 0x4000 : 0x20000;
88                                 break;
89                         case (FLASH_AM640U & FLASH_TYPEMASK):
90                                 /* Uniform sector type: 128 kB */
91                                 flashbase += 0x20000;
92                                 break;
93                         default:
94                                 printf ("## Bad flash chip type 0x%04lX\n",
95                                         info->flash_id & FLASH_TYPEMASK);
96                         }
97                 }
98         }
99
100         /*
101          * Protect monitor and environment sectors
102          */
103         flash_protect ( FLAG_PROTECT_SET,
104                         CFG_FLASH_BASE,
105                         CFG_FLASH_BASE + monitor_flash_len - 1,
106                         &flash_info[0]);
107
108         flash_protect ( FLAG_PROTECT_SET,
109                         CFG_ENV_ADDR,
110                         CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
111
112 #ifdef CFG_ENV_ADDR_REDUND
113         flash_protect ( FLAG_PROTECT_SET,
114                         CFG_ENV_ADDR_REDUND,
115                         CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
116                         &flash_info[0]);
117 #endif
118
119         return size;
120 }
121
122 /*-----------------------------------------------------------------------
123  */
124 void flash_print_info (flash_info_t * info)
125 {
126         int i;
127
128         switch (info->flash_id & FLASH_VENDMASK) {
129         case (FLASH_MAN_AMD & FLASH_VENDMASK):
130                         printf ("AMD ");                break;
131         case (FLASH_MAN_FUJ & FLASH_VENDMASK):
132                         printf ("FUJITSU ");            break;
133         default:        printf ("Unknown Vendor ");     break;
134         }
135
136         switch (info->flash_id & FLASH_TYPEMASK) {
137         case (FLASH_AM320B & FLASH_TYPEMASK):
138                 printf ("2x Am29LV320DB (32Mbit)\n");
139                 break;
140         case (FLASH_AM640U & FLASH_TYPEMASK):
141                 printf ("2x Am29LV640D (64Mbit)\n");
142                 break;
143         default:
144                 printf ("Unknown Chip Type\n");
145                 goto Done;
146                 break;
147         }
148
149         printf ("  Size: %ld MB in %d Sectors\n",
150                         info->size >> 20, info->sector_count);
151
152         printf ("  Sector Start Addresses:");
153         for (i = 0; i < info->sector_count; i++) {
154                 if ((i % 5) == 0) {
155                         printf ("\n   ");
156                 }
157                 printf (" %08lX%s",
158                         info->start[i],
159                         info->protect[i] ? " (RO)" : "     ");
160         }
161         printf ("\n");
162
163   Done:
164 }
165
166 /*-----------------------------------------------------------------------
167  */
168
169 int flash_erase (flash_info_t * info, int s_first, int s_last)
170 {
171         ulong result;
172
173 #if 0
174         int cflag;
175 #endif
176         int iflag, prot, sect;
177         int rc = ERR_OK;
178         int chip1, chip2;
179
180         debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last);
181
182         /* first look for protection bits */
183
184         if (info->flash_id == FLASH_UNKNOWN)
185                 return ERR_UNKNOWN_FLASH_TYPE;
186
187         if ((s_first < 0) || (s_first > s_last)) {
188                 return ERR_INVAL;
189         }
190
191         switch (info->flash_id & FLASH_VENDMASK) {
192         case (FLASH_MAN_AMD & FLASH_VENDMASK):  break;  /* OK */
193         case (FLASH_MAN_FUJ & FLASH_VENDMASK):  break;  /* OK */
194         default:
195                 debug ("## flash_erase: unknown manufacturer\n");
196                 return (ERR_UNKNOWN_FLASH_VENDOR);
197         }
198
199         prot = 0;
200         for (sect = s_first; sect <= s_last; ++sect) {
201                 if (info->protect[sect]) {
202                         prot++;
203                 }
204         }
205
206         if (prot) {
207                 printf ("- Warning: %d protected sectors will not be erased!\n",
208                         prot);
209         } else {
210                 printf ("\n");
211         }
212
213         /*
214          * Disable interrupts which might cause a timeout
215          * here. Remember that our exception vectors are
216          * at address 0 in the flash, and we don't want a
217          * (ticker) exception to happen while the flash
218          * chip is in programming mode.
219          */
220 #if 0
221         cflag = icache_status ();
222         icache_disable ();
223 #endif
224         iflag = disable_interrupts ();
225
226         /* Start erase on unprotected sectors */
227         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
228
229                 debug ("Erasing sector %2d @ %08lX... ",
230                         sect, info->start[sect]);
231
232                 /* arm simple, non interrupt dependent timer */
233                 reset_timer_masked ();
234
235                 if (info->protect[sect] == 0) { /* not protected */
236                         vu_long *addr = (vu_long *) (info->start[sect]);
237
238                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
239                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
240                         MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
241
242                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
243                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
244                         *addr = CMD_ERASE_CONFIRM;
245
246                         /* wait until flash is ready */
247                         chip1 = chip2 = 0;
248
249                         do {
250                                 result = *addr;
251
252                                 /* check timeout */
253                                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
254                                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
255                                         chip1 = TMO;
256                                         break;
257                                 }
258
259                                 if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
260                                         chip1 = READY;
261
262                                 if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
263                                         chip1 = ERR;
264
265                                 if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
266                                         chip2 = READY;
267
268                                 if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
269                                         chip2 = ERR;
270
271                         } while (!chip1 || !chip2);
272
273                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
274
275                         if (chip1 == ERR || chip2 == ERR) {
276                                 rc = ERR_PROG_ERROR;
277                                 goto outahere;
278                         }
279                         if (chip1 == TMO) {
280                                 rc = ERR_TIMOUT;
281                                 goto outahere;
282                         }
283                 }
284         }
285
286 outahere:
287         /* allow flash to settle - wait 10 ms */
288         udelay_masked (10000);
289
290         if (iflag)
291                 enable_interrupts ();
292
293 #if 0
294         if (cflag)
295                 icache_enable ();
296 #endif
297         return rc;
298 }
299
300 /*-----------------------------------------------------------------------
301  * Copy memory to flash
302  */
303
304 volatile static int write_word (flash_info_t * info, ulong dest,
305                                                                 ulong data)
306 {
307         vu_long *addr = (vu_long *) dest;
308         ulong result;
309         int rc = ERR_OK;
310
311 #if 0
312         int cflag;
313 #endif
314         int iflag;
315         int chip1, chip2;
316
317         /*
318          * Check if Flash is (sufficiently) erased
319          */
320         result = *addr;
321         if ((result & data) != data)
322                 return ERR_NOT_ERASED;
323
324         /*
325          * Disable interrupts which might cause a timeout
326          * here. Remember that our exception vectors are
327          * at address 0 in the flash, and we don't want a
328          * (ticker) exception to happen while the flash
329          * chip is in programming mode.
330          */
331 #if 0
332         cflag = icache_status ();
333         icache_disable ();
334 #endif
335         iflag = disable_interrupts ();
336
337         *addr = CMD_PROGRAM;
338         *addr = data;
339
340         /* arm simple, non interrupt dependent timer */
341         reset_timer_masked ();
342
343         /* wait until flash is ready */
344         chip1 = chip2 = 0;
345         do {
346                 result = *addr;
347
348                 /* check timeout */
349                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
350                         chip1 = ERR | TMO;
351                         break;
352                 }
353                 if (!chip1 && ((result & 0x80) == (data & 0x80)))
354                         chip1 = READY;
355
356                 if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
357                         result = *addr;
358
359                         if ((result & 0x80) == (data & 0x80))
360                                 chip1 = READY;
361                         else
362                                 chip1 = ERR;
363                 }
364
365                 if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
366                         chip2 = READY;
367
368                 if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR)) {
369                         result = *addr;
370
371                         if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
372                                 chip2 = READY;
373                         else
374                                 chip2 = ERR;
375                 }
376
377         } while (!chip1 || !chip2);
378
379         *addr = CMD_READ_ARRAY;
380
381         if (chip1 == ERR || chip2 == ERR || *addr != data)
382                 rc = ERR_PROG_ERROR;
383
384         if (iflag)
385                 enable_interrupts ();
386
387 #if 0
388         if (cflag)
389                 icache_enable ();
390 #endif
391
392         return rc;
393 }
394
395 /*-----------------------------------------------------------------------
396  * Copy memory to flash.
397  */
398
399 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
400 {
401         ulong cp, wp, data;
402         int l;
403         int i, rc;
404
405         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
406         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
407         MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
408
409         wp = (addr & ~3);       /* get lower word aligned address */
410
411         /*
412          * handle unaligned start bytes
413          */
414         if ((l = addr - wp) != 0) {
415                 data = 0;
416                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
417                         data = (data >> 8) | (*(uchar *) cp << 24);
418                 }
419                 for (; i < 4 && cnt > 0; ++i) {
420                         data = (data >> 8) | (*src++ << 24);
421                         --cnt;
422                         ++cp;
423                 }
424                 for (; cnt == 0 && i < 4; ++i, ++cp) {
425                         data = (data >> 8) | (*(uchar *) cp << 24);
426                 }
427
428                 if ((rc = write_word (info, wp, data)) != 0) {
429                         goto Done;
430                 }
431                 wp += 4;
432         }
433
434         /*
435          * handle word aligned part
436          */
437         while (cnt >= 4) {
438                 if (((ulong)src) & 0x3) {
439                         for (i = 0; i < 4; i++) {
440                                 ((char *)&data)[i] = ((vu_char *)src)[i];
441                         }
442                 }
443                 else {
444                         data = *((vu_long *) src);
445                 }
446
447                 if ((rc = write_word (info, wp, data)) != 0) {
448                         goto Done;
449                 }
450                 src += 4;
451                 wp += 4;
452                 cnt -= 4;
453         }
454
455         if (cnt == 0) {
456                 rc = ERR_OK;
457                 goto Done;
458         }
459
460         /*
461          * handle unaligned tail bytes
462          */
463         data = 0;
464         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
465                 data = (data >> 8) | (*src++ << 24);
466                 --cnt;
467         }
468         for (; i < 4; ++i, ++cp) {
469                 data = (data >> 8) | (*(uchar *) cp << 24);
470         }
471
472         rc = write_word (info, wp, data);
473
474         Done:
475
476         MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES1;
477         MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES2;
478
479         return (rc);
480 }
481
482 /*-----------------------------------------------------------------------
483  */
484
485 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
486 {
487         ulong value;
488
489         /* Write auto select command sequence and read Manufacturer ID */
490         addr[0x0555] = CMD_UNLOCK1;
491         addr[0x02AA] = CMD_UNLOCK2;
492         addr[0x0555] = CMD_READ_MANF_ID;
493
494         value = addr[0];
495
496         debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
497
498         switch (value) {
499         case AMD_MANUFACT:
500                 info->flash_id = FLASH_MAN_AMD;
501                 break;
502         case FUJ_MANUFACT:
503                 info->flash_id = FLASH_MAN_FUJ;
504                 break;
505         default:
506                 info->flash_id = FLASH_UNKNOWN;
507                 info->sector_count = 0;
508                 info->size = 0;
509                 addr[0] = 0x00FF00FF;           /* restore read mode */
510                 debug ("## flash_init: unknown manufacturer\n");
511                 return (0);                     /* no or unknown flash  */
512         }
513
514         value = addr[1];                        /* device ID            */
515
516         debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
517
518         switch (value) {
519         case AMD_ID_LV320B:
520                 info->flash_id += FLASH_AM320B;
521                 info->sector_count = 71;
522                 info->size = 0x00800000;
523
524                 addr[0] = 0x00FF00FF;           /* restore read mode */
525                 break;                          /* =>  8 MB             */
526
527         case AMD_ID_LV640U:
528                 info->flash_id += FLASH_AM640U;
529                 info->sector_count = 128;
530                 info->size = 0x01000000;
531
532                 addr[0] = 0x00F000F0;           /* restore read mode */
533                 break;                          /* => 16 MB             */
534
535         default:
536                 debug ("## flash_init: unknown flash chip\n");
537                 info->flash_id = FLASH_UNKNOWN;
538                 addr[0] = 0x00FF00FF;           /* restore read mode */
539                 return (0);                     /* => no or unknown flash */
540
541         }
542
543         if (info->sector_count > CFG_MAX_FLASH_SECT) {
544                 printf ("** ERROR: sector count %d > max (%d) **\n",
545                         info->sector_count, CFG_MAX_FLASH_SECT);
546                 info->sector_count = CFG_MAX_FLASH_SECT;
547         }
548
549         return (info->size);
550 }