diff options
author | Øyvind Harboe <oyvind.harboe@zylin.com> | 2009-10-14 12:01:52 +0200 |
---|---|---|
committer | Øyvind Harboe <oyvind.harboe@zylin.com> | 2009-10-14 12:01:52 +0200 |
commit | a894c2d8b23a711ac62a70f65c0a2901425adde1 (patch) | |
tree | cd4dda24ef886d71bda5650649d092bcdf21a3b0 | |
parent | 4490a42a09c16673769cada0db2d654fcb93edad (diff) | |
download | openocd_libswd-a894c2d8b23a711ac62a70f65c0a2901425adde1.tar.gz openocd_libswd-a894c2d8b23a711ac62a70f65c0a2901425adde1.tar.bz2 openocd_libswd-a894c2d8b23a711ac62a70f65c0a2901425adde1.tar.xz openocd_libswd-a894c2d8b23a711ac62a70f65c0a2901425adde1.zip |
S29WS-N CFI query fix is to try 0x555 if 0x55 fails.
-rw-r--r-- | src/flash/cfi.c | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/src/flash/cfi.c b/src/flash/cfi.c index ffc9d270..2d75ff44 100644 --- a/src/flash/cfi.c +++ b/src/flash/cfi.c @@ -2143,6 +2143,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 +2275,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 +2284,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); |