jedec_probe problems with 16bit devices

Ben Dooks ben-mtd at fluff.org
Sat Sep 4 13:37:03 EDT 2004


I have been trying to get an SST 39LF160 on an Simtec Electronics
EB2410ITX (aka Bast). I have found some problems with jedec_probe
with non-8bit devices.

Basically, the two problems are as follows:

1) A number of functions are masking out bits from the command
addresses, but the cfi_send_gen_cmd() moves the addresses up
depending on the chip type, so the masking is not needed.

2) the cfi_send_gen_cmd() is called with CFI_DEVICETYPE_X8
instead of cfi->device_type, which causes the wrong accesses to
be generated to the chip.


This is the patch generated from the 03 Sep 2004 CVS drop:

--- mtd/drivers/mtd/chips/jedec_probe.c	2004-08-25 23:00:11.000000000 +0100
+++ linux-2.6.8.1-patched-work2/drivers/mtd/chips/jedec_probe.c	2004-09-04 18:18:51.000000000 +0100
@@ -8,6 +8,15 @@
    Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
 */
 
+/* Note from Ben Dooks:
+ *
+ * There was an attempt to mask off unused address bits depending on the
+ * device width (ie, remove A0 for 16bit). This is a proble since the 
+ * command functions shift the addresses up for the chip-width, thus
+ * negating the need to mask, as all bits of the address are presented
+ * to the chip.
+ */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -1379,6 +1388,22 @@
 			ERASEINFO(0x01000,256),
 		}
 	}, {
+		.mfr_id		= MANUFACTURER_SST,	/* should be CFI */
+		.dev_id		= SST39LF160,
+		.name		= "SST 39LF160",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+			[1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x1000,256),
+			ERASEINFO(0x1000,256)
+		}
+
+	}, {
 		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
 		.dev_id		= M29W800DT,
 		.name		= "ST M29W800DT",
@@ -1654,8 +1679,8 @@
 	 * the F0 is written to */
 	if(cfi->addr_unlock1) {
 		/*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/
-		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
 	}
 
 	cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
@@ -1700,7 +1725,6 @@
 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
 {
 	int i,num_erase_regions;
-	unsigned long mask;
 	__u8 uaddr;
 
 	printk("Found: %s\n",jedec_table[index].name);
@@ -1735,10 +1759,11 @@
 		return 0;
 	}
 
-	/* Mask out address bits which are smaller than the device type */
-	mask = ~(p_cfi->device_type-1);
-	p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask;
-	p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask;
+	/* Do not mask out `unused bits` due to the command function
+	 * shifting the addresses depdning on the chip type */
+
+	p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1;
+	p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2;
 
 	return 1; 	/* ok */
 }
@@ -1759,7 +1784,6 @@
 	int rc = 0;           /* failure until all tests pass */
 	u32 mfr, id;
 	__u8 uaddr;
-	unsigned long mask;
 
 	/*
 	 * The IDs must match.  For X16 and X32 devices operating in
@@ -1810,18 +1834,17 @@
 		goto match_done;
 	}
 
-	mask = ~(cfi->device_type-1);
 
 	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
 	       __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
 	if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
-	     && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 ||
-		  (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) {
+	     && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1 ||
+		  unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) {
 		DEBUG( MTD_DEBUG_LEVEL3,
 		       "MTD %s(): 0x%.4lx 0x%.4lx did not match\n",
 		       __func__,
-		       unlock_addrs[uaddr].addr1 & mask,
-		       unlock_addrs[uaddr].addr2 & mask);
+		       unlock_addrs[uaddr].addr1,
+		       unlock_addrs[uaddr].addr2);
 		goto match_done;
 	}
 
@@ -1857,10 +1880,10 @@
 	 */
 	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
 	if(cfi->addr_unlock1) {
-		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
 	}
-	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
 	/* FIXME - should have a delay before continuing */
 
  match_done:	
@@ -1876,16 +1899,13 @@
 
  retry:
 	if (!cfi->numchips) {
-		unsigned long mask = ~(cfi->device_type-1);
-
 		uaddr_idx++;
 
 		if (MTD_UADDR_UNNECESSARY == uaddr_idx)
 			return 0;
 
-		/* Mask out address bits which are smaller than the device type */
-		cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask;
-		cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask;
+		cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
+		cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
 	}
 
 	/* Make certain we aren't probing past the end of map */
@@ -1916,10 +1936,10 @@
 
 	/* Autoselect Mode */
 	if(cfi->addr_unlock1) {
-		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
 	}
-	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
 	/* FIXME - should have a delay before continuing */
 
 	if (!cfi->numchips) {




More information about the linux-mtd mailing list