On 19.10.2007 23:01, Uwe Hermann wrote:
On Thu, Oct 18, 2007 at 10:32:01PM +0200, Carl-Daniel Hailfinger wrote:
[...]
Looks good IMO. With the above fixes:
Acked-by: Uwe Hermann uwe@hermann-uwe.de
Thanks for the review! I fixed most of the points you raised, but especially constification was not possible everywhere without changing all erase and write prototypes in all files. Something to be left for future commits.
Can you re-review?
Carl-Daniel
This patch introduces block and sector erase routines, but does not use them yet.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
--- Index: util/flashrom/flash.h =================================================================== --- util/flashrom/flash.h (Revision 2876) +++ util/flashrom/flash.h (Arbeitskopie) @@ -72,7 +72,7 @@
#define EON_ID 0x1C /* EN25 chips are SPI, first byte of device id is memory type, - second byte of device id is log(bitsize)-9 */ + * second byte of device id is log(bitsize)-9. */ #define EN_25B05 0x2010 /* 2^19 kbit or 2^16 kByte */ #define EN_25B10 0x2011 #define EN_25B20 0x2012 @@ -82,9 +82,8 @@ #define EN_25B32 0x2016
#define MX_ID 0xC2 /* Macronix (MX) */ -#define MX_29F002 0xB0 -/* MX25L chips are SPI, first byte of device id is memory type, - second byte of device id is log(bitsize)-9 */ +/* MX25 chips are SPI, first byte of device id is memory type, + * second byte of device id is log(bitsize)-9. */ #define MX_25L512 0x2010 /* 2^19 kbit or 2^16 kByte */ #define MX_25L1005 0x2011 #define MX_25L2005 0x2012 @@ -95,11 +94,22 @@ #define MX_25L6405 0x2017 /* MX25L3205{,D} */ #define MX_25L1635D 0x2415 #define MX_25L3235D 0x2416 +#define MX_29F002 0xB0
#define SHARP_ID 0xB0 /* Sharp */ #define SHARP_LHF00L04 0xCF
#define SST_ID 0xBF /* SST */ +/* SST25 chips are SPI, first byte of device id is memory type, second + * byte of device id is related to log(bitsize) at least for some chips. */ +#define SST_25WF512 0x2501 +#define SST_25WF010 0x2502 +#define SST_25WF020 0x2503 +#define SST_25WF040 0x2504 +#define SST_25VF016B 0x2541 +#define SST_25VF032B 0x254A +#define SST_25VF040B 0x258D +#define SST_25VF080B 0x258E #define SST_29EE020A 0x10 #define SST_28SF040 0x04 #define SST_39SF010 0xB5 @@ -210,7 +220,7 @@ /* spi.c */ int probe_spi(struct flashchip *flash); int it87xx_probe_spi_flash(const char *name); -int generic_spi_command(unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr); +int generic_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); void generic_spi_write_enable(); void generic_spi_write_disable(); int generic_spi_chip_erase(struct flashchip *flash); Index: util/flashrom/flashchips.c =================================================================== --- util/flashrom/flashchips.c (Revision 2876) +++ util/flashrom/flashchips.c (Arbeitskopie) @@ -36,7 +36,7 @@ probe_jedec, erase_chip_jedec, write_jedec}, {"At29C020", ATMEL_ID, AT_29C020, 256, 256, probe_jedec, erase_chip_jedec, write_jedec}, - {"Mx29f002", MX_ID, MX_29F002, 256, 64 * 1024, + {"MX29F002", MX_ID, MX_29F002, 256, 64 * 1024, probe_29f002, erase_29f002, write_29f002}, {"MX25L4005", MX_ID, MX_25L4005, 512, 4 * 1024, probe_spi, generic_spi_chip_erase, generic_spi_chip_write}, Index: util/flashrom/spi.c =================================================================== --- util/flashrom/spi.c (Revision 2876) +++ util/flashrom/spi.c (Arbeitskopie) @@ -45,17 +45,31 @@ #define JEDEC_WRDI_OUTSIZE 0x01 #define JEDEC_WRDI_INSIZE 0x00
-/* Both Chip Erase commands below should work */ -/* Chip Erase 0x60 */ +/* Chip Erase 0x60 is supported by Macronix/SST chips. */ #define JEDEC_CE_1 {0x60}; #define JEDEC_CE_1_OUTSIZE 0x01 #define JEDEC_CE_1_INSIZE 0x00
-/* Chip Erase 0xc7 */ +/* Chip Erase 0xc7 is supported by EON/Macronix chips. */ #define JEDEC_CE_2 {0xc7}; #define JEDEC_CE_2_OUTSIZE 0x01 #define JEDEC_CE_2_INSIZE 0x00
+/* Block Erase 0x52 is supported by SST chips. */ +#define JEDEC_BE_1 {0x52}; +#define JEDEC_BE_1_OUTSIZE 0x04 +#define JEDEC_BE_1_INSIZE 0x00 + +/* Block Erase 0xd8 is supported by EON/Macronix chips. */ +#define JEDEC_BE_2 {0xd8}; +#define JEDEC_BE_2_OUTSIZE 0x04 +#define JEDEC_BE_2_INSIZE 0x00 + +/* Sector Erase 0x20 is supported by Macronix/SST chips. */ +#define JEDEC_SE {0x20}; +#define JEDEC_SE_OUTSIZE 0x04 +#define JEDEC_SE_INSIZE 0x00 + /* Read Status Register */ #define JEDEC_RDSR {0x05}; #define JEDEC_RDSR_OUTSIZE 0x01 @@ -144,7 +158,7 @@ whereas the IT8716F splits commands internally into address and non-address commands with the address in inverse wire order. That's why the register ordering in case 4 and 5 may seem strange. */ -static int it8716f_spi_command(uint16_t port, unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr) +static int it8716f_spi_command(uint16_t port, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { uint8_t busy, writeenc; int i; @@ -188,7 +202,7 @@ return 1; } /* Start IO, 33MHz, readcnt input bytes, writecnt output bytes. Note: - * We can't use writecnt directly, but have to use a strange encoding + * We can't use writecnt directly, but have to use a strange encoding. */ outb((0x5 << 4) | ((readcnt & 0x3) << 2) | (writeenc), port); do { @@ -202,7 +216,7 @@ return 0; }
-int generic_spi_command(unsigned char writecnt, unsigned char readcnt, const unsigned char *writearr, unsigned char *readarr) +int generic_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { if (it8716f_flashport) return it8716f_spi_command(it8716f_flashport, writecnt, readcnt, writearr, readarr); @@ -269,13 +283,58 @@
generic_spi_write_enable(); /* Send CE (Chip Erase) */ - generic_spi_command(1, 0, cmd, NULL); - /* Wait until the Write-In-Progress bit is cleared */ + generic_spi_command(JEDEC_CE_2_OUTSIZE, JEDEC_CE_2_INSIZE, cmd, NULL); + /* Wait until the Write-In-Progress bit is cleared. + * This usually takes 1-85 s, so wait in 1 s steps. + */ while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP) sleep(1); return 0; }
+/* Block size is usually + * 64k for Macronix + * 32k for SST + * 4-32k non-uniform for EON + */ +int generic_spi_block_erase(const struct flashchip *flash, unsigned long addr) +{ + unsigned char cmd[JEDEC_BE_2_OUTSIZE] = JEDEC_BE_2; + + cmd[1] = (addr & 0x00ff0000) >> 16; + cmd[2] = (addr & 0x0000ff00) >> 8; + cmd[3] = (addr & 0x000000ff); + generic_spi_write_enable(); + /* Send BE (Block Erase) */ + generic_spi_command(JEDEC_BE_2_OUTSIZE, JEDEC_BE_2_INSIZE, cmd, NULL); + /* Wait until the Write-In-Progress bit is cleared. + * This usually takes 100-4000 ms, so wait in 100 ms steps. + */ + while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP) + usleep(100 * 1000); + return 0; +} + +/* Sector size is usually 4k, though Macronix eliteflash has 64k */ +int generic_spi_sector_erase(const struct flashchip *flash, unsigned long addr) +{ + unsigned char cmd[JEDEC_SE_OUTSIZE] = JEDEC_SE; + cmd[1] = (addr & 0x00ff0000) >> 16; + cmd[2] = (addr & 0x0000ff00) >> 8; + cmd[3] = (addr & 0x000000ff); + + generic_spi_write_enable(); + /* Send SE (Sector Erase) */ + generic_spi_command(JEDEC_SE_OUTSIZE, JEDEC_SE_INSIZE, cmd, NULL); + /* Wait until the Write-In-Progress bit is cleared. + * This usually takes 15-800 ms, so wait in 10 ms steps. + */ + while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP) + usleep(10 * 1000); + return 0; +} + +/* Page size is usually 256 bytes */ void it8716f_spi_page_program(int block, uint8_t *buf, uint8_t *bios) { int i;
@@ -286,7 +345,9 @@ bios[256 * block + i] = buf[256 * block + i]; } outb(0, it8716f_flashport); - /* Wait until the Write-In-Progress bit is cleared */ + /* Wait until the Write-In-Progress bit is cleared. + * This usually takes 1-10 ms, so wait in 1 ms steps. + */ while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP) usleep(1000); }