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