to make u-boot work for fat32 filesystem
[jz_uboot.git] / board / siemens / pcu_e / flash.c
blob05c364bb23f8d63dd97c25b8b44d46ee9f7820a8
1 /*
2 * (C) Copyright 2001
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
6 * project.
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.
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.
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
24 #include <common.h>
25 #include <mpc8xx.h>
27 #if defined(CFG_ENV_IS_IN_FLASH)
28 # ifndef CFG_ENV_ADDR
29 # define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
30 # endif
31 # ifndef CFG_ENV_SIZE
32 # define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
33 # endif
34 # ifndef CFG_ENV_SECT_SIZE
35 # define CFG_ENV_SECT_SIZE CFG_ENV_SIZE
36 # endif
37 #endif
39 /*---------------------------------------------------------------------*/
40 #undef DEBUG_FLASH
42 #ifdef DEBUG_FLASH
43 #define DEBUGF(fmt,args...) printf(fmt ,##args)
44 #else
45 #define DEBUGF(fmt,args...)
46 #endif
47 /*---------------------------------------------------------------------*/
50 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
52 /*-----------------------------------------------------------------------
53 * Functions
55 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
56 static int write_data (flash_info_t *info, ulong dest, ulong data);
57 static void flash_get_offsets (ulong base, flash_info_t *info);
59 /*-----------------------------------------------------------------------
61 * The PCU E uses an address map where flash banks are aligned top
62 * down, so that the "first" flash bank ends at top of memory, and
63 * the monitor entry point is at address (0xFFF00100). The second
64 * flash bank is mapped immediately below bank 0.
66 * This is NOT in conformance to the "official" memory map!
70 #define PCU_MONITOR_BASE ( (flash_info[0].start[0] + flash_info[0].size - 1) \
71 - (0xFFFFFFFF - CFG_MONITOR_BASE) )
73 /*-----------------------------------------------------------------------
76 unsigned long flash_init (void)
78 volatile immap_t *immap = (immap_t *)CFG_IMMR;
79 volatile memctl8xx_t *memctl = &immap->im_memctl;
80 unsigned long base, size_b0, size_b1;
81 int i;
83 /* Init: no FLASHes known */
84 for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
85 flash_info[i].flash_id = FLASH_UNKNOWN;
88 /* Static FLASH Bank configuration here - FIXME XXX */
91 * Warning:
93 * Since the PCU E memory map assigns flash banks top down,
94 * we swap the numbering later if both banks are equipped,
95 * so they look like a contiguous area of memory.
97 DEBUGF("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
99 size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
101 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
102 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
103 size_b0, size_b0<<20);
106 DEBUGF("## Get flash bank 2 size @ 0x%08x\n",FLASH_BASE6_PRELIM);
107 size_b1 = flash_get_size((vu_long *)FLASH_BASE6_PRELIM, &flash_info[1]);
109 DEBUGF("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n", size_b0, size_b1);
111 if (size_b1 > size_b0) {
112 printf ("## ERROR: "
113 "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
114 size_b1, size_b1<<20,
115 size_b0, size_b0<<20
117 flash_info[0].flash_id = FLASH_UNKNOWN;
118 flash_info[1].flash_id = FLASH_UNKNOWN;
119 flash_info[0].sector_count = -1;
120 flash_info[1].sector_count = -1;
121 flash_info[0].size = 0;
122 flash_info[1].size = 0;
123 return (0);
126 DEBUGF ("## Before remap: "
127 "BR0: 0x%08x OR0: 0x%08x "
128 "BR6: 0x%08x OR6: 0x%08x\n",
129 memctl->memc_br0, memctl->memc_or0,
130 memctl->memc_br6, memctl->memc_or6);
132 /* Remap FLASH according to real size */
133 base = 0 - size_b0;
134 memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
135 memctl->memc_br0 = (base & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V;
137 DEBUGF("## BR0: 0x%08x OR0: 0x%08x\n",
138 memctl->memc_br0, memctl->memc_or0);
140 /* Re-do sizing to get full correct info */
141 size_b0 = flash_get_size((vu_long *)base, &flash_info[0]);
142 base = 0 - size_b0;
144 flash_info[0].size = size_b0;
146 flash_get_offsets (base, &flash_info[0]);
148 /* monitor protection ON by default */
149 flash_protect(FLAG_PROTECT_SET,
150 PCU_MONITOR_BASE,
151 PCU_MONITOR_BASE+monitor_flash_len-1,
152 &flash_info[0]);
154 #ifdef CFG_ENV_IS_IN_FLASH
155 /* ENV protection ON by default */
156 flash_protect(FLAG_PROTECT_SET,
157 CFG_ENV_ADDR,
158 CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
159 &flash_info[0]);
160 #endif
162 if (size_b1) {
163 flash_info_t tmp_info;
165 memctl->memc_or6 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
166 memctl->memc_br6 = ((base - size_b1) & BR_BA_MSK) |
167 BR_PS_16 | BR_MS_GPCM | BR_V;
169 DEBUGF("## New BR6: 0x%08x OR6: 0x%08x\n",
170 memctl->memc_br6, memctl->memc_or6);
172 /* Re-do sizing to get full correct info */
173 size_b1 = flash_get_size((vu_long *)(base - size_b1),
174 &flash_info[1]);
175 base -= size_b1;
177 flash_get_offsets (base, &flash_info[1]);
179 flash_info[1].size = size_b1;
181 #ifdef CFG_ENV_IS_IN_FLASH
182 /* ENV protection ON by default */
183 flash_protect(FLAG_PROTECT_SET,
184 CFG_ENV_ADDR,
185 CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
186 &flash_info[1]);
187 #endif
189 * Swap bank numbers so that addresses are in ascending order
191 tmp_info = flash_info[0];
192 flash_info[0] = flash_info[1];
193 flash_info[1] = tmp_info;
194 } else {
195 memctl->memc_br1 = 0; /* invalidate bank */
197 flash_info[1].flash_id = FLASH_UNKNOWN;
198 flash_info[1].sector_count = -1;
202 DEBUGF("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
204 return (size_b0 + size_b1);
207 /*-----------------------------------------------------------------------
209 static void flash_get_offsets (ulong base, flash_info_t *info)
211 int i;
212 short n;
214 if (info->flash_id == FLASH_UNKNOWN) {
215 return;
218 if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD) {
219 return;
222 switch (info->flash_id & FLASH_TYPEMASK) {
223 case FLASH_AMDL322T:
224 case FLASH_AMDL323T:
225 case FLASH_AMDL324T:
226 /* set sector offsets for top boot block type */
228 base += info->size;
229 i = info->sector_count;
230 for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
231 base -= 8 << 10;
232 --i;
233 info->start[i] = base;
235 while (i > 0) { /* 64k regular sectors */
236 base -= 64 << 10;
237 --i;
238 info->start[i] = base;
240 return;
241 case FLASH_AMDL322B:
242 case FLASH_AMDL323B:
243 case FLASH_AMDL324B:
244 /* set sector offsets for bottom boot block type */
245 for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
246 info->start[i] = base;
247 base += 8 << 10;
249 while (base < info->size) { /* 64k regular sectors */
250 info->start[i] = base;
251 base += 64 << 10;
252 ++i;
254 return;
255 case FLASH_AMDL640:
256 /* set sector offsets for dual boot block type */
257 for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
258 info->start[i] = base;
259 base += 8 << 10;
261 n = info->sector_count - 8;
262 while (i < n) { /* 64k regular sectors */
263 info->start[i] = base;
264 base += 64 << 10;
265 ++i;
267 while (i < info->sector_count) { /* 8 x 8k boot sectors */
268 info->start[i] = base;
269 base += 8 << 10;
270 ++i;
272 return;
273 default:
274 return;
276 /* NOTREACHED */
279 /*-----------------------------------------------------------------------
281 void flash_print_info (flash_info_t *info)
283 int i;
285 if (info->flash_id == FLASH_UNKNOWN) {
286 printf ("missing or unknown FLASH type\n");
287 return;
290 switch (info->flash_id & FLASH_VENDMASK) {
291 case FLASH_MAN_AMD: printf ("AMD "); break;
292 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
293 default: printf ("Unknown Vendor "); break;
296 switch (info->flash_id & FLASH_TYPEMASK) {
297 case FLASH_AMDL322B: printf ("AM29DL322B (32 Mbit, bottom boot sect)\n");
298 break;
299 case FLASH_AMDL322T: printf ("AM29DL322T (32 Mbit, top boot sector)\n");
300 break;
301 case FLASH_AMDL323B: printf ("AM29DL323B (32 Mbit, bottom boot sect)\n");
302 break;
303 case FLASH_AMDL323T: printf ("AM29DL323T (32 Mbit, top boot sector)\n");
304 break;
305 case FLASH_AMDL324B: printf ("AM29DL324B (32 Mbit, bottom boot sect)\n");
306 break;
307 case FLASH_AMDL324T: printf ("AM29DL324T (32 Mbit, top boot sector)\n");
308 break;
309 case FLASH_AMDL640: printf ("AM29DL640D (64 Mbit, dual boot sector)\n");
310 break;
311 default: printf ("Unknown Chip Type 0x%lX\n",
312 info->flash_id);
313 break;
316 printf (" Size: %ld MB in %d Sectors\n",
317 info->size >> 20, info->sector_count);
319 printf (" Sector Start Addresses:");
320 for (i=0; i<info->sector_count; ++i) {
321 if ((i % 5) == 0)
322 printf ("\n ");
323 printf (" %08lX%s",
324 info->start[i],
325 info->protect[i] ? " (RO)" : " "
328 printf ("\n");
329 return;
332 /*-----------------------------------------------------------------------
336 /*-----------------------------------------------------------------------
340 * The following code cannot be run from FLASH!
343 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
345 short i;
346 ushort value;
347 vu_short *saddr = (vu_short *)addr;
349 /* Write auto select command: read Manufacturer ID */
350 saddr[0x0555] = 0x00AA;
351 saddr[0x02AA] = 0x0055;
352 saddr[0x0555] = 0x0090;
354 value = saddr[0];
356 DEBUGF("Manuf. ID @ 0x%08lx: 0x%04x\n", (ulong)addr, value);
358 switch (value) {
359 case (AMD_MANUFACT & 0xFFFF):
360 info->flash_id = FLASH_MAN_AMD;
361 break;
362 case (FUJ_MANUFACT & 0xFFFF):
363 info->flash_id = FLASH_MAN_FUJ;
364 break;
365 default:
366 DEBUGF("Unknown Manufacturer ID\n");
367 info->flash_id = FLASH_UNKNOWN;
368 info->sector_count = 0;
369 info->size = 0;
370 return (0); /* no or unknown flash */
373 value = saddr[1]; /* device ID */
375 DEBUGF("Device ID @ 0x%08lx: 0x%04x\n", (ulong)(&addr[1]), value);
377 switch (value) {
379 case (AMD_ID_DL322T & 0xFFFF):
380 info->flash_id += FLASH_AMDL322T;
381 info->sector_count = 71;
382 info->size = 0x00400000;
383 break; /* => 8 MB */
385 case (AMD_ID_DL322B & 0xFFFF):
386 info->flash_id += FLASH_AMDL322B;
387 info->sector_count = 71;
388 info->size = 0x00400000;
389 break; /* => 8 MB */
391 case (AMD_ID_DL323T & 0xFFFF):
392 info->flash_id += FLASH_AMDL323T;
393 info->sector_count = 71;
394 info->size = 0x00400000;
395 break; /* => 8 MB */
397 case (AMD_ID_DL323B & 0xFFFF):
398 info->flash_id += FLASH_AMDL323B;
399 info->sector_count = 71;
400 info->size = 0x00400000;
401 break; /* => 8 MB */
403 case (AMD_ID_DL324T & 0xFFFF):
404 info->flash_id += FLASH_AMDL324T;
405 info->sector_count = 71;
406 info->size = 0x00400000;
407 break; /* => 8 MB */
409 case (AMD_ID_DL324B & 0xFFFF):
410 info->flash_id += FLASH_AMDL324B;
411 info->sector_count = 71;
412 info->size = 0x00400000;
413 break; /* => 8 MB */
414 case (AMD_ID_DL640 & 0xFFFF):
415 info->flash_id += FLASH_AMDL640;
416 info->sector_count = 142;
417 info->size = 0x00800000;
418 break;
419 default:
420 DEBUGF("Unknown Device ID\n");
421 info->flash_id = FLASH_UNKNOWN;
422 return (0); /* => no or unknown flash */
426 flash_get_offsets ((ulong)addr, info);
428 /* check for protected sectors */
429 for (i = 0; i < info->sector_count; i++) {
430 #if 0
431 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
432 /* D0 = 1 if protected */
433 saddr = (vu_short *)(info->start[i]);
434 info->protect[i] = saddr[2] & 1;
435 #else
436 info->protect[i] =0;
437 #endif
440 if (info->sector_count > CFG_MAX_FLASH_SECT) {
441 printf ("** ERROR: sector count %d > max (%d) **\n",
442 info->sector_count, CFG_MAX_FLASH_SECT);
443 info->sector_count = CFG_MAX_FLASH_SECT;
446 saddr = (vu_short *)info->start[0];
447 *saddr = 0x00F0; /* restore read mode */
449 return (info->size);
453 /*-----------------------------------------------------------------------
456 int flash_erase (flash_info_t *info, int s_first, int s_last)
458 vu_short *addr = (vu_short*)(info->start[0]);
459 int flag, prot, sect, l_sect;
460 ulong start, now, last;
462 if ((s_first < 0) || (s_first > s_last)) {
463 if (info->flash_id == FLASH_UNKNOWN) {
464 printf ("- missing\n");
465 } else {
466 printf ("- no sectors to erase\n");
468 return 1;
471 if ((info->flash_id == FLASH_UNKNOWN) ||
472 (info->flash_id > FLASH_AMD_COMP)) {
473 printf ("Can't erase unknown flash type %08lx - aborted\n",
474 info->flash_id);
475 return 1;
478 prot = 0;
479 for (sect=s_first; sect<=s_last; ++sect) {
480 if (info->protect[sect]) {
481 prot++;
485 if (prot) {
486 printf ("- Warning: %d protected sectors will not be erased!\n",
487 prot);
488 } else {
489 printf ("\n");
492 l_sect = -1;
494 /* Disable interrupts which might cause a timeout here */
495 flag = disable_interrupts();
497 addr[0x0555] = 0x00AA;
498 addr[0x02AA] = 0x0055;
499 addr[0x0555] = 0x0080;
500 addr[0x0555] = 0x00AA;
501 addr[0x02AA] = 0x0055;
503 /* Start erase on unprotected sectors */
504 for (sect = s_first; sect<=s_last; sect++) {
505 if (info->protect[sect] == 0) { /* not protected */
506 addr = (vu_short*)(info->start[sect]);
507 addr[0] = 0x0030;
508 l_sect = sect;
512 /* re-enable interrupts if necessary */
513 if (flag)
514 enable_interrupts();
516 /* wait at least 80us - let's wait 1 ms */
517 udelay (1000);
520 * We wait for the last triggered sector
522 if (l_sect < 0)
523 goto DONE;
525 start = get_timer (0);
526 last = start;
527 addr = (vu_short*)(info->start[l_sect]);
528 while ((addr[0] & 0x0080) != 0x0080) {
529 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
530 printf ("Timeout\n");
531 return 1;
533 /* show that we're waiting */
534 if ((now - last) > 1000) { /* every second */
535 putc ('.');
536 last = now;
540 DONE:
541 /* reset to read mode */
542 addr = (vu_short *)info->start[0];
543 addr[0] = 0x00F0; /* reset bank */
545 printf (" done\n");
546 return 0;
549 /*-----------------------------------------------------------------------
550 * Copy memory to flash, returns:
551 * 0 - OK
552 * 1 - write timeout
553 * 2 - Flash not erased
556 #define FLASH_WIDTH 2 /* flash bus width in bytes */
558 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
560 ulong cp, wp, data;
561 int i, l, rc;
563 wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */
566 * handle unaligned start bytes
568 if ((l = addr - wp) != 0) {
569 data = 0;
570 for (i=0, cp=wp; i<l; ++i, ++cp) {
571 data = (data << 8) | (*(uchar *)cp);
573 for (; i<FLASH_WIDTH && cnt>0; ++i) {
574 data = (data << 8) | *src++;
575 --cnt;
576 ++cp;
578 for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
579 data = (data << 8) | (*(uchar *)cp);
582 if ((rc = write_data(info, wp, data)) != 0) {
583 return (rc);
585 wp += FLASH_WIDTH;
589 * handle FLASH_WIDTH aligned part
591 while (cnt >= FLASH_WIDTH) {
592 data = 0;
593 for (i=0; i<FLASH_WIDTH; ++i) {
594 data = (data << 8) | *src++;
596 if ((rc = write_data(info, wp, data)) != 0) {
597 return (rc);
599 wp += FLASH_WIDTH;
600 cnt -= FLASH_WIDTH;
603 if (cnt == 0) {
604 return (0);
608 * handle unaligned tail bytes
610 data = 0;
611 for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
612 data = (data << 8) | *src++;
613 --cnt;
615 for (; i<FLASH_WIDTH; ++i, ++cp) {
616 data = (data << 8) | (*(uchar *)cp);
619 return (write_data(info, wp, data));
622 /*-----------------------------------------------------------------------
623 * Write a word to Flash, returns:
624 * 0 - OK
625 * 1 - write timeout
626 * 2 - Flash not erased
628 static int write_data (flash_info_t *info, ulong dest, ulong data)
630 vu_short *addr = (vu_short*)(info->start[0]);
631 vu_short *sdest = (vu_short *)dest;
632 ushort sdata = (ushort)data;
633 ushort sval;
634 ulong start, passed;
635 int flag, rc;
637 /* Check if Flash is (sufficiently) erased */
638 if ((*sdest & sdata) != sdata) {
639 return (2);
641 /* Disable interrupts which might cause a timeout here */
642 flag = disable_interrupts();
644 addr[0x0555] = 0x00AA;
645 addr[0x02AA] = 0x0055;
646 addr[0x0555] = 0x00A0;
648 #ifdef WORKAROUND_FOR_BROKEN_HARDWARE
649 /* work around the timeout bugs */
650 udelay(20);
651 #endif
653 *sdest = sdata;
655 /* re-enable interrupts if necessary */
656 if (flag)
657 enable_interrupts();
659 rc = 0;
660 /* data polling for D7 */
661 start = get_timer (0);
663 for (passed=0; passed < CFG_FLASH_WRITE_TOUT; passed=get_timer(start)) {
665 sval = *sdest;
667 if ((sval & 0x0080) == (sdata & 0x0080))
668 break;
670 if ((sval & 0x0020) == 0) /* DQ5: Timeout? */
671 continue;
673 sval = *sdest;
675 if ((sval & 0x0080) != (sdata & 0x0080))
676 rc = 1;
678 break;
681 if (rc) {
682 DEBUGF ("Program cycle failed @ addr 0x%08lX: val %04X data %04X\n",
683 dest, sval, sdata);
686 if (passed >= CFG_FLASH_WRITE_TOUT) {
687 DEBUGF ("Timeout @ addr 0x%08lX: val %04X data %04X\n",
688 dest, sval, sdata);
689 rc = 1;
692 /* reset to read mode */
693 addr = (vu_short *)info->start[0];
694 addr[0] = 0x00F0; /* reset bank */
696 return (rc);
699 /*-----------------------------------------------------------------------