diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | src/flash/cfi.c | 8 | ||||
-rw-r--r-- | src/flash/cfi.h | 6 | ||||
-rw-r--r-- | src/flash/non_cfi.c | 119 | ||||
-rw-r--r-- | src/flash/non_cfi.h | 1 |
5 files changed, 118 insertions, 17 deletions
@@ -5,3 +5,4 @@ Spencer Oliver <spen@spen-soft.co.uk> Carsten Schlote <schlote@vahanus.net> Øyvind Harboe <oyvind.harboe@zylin.com> Duane Ellis <openocd@duaneellis.com> +Michael Schwingen <michael@schwingen.org> diff --git a/src/flash/cfi.c b/src/flash/cfi.c index 0426fd2..b4bb605 100644 --- a/src/flash/cfi.c +++ b/src/flash/cfi.c @@ -296,13 +296,14 @@ u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout) int cfi_spansion_wait_status_busy(flash_bank_t *bank, int timeout) { u8 status, oldstatus; + cfi_flash_bank_t *cfi_info = bank->driver_priv; oldstatus = cfi_get_u8(bank, 0, 0x0); do { status = cfi_get_u8(bank, 0, 0x0); if ((status ^ oldstatus) & 0x40) { - if (status & 0x20) { + if (status & cfi_info->status_poll_mask & 0x20) { oldstatus = cfi_get_u8(bank, 0, 0x0); status = cfi_get_u8(bank, 0, 0x0); if ((status ^ oldstatus) & 0x40) { @@ -313,7 +314,7 @@ int cfi_spansion_wait_status_busy(flash_bank_t *bank, int timeout) return(ERROR_OK); } } - } else { + } else { /* no toggle: finished, OK */ LOG_DEBUG("status: 0x%x", status); return(ERROR_OK); } @@ -2283,6 +2284,7 @@ static int cfi_probe(struct flash_bank_s *bank) break; /* AMD/Spansion, Atmel, ... command set */ case 0x0002: + cfi_info->status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7; /* default for all CFI flashs */ cfi_read_0002_pri_ext(bank); break; default: @@ -2303,7 +2305,7 @@ static int cfi_probe(struct flash_bank_s *bank) { return retval; } - } + } /* end CFI case */ /* apply fixups depending on the primary command set */ switch(cfi_info->pri_id) diff --git a/src/flash/cfi.h b/src/flash/cfi.h index 5eab7ef..dc43dd1 100644 --- a/src/flash/cfi.h +++ b/src/flash/cfi.h @@ -23,11 +23,13 @@ #include "flash.h" #include "target.h" +#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */ +#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */ + typedef struct cfi_flash_bank_s { working_area_t *write_algorithm; - int x16_as_x8; int jedec_probe; int not_cfi; @@ -58,6 +60,8 @@ typedef struct cfi_flash_bank_s u8 block_erase_timeout_max; u8 chip_erase_timeout_max; + u8 status_poll_mask; + /* flash geometry */ u32 dev_size; u16 interface_desc; diff --git a/src/flash/non_cfi.c b/src/flash/non_cfi.c index b9ef112..20aa9f1 100644 --- a/src/flash/non_cfi.c +++ b/src/flash/non_cfi.c @@ -44,6 +44,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 64*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { @@ -57,6 +58,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 128*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { @@ -70,6 +72,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 256*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { @@ -83,6 +86,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 512*KB, .interface_desc = 0x0, /* x8 only device */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { @@ -96,6 +100,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 1, .erase_region_info = { @@ -109,6 +114,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -125,6 +131,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -134,6 +141,94 @@ non_cfi_t non_cfi_flashes[] = { ERASE_REGION( 1, 16*KB) } }, + + /* SST 39VF* do not support DQ5 status polling - this currently is + only supported by the host algorithm, not by the target code using + the work area. */ + { + .mfr = CFI_MFR_SST, + .id = 0x2782, /* SST39xF160 */ + .pri_id = 0x02, + .dev_size = 2*MB, + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, + .num_erase_regions = 1, + .erase_region_info = + { + ERASE_REGION(512, 4*KB) + } + }, + { + .mfr = CFI_MFR_SST, + .id = 0x2783, /* SST39VF320 */ + .pri_id = 0x02, + .dev_size = 4*MB, + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, + .num_erase_regions = 1, + .erase_region_info = + { + ERASE_REGION(1024, 4*KB) + } + }, + { + .mfr = CFI_MFR_SST, + .id = 0x234b, /* SST39VF1601 */ + .pri_id = 0x02, + .dev_size = 2*MB, + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, + .num_erase_regions = 1, + .erase_region_info = + { + ERASE_REGION(512, 4*KB) + } + }, + { + .mfr = CFI_MFR_SST, + .id = 0x234a, /* SST39VF1602 */ + .pri_id = 0x02, + .dev_size = 2*MB, + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, + .num_erase_regions = 1, + .erase_region_info = + { + ERASE_REGION(512, 4*KB) + } + }, + { + .mfr = CFI_MFR_SST, + .id = 0x235b, /* SST39VF3201 */ + .pri_id = 0x02, + .dev_size = 4*MB, + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, + .num_erase_regions = 1, + .erase_region_info = + { + ERASE_REGION(1024, 4*KB) + } + }, + { + .mfr = CFI_MFR_SST, + .id = 0x235a, /* SST39VF3202 */ + .pri_id = 0x02, + .dev_size = 4*MB, + .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ + .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7, + .num_erase_regions = 1, + .erase_region_info = + { + ERASE_REGION(1024, 4*KB) + } + }, { .mfr = CFI_MFR_AMD, .id = 0x22ab, /* AM29F400BB */ @@ -141,6 +236,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -157,6 +253,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 512*KB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -173,6 +270,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -189,6 +287,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 1*MB, .interface_desc = 0x2, .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -205,6 +304,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -222,6 +322,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -238,6 +339,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -248,25 +350,13 @@ non_cfi_t non_cfi_flashes[] = { } }, { - .mfr = CFI_MFR_SST, - .id = 0x2782, /* SST39xF160 */ - .pri_id = 0x02, - .dev_size = 2*MB, - .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ - .max_buf_write_size = 0x0, - .num_erase_regions = 1, - .erase_region_info = - { - ERASE_REGION(512, 4*KB) - } - }, - { .mfr = CFI_MFR_ATMEL, .id = 0x00c0, /* Atmel 49BV1614 */ .pri_id = 0x02, .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 3, .erase_region_info = { @@ -282,6 +372,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 2*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 3, .erase_region_info = { @@ -297,6 +388,7 @@ non_cfi_t non_cfi_flashes[] = { .dev_size = 1*MB, .interface_desc = 0x2, /* x8 or x16 device with nBYTE */ .max_buf_write_size = 0x0, + .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7, .num_erase_regions = 4, .erase_region_info = { @@ -358,6 +450,7 @@ void cfi_fixup_non_cfi(flash_bank_t *bank) cfi_info->interface_desc = non_cfi->interface_desc; cfi_info->max_buf_write_size = non_cfi->max_buf_write_size; + cfi_info->status_poll_mask = non_cfi->status_poll_mask; cfi_info->num_erase_regions = non_cfi->num_erase_regions; cfi_info->erase_region_info = non_cfi->erase_region_info; cfi_info->dev_size = non_cfi->dev_size; diff --git a/src/flash/non_cfi.h b/src/flash/non_cfi.h index 19fef85..e4b33d4 100644 --- a/src/flash/non_cfi.h +++ b/src/flash/non_cfi.h @@ -32,6 +32,7 @@ typedef struct non_cfi_s u16 max_buf_write_size; u8 num_erase_regions; u32 erase_region_info[6]; + u8 status_poll_mask; } non_cfi_t; extern non_cfi_t non_cfi_flashes[]; |