mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 15:12:36 +02:00
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. Corresponding to flashrom svn r1210. 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>
This commit is contained in:
parent
184b95f449
commit
79e6757d26
@ -160,6 +160,7 @@ int write_page_82802ab(struct flashchip *flash, uint8_t *src, int start, int len
|
||||
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);
|
||||
|
@ -86,8 +86,8 @@ int write_jedec_1(struct flashchip *flash, uint8_t *buf);
|
||||
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_chip_28sf040(struct flashchip *flash, unsigned int addr, unsigned int
|
||||
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 */
|
||||
|
17
flashchips.c
17
flashchips.c
@ -2995,7 +2995,7 @@ struct flashchip flashchips[] = {
|
||||
.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 @@ struct flashchip flashchips[] = {
|
||||
.block_erase = block_erase_chip_m29f400bt,
|
||||
},
|
||||
},
|
||||
.write = NULL,
|
||||
.write = write_m29f400bt,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
|
||||
@ -5107,6 +5107,7 @@ struct flashchip flashchips[] = {
|
||||
.block_erase = erase_chip_28sf040,
|
||||
}
|
||||
},
|
||||
.unlock = unprotect_28sf040,
|
||||
.write = write_28sf040,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
@ -5564,7 +5565,7 @@ struct flashchip flashchips[] = {
|
||||
}
|
||||
},
|
||||
.unlock = unlock_49lfxxxc,
|
||||
.write = write_49lfxxxc,
|
||||
.write = write_82802ab,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
|
||||
@ -5627,7 +5628,7 @@ struct flashchip flashchips[] = {
|
||||
}
|
||||
},
|
||||
.unlock = unlock_49lfxxxc,
|
||||
.write = write_49lfxxxc,
|
||||
.write = write_82802ab,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
|
||||
@ -5659,7 +5660,7 @@ struct flashchip flashchips[] = {
|
||||
}
|
||||
},
|
||||
.unlock = unlock_49lfxxxc,
|
||||
.write = write_49lfxxxc,
|
||||
.write = write_82802ab,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
|
||||
@ -5837,7 +5838,7 @@ struct flashchip flashchips[] = {
|
||||
}
|
||||
},
|
||||
.unlock = unlock_49lfxxxc,
|
||||
.write = write_49lfxxxc,
|
||||
.write = write_82802ab,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
|
||||
@ -6315,7 +6316,7 @@ struct flashchip flashchips[] = {
|
||||
.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 @@ struct flashchip flashchips[] = {
|
||||
.block_erase = block_erase_chip_m29f400bt,
|
||||
}
|
||||
},
|
||||
.write = NULL,
|
||||
.write = write_m29f400bt,
|
||||
.read = read_memmapped,
|
||||
},
|
||||
{
|
||||
|
101
jedec.c
101
jedec.c
@ -92,6 +92,25 @@ void data_polling_jedec(chipaddr dst, uint8_t data)
|
||||
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 @@ retry:
|
||||
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 @@ int write_sector_jedec_common(struct flashchip *flash, uint8_t *src, int start,
|
||||
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 @@ retry:
|
||||
return failed;
|
||||
}
|
||||
|
||||
static int getaddrmask(struct flashchip *flash)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* chunksize is page_size */
|
||||
int write_jedec(struct flashchip *flash, uint8_t *buf)
|
||||
{
|
||||
return write_jedec_pages(flash, buf, 0, flash->total_size * 1024);
|
||||
}
|
||||
|
||||
/* chunksize is 1 */
|
||||
int write_jedec_1(struct flashchip *flash, uint8_t * buf)
|
||||
{
|
||||
int mask;
|
||||
|
||||
mask = getaddrmask(flash);
|
||||
|
||||
return write_sector_jedec_common(flash, buf, 0, flash->total_size * 1024, mask);
|
||||
return write_sector_jedec_common(flash, buf, 0, flash->total_size * 1024);
|
||||
}
|
||||
|
||||
/* erase chip with block_erase() prototype */
|
||||
|
@ -140,6 +140,7 @@ int block_erase_chip_m29f400bt(struct flashchip *flash, unsigned int address, un
|
||||
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);
|
||||
|
20
sst28sf040.c
20
sst28sf040.c
@ -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 @@ static void protect_28sf040(struct flashchip *flash)
|
||||
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 @@ static void unprotect_28sf040(struct flashchip *flash)
|
||||
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 @@ static int erase_28sf040(struct flashchip *flash)
|
||||
{
|
||||
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 @@ static int erase_28sf040(struct flashchip *flash)
|
||||
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)
|
||||
|
@ -75,15 +75,3 @@ int erase_sector_49lfxxxc(struct flashchip *flash, unsigned int address, unsigne
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user