Author: hailfinger Date: Wed Oct 13 23:49:30 2010 New Revision: 1210 URL: http://flashrom.org/trac/flashrom/changeset/1210
Log: Refactor remaining write wrappers.
Kill duplicated code.
Annotate write functions with their chunk size.
Mark Fujitsu MBM29F400BC and ST M29F400BB as untested because their write code no longer uses a broken layout.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net Acked-by: Uwe Hermann uwe@hermann-uwe.de Tested-by: Maciej Pijanka maciej.pijanka@gmail.com Tested-by: Idwer Vollering vidwer@gmail.com Acked-by: Idwer Vollering vidwer@gmail.com Tested-by: Sean Nelson audiohacked@gmail.com Acked-by: Sean Nelson audiohacked@gmail.com
Modified: trunk/82802ab.c trunk/chipdrivers.h trunk/flashchips.c trunk/jedec.c trunk/m29f400bt.c trunk/sst28sf040.c trunk/sst49lfxxxc.c
Modified: trunk/82802ab.c ============================================================================== --- trunk/82802ab.c Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/82802ab.c Wed Oct 13 23:49:30 2010 (r1210) @@ -160,6 +160,7 @@ return 0; }
+/* chunksize is 1 */ int write_82802ab(struct flashchip *flash, uint8_t *buf) { return write_page_82802ab(flash, buf, 0, flash->total_size * 1024);
Modified: trunk/chipdrivers.h ============================================================================== --- trunk/chipdrivers.h Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/chipdrivers.h Wed Oct 13 23:49:30 2010 (r1210) @@ -86,8 +86,8 @@ int erase_sector_jedec(struct flashchip *flash, unsigned int page, unsigned int pagesize); int erase_block_jedec(struct flashchip *flash, unsigned int page, unsigned int blocksize); int erase_chip_block_jedec(struct flashchip *flash, unsigned int page, unsigned int blocksize); -int write_sector_jedec_common(struct flashchip *flash, uint8_t *src, int start, int len, unsigned int mask); -int write_page_write_jedec_common(struct flashchip *flash, uint8_t *src, int start, int page_size, unsigned int mask); +int write_sector_jedec_common(struct flashchip *flash, uint8_t *src, int start, int len); +int write_page_write_jedec_common(struct flashchip *flash, uint8_t *src, int start, int page_size);
/* m29f400bt.c */ int probe_m29f400bt(struct flashchip *flash); @@ -106,10 +106,11 @@ int erase_sector_28sf040(struct flashchip *flash, unsigned int address, unsigned int sector_size); int write_28sf040(struct flashchip *flash, uint8_t *buf); int write_sector_28sf040(struct flashchip *flash, uint8_t *src, int start, int len); +int unprotect_28sf040(struct flashchip *flash); +int protect_28sf040(struct flashchip *flash);
/* sst49lfxxxc.c */ int erase_sector_49lfxxxc(struct flashchip *flash, unsigned int address, unsigned int sector_size); -int write_49lfxxxc(struct flashchip *flash, uint8_t *buf); int unlock_49lfxxxc(struct flashchip *flash);
/* sst_fwhub.c */
Modified: trunk/flashchips.c ============================================================================== --- trunk/flashchips.c Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/flashchips.c Wed Oct 13 23:49:30 2010 (r1210) @@ -2995,7 +2995,7 @@ .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_EITHER_RESET, - .tested = TEST_BAD_WRITE, /* Implicit eraseblock layout in write_m29f400bt is broken. */ + .tested = TEST_UNTESTED, .probe = probe_m29f400bt, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (m29f400bt.c) */ .block_erasers = @@ -3013,7 +3013,7 @@ .block_erase = block_erase_chip_m29f400bt, }, }, - .write = NULL, + .write = write_m29f400bt, .read = read_memmapped, },
@@ -5107,6 +5107,7 @@ .block_erase = erase_chip_28sf040, } }, + .unlock = unprotect_28sf040, .write = write_28sf040, .read = read_memmapped, }, @@ -5564,7 +5565,7 @@ } }, .unlock = unlock_49lfxxxc, - .write = write_49lfxxxc, + .write = write_82802ab, .read = read_memmapped, },
@@ -5627,7 +5628,7 @@ } }, .unlock = unlock_49lfxxxc, - .write = write_49lfxxxc, + .write = write_82802ab, .read = read_memmapped, },
@@ -5659,7 +5660,7 @@ } }, .unlock = unlock_49lfxxxc, - .write = write_49lfxxxc, + .write = write_82802ab, .read = read_memmapped, },
@@ -5837,7 +5838,7 @@ } }, .unlock = unlock_49lfxxxc, - .write = write_49lfxxxc, + .write = write_82802ab, .read = read_memmapped, },
@@ -6315,7 +6316,7 @@ .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_EITHER_RESET, - .tested = TEST_BAD_WRITE, /* Implicit eraseblock layout in write_m29f400bt is broken. */ + .tested = TEST_UNTESTED, .probe = probe_m29f400bt, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (m29f400bt.c) */ .block_erasers = @@ -6333,7 +6334,7 @@ .block_erase = block_erase_chip_m29f400bt, } }, - .write = NULL, + .write = write_m29f400bt, .read = read_memmapped, }, {
Modified: trunk/jedec.c ============================================================================== --- trunk/jedec.c Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/jedec.c Wed Oct 13 23:49:30 2010 (r1210) @@ -92,6 +92,25 @@ msg_cdbg("%s: excessive loops, i=0x%x\n", __func__, i); }
+static int getaddrmask(struct flashchip *flash) +{ + switch (flash->feature_bits & FEATURE_ADDR_MASK) { + case FEATURE_ADDR_FULL: + return MASK_FULL; + break; + case FEATURE_ADDR_2AA: + return MASK_2AA; + break; + case FEATURE_ADDR_AAA: + return MASK_AAA; + break; + default: + msg_cerr("%s called with unknown mask\n", __func__); + return 0; + break; + } +} + static void start_program_jedec_common(struct flashchip *flash, unsigned int mask) { chipaddr bios = flash->virtual_memory; @@ -317,11 +336,14 @@ return failed; }
-int write_sector_jedec_common(struct flashchip *flash, uint8_t *src, int start, int len, unsigned int mask) +int write_sector_jedec_common(struct flashchip *flash, uint8_t *src, int start, int len) { int i, failed = 0; chipaddr dst = flash->virtual_memory + start; chipaddr olddst; + int mask; + + mask = getaddrmask(flash);
olddst = dst; for (i = 0; i < len; i++) { @@ -335,13 +357,16 @@ return failed; }
-int write_page_write_jedec_common(struct flashchip *flash, uint8_t *src, int start, int page_size, unsigned int mask) +int write_page_write_jedec_common(struct flashchip *flash, uint8_t *src, int start, int page_size) { int i, tried = 0, failed; uint8_t *s = src; chipaddr bios = flash->virtual_memory; chipaddr dst = bios + start; chipaddr d = dst; + int mask; + + mask = getaddrmask(flash);
retry: /* Issue JEDEC Start Program command */ @@ -373,49 +398,55 @@ return failed; }
-static int getaddrmask(struct flashchip *flash) -{ - switch (flash->feature_bits & FEATURE_ADDR_MASK) { - case FEATURE_ADDR_FULL: - return MASK_FULL; - break; - case FEATURE_ADDR_2AA: - return MASK_2AA; - break; - case FEATURE_ADDR_AAA: - return MASK_AAA; - break; - default: - msg_cerr("%s called with unknown mask\n", __func__); - return 0; - break; - } -} - -int write_jedec(struct flashchip *flash, uint8_t *buf) -{ - int mask; - int i, failed = 0; - int total_size = flash->total_size * 1024; +/* + * Write a part of the flash chip. + * FIXME: Use the chunk code from Michael Karcher instead. + * This function is a slightly modified copy of spi_write_chunked. + * Each page is written separately in chunks with a maximum size of chunksize. + */ +int write_jedec_pages(struct flashchip *flash, uint8_t *buf, int start, int len) +{ + int i, starthere, lenhere; + /* FIXME: page_size is the wrong variable. We need max_writechunk_size + * in struct flashchip to do this properly. All chips using + * write_jedec have page_size set to max_writechunk_size, so + * we're OK for now. + */ int page_size = flash->page_size;
- mask = getaddrmask(flash); + /* Warning: This loop has a very unusual condition and body. + * The loop needs to go through each page with at least one affected + * byte. The lowest page number is (start / page_size) since that + * division rounds down. The highest page number we want is the page + * where the last byte of the range lives. That last byte has the + * address (start + len - 1), thus the highest page number is + * (start + len - 1) / page_size. Since we want to include that last + * page as well, the loop condition uses <=. + */ + for (i = start / page_size; i <= (start + len - 1) / page_size; i++) { + /* Byte position of the first byte in the range in this page. */ + /* starthere is an offset to the base address of the chip. */ + starthere = max(start, i * page_size); + /* Length of bytes in the range in this page. */ + lenhere = min(start + len, (i + 1) * page_size) - starthere;
- for (i = 0; i < total_size / page_size; i++) { - if (write_page_write_jedec_common(flash, buf + i * page_size, i * page_size, page_size, mask)) - failed = 1; + if (write_page_write_jedec_common(flash, buf + starthere - start, starthere, lenhere)) + return 1; }
- return failed; + return 0; }
-int write_jedec_1(struct flashchip *flash, uint8_t * buf) +/* chunksize is page_size */ +int write_jedec(struct flashchip *flash, uint8_t *buf) { - int mask; - - mask = getaddrmask(flash); + return write_jedec_pages(flash, buf, 0, flash->total_size * 1024); +}
- return write_sector_jedec_common(flash, buf, 0, flash->total_size * 1024, mask); +/* chunksize is 1 */ +int write_jedec_1(struct flashchip *flash, uint8_t * buf) +{ + return write_sector_jedec_common(flash, buf, 0, flash->total_size * 1024); }
/* erase chip with block_erase() prototype */
Modified: trunk/m29f400bt.c ============================================================================== --- trunk/m29f400bt.c Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/m29f400bt.c Wed Oct 13 23:49:30 2010 (r1210) @@ -140,6 +140,7 @@ return erase_m29f400bt(flash); }
+/* chunksize is 1 */ int write_m29f400bt(struct flashchip *flash, uint8_t *buf) { return write_page_m29f400bt(flash, buf, 0, flash->total_size * 1024);
Modified: trunk/sst28sf040.c ============================================================================== --- trunk/sst28sf040.c Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/sst28sf040.c Wed Oct 13 23:49:30 2010 (r1210) @@ -30,7 +30,7 @@ #define RESET 0xFF #define READ_ID 0x90
-static void protect_28sf040(struct flashchip *flash) +int protect_28sf040(struct flashchip *flash) { chipaddr bios = flash->virtual_memory;
@@ -41,9 +41,11 @@ chip_readb(bios + 0x041B); chip_readb(bios + 0x0419); chip_readb(bios + 0x040A); + + return 0; }
-static void unprotect_28sf040(struct flashchip *flash) +int unprotect_28sf040(struct flashchip *flash) { chipaddr bios = flash->virtual_memory;
@@ -54,12 +56,15 @@ chip_readb(bios + 0x041B); chip_readb(bios + 0x0419); chip_readb(bios + 0x041A); + + return 0; }
int erase_sector_28sf040(struct flashchip *flash, unsigned int address, unsigned int sector_size) { chipaddr bios = flash->virtual_memory;
+ /* This command sequence is very similar to erase_block_82802ab. */ chip_writeb(AUTO_PG_ERASE1, bios); chip_writeb(AUTO_PG_ERASE2, bios + address);
@@ -101,10 +106,8 @@ { chipaddr bios = flash->virtual_memory;
- unprotect_28sf040(flash); chip_writeb(CHIP_ERASE, bios); chip_writeb(CHIP_ERASE, bios); - protect_28sf040(flash);
programmer_delay(10); toggle_ready_jedec(bios); @@ -116,15 +119,10 @@ return 0; }
+/* chunksize is 1 */ int write_28sf040(struct flashchip *flash, uint8_t *buf) { - unprotect_28sf040(flash); - - write_sector_28sf040(flash, buf, 0, flash->total_size * 1024); - - protect_28sf040(flash); - - return 0; + return write_sector_28sf040(flash, buf, 0, flash->total_size * 1024); }
int erase_chip_28sf040(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
Modified: trunk/sst49lfxxxc.c ============================================================================== --- trunk/sst49lfxxxc.c Sun Oct 10 18:10:49 2010 (r1209) +++ trunk/sst49lfxxxc.c Wed Oct 13 23:49:30 2010 (r1210) @@ -75,15 +75,3 @@ } return 0; } - -int write_49lfxxxc(struct flashchip *flash, uint8_t *buf) -{ - chipaddr bios = flash->virtual_memory; - - write_lockbits_49lfxxxc(flash, 0); - write_page_82802ab(flash, buf, 0, flash->total_size * 1024); - - chip_writeb(0xFF, bios); - - return 0; -}