diff options
author | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2009-12-17 16:20:26 +0000 |
---|---|---|
committer | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2009-12-17 16:20:26 +0000 |
commit | aa000982f40fa68ceea7ff19d77a0d5965164525 (patch) | |
tree | c193b049a268de3d198b4b981198b6683794152e | |
parent | 2a9e2455cd4f9b9fc5421e9b6b786a9010daf934 (diff) | |
download | flashrom-aa000982f40fa68ceea7ff19d77a0d5965164525.tar.gz flashrom-aa000982f40fa68ceea7ff19d77a0d5965164525.tar.bz2 flashrom-aa000982f40fa68ceea7ff19d77a0d5965164525.zip |
jedec: warn if toggle bit is stuck for too long and allow for delays between tries
If the JEDEC Toggle Bit algorithm needs more than 2^20 loops, it is a
good sign we should have used delays between toggle bit reads.
Tell the user about this. 2^20 loops need roughly a second depending on
flash bus speed. One reason for excessive loops can be a slow operation
like erase.
The Winbond W39V040C requires a 50 ms delay between toggle bit reads
during erase according to the datasheet. Turns out a 2 ms delay is
sufficient. Use a safety factor of 4 and default all erase operations
to 8 ms delay between toggle reads. This is short enough not to have
a substantial negative impact on erase times, and should improve
reliability.
This patch addresses the excessive toggle behaviour (observed on some
non-Winbond chips) and the toggle delay requirement (Winbond W39V040C).
Corresponding to flashrom svn r807.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Javier Ortega Conde (aka Malkavian) <malkavian666@gmail.com>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
-rw-r--r-- | jedec.c | 31 |
1 files changed, 27 insertions, 4 deletions
@@ -33,7 +33,7 @@ uint8_t oddparity(uint8_t val) return (val ^ (val >> 1)) & 0x1; } -void toggle_ready_jedec(chipaddr dst) +void toggle_ready_jedec_common(chipaddr dst, int delay) { unsigned int i = 0; uint8_t tmp1, tmp2; @@ -41,12 +41,33 @@ void toggle_ready_jedec(chipaddr dst) tmp1 = chip_readb(dst) & 0x40; while (i++ < 0xFFFFFFF) { + if (delay) + programmer_delay(delay); tmp2 = chip_readb(dst) & 0x40; if (tmp1 == tmp2) { break; } tmp1 = tmp2; } + if (i > 0x100000) + printf_debug("%s: excessive loops, i=0x%x\n", __func__, i); +} + +void toggle_ready_jedec(chipaddr dst) +{ + toggle_ready_jedec_common(dst, 0); +} + +/* Some chips require a minimum delay between toggle bit reads. + * The Winbond W39V040C wants 50 ms between reads on sector erase toggle, + * but experiments show that 2 ms are already enough. Pick a safety factor + * of 4 and use an 8 ms delay. + * Given that erase is slow on all chips, it is recommended to use + * toggle_ready_jedec_slow in erase functions. + */ +void toggle_ready_jedec_slow(chipaddr dst) +{ + toggle_ready_jedec_common(dst, 8 * 1000); } void data_polling_jedec(chipaddr dst, uint8_t data) @@ -62,6 +83,8 @@ void data_polling_jedec(chipaddr dst, uint8_t data) break; } } + if (i > 0x100000) + printf_debug("%s: excessive loops, i=0x%x\n", __func__, i); } void start_program_jedec(chipaddr bios) @@ -184,7 +207,7 @@ int erase_sector_jedec(struct flashchip *flash, unsigned int page, unsigned int programmer_delay(10); /* wait for Toggle bit ready */ - toggle_ready_jedec(bios); + toggle_ready_jedec_slow(bios); if (check_erased_range(flash, page, pagesize)) { fprintf(stderr,"ERASE FAILED!\n"); @@ -213,7 +236,7 @@ int erase_block_jedec(struct flashchip *flash, unsigned int block, unsigned int programmer_delay(10); /* wait for Toggle bit ready */ - toggle_ready_jedec(bios); + toggle_ready_jedec_slow(bios); if (check_erased_range(flash, block, blocksize)) { fprintf(stderr,"ERASE FAILED!\n"); @@ -242,7 +265,7 @@ int erase_chip_jedec(struct flashchip *flash) chip_writeb(0x10, bios + 0x5555); programmer_delay(10); - toggle_ready_jedec(bios); + toggle_ready_jedec_slow(bios); if (check_erased_range(flash, 0, total_size)) { fprintf(stderr,"ERASE FAILED!\n"); |