Author: hailfinger
Date: 2009-12-17 17:20:26 +0100 (Thu, 17 Dec 2009)
New Revision: 807

Modified:
   trunk/jedec.c
Log:
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).

Signed-off-by: Carl-Daniel Hailfinger <[email protected]>
Acked-by: Javier Ortega Conde (aka Malkavian) <[email protected]>
Acked-By: Michael Karcher <[email protected]>


Modified: trunk/jedec.c
===================================================================
--- trunk/jedec.c       2009-12-17 15:20:01 UTC (rev 806)
+++ trunk/jedec.c       2009-12-17 16:20:26 UTC (rev 807)
@@ -33,7 +33,7 @@
        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,14 +41,35 @@
        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)
 {
        unsigned int i = 0;
@@ -62,6 +83,8 @@
                        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 @@
        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 @@
        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 @@
        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");


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to