]> git.sur5r.net Git - openocd/blobdiff - src/flash/cfi.c
Improve pic32mx.c command argument parsing.
[openocd] / src / flash / cfi.c
index ffc9d27069f7bbec08d3fff649e9719fd7b58ac5..93e661c2f2eb5edc6286043c698f87672b7cbf3f 100644 (file)
@@ -641,8 +641,12 @@ static int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd,
                return ERROR_FLASH_BANK_INVALID;
        }
 
-       if ((strtoul(args[4], NULL, 0) > CFI_MAX_CHIP_WIDTH)
-               || (strtoul(args[3], NULL, 0) > CFI_MAX_BUS_WIDTH))
+       uint16_t chip_width, bus_width;
+       COMMAND_PARSE_NUMBER(u16, args[3], bus_width);
+       COMMAND_PARSE_NUMBER(u16, args[4], chip_width);
+
+       if ((chip_width > CFI_MAX_CHIP_WIDTH)
+                       || (bus_width > CFI_MAX_BUS_WIDTH))
        {
                LOG_ERROR("chip and bus width have to specified in bytes");
                return ERROR_FLASH_BANK_INVALID;
@@ -2143,6 +2147,45 @@ static void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param)
        pri_ext->_unlock2 = unlock_addresses->unlock2;
 }
 
+
+static int cfi_query_string(struct flash_bank_s *bank, int address)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       int retval;
+       uint8_t command[8];
+
+       cfi_command(bank, 0x98, command);
+       if ((retval = target_write_memory(target, flash_address(bank, 0, address), bank->bus_width, 1, command)) != ERROR_OK)
+       {
+               return retval;
+       }
+
+       cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
+       cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
+       cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
+
+       LOG_DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
+
+       if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
+       {
+               cfi_command(bank, 0xf0, command);
+               if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
+               {
+                       return retval;
+               }
+               cfi_command(bank, 0xff, command);
+               if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
+               {
+                       return retval;
+               }
+               LOG_ERROR("Could not probe bank: no QRY");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       return ERROR_OK;
+}
+
 static int cfi_probe(struct flash_bank_s *bank)
 {
        cfi_flash_bank_t *cfi_info = bank->driver_priv;
@@ -2236,6 +2279,8 @@ static int cfi_probe(struct flash_bank_s *bank)
         */
        if (cfi_info->not_cfi == 0)
        {
+               int retval;
+
                /* enter CFI query mode
                 * according to JEDEC Standard No. 68.01,
                 * a single bus sequence with address = 0x55, data = 0x98 should put
@@ -2243,33 +2288,21 @@ static int cfi_probe(struct flash_bank_s *bank)
                 *
                 * SST flashes clearly violate this, and we will consider them incompatbile for now
                 */
-               cfi_command(bank, 0x98, command);
-               if ((retval = target_write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command)) != ERROR_OK)
-               {
-                       return retval;
-               }
 
-               cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
-               cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
-               cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
-
-               LOG_DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
-
-               if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
+               retval = cfi_query_string(bank, 0x55);
+               if (retval != ERROR_OK)
                {
-                       cfi_command(bank, 0xf0, command);
-                       if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
-                       {
-                               return retval;
-                       }
-                       cfi_command(bank, 0xff, command);
-                       if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
-                       {
-                               return retval;
-                       }
-                       LOG_ERROR("Could not probe bank: no QRY");
-                       return ERROR_FLASH_BANK_INVALID;
+                       /*
+                        * Spansion S29WS-N CFI query fix is to try 0x555 if 0x55 fails. Should
+                        * be harmless enough:
+                        *
+                        * http://www.infradead.org/pipermail/linux-mtd/2005-September/013618.html
+                        */
+                       LOG_USER("Try workaround w/0x555 instead of 0x55 to get QRY.");
+                       retval = cfi_query_string(bank, 0x555);
                }
+               if (retval != ERROR_OK)
+                       return retval;
 
                cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);
                cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);