cfi: add Numonyx M29W128G reset workaround
authorSpencer Oliver <ntfreak@users.sourceforge.net>
Mon, 10 May 2010 11:23:41 +0000 (12:23 +0100)
committerSpencer Oliver <ntfreak@users.sourceforge.net>
Mon, 10 May 2010 14:39:29 +0000 (15:39 +0100)
The ST/Numonix M29W128G has an issue when a 0xff cmd is sent,
it cause an internal undefined state. The workaround according
to the Numonyx is to send another 0xf0 reset cmd

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
src/flash/nor/cfi.c

index 4ef41b9ad72f6dcf437400841a10e28877225405..aa4540af553c91bd8dc65927ba7a8ef0a223a7a1 100644 (file)
@@ -104,7 +104,6 @@ static __inline__ uint32_t flash_address(struct flash_bank *bank, int sector, ui
                }
                return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;
        }
-
 }
 
 static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
@@ -232,6 +231,35 @@ static uint32_t cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offs
                                data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;
 }
 
+static int cfi_reset(struct flash_bank *bank)
+{
+       struct cfi_flash_bank *cfi_info = bank->driver_priv;
+       int retval = ERROR_OK;
+
+       if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
+       {
+               return retval;
+       }
+
+       if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+       {
+               return retval;
+       }
+
+       if (cfi_info->manufacturer == 0x20 &&
+                       (cfi_info->device_id == 0x227E || cfi_info->device_id == 0x7E))
+       {
+               /* Numonix M29W128G is cmd 0xFF intolerant - causes internal undefined state
+                * so we send an extra 0xF0 reset to fix the bug */
+               if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00))) != ERROR_OK)
+               {
+                       return retval;
+               }
+       }
+
+       return retval;
+}
+
 static void cfi_intel_clear_status_register(struct flash_bank *bank)
 {
        struct target *target = bank->target;
@@ -335,11 +363,7 @@ static int cfi_read_intel_pri_ext(struct flash_bank *bank)
 
        if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
        {
-               if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
-               {
-                       return retval;
-               }
-               if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+               if ((retval = cfi_reset(bank)) != ERROR_OK)
                {
                        return retval;
                }
@@ -1977,11 +2001,7 @@ static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
        }
 
        /* return to read array mode, so we can read from flash again for padding */
-       if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
-       {
-               return retval;
-       }
-       if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+       if ((retval = cfi_reset(bank)) != ERROR_OK)
        {
                return retval;
        }
@@ -2015,11 +2035,7 @@ static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
        }
 
        /* return to read array mode */
-       if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
-       {
-               return retval;
-       }
-       return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
+       return cfi_reset(bank);
 }
 
 static void cfi_fixup_atmel_reversed_erase_regions(struct flash_bank *bank, void *param)
@@ -2083,11 +2099,7 @@ static int cfi_query_string(struct flash_bank *bank, int address)
 
        if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
        {
-               if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
-               {
-                       return retval;
-               }
-               if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+               if ((retval = cfi_reset(bank)) != ERROR_OK)
                {
                        return retval;
                }
@@ -2168,11 +2180,7 @@ static int cfi_probe(struct flash_bank *bank)
 
        LOG_INFO("Flash Manufacturer/Device: 0x%04x 0x%04x", cfi_info->manufacturer, cfi_info->device_id);
        /* switch back to read array mode */
-       if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00))) != ERROR_OK)
-       {
-               return retval;
-       }
-       if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x00))) != ERROR_OK)
+       if ((retval = cfi_reset(bank)) != ERROR_OK)
        {
                return retval;
        }
@@ -2289,11 +2297,7 @@ static int cfi_probe(struct flash_bank *bank)
                /* return to read array mode
                 * we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command
                 */
-               if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
-               {
-                       return retval;
-               }
-               if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+               if ((retval = cfi_reset(bank)) != ERROR_OK)
                {
                        return retval;
                }
@@ -2377,7 +2381,6 @@ static int cfi_auto_probe(struct flash_bank *bank)
        return cfi_probe(bank);
 }
 
-
 static int cfi_intel_protect_check(struct flash_bank *bank)
 {
        int retval;