diff options
Diffstat (limited to 'board/hymod/flash.c')
-rw-r--r-- | board/hymod/flash.c | 509 |
1 files changed, 135 insertions, 374 deletions
diff --git a/board/hymod/flash.c b/board/hymod/flash.c index 0a09b4a70e5..7d1ae30e48c 100644 --- a/board/hymod/flash.c +++ b/board/hymod/flash.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * - * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00 + * Hacked for the Hymod board by Murray.Jensen@csiro.au, 20-Oct-00 */ #include <common.h> @@ -36,234 +36,154 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ #define FLAG_PROTECT_CLEAR 0x02 /*----------------------------------------------------------------------- - * Functions - */ -#if 0 -static ulong flash_get_size (vu_long *addr, flash_info_t *info); -static void flash_get_offsets (ulong base, flash_info_t *info); -#endif -static int write_word (flash_info_t *info, ulong dest, ulong data); - -/*----------------------------------------------------------------------- */ /* - * probe for the existence of flash at bank word address "addr" - * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id + * probe for flash bank at address "base" and store info about it + * in the flash_info entry "fip". Fatal error if nothing there. */ -static int -bank_probe_word(bank_addr_t addr) +static void +bank_probe (flash_info_t *fip, bank_addr_t base) { - int retval; + bank_addr_t addr; + bank_word_t word; + int i; /* reset the flash */ - *addr = BANK_CMD_RST; + *base = BANK_CMD_RST; - /* check the manufacturer id */ - *addr = BANK_CMD_RD_ID; - if (*BANK_ADDR_REG_MAN(addr) != BANK_RD_ID_MAN) { - retval = -1; - goto out; - } - - /* check the device id */ - *addr = BANK_CMD_RD_ID; - if (*BANK_ADDR_REG_DEV(addr) != BANK_RD_ID_DEV) { - retval = -2; - goto out; - } + /* check the manufacturer id - must be intel */ + *base = BANK_CMD_RD_ID; + word = *BANK_REG_MAN_CODE (base); + *base = BANK_CMD_RST; - retval = CFG_FLASH_TYPE; + if (word != BANK_FILL_WORD (INTEL_MANUFACT&0xff)) + panic ("\nbad manufacturer's code (0x%08lx) at addr 0x%08lx", + (unsigned long)word, (unsigned long)base); -out: - /* reset the flash again */ - *addr = BANK_CMD_RST; - - return retval; -} + /* check the device id */ + *base = BANK_CMD_RD_ID; + word = *BANK_REG_DEV_CODE (base); + *base = BANK_CMD_RST; -/* - * probe for flash banks at address "base" and store info for any found - * into flash_info entry "fip". Must find at least one bank. - */ -static void -bank_probe(flash_info_t *fip, bank_addr_t base) -{ - bank_addr_t addr, eaddr; - int nbanks; + switch (word) { - fip->flash_id = FLASH_UNKNOWN; - fip->size = 0L; - fip->sector_count = 0; + case BANK_FILL_WORD (INTEL_ID_28F320J5&0xff): + fip->flash_id = FLASH_MAN_INTEL | FLASH_28F320J5; + fip->sector_count = 32; + break; - addr = base; - eaddr = BANK_ADDR_BASE(addr, MAX_BANKS); - nbanks = 0; + case BANK_FILL_WORD (INTEL_ID_28F640J5&0xff): + fip->flash_id = FLASH_MAN_INTEL | FLASH_28F640J5; + fip->sector_count = 64; + break; - while (addr < eaddr) { - bank_addr_t addrw, eaddrw, addrb; - int i, osc, nsc, curtype = -1; + case BANK_FILL_WORD (INTEL_ID_28F320J3A&0xff): + fip->flash_id = FLASH_MAN_INTEL | FLASH_28F320J3A; + fip->sector_count = 32; + break; - addrw = addr; - eaddrw = BANK_ADDR_NEXT_WORD(addrw); + case BANK_FILL_WORD (INTEL_ID_28F640J3A&0xff): + fip->flash_id = FLASH_MAN_INTEL | FLASH_28F640J3A; + fip->sector_count = 64; + break; - while (addrw < eaddrw) { - int thistype; + case BANK_FILL_WORD (INTEL_ID_28F128J3A&0xff): + fip->flash_id = FLASH_MAN_INTEL | FLASH_28F128J3A; + fip->sector_count = 128; + break; -#ifdef FLASH_DEBUG - printf(" probing for flash at addr 0x%08lx\n", - (unsigned long)addrw); -#endif - if ((thistype = bank_probe_word(addrw++)) < 0) - goto out; - - if (curtype < 0) - curtype = thistype; - else { - if (thistype != curtype) { - printf("Differing flash type found!\n"); - goto out; - } - } - } + default: + panic ("\nbad device code (0x%08lx) at addr 0x%08lx", + (unsigned long)word, (unsigned long)base); + } - if (curtype < 0) - goto out; - - /* bank exists - append info for this bank to *fip */ - fip->flash_id = FLASH_MAN_INTEL|curtype; - fip->size += BANK_SIZE; - osc = fip->sector_count; - fip->sector_count += BANK_NBLOCKS; - if ((nsc = fip->sector_count) >= CFG_MAX_FLASH_SECT) - panic("Too many sectors in flash at address 0x%08lx\n", - (unsigned long)base); - - addrb = addr; - for (i = osc; i < nsc; i++) { - fip->start[i] = (ulong)addrb; - fip->protect[i] = 0; - addrb = BANK_ADDR_NEXT_BLK(addrb); - } + if (fip->sector_count >= CFG_MAX_FLASH_SECT) + panic ("\ntoo many sectors (%d) in flash at address 0x%08lx", + fip->sector_count, (unsigned long)base); - addr = BANK_ADDR_NEXT_BANK(addr); - nbanks++; + addr = base; + for (i = 0; i < fip->sector_count; i++) { + fip->start[i] = (unsigned long)addr; + fip->protect[i] = 0; + addr = BANK_ADDR_NEXT_BLK (addr); } -out: - if (nbanks == 0) - panic("ERROR: no flash found at address 0x%08lx\n", - (unsigned long)base); + fip->size = (bank_size_t)addr - (bank_size_t)base; } static void -bank_reset(flash_info_t *info, int sect) +bank_reset (flash_info_t *info, int sect) { - bank_addr_t addrw, eaddrw; + bank_addr_t addr = (bank_addr_t)info->start[sect]; - addrw = (bank_addr_t)info->start[sect]; - eaddrw = BANK_ADDR_NEXT_WORD(addrw); - - while (addrw < eaddrw) { #ifdef FLASH_DEBUG - printf(" writing reset cmd to addr 0x%08lx\n", - (unsigned long)addrw); + printf ("writing reset cmd to addr 0x%08lx\n", (unsigned long)addr); #endif - *addrw = BANK_CMD_RST; - addrw++; - } + + *addr = BANK_CMD_RST; } static void -bank_erase_init(flash_info_t *info, int sect) +bank_erase_init (flash_info_t *info, int sect) { - bank_addr_t addrw, saddrw, eaddrw; + bank_addr_t addr = (bank_addr_t)info->start[sect]; int flag; #ifdef FLASH_DEBUG - printf("0x%08lx BANK_CMD_PROG\n", BANK_CMD_PROG); - printf("0x%08lx BANK_CMD_ERASE1\n", BANK_CMD_ERASE1); - printf("0x%08lx BANK_CMD_ERASE2\n", BANK_CMD_ERASE2); - printf("0x%08lx BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT); - printf("0x%08lx BANK_CMD_RST\n", BANK_CMD_RST); - printf("0x%08lx BANK_STAT_RDY\n", BANK_STAT_RDY); - printf("0x%08lx BANK_STAT_ERR\n", BANK_STAT_ERR); -#endif - - saddrw = (bank_addr_t)info->start[sect]; - eaddrw = BANK_ADDR_NEXT_WORD(saddrw); - -#ifdef FLASH_DEBUG - printf("erasing sector %d, start addr = 0x%08lx " - "(bank next word addr = 0x%08lx)\n", sect, - (unsigned long)saddrw, (unsigned long)eaddrw); + printf ("erasing sector %d, addr = 0x%08lx\n", + sect, (unsigned long)addr); #endif /* Disable intrs which might cause a timeout here */ - flag = disable_interrupts(); + flag = disable_interrupts (); - for (addrw = saddrw; addrw < eaddrw; addrw++) { #ifdef FLASH_DEBUG - printf(" writing erase cmd to addr 0x%08lx\n", - (unsigned long)addrw); + printf ("writing erase cmd to addr 0x%08lx\n", (unsigned long)addr); #endif - *addrw = BANK_CMD_ERASE1; - *addrw = BANK_CMD_ERASE2; - } + *addr = BANK_CMD_ERASE1; + *addr = BANK_CMD_ERASE2; /* re-enable interrupts if necessary */ if (flag) - enable_interrupts(); + enable_interrupts (); } static int -bank_erase_poll(flash_info_t *info, int sect) +bank_erase_poll (flash_info_t *info, int sect) { - bank_addr_t addrw, saddrw, eaddrw; - int sectdone, haderr; - - saddrw = (bank_addr_t)info->start[sect]; - eaddrw = BANK_ADDR_NEXT_WORD(saddrw); - - sectdone = 1; - haderr = 0; - - for (addrw = saddrw; addrw < eaddrw; addrw++) { - bank_word_t stat = *addrw; + bank_addr_t addr = (bank_addr_t)info->start[sect]; + bank_word_t stat = *addr; #ifdef FLASH_DEBUG - printf(" checking status at addr " - "0x%08lx [0x%08lx]\n", - (unsigned long)addrw, stat); + printf ("checking status at addr 0x%08lx [0x%08lx]\n", + (unsigned long)addr, (unsigned long)stat); #endif - if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY) - sectdone = 0; - else if ((stat & BANK_STAT_ERR) != 0) { - printf(" failed on sector %d " - "(stat = 0x%08lx) at " - "address 0x%08lx\n", - sect, stat, - (unsigned long)addrw); - *addrw = BANK_CMD_CLR_STAT; - haderr = 1; + + if ((stat & BANK_STAT_RDY) == BANK_STAT_RDY) { + if ((stat & BANK_STAT_ERR) != 0) { + printf ("failed on sector %d [0x%08lx] at " + "address 0x%08lx\n", sect, + (unsigned long)stat, (unsigned long)addr); + *addr = BANK_CMD_CLR_STAT; + return (-1); } + else + return (1); } - - if (haderr) - return (-1); else - return (sectdone); + return (0); } static int -bank_write_word(bank_addr_t addr, bank_word_t value) +bank_write_word (bank_addr_t addr, bank_word_t value) { bank_word_t stat; ulong start; int flag, retval; /* Disable interrupts which might cause a timeout here */ - flag = disable_interrupts(); + flag = disable_interrupts (); *addr = BANK_CMD_PROG; @@ -271,14 +191,14 @@ bank_write_word(bank_addr_t addr, bank_word_t value) /* re-enable interrupts if necessary */ if (flag) - enable_interrupts(); + enable_interrupts (); retval = 0; /* data polling for D7 */ start = get_timer (0); do { - if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { retval = 1; goto done; } @@ -286,8 +206,8 @@ bank_write_word(bank_addr_t addr, bank_word_t value) } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY); if ((stat & BANK_STAT_ERR) != 0) { - printf("flash program failed (stat = 0x%08lx) " - "at address 0x%08lx\n", (ulong)stat, (ulong)addr); + printf ("flash program failed [0x%08lx] at address 0x%08lx\n", + (unsigned long)stat, (unsigned long)addr); *addr = BANK_CMD_CLR_STAT; retval = 3; } @@ -303,7 +223,7 @@ done: */ unsigned long -flash_init(void) +flash_init (void) { int i; @@ -312,21 +232,21 @@ flash_init(void) flash_info[i].flash_id = FLASH_UNKNOWN; } - bank_probe(&flash_info[0], (bank_addr_t)CFG_FLASH_BASE); + bank_probe (&flash_info[0], (bank_addr_t)CFG_FLASH_BASE); /* * protect monitor and environment sectors */ #if CFG_MONITOR_BASE == CFG_FLASH_BASE - (void)flash_protect(FLAG_PROTECT_SET, + (void)flash_protect (FLAG_PROTECT_SET, CFG_MONITOR_BASE, CFG_MONITOR_BASE+monitor_flash_len-1, &flash_info[0]); #endif #if defined(CFG_FLASH_ENV_ADDR) - (void)flash_protect(FLAG_PROTECT_SET, + (void)flash_protect (FLAG_PROTECT_SET, CFG_FLASH_ENV_ADDR, #if defined(CFG_FLASH_ENV_BUF) CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_BUF - 1, @@ -341,40 +261,8 @@ flash_init(void) /*----------------------------------------------------------------------- */ -#if 0 -static void -flash_get_offsets(ulong base, flash_info_t *info) -{ - int i; - - /* set up sector start adress table */ - if (info->flash_id & FLASH_BTYPE) { - /* set sector offsets for bottom boot block type */ - info->start[0] = base + 0x00000000; - info->start[1] = base + 0x00008000; - info->start[2] = base + 0x0000C000; - info->start[3] = base + 0x00010000; - for (i = 4; i < info->sector_count; i++) { - info->start[i] = base + (i * 0x00020000) - 0x00060000; - } - } else { - /* set sector offsets for top boot block type */ - i = info->sector_count - 1; - info->start[i--] = base + info->size - 0x00008000; - info->start[i--] = base + info->size - 0x0000C000; - info->start[i--] = base + info->size - 0x00010000; - for (; i >= 0; i--) { - info->start[i] = base + i * 0x00020000; - } - } - -} -#endif /* 0 */ - -/*----------------------------------------------------------------------- - */ void -flash_print_info(flash_info_t *info) +flash_print_info (flash_info_t *info) { int i; @@ -391,6 +279,14 @@ flash_print_info(flash_info_t *info) switch (info->flash_id & FLASH_TYPEMASK) { case FLASH_28F320J5: printf ("28F320J5 (32 Mbit, 2 x 16bit)\n"); break; + case FLASH_28F640J5: printf ("28F640J5 (64 Mbit, 2 x 16bit)\n"); + break; + case FLASH_28F320J3A: printf ("28F320J3A (32 Mbit, 2 x 16bit)\n"); + break; + case FLASH_28F640J3A: printf ("28F640J3A (64 Mbit, 2 x 16bit)\n"); + break; + case FLASH_28F128J3A: printf ("28F320J3A (128 Mbit, 2 x 16bit)\n"); + break; default: printf ("Unknown Chip Type\n"); break; } @@ -411,157 +307,25 @@ flash_print_info(flash_info_t *info) return; } -/*----------------------------------------------------------------------- - */ - /* * The following code cannot be run from FLASH! */ -#if 0 -static ulong -flash_get_size(vu_long *addr, flash_info_t *info) -{ - short i; - ulong value; - ulong base = (ulong)addr; - - - /* Write auto select command: read Manufacturer ID */ - addr[0x0555] = 0x00AA00AA; - addr[0x02AA] = 0x00550055; - addr[0x0555] = 0x00900090; - - value = addr[0]; - - switch (value) { - case AMD_MANUFACT: - info->flash_id = FLASH_MAN_AMD; - break; - case FUJ_MANUFACT: - info->flash_id = FLASH_MAN_FUJ; - break; - default: - info->flash_id = FLASH_UNKNOWN; - info->sector_count = 0; - info->size = 0; - return (0); /* no or unknown flash */ - } - - value = addr[1]; /* device ID */ - - switch (value) { - case AMD_ID_LV400T: - info->flash_id += FLASH_AM400T; - info->sector_count = 11; - info->size = 0x00100000; - break; /* => 1 MB */ - - case AMD_ID_LV400B: - info->flash_id += FLASH_AM400B; - info->sector_count = 11; - info->size = 0x00100000; - break; /* => 1 MB */ - - case AMD_ID_LV800T: - info->flash_id += FLASH_AM800T; - info->sector_count = 19; - info->size = 0x00200000; - break; /* => 2 MB */ - - case AMD_ID_LV800B: - info->flash_id += FLASH_AM800B; - info->sector_count = 19; - info->size = 0x00200000; - break; /* => 2 MB */ - - case AMD_ID_LV160T: - info->flash_id += FLASH_AM160T; - info->sector_count = 35; - info->size = 0x00400000; - break; /* => 4 MB */ - - case AMD_ID_LV160B: - info->flash_id += FLASH_AM160B; - info->sector_count = 35; - info->size = 0x00400000; - break; /* => 4 MB */ -#if 0 /* enable when device IDs are available */ - case AMD_ID_LV320T: - info->flash_id += FLASH_AM320T; - info->sector_count = 67; - info->size = 0x00800000; - break; /* => 8 MB */ - - case AMD_ID_LV320B: - info->flash_id += FLASH_AM320B; - info->sector_count = 67; - info->size = 0x00800000; - break; /* => 8 MB */ -#endif - default: - info->flash_id = FLASH_UNKNOWN; - return (0); /* => no or unknown flash */ - - } - - /* set up sector start adress table */ - if (info->flash_id & FLASH_BTYPE) { - /* set sector offsets for bottom boot block type */ - info->start[0] = base + 0x00000000; - info->start[1] = base + 0x00008000; - info->start[2] = base + 0x0000C000; - info->start[3] = base + 0x00010000; - for (i = 4; i < info->sector_count; i++) { - info->start[i] = base + (i * 0x00020000) - 0x00060000; - } - } else { - /* set sector offsets for top boot block type */ - i = info->sector_count - 1; - info->start[i--] = base + info->size - 0x00008000; - info->start[i--] = base + info->size - 0x0000C000; - info->start[i--] = base + info->size - 0x00010000; - for (; i >= 0; i--) { - info->start[i] = base + i * 0x00020000; - } - } - - /* check for protected sectors */ - for (i = 0; i < info->sector_count; i++) { - /* read sector protection at sector address, (A7 .. A0) = 0x02 */ - /* D0 = 1 if protected */ - addr = (volatile unsigned long *)(info->start[i]); - info->protect[i] = addr[2] & 1; - } - - /* - * Prevent writes to uninitialized FLASH. - */ - if (info->flash_id != FLASH_UNKNOWN) { - addr = (volatile unsigned long *)info->start[0]; - - *addr = 0x00F000F0; /* reset bank */ - } - - return (info->size); -} -#endif /* 0 */ - /*----------------------------------------------------------------------- */ int -flash_erase(flash_info_t *info, int s_first, int s_last) +flash_erase (flash_info_t *info, int s_first, int s_last) { int prot, sect, haderr; ulong start, now, last; int rcode = 0; #ifdef FLASH_DEBUG - printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n" + printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n" " Bank # %d: ", s_last - s_first + 1, s_first, s_last, (info - flash_info) + 1); - flash_print_info(info); + flash_print_info (info); #endif if ((s_first < 0) || (s_first > s_last)) { @@ -574,14 +338,14 @@ flash_erase(flash_info_t *info, int s_first, int s_last) } prot = 0; - for (sect=s_first; sect<=s_last; ++sect) { + for (sect = s_first; sect <= s_last; ++sect) { if (info->protect[sect]) { prot++; } } if (prot) { - printf("- Warning: %d protected sector%s will not be erased!\n", + printf ("- Warning: %d protected sector%s will not be erased\n", prot, (prot > 1 ? "s" : "")); } @@ -594,15 +358,15 @@ flash_erase(flash_info_t *info, int s_first, int s_last) ulong estart; int sectdone; - bank_erase_init(info, sect); + bank_erase_init (info, sect); /* wait at least 80us - let's wait 1 ms */ udelay (1000); - estart = get_timer(start); + estart = get_timer (start); do { - now = get_timer(start); + now = get_timer (start); if (now - estart > CFG_FLASH_ERASE_TOUT) { printf ("Timeout (sect %d)\n", sect); @@ -619,7 +383,7 @@ flash_erase(flash_info_t *info, int s_first, int s_last) } #endif - sectdone = bank_erase_poll(info, sect); + sectdone = bank_erase_poll (info, sect); if (sectdone < 0) { haderr = 1; @@ -642,21 +406,39 @@ flash_erase(flash_info_t *info, int s_first, int s_last) /* reset to read mode */ for (sect = s_first; sect <= s_last; sect++) { if (info->protect[sect] == 0) { /* not protected */ - bank_reset(info, sect); + bank_reset (info, sect); } } return rcode; } /*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 3 - Program failed + */ +static int +write_word (flash_info_t *info, ulong dest, ulong data) +{ + /* Check if Flash is (sufficiently) erased */ + if ((*(ulong *)dest & data) != data) + return (2); + + return (bank_write_word ((bank_addr_t)dest, (bank_word_t)data)); +} + +/*----------------------------------------------------------------------- * Copy memory to flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased + * 3 - Program failed */ int -write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) { ulong cp, wp, data; int i, l, rc; @@ -680,7 +462,7 @@ write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) data = (data << 8) | (*(uchar *)cp); } - if ((rc = write_word(info, wp, data)) != 0) { + if ((rc = write_word (info, wp, data)) != 0) { return (rc); } wp += 4; @@ -694,7 +476,7 @@ write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) for (i=0; i<4; ++i) { data = (data << 8) | *src++; } - if ((rc = write_word(info, wp, data)) != 0) { + if ((rc = write_word (info, wp, data)) != 0) { return (rc); } wp += 4; @@ -717,28 +499,7 @@ write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) data = (data << 8) | (*(uchar *)cp); } - return (write_word(info, wp, data)); -} - -/*----------------------------------------------------------------------- - * Write a word to Flash, returns: - * 0 - OK - * 1 - write timeout - * 2 - Flash not erased - */ -static int -write_word(flash_info_t *info, ulong dest, ulong data) -{ - int retval; - - /* Check if Flash is (sufficiently) erased */ - if ((*(ulong *)dest & data) != data) { - return (2); - } - - retval = bank_write_word((bank_addr_t)dest, (bank_word_t)data); - - return (retval); + return (write_word (info, wp, data)); } /*----------------------------------------------------------------------- |