summaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
authorSpencer Oliver <ntfreak@users.sourceforge.net>2010-05-10 12:23:41 +0100
committerSpencer Oliver <ntfreak@users.sourceforge.net>2010-05-10 15:39:29 +0100
commitbbc8f4e6cec361a34028dad4b5000c136f4f48b2 (patch)
treebd552443d25620bc147510d6f63c92186fa9e3be /src/flash
parentcf811d8e6b7228348658f9211e0628fb725c5466 (diff)
downloadopenocd+libswd-bbc8f4e6cec361a34028dad4b5000c136f4f48b2.tar.gz
openocd+libswd-bbc8f4e6cec361a34028dad4b5000c136f4f48b2.tar.bz2
openocd+libswd-bbc8f4e6cec361a34028dad4b5000c136f4f48b2.tar.xz
openocd+libswd-bbc8f4e6cec361a34028dad4b5000c136f4f48b2.zip
cfi: add Numonyx M29W128G reset workaround
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>
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/cfi.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c
index 4ef41b9a..aa4540af 100644
--- a/src/flash/nor/cfi.c
+++ b/src/flash/nor/cfi.c
@@ -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;