[U-Boot-Users] Patch: Fixes for XES Xpedite1000 Board Support

This patch fixes the flash support for the XES Xpedite1000 PrPMC board.
Previously only the socketed AMD 1/2MB flash was supported. This patch adds the intel strata flash and moves the environment from i2c eeprom to the first sector of the intel strata flash.
This patch also addresses the hardware write protect for the socketed flash introduced on newer xpedite1k boards.
CHANGELOG: * Update XPedite1000 board support to fix flash access and move the environment from i2c eeprom to flash. Patch by Travis B. Sawyer, 16 Feb 2006
Regards,
Travis Sawyer
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, travis.sawyer@sandburst.com */
#include <common.h> #include <ppc4xx.h> #include <asm/processor.h> - +#include <config.h>
#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; i<CFG_MAX_FLASH_BANKS; ++i) { - flash_info[i].flash_id = FLASH_UNKNOWN; - flash_info[i].sector_count = -1; - flash_info[i].size = 0; +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i;
- /* check whether the address is 0 */ - if (flash_addr_table[index][i] == 0) { - continue; - } + if (info->flash_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; i<info->sector_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; k<size; k++) - { - if (*flash++ != 0xffffffff) - { - erased = 0; - break; - } - } - + for (i = 0; i < info->sector_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; i<l; ++i, ++cp) { - data = (data << 8) | (*(uchar *)cp); + FLASH_WP_OFF(); + + switch (info->flash_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 travis.sawyer@sandburst.com + * Copyright (C) 2003-2006 Travis B. Sawyer travis.sawyer@sandburst.com * * 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 <common.h> #include <asm/processor.h> #include <spd_sdram.h> #include <i2c.h>
-#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
participants (1)
-
Travis B. Sawyer