diff --git a/board/xpedite1k/flash.c b/board/xpedite1k/flash.c index ce5d4e1..d840369 100644 --- a/board/xpedite1k/flash.c +++ b/board/xpedite1k/flash.c @@ -32,14 +32,16 @@ */ /* - * Ported to XPedite1000, 1/2 mb boot flash only + * Ported to XPedite1000 + * Use first sector of strata flash for environment + * Previously used i2c eeprom * Travis B. Sawyer, */ #include #include #include - +#include #undef DEBUG #ifdef DEBUG @@ -48,93 +50,124 @@ #define DEBUGF(x...) #endif /* DEBUG */ -#define BOOT_SMALL_FLASH 32 /* 00100000 */ -#define FLASH_ONBD_N 2 /* 00000010 */ -#define FLASH_SRAM_SEL 1 /* 00000001 */ - -#define BOOT_SMALL_FLASH_VAL 4 -#define FLASH_ONBD_N_VAL 2 -#define FLASH_SRAM_SEL_VAL 1 - flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ -static unsigned long flash_addr_table[8][CFG_MAX_FLASH_BANKS] = { - {0xfff80000}, /* 0:000: configuraton 3 */ - {0xfff90000}, /* 1:001: configuraton 4 */ - {0xfffa0000}, /* 2:010: configuraton 7 */ - {0xfffb0000}, /* 3:011: configuraton 8 */ - {0xfffc0000}, /* 4:100: configuraton 1 */ - {0xfffd0000}, /* 5:101: configuraton 2 */ - {0xfffe0000}, /* 6:110: configuraton 5 */ - {0xffff0000} /* 7:111: configuraton 6 */ -}; +/* Board support for 1 or 2 flash devices */ +#define FLASH_PORT_WIDTH8 + +typedef unsigned char FLASH_PORT_WIDTH; +typedef volatile unsigned char FLASH_PORT_WIDTHV; + +#define SWAP(x) (x) + +/* Intel-compatible flash ID */ +#define INTEL_COMPAT 0x89 +#define INTEL_ALT 0xB0 + +/* Intel-compatible flash commands */ +#define INTEL_PROGRAM 0x10 +#define INTEL_ERASE 0x20 +#define INTEL_CLEAR 0x50 +#define INTEL_LOCKBIT 0x60 +#define INTEL_PROTECT 0x01 +#define INTEL_STATUS 0x70 +#define INTEL_READID 0x90 +#define INTEL_CONFIRM 0xD0 +#define INTEL_RESET 0xFF + +/* Intel-compatible flash status bits */ +#define INTEL_FINISHED 0x80 +#define INTEL_OK 0x80 + +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define FLASH_CYCLE1 0x0555 +#define FLASH_CYCLE2 0x02aa + +#define WR_BLOCK 0x20 /*----------------------------------------------------------------------- * Functions */ -static ulong flash_get_size (vu_long *addr, flash_info_t *info); -static int write_word (flash_info_t *info, ulong dest, ulong data); - - -#ifdef CONFIG_XPEDITE1K -#define ADDR0 0x5555 -#define ADDR1 0x2aaa -#define FLASH_WORD_SIZE unsigned char -#endif +static ulong flash_get_size (FPW * addr, flash_info_t * info); +static int write_data (flash_info_t * info, ulong dest, FPW data); +static int write_data_block (flash_info_t * info, ulong src, ulong dest); +static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data); +static void flash_get_offsets (ulong base, flash_info_t * info); +void inline spin_wheel (void); /*----------------------------------------------------------------------- */ unsigned long flash_init (void) { - unsigned long total_b = 0; - unsigned long size_b[CFG_MAX_FLASH_BANKS]; - unsigned short index = 0; int i; + ulong size = 0; + /* + * Turn off flash write protect + */ + FLASH_WP_OFF(); + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + memset (&flash_info[i], 0, sizeof (flash_info_t)); + + switch (i) { + case 0: + flash_get_size ((FPW *) CFG_FLASH_BASE, + &flash_info[i]); + flash_get_offsets (CFG_FLASH_BASE, &flash_info[i]); + break; + case 1: + flash_get_size ((FPW *) CFG_FLASH_USR_BASE, + &flash_info[i]); + flash_get_offsets (CFG_FLASH_USR_BASE, &flash_info[i]); + break; + default: + panic ("configured to many flash banks!\n"); + break; + } + size += flash_info[i].size; + } + /* + * Turn on flash write protect + */ + FLASH_WP_ON(); - DEBUGF("\n"); - DEBUGF("FLASH: Index: %d\n", index); + return size; +} - /* Init: no FLASHes known */ - for (i=0; iflash_id == FLASH_UNKNOWN) + return; - /* call flash_get_size() to initialize sector address */ - size_b[i] = flash_get_size( - (vu_long *)flash_addr_table[index][i], &flash_info[i]); - flash_info[i].size = size_b[i]; - if (flash_info[i].flash_id == FLASH_UNKNOWN) { - printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", - i, size_b[i], size_b[i]<<20); - flash_info[i].sector_count = -1; - flash_info[i].size = 0; + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * PHYS_AMD_SECT_SIZE); + info->protect[i] = 0; } - - total_b += flash_info[i].size; } - return total_b; + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * PHYS_INTEL_SECT_SIZE); + info->protect[i] = 0; + } + } } - /*----------------------------------------------------------------------- */ -void flash_print_info (flash_info_t *info) +void flash_print_info (flash_info_t * info) { int i; - int k; - int size; - int erased; - volatile unsigned long *flash; if (info->flash_id == FLASH_UNKNOWN) { printf ("missing or unknown FLASH type\n"); @@ -142,144 +175,93 @@ void flash_print_info (flash_info_t *in } switch (info->flash_id & FLASH_VENDMASK) { - case FLASH_MAN_AMD: printf ("AMD "); break; - case FLASH_MAN_FUJ: printf ("FUJITSU "); break; - case FLASH_MAN_SST: printf ("SST "); break; - default: printf ("Unknown Vendor "); break; - } - - switch (info->flash_id & FLASH_TYPEMASK) { - case FLASH_AMD016: printf ("AM29F016D (16 Mbit, uniform sector size)\n"); - break; - case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\n"); - break; - case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); - break; - case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); - break; - case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); - break; - case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); - break; - case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + case FLASH_MAN_INTEL: + printf ("INTEL "); break; - case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + case FLASH_MAN_AMD: + printf ("AMD "); break; - case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); - break; - case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + default: + printf ("Unknown Vendor "); break; - case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F128J3A: + printf ("28F128J3A\n"); break; - case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + + case FLASH_AM040: + printf ("AMD29F040B\n"); break; - default: printf ("Unknown Chip Type\n"); + + default: + printf ("Unknown Chip Type\n"); break; } - printf (" Size: %ld KB in %d Sectors\n", - info->size >> 10, info->sector_count); + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); printf (" Sector Start Addresses:"); - for (i=0; isector_count; ++i) { - /* - * Check if whole sector is erased - */ - if (i != (info->sector_count-1)) - size = info->start[i+1] - info->start[i]; - else - size = info->start[0] + info->size - info->start[i]; - erased = 1; - flash = (volatile unsigned long *)info->start[i]; - size = size >> 2; /* divide by 4 for longword access */ - for (k=0; ksector_count; ++i) { if ((i % 5) == 0) printf ("\n "); - printf (" %08lX%s%s", - info->start[i], - erased ? " E" : " ", - info->protect[i] ? "RO " : " " - ); - } - printf ("\n"); - return; + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); } - -/*----------------------------------------------------------------------- - */ - - -/*----------------------------------------------------------------------- - */ + printf ("\n"); + return; +} /* * The following code cannot be run from FLASH! */ -static ulong flash_get_size (vu_long *addr, flash_info_t *info) +static ulong flash_get_size (FPW * addr, flash_info_t * info) { - short i; - FLASH_WORD_SIZE value; - ulong base = (ulong)addr; - volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; - - DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr ); + FPWV value; /* Write auto select command: read Manufacturer ID */ - udelay(10000); - addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; - udelay(1000); - addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; - udelay(1000); - addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; - udelay(1000); + /* Write auto select command sequence and test FLASH answer */ + addr[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* for AMD, Intel ignores this */ + __asm__ ("sync"); + addr[FLASH_CYCLE2] = (FPW) 0x00550055; /* for AMD, Intel ignores this */ + __asm__ ("sync"); + addr[FLASH_CYCLE1] = (FPW) 0x00900090; /* selects Intel or AMD */ + __asm__ ("sync"); -#ifdef CONFIG_ADCIOP - value = addr2[2]; -#else - value = addr2[0]; -#endif + udelay (100); - DEBUGF("FLASH MANUFACT: %x\n", value); + switch (addr[0] & 0xff) { - switch (value) { - case (FLASH_WORD_SIZE)AMD_MANUFACT: + case (uchar) AMD_MANUFACT: info->flash_id = FLASH_MAN_AMD; + value = addr[1]; break; - case (FLASH_WORD_SIZE)FUJ_MANUFACT: - info->flash_id = FLASH_MAN_FUJ; - break; - case (FLASH_WORD_SIZE)SST_MANUFACT: - info->flash_id = FLASH_MAN_SST; - break; - case (FLASH_WORD_SIZE)STM_MANUFACT: - info->flash_id = FLASH_MAN_STM; + + case (uchar) INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + value = addr[2]; break; + default: + printf ("unknown\n"); info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; info->size = 0; - return (0); /* no or unknown flash */ + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ } -#ifdef CONFIG_ADCIOP - value = addr2[0]; /* device ID */ - debug ("\ndev_code=%x\n", value); -#else - value = addr2[1]; /* device ID */ -#endif + switch (value) { - DEBUGF("\nFLASH DEVICEID: %x\n", value); + case (FPW) INTEL_ID_28F128J3A: + info->flash_id += FLASH_28F128J3A; + info->sector_count = 64; + info->size = 0x01000000; /* => 16 MB */ + break; - switch (value) { - case (FLASH_WORD_SIZE)AMD_ID_LV040B: + case (FPW) AMD_ID_LV040B: info->flash_id += FLASH_AM040; info->sector_count = 8; info->size = 0x00080000; /* => 512 kb */ @@ -287,199 +269,134 @@ static ulong flash_get_size (vu_long *ad default: info->flash_id = FLASH_UNKNOWN; - return (0); /* => no or unknown flash */ - - } - - /* set up sector start address table */ - if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || - (info->flash_id == FLASH_AM040) || - (info->flash_id == FLASH_AMD016)) { - for (i = 0; i < info->sector_count; i++) - info->start[i] = base + (i * 0x00010000); - } else { - if (info->flash_id & FLASH_BTYPE) { - /* set sector offsets for bottom boot block type */ - info->start[0] = base + 0x00000000; - info->start[1] = base + 0x00004000; - info->start[2] = base + 0x00006000; - info->start[3] = base + 0x00008000; - for (i = 4; i < info->sector_count; i++) { - info->start[i] = base + (i * 0x00010000) - 0x00030000; - } - } else { - /* set sector offsets for top boot block type */ - i = info->sector_count - 1; - info->start[i--] = base + info->size - 0x00004000; - info->start[i--] = base + info->size - 0x00006000; - info->start[i--] = base + info->size - 0x00008000; - for (; i >= 0; i--) { - info->start[i] = base + i * 0x00010000; - } - } + break; } - /* 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 */ -#ifdef CONFIG_ADCIOP - addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); - info->protect[i] = addr2[4] & 1; -#else - addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); - if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) - info->protect[i] = 0; - else - info->protect[i] = addr2[2] & 1; -#endif + if (info->sector_count > CFG_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CFG_MAX_FLASH_SECT); + info->sector_count = CFG_MAX_FLASH_SECT; } - /* - * Prevent writes to uninitialized FLASH. - */ - if (info->flash_id != FLASH_UNKNOWN) { -#if 0 /* test-only */ -#ifdef CONFIG_ADCIOP - addr2 = (volatile unsigned char *)info->start[0]; - addr2[ADDR0] = 0xAA; - addr2[ADDR1] = 0x55; - addr2[ADDR0] = 0xF0; /* reset bank */ -#else - addr2 = (FLASH_WORD_SIZE *)info->start[0]; - *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ -#endif -#else /* test-only */ - addr2 = (FLASH_WORD_SIZE *)info->start[0]; - *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ -#endif /* test-only */ - } + if (value == (FPW) INTEL_ID_28F128J3A) + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + else + addr[0] = (FPW) 0x00F000F0; /* restore read mode */ return (info->size); } -int wait_for_DQ7(flash_info_t *info, int sect) -{ - ulong start, now, last; - volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); - - start = get_timer (0); - last = start; - while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { - if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { - printf ("Timeout\n"); - return -1; - } - /* show that we're waiting */ - if ((now - last) > 1000) { /* every second */ - putc ('.'); - last = now; - } - } - return 0; -} - /*----------------------------------------------------------------------- */ - -int flash_erase (flash_info_t *info, int s_first, int s_last) +int flash_erase (flash_info_t * info, int s_first, int s_last) { - volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); - volatile FLASH_WORD_SIZE *addr2; - int flag, prot, sect, l_sect; - int i; + int flag, prot, sect; + ulong type, start, last; + int rcode = 0, intel = 0; + + /* + * Turn off flash write protect + */ + FLASH_WP_OFF(); if ((s_first < 0) || (s_first > s_last)) { - if (info->flash_id == FLASH_UNKNOWN) { + if (info->flash_id == FLASH_UNKNOWN) printf ("- missing\n"); - } else { + else printf ("- no sectors to erase\n"); - } return 1; } - if (info->flash_id == FLASH_UNKNOWN) { - printf ("Can't erase unknown flash type - aborted\n"); - return 1; + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_INTEL)) { + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_AMD)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } } + if (type == FLASH_MAN_INTEL) + intel = 1; + 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 sectors will not be erased!\n", - prot); + printf ("- Warning: %d protected sectors will not be erased!\n", prot); } else { printf ("\n"); } - l_sect = -1; + start = get_timer (0); + last = start; /* Disable interrupts which might cause a timeout here */ - flag = disable_interrupts(); + flag = disable_interrupts (); /* Start erase on unprotected sectors */ - for (sect = s_first; sect<=s_last; sect++) { - if (info->protect[sect] == 0) { /* not protected */ - addr2 = (FLASH_WORD_SIZE *)(info->start[sect]); - printf("Erasing sector %p\n", addr2); - - if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { - addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; - addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; - addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; - addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; - addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; - addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */ - for (i=0; i<50; i++) - udelay(1000); /* wait 1 ms */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + FPWV *addr = (FPWV *) (info->start[sect]); + FPW status; + + printf ("Erasing sector %2d ... ", sect); + + /* arm simple, non interrupt dependent timer */ + start = get_timer (0); + + if (intel) { + *addr = (FPW) 0x00500050; /* clear status register */ + *addr = (FPW) 0x00200020; /* erase setup */ + *addr = (FPW) 0x00D000D0; /* erase confirm */ } else { - addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; - addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; - addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; - addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; - addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; - addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + FPWV *base; /* first address in bank */ + + base = (FPWV *) (CFG_FLASH_BASE); + base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */ + base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */ + base[FLASH_CYCLE1] = (FPW) 0x00800080; /* erase mode */ + base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */ + base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */ + *addr = (FPW) 0x00300030; /* erase sector */ } - l_sect = sect; - /* - * Wait for each sector to complete, it's more - * reliable. According to AMD Spec, you must - * issue all erase commands within a specified - * timeout. This has been seen to fail, especially - * if printf()s are included (for debug)!! - */ - wait_for_DQ7(info, sect); - } - } - /* re-enable interrupts if necessary */ - if (flag) - enable_interrupts(); + while (((status = + *addr) & (FPW) 0x00800080) != + (FPW) 0x00800080) { + if (get_timer (start) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + if (intel) { + *addr = (FPW) 0x00B000B0; /* suspend erase */ + *addr = (FPW) 0x00FF00FF; /* reset to read mode */ + } else + *addr = (FPW) 0x00F000F0; /* reset to read mode */ + + rcode = 1; + break; + } + } - /* wait at least 80us - let's wait 1 ms */ - udelay (1000); + if (intel) { + *addr = (FPW) 0x00500050; /* clear status register cmd. */ + *addr = (FPW) 0x00FF00FF; /* resest to read mode */ + } else + *addr = (FPW) 0x00F000F0; /* reset to read mode */ -#if 0 + printf (" done\n"); + } + } /* - * We wait for the last triggered sector + * Turn on flash write protect */ - if (l_sect < 0) - goto DONE; - wait_for_DQ7(info, l_sect); - -DONE: -#endif - /* reset to read mode */ - addr = (FLASH_WORD_SIZE *)info->start[0]; - addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + FLASH_WP_ON(); - printf (" done\n"); - return 0; + return rcode; } /*----------------------------------------------------------------------- @@ -487,121 +404,407 @@ DONE: * 0 - OK * 1 - write timeout * 2 - Flash not erased + * 4 - Flash not identified */ - -int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) { - ulong cp, wp, data; - int i, l, rc; - - wp = (addr & ~3); /* get lower word aligned address */ + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } /* - * handle unaligned start bytes + * Turn off flash write protect */ - if ((l = addr - wp) != 0) { - data = 0; - for (i=0, cp=wp; iflash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: + { + FPW data = 0; /* 16 or 32 bit word, matches flash bus width */ + int bytes; /* number of bytes to program in current word */ + int left; /* number of bytes left to program */ + int i, res; + + for (left = cnt, res = 0; + left > 0 && res == 0; + addr += sizeof (data), left -= + sizeof (data) - bytes) { + + bytes = addr & (sizeof (data) - 1); + addr &= ~(sizeof (data) - 1); + + /* combine source and destination data so can program + * an entire word of 16 or 32 bits + */ + for (i = 0; i < sizeof (data); i++) { + data <<= 8; + if (i < bytes || i - bytes >= left) + data += *((uchar *) addr + i); + else + data += *src++; + } + + res = write_word_amd (info, (FPWV *) addr, + data); } - for (; i<4 && cnt>0; ++i) { - data = (data << 8) | *src++; - --cnt; - ++cp; + /* + * Turn on flash write protect + */ + FLASH_WP_ON(); + return res; + } /* case FLASH_MAN_AMD */ + + case FLASH_MAN_INTEL: + { + ulong cp, wp; + FPW data; + int count, i, l, rc, port_width; + + /* get lower word aligned address */ + wp = addr; + port_width = 1; + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + for (; i < port_width && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + + for (; cnt == 0 && i < port_width; ++i, ++cp) + data = (data << 8) | (*(uchar *) cp); + + if ((rc = + write_data (info, wp, SWAP (data))) != 0) + return (rc); + wp += port_width; } - for (; cnt==0 && i<4; ++i, ++cp) { - data = (data << 8) | (*(uchar *)cp); + + if (cnt > WR_BLOCK) { + /* + * handle word aligned part + */ + count = 0; + while (cnt >= WR_BLOCK) { + + if ((rc = + write_data_block (info, + (ulong) src, + wp)) != 0) + return (rc); + + wp += WR_BLOCK; + src += WR_BLOCK; + cnt -= WR_BLOCK; + + if (count++ > 0x800) { + spin_wheel (); + count = 0; + } + } } - if ((rc = write_word(info, wp, data)) != 0) { - return (rc); + if (cnt < WR_BLOCK) { + /* + * handle word aligned part + */ + count = 0; + while (cnt >= port_width) { + data = 0; + for (i = 0; i < port_width; ++i) + data = (data << 8) | *src++; + + if ((rc = + write_data (info, wp, + SWAP (data))) != 0) + return (rc); + + wp += port_width; + cnt -= port_width; + if (count++ > 0x800) { + spin_wheel (); + count = 0; + } + } } - wp += 4; - } - /* - * handle word aligned part - */ - while (cnt >= 4) { + if (cnt == 0) + return (0); + + /* + * handle unaligned tail bytes + */ data = 0; - for (i=0; i<4; ++i) { + for (i = 0, cp = wp; i < port_width && cnt > 0; + ++i, ++cp) { data = (data << 8) | *src++; + --cnt; } - if ((rc = write_word(info, wp, data)) != 0) { - return (rc); - } - wp += 4; - cnt -= 4; - } - if (cnt == 0) { - return (0); - } + for (; i < port_width; ++i, ++cp) + data = (data << 8) | (*(uchar *) cp); + return (write_data (info, wp, SWAP (data))); + } /* case FLASH_MAN_INTEL */ + + } /* switch */ /* - * handle unaligned tail bytes + * Turn on flash write protect */ - data = 0; - for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { - data = (data << 8) | *src++; - --cnt; + FLASH_WP_ON(); + return (0); +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t * info, ulong dest, FPW data) +{ + FPWV *addr = (FPWV *) dest; + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr); + return (2); } - for (; i<4; ++i, ++cp) { - data = (data << 8) | (*(uchar *)cp); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + *addr = (FPW) 0x00400040; /* write setup */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + start = get_timer (0); + + /* wait while polling the status register */ + while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (1); + } } - return (write_word(info, wp, data)); + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + + return (0); } /*----------------------------------------------------------------------- - * Write a word to Flash, returns: + * Write a word or halfword to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */ -static int write_word (flash_info_t * info, ulong dest, ulong data) +static int write_data_block (flash_info_t * info, ulong src, ulong dest) { - volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]); - volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest; - volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data; + FPWV *srcaddr = (FPWV *) src; + FPWV *dstaddr = (FPWV *) dest; ulong start; - int i; + int flag, i; + + /* Check if Flash is (sufficiently) erased */ + for (i = 0; i < WR_BLOCK; i++) + if ((*dstaddr++ & 0xff) != 0xff) { + printf ("not erased at %08lx (%lx)\n", + (ulong) dstaddr, *dstaddr); + return (2); + } + + dstaddr = (FPWV *) dest; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + *dstaddr = (FPW) 0x00e800e8; /* write block setup */ + + /* arm simple, non interrupt dependent timer */ + start = get_timer (0); + + /* wait while polling the status register */ + while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */ + return (1); + } + } + + *dstaddr = (FPW) 0x001f001f; /* write 32 to buffer */ + for (i = 0; i < WR_BLOCK; i++) + *dstaddr++ = *srcaddr++; + + dstaddr -= 1; + *dstaddr = (FPW) 0x00d000d0; /* write 32 to buffer */ + + /* arm simple, non interrupt dependent timer */ + start = get_timer (0); + + /* wait while polling the status register */ + while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */ + return (1); + } + } + + *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */ + + return (0); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash for AMD FLASH + * A word is 16 or 32 bits, whichever the bus width of the flash bank + * (not an individual chip) is. + * + * returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data) +{ + ulong start; + int flag; + int res = 0; /* result, assume success */ + FPWV *base; /* first address in flash bank */ /* Check if Flash is (sufficiently) erased */ - if ((*((volatile FLASH_WORD_SIZE *) dest) & - (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) { + if ((*dest & data) != data) { return (2); } - for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) { - int flag; + base = (FPWV *) (CFG_FLASH_BASE); - /* Disable interrupts which might cause a timeout here */ - flag = disable_interrupts (); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); - addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; - addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; - addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0; + base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */ + base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */ + base[FLASH_CYCLE1] = (FPW) 0x00A000A0; /* selects program mode */ - dest2[i] = data2[i]; + *dest = data; /* start programming the data */ - /* re-enable interrupts if necessary */ - if (flag) - enable_interrupts (); + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); - /* data polling for D7 */ - start = get_timer (0); - while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) != - (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) { + start = get_timer (0); - if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { - return (1); - } + /* data polling for D7 */ + while (res == 0 + && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + *dest = (FPW) 0x00F000F0; /* reset bank */ + res = 1; } } - return (0); + return (res); +} + +void inline spin_wheel (void) +{ + static int p = 0; + static char w[] = "\\/-"; + + printf ("\010%c", w[p]); + (++p == 3) ? (p = 0) : 0; } /*----------------------------------------------------------------------- + * Set/Clear sector's lock bit, returns: + * 0 - OK + * 1 - Error (timeout, voltage problems, etc.) */ +int flash_real_protect (flash_info_t * info, long sector, int prot) +{ + ulong start; + int i; + int rc = 0; + FPWV *addr = (FPWV *) (info->start[sector]); + int flag = disable_interrupts (); + + /* + * 29F040B AMD flash does not support software protection/unprotection, + * the only way to protect the AMD flash is marked it as prot bit. + * This flash only support hardware protection, by supply or not supply + * 12vpp to the flash + */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) { + info->protect[sector] = prot; + + return 0; + } + + *addr = INTEL_CLEAR; /* Clear status register */ + if (prot) { /* Set sector lock bit */ + *addr = INTEL_LOCKBIT; /* Sector lock bit */ + *addr = INTEL_PROTECT; /* set */ + } else { /* Clear sector lock bit */ + *addr = INTEL_LOCKBIT; /* All sectors lock bits */ + *addr = INTEL_CONFIRM; /* clear */ + } + + start = get_timer (0); + + while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { + if (get_timer (start) > CFG_FLASH_UNLOCK_TOUT) { + printf ("Flash lock bit operation timed out\n"); + rc = 1; + break; + } + } + + if (*addr != INTEL_OK) { + printf ("Flash lock bit operation failed at %08X, CSR=%08X\n", + (uint) addr, (uint) * addr); + rc = 1; + } + + if (!rc) + info->protect[sector] = prot; + + /* + * Clear lock bit command clears all sectors lock bits, so + * we have to restore lock bits of protected sectors. + */ + if (!prot) { + for (i = 0; i < info->sector_count; i++) { + if (info->protect[i]) { + start = get_timer (0); + addr = (FPWV *) (info->start[i]); + *addr = INTEL_LOCKBIT; /* Sector lock bit */ + *addr = INTEL_PROTECT; /* set */ + while ((*addr & INTEL_FINISHED) != + INTEL_FINISHED) { + if (get_timer (start) > + CFG_FLASH_UNLOCK_TOUT) { + printf ("Flash lock bit operation timed out\n"); + rc = 1; + break; + } + } + } + } + } + + if (flag) + enable_interrupts (); + + *addr = INTEL_RESET; /* Reset to read array mode */ + + return rc; +} diff --git a/board/xpedite1k/xpedite1k.c b/board/xpedite1k/xpedite1k.c index bb36c96..1ec7bef 100644 --- a/board/xpedite1k/xpedite1k.c +++ b/board/xpedite1k/xpedite1k.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 Travis B. Sawyer + * Copyright (C) 2003-2006 Travis B. Sawyer * * See file CREDITS for list of people who contributed to this * project. @@ -19,40 +19,62 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ - - #include #include #include #include -#define BOOT_SMALL_FLASH 32 /* 00100000 */ -#define FLASH_ONBD_N 2 /* 00000010 */ -#define FLASH_SRAM_SEL 1 /* 00000001 */ - long int fixed_sdram (void); int board_early_init_f(void) { unsigned long sdrreg; - /* TBS: Setup the GPIO access for the user LEDs */ + /* TBS: Setup the GPIO access for the user LEDs and flash write protect */ mfsdr(sdr_pfc0, sdrreg); - mtsdr(sdr_pfc0, (sdrreg & ~0x00000100) | 0x00000E00); - out32(CFG_GPIO_BASE + 0x018, (USR_LED0 | USR_LED1 | USR_LED2 | USR_LED3)); + mtsdr(sdr_pfc0, 0xF0E33E00); + out32(CFG_GPIO_BASE + 0x018, USR_LED0 | USR_LED1 | USR_LED2 | USR_LED3 | GPIO_FLASH_WP); + LED0_OFF(); LED1_OFF(); LED2_OFF(); LED3_OFF(); + FLASH_WP_ON(); + FLASH_WP_OFF(); /*-------------------------------------------------------------------- * Setup the external bus controller/chip selects *-------------------------------------------------------------------*/ /* set the bus controller */ - mtebc (pb0ap, 0x04055200); /* FLASH/SRAM */ - mtebc (pb0cr, 0xfff18000); /* BAS=0xfff 1MB R/W 8-bit */ - mtebc (pb1ap, 0x04055200); /* FLASH/SRAM */ - mtebc (pb1cr, 0xfe098000); /* BAS=0xff8 16MB R/W 8-bit */ + /*--------------------------------------------------------------------+ + | Initialize EBC CONFIG + +-------------------------------------------------------------------*/ + mtebc(xbcfg, 0x07000000); + + /*--------------------------------------------------------------------+ + | 1/2 MB FLASH. Initialize bank 0 with default values. + +-------------------------------------------------------------------*/ + mtebc(pb0ap, + EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(10) | + EBC_BXAP_BCE_DISABLE | EBC_BXAP_CSN_ENCODE(0) | + EBC_BXAP_OEN_ENCODE(0)| EBC_BXAP_WBN_ENCODE(1) | + EBC_BXAP_WBF_ENCODE(2)| EBC_BXAP_TH_ENCODE(2) | + EBC_BXAP_RE_DISABLED | EBC_BXAP_BEM_WRITEONLY | + EBC_BXAP_PEN_DISABLED); + + mtebc(pb0cr, EBC_BXCR_BAS_ENCODE(CFG_FLASH_BASE) | + EBC_BXCR_BS_1MB | EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT); + + mtebc(pb1ap, + EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(10) | + EBC_BXAP_BCE_DISABLE | EBC_BXAP_CSN_ENCODE(0) | + EBC_BXAP_OEN_ENCODE(0)| EBC_BXAP_WBN_ENCODE(1) | + EBC_BXAP_WBF_ENCODE(2)| EBC_BXAP_TH_ENCODE(2) | + EBC_BXAP_RE_DISABLED | EBC_BXAP_BEM_WRITEONLY | + EBC_BXAP_PEN_DISABLED); + + mtebc (pb1cr, EBC_BXCR_BAS_ENCODE(CFG_FLASH_USR_BASE) | + EBC_BXCR_BS_16MB | EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT); /*-------------------------------------------------------------------- * Setup the interrupt controller polarities, triggers, etc. @@ -90,7 +112,6 @@ int board_early_init_f(void) LED0_ON(); - return 0; } diff --git a/include/configs/XPEDITE1K.h b/include/configs/XPEDITE1K.h index 9b32514..9056ea9 100644 --- a/include/configs/XPEDITE1K.h +++ b/include/configs/XPEDITE1K.h @@ -52,7 +52,7 @@ *----------------------------------------------------------------------*/ #define CFG_SDRAM_BASE 0x00000000 /* _must_ be 0 */ #define CFG_FLASH_BASE 0xfff80000 /* start of FLASH */ - +#define CFG_FLASH_USR_BASE 0xf8000000 /* Strata Flash */ #define CFG_MONITOR_BASE CFG_FLASH_BASE /* start of monitor */ #define CFG_PCI_MEMBASE 0x80000000 /* mapped pci memory */ #define CFG_PERIPHERAL_BASE 0xe0000000 /* internal peripherals */ @@ -66,6 +66,7 @@ #define USR_LED1 0x00000100 #define USR_LED2 0x00000200 #define USR_LED3 0x00000400 +#define GPIO_FLASH_WP 0x00000020 #ifndef __ASSEMBLY__ extern unsigned long in32(unsigned int); @@ -76,6 +77,9 @@ extern void out32(unsigned int, unsigned #define LED2_ON() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) & ~USR_LED2)) #define LED3_ON() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) & ~USR_LED3)) +#define FLASH_WP_OFF() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) & ~GPIO_FLASH_WP)) +#define FLASH_WP_ON() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) | GPIO_FLASH_WP)) + #define LED0_OFF() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) | USR_LED0)) #define LED1_OFF() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) | USR_LED1)) #define LED2_OFF() out32(CFG_GPIO_BASE, (in32(CFG_GPIO_BASE) | USR_LED2)) @@ -126,12 +130,17 @@ extern void out32(unsigned int, unsigned /*----------------------------------------------------------------------- * FLASH related *----------------------------------------------------------------------*/ -#define CFG_MAX_FLASH_BANKS 1 /* number of banks */ -#define CFG_MAX_FLASH_SECT 8 /* sectors per device */ +#define CFG_MAX_FLASH_BANKS 2 /* number of banks */ +#define CFG_MAX_FLASH_SECT 128 /* sectors per device */ #undef CFG_FLASH_CHECKSUM -#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_ERASE_TOUT 240000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ +#define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */ +#define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ +#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ +#define PHYS_AMD_SECT_SIZE 0x00010000 /* 64 KB sectors (x2) */ +#define PHYS_INTEL_SECT_SIZE 0x00020000 /* 128 KB sectors (x2) */ /*----------------------------------------------------------------------- * DDR SDRAM @@ -151,9 +160,14 @@ extern void out32(unsigned int, unsigned /*----------------------------------------------------------------------- * Environment *----------------------------------------------------------------------*/ -#define CFG_ENV_IS_IN_EEPROM 1 -#define CFG_ENV_SIZE 0x100 /* Size of Environment vars */ -#define CFG_ENV_OFFSET 0x100 +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SIZE (PHYS_INTEL_SECT_SIZE) +#define CFG_ENV_ADDR (CFG_FLASH_USR_BASE) +#define CFG_ENV_SECT_SIZE PHYS_INTEL_SECT_SIZE +#define CONFIG_ENV_OVERWRITE 1 +#undef CFG_ENV_IS_IN_NVRAM +#undef CFG_ENV_IS_IN_EEPROM + #define CFG_I2C_EEPROM_ADDR 0x50 /* this is actually the second page of the eeprom */ #define CFG_I2C_EEPROM_ADDR_LEN 1 #define CFG_EEPROM_PAGE_WRITE_ENABLE