Author: hailfinger
Date: Fri Oct  8 02:37:55 2010
New Revision: 1201
URL: http://flashrom.org/trac/flashrom/changeset/1201

Log:
SPI write status register (WRSR) may take longer than 100 ms, and it
makes sense to poll for completion in 10 ms steps until 5 s are over.
This patch complements r1115.

Signed-off-by: Carl-Daniel Hailfinger <[email protected]>
Acked-by: Joshua Roys <[email protected]>

Modified:
   trunk/flash.h
   trunk/spi25.c

Modified: trunk/flash.h
==============================================================================
--- trunk/flash.h       Fri Oct  8 00:21:45 2010        (r1200)
+++ trunk/flash.h       Fri Oct  8 02:37:55 2010        (r1201)
@@ -35,6 +35,9 @@
 
 #define ERROR_PTR ((void*)-1)
 
+/* Error codes */
+#define TIMEOUT_ERROR  -101
+
 typedef unsigned long chipaddr;
 
 int register_shutdown(void (*function) (void *data), void *data);

Modified: trunk/spi25.c
==============================================================================
--- trunk/spi25.c       Fri Oct  8 00:21:45 2010        (r1200)
+++ trunk/spi25.c       Fri Oct  8 02:37:55 2010        (r1201)
@@ -856,6 +856,7 @@
 static int spi_write_status_register_ewsr(struct flashchip *flash, int status)
 {
        int result;
+       int i = 0;
        struct spi_command cmds[] = {
        {
        /* WRSR requires either EWSR or WREN depending on chip type. */
@@ -879,15 +880,31 @@
        if (result) {
                msg_cerr("%s failed during command execution\n",
                        __func__);
+               /* No point in waiting for the command to complete if execution
+                * failed.
+                */
+               return result;
        }
-       /* WRSR performs a self-timed erase before the changes take effect. */
+       /* WRSR performs a self-timed erase before the changes take effect.
+        * This may take 50-85 ms in most cases, and some chips apparently
+        * allow running RDSR only once. Therefore pick an initial delay of
+        * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
+        */
        programmer_delay(100 * 1000);
-       return result;
+       while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
+               if (++i > 490) {
+                       msg_cerr("Error: WIP bit after WRSR never cleared\n");
+                       return TIMEOUT_ERROR;
+               }
+               programmer_delay(10 * 1000);
+       }
+       return 0;
 }
 
 static int spi_write_status_register_wren(struct flashchip *flash, int status)
 {
        int result;
+       int i = 0;
        struct spi_command cmds[] = {
        {
        /* WRSR requires either EWSR or WREN depending on chip type. */
@@ -911,10 +928,25 @@
        if (result) {
                msg_cerr("%s failed during command execution\n",
                        __func__);
+               /* No point in waiting for the command to complete if execution
+                * failed.
+                */
+               return result;
        }
-       /* WRSR performs a self-timed erase before the changes take effect. */
+       /* WRSR performs a self-timed erase before the changes take effect.
+        * This may take 50-85 ms in most cases, and some chips apparently
+        * allow running RDSR only once. Therefore pick an initial delay of
+        * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
+        */
        programmer_delay(100 * 1000);
-       return result;
+       while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
+               if (++i > 490) {
+                       msg_cerr("Error: WIP bit after WRSR never cleared\n");
+                       return TIMEOUT_ERROR;
+               }
+               programmer_delay(10 * 1000);
+       }
+       return 0;
 }
 
 static int spi_write_status_register(struct flashchip *flash, int status)

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

Reply via email to