Hi, this is the 2nd flash patch - it adds support for some non-CFI SST flashs: SST39VF320 * SST39VF1601 SST39VF1602 SST39VF3201 * SST39VF3202 (* = tested)
The SST flashs have a problem: they do not support the DQ5 status bit to indicate errors, so checking that bit in cfi_spansion_wait_status_busy leads to aborted operation. I added a status_poll_mask that is used for spansion algorithm only and is initialized to the previous default for all CFI flashs, and is taken from the device table in the non-CFI case. I suspect the older 8-bit SST flashs that were already in the table in non_cfi.c might also need DQ5 removed, but I have no hardware to test, so I did not touch these. (even if it works, this does not guarantee it is right - my SST 39VF160 worked with DQ5-status enabled, while the SST 39VF3201 would not even erase - the datasheet states DQ5 is not supported in both cases). BTW: it's a good thing that SST screwed up the CFI query: if you work around this, you get broken CFI tables anyway ... Using this patch, the listed SST flashs work - but only without a target work_area, because the target code also needs to mask out DQ5, which requires rewriting the assembly part. I would like to postpone that until we have a framework where we can write the target code in C or assembly with only a small bit of startup glue that is target-specific - we had discussions about this some time ago on the list, and I might give it a try some time now, so touching the embedded assembly code now is probably a waste, unless someone really needs fast programming on the SST parts *now* (I don't). cu Michael -- Some people have no respect of age unless it is bottled.
Index: AUTHORS =================================================================== --- AUTHORS (revision 1470) +++ AUTHORS (working copy) @@ -5,3 +5,4 @@ Carsten Schlote <schl...@vahanus.net> Ãyvind Harboe <oyvind.har...@zylin.com> Duane Ellis <open...@duaneellis.com> +Michael Schwingen <mich...@schwingen.org> Index: src/flash/cfi.c =================================================================== --- src/flash/cfi.c (revision 1470) +++ src/flash/cfi.c (working copy) @@ -296,13 +296,14 @@ 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 @@ return(ERROR_OK); } } - } else { + } else { /* no toggle: finished, OK */ LOG_DEBUG("status: 0x%x", status); return(ERROR_OK); } @@ -2283,6 +2284,7 @@ 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 @@ { return retval; } - } + } /* end CFI case */ /* apply fixups depending on the primary command set */ switch(cfi_info->pri_id) Index: src/flash/cfi.h =================================================================== --- src/flash/cfi.h (revision 1470) +++ src/flash/cfi.h (working copy) @@ -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 @@ u8 block_erase_timeout_max; u8 chip_erase_timeout_max; + u8 status_poll_mask; + /* flash geometry */ u32 dev_size; u16 interface_desc; Index: src/flash/non_cfi.c =================================================================== --- src/flash/non_cfi.c (revision 1470) +++ src/flash/non_cfi.c (working copy) @@ -44,6 +44,7 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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,13 +141,102 @@ 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 */ .pri_id = 0x02, .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ } }, { - .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 @@ .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 @@ .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 @@ 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; Index: src/flash/non_cfi.h =================================================================== --- src/flash/non_cfi.h (revision 1470) +++ src/flash/non_cfi.h (working copy) @@ -32,6 +32,7 @@ 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[];
_______________________________________________ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development