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

Reply via email to