mtd/drivers/mtd/chips cfi_cmdset_0002.c,1.97,1.98

dvrabel at infradead.org dvrabel at infradead.org
Wed Apr 14 07:15:39 EDT 2004


Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv10260/drivers/mtd/chips

Modified Files:
	cfi_cmdset_0002.c 
Log Message:
Fix status checking of interleaved chips.

This is done by removing chip_status() (which was broken for interleaved chips)
and replacing it with the much simpler chip_ready().  This also removed
checking of the DQ5 error toggle bit -- errors are left to the software timeout to handle.


Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.97
retrieving revision 1.98
diff -u -r1.97 -r1.98
--- cfi_cmdset_0002.c	24 Feb 2004 13:50:21 -0000	1.97
+++ cfi_cmdset_0002.c	14 Apr 2004 11:15:36 -0000	1.98
@@ -38,14 +38,6 @@
 #define AMD_BOOTLOC_BUG
 #define FORCE_WORD_WRITE 0
 
-/* The status (from the various toggle/status bits) of a chip as returned by
- * chip_status(..). */
-#define CHIP_READY	0
-#define CHIP_BUSY	1
-#define CHIP_TIMEDOUT	2
-#define CHIP_ERASE_SUSP 3
-#define CHIP_ERROR	4
-
 
 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
@@ -392,63 +384,25 @@
 	return NULL;
 }
 
-
 /*
- * Get the status of the chip using the various toggle bits.
- *
- * Conditions checked for are:
- *  CHIP_READY:	     no bits are toggling -- Read or Erase-Suspend-Read (in non erasing sector) mode.
- *  CHIP_ERASE_SUSP: only DQ2 is toggling -- Erase-Suspend-Read (in erasing sector) mode.
- *  CHIP_BUSY:	     DQ6 toggling and DQ5 == 0 -- programming or erasing.
- *  CHIP_TIMEDOUT:   DQ6 toggling and DQ5 == 1 -- program or erase timed out.
- *  CHIP_ERROR:	     Any other condition (shouldn't happen).
+ * Return true if the chip is ready.
  *
- * For interleaved chips we return:
- *   CHIP_READY if all chips are in Read or Erase-Suspend-Read (non-erasing sector).
- *   CHIP_ERASE_SUSP if all chips are in Erase-Suspend-Read (any sector) or Read.
- *   CHIP_BUSY if any chip is busy and no DQ5 bits are set.
- *   CHIP_TIMEDOUT if any chip is busy and has its DQ5 bit set.
+ * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
+ * non-suspended sector) and is indicated by no toggle bits toggling.
  *
- * The retries when checking DQ5 are required due to the asynchronous nature
- * of the internal state machine.  Refer to the chip datasheets for details.
- *
- * The other retries are because it is possible for bits to appear to toggle
- * when in fact what's happened is that the chip has switched from providing
- * status to providing data.
+ * Note that anything more complicated than checking if no bits are toggling
+ * (including checking DQ5 for an error status) is tricky to get working
+ * correctly and is therefore not done	(particulary with interleaved chips
+ * as each chip must be checked independantly of the others).
  */
-static int chip_status(struct map_info *map, unsigned long addr)
+static int chip_ready(struct map_info *map, unsigned long addr)
 {
-	struct cfi_private *cfi = map->fldrv_priv;
-	cfi_word dq6 = CMD(1<<6);
-	cfi_word dq5 = CMD(1<<5);
-	cfi_word dq2 = CMD(1<<2);
-
-	cfi_word d, t;
-	int retry = 1;
-
-	do {
-		d = cfi_read(map, addr);
-		t = d ^ cfi_read(map, addr);
-	
-		if (t == 0)		       /* no toggles -- Read or Erase-Suspend-Read mode */
-			return CHIP_READY;
-		if (!(t & ~dq2) && (t & dq2)) { /* only DQ2 toggling -- this sector is erase suspended */
-			if (retry)
-				continue;      /* program/erase may just have finished */
-			return CHIP_ERASE_SUSP;
-		}
-		if (t & dq6) {		       /* programming or erasing */
-			if (d & dq5) {	       /* internal timeout */
-				if (retry)
-					continue;
-				return CHIP_TIMEDOUT;
-			}
-			return CHIP_BUSY;
-		}
-		/* some other bits toggled -- probably a program/erase just finished */
-	} while(retry--);
-	
-	return CHIP_ERROR;
+    cfi_word d, t;
+
+    d = cfi_read(map, addr);
+    t = d ^ cfi_read(map, addr);
+
+    return t == 0;
 }
 
 static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
@@ -465,7 +419,7 @@
 
 	case FL_STATUS:
 		for (;;) {
-			if (chip_status(map, adr) == CHIP_READY)
+			if (chip_ready(map, adr))
 				break;
 
 			if (time_after(jiffies, timeo)) {
@@ -506,7 +460,7 @@
 		chip->state = FL_ERASE_SUSPENDING;
 		chip->erase_suspended = 1;
 		for (;;) {
-			if (chip_status(map, adr) == CHIP_READY)
+			if (chip_ready(map, adr))
 				break;
 
 			if (time_after(jiffies, timeo)) {
@@ -758,8 +712,6 @@
 	 */
 	unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
 	int ret = 0;
-	int ta = 0;
-	int status;
 
 	adr += chip->start;
 
@@ -786,17 +738,17 @@
 	}
 
 	ENABLE_VPP(map);
-        /*
-         * The CFI_DEVICETYPE_X8 argument is needed even when
-         * cfi->device_type != CFI_DEVICETYPE_X8.  The addresses for
-         * command sequences don't scale even when the device is
-         * wider.  This is the case for many of the cfi_send_gen_cmd()
-         * below.  I'm not sure, however, why some use
-         * cfi->device_type.
-         */
-        cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
-        cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
-        cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
+	/*
+	 * The CFI_DEVICETYPE_X8 argument is needed even when
+	 * cfi->device_type != CFI_DEVICETYPE_X8.  The addresses for
+	 * command sequences don't scale even when the device is
+	 * wider.  This is the case for many of the cfi_send_gen_cmd()
+	 * below.  I'm not sure, however, why some use
+	 * cfi->device_type.
+	 */
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
+	cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
 	cfi_write(map, datum, adr);
 	chip->state = FL_WRITING;
 
@@ -821,7 +773,10 @@
 			continue;
 		}
 
-		if ((status = chip_status(map, adr)) != CHIP_BUSY)
+		if (chip_ready(map, adr))
+			goto op_done;
+
+		if (time_after(jiffies, timeo))
 			break;
 
 		/* Latency issues. Drop the lock, wait a while and retry */
@@ -830,18 +785,8 @@
 		cfi_spin_lock(chip->mutex);
 	}
 
-	if (status == CHIP_READY)
-		goto op_done;
-
-	if (status == CHIP_TIMEDOUT)
-		printk(KERN_WARNING "MTD %s(): flash internal timeout\n",
-		       __func__);
-	else if (ta)
-		printk(KERN_WARNING "MTD %s(): software timeout\n",
-		       __func__ );
-	else
-		printk(KERN_WARNING "MTD %s(): unexpected failure.  status = %d\n",
-			__func__, status);
+	printk(KERN_WARNING "MTD %s(): software timeout\n",
+	       __func__ );
 
  op_failed:
 	/* reset on all failures. */
@@ -1055,11 +1000,9 @@
 	/* see comments in do_write_oneword() regarding uWriteTimeo. */
 	static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
 	int ret = -EIO;
-	int ta = 0;
 	unsigned long cmd_adr;
 	int z, bytes, words;
 	cfi_word datum;
-	int status;
 
 	adr += chip->start;
 	cmd_adr = adr;
@@ -1185,10 +1128,11 @@
 			continue;
 		}
 
-		if( (status = chip_status(map, adr)) != CHIP_BUSY
-		    || ( ta = time_after(jiffies, timeo)) ) {
+		if (chip_ready(map, adr))
+			goto op_done;
+		    
+		if( time_after(jiffies, timeo))
 			break;
-		}
 
 		/* Latency issues. Drop the lock, wait a while and retry */
 		cfi_spin_unlock(chip->mutex);
@@ -1196,20 +1140,8 @@
 		cfi_spin_lock(chip->mutex);
 	}
 
-
-	if (status == CHIP_READY)
-		goto op_done;
-
-	if (status == CHIP_TIMEDOUT) {
-		printk(KERN_WARNING "MTD %s(): flash internal timeout\n",
-		       __func__);
-	}
-	else if (ta)
-		printk(KERN_WARNING "MTD %s(): software timeout\n",
-		       __func__ );
-	else
-		printk(KERN_WARNING "MTD %s(): unexpected failure.  status = %d\n",
-			__func__, status);
+	printk(KERN_WARNING "MTD %s(): software timeout\n",
+	       __func__ );
 
  op_failed:
 	/* reset on all failures. */
@@ -1304,8 +1236,6 @@
 	unsigned long int adr;
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
-	int ta = 0;
-	int status;
 
 	adr = cfi->addr_unlock1;
 
@@ -1356,10 +1286,12 @@
 			chip->erase_suspended = 0;
 		}
 
-		if ((status = chip_status(map, adr)) != CHIP_BUSY
-		    || ( ta = time_after(jiffies, timeo)) )
+		if (chip_ready(map, adr))
+			goto op_done;
+
+		if (time_after(jiffies, timeo))
 			break;
-		
+
 		/* Latency issues. Drop the lock, wait a while and retry */
 		cfi_spin_unlock(chip->mutex);
 		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1367,18 +1299,8 @@
 		cfi_spin_lock(chip->mutex);
 	}
 
-	if (status == CHIP_READY)
-		goto op_done;
-
-	if (status == CHIP_TIMEDOUT)
-		printk(KERN_WARNING "MTD %s(): flash internal timeout\n",
-		       __func__);
-	else if (ta)
-		printk(KERN_WARNING "MTD %s(): software timeout\n",
-		       __func__ );
-	else
-		printk(KERN_WARNING "MTD %s(): unexpected failure.  status = %d\n",
-		       __func__, status);
+	printk(KERN_WARNING "MTD %s(): software timeout\n",
+	       __func__ );
 
  op_failed:
 	/* reset on all failures. */
@@ -1494,8 +1416,6 @@
 	unsigned long timeo = jiffies + HZ;
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
-	int ta = 0;
-	int status;
 
 	adr += chip->start;
 
@@ -1546,30 +1466,22 @@
 			chip->erase_suspended = 0;
 		}
 
-		if ((status = chip_status(map, adr)) != CHIP_BUSY
-		    || ( ta = time_after(jiffies, timeo)) )
+		if (chip_ready(map, adr))
+			goto op_done;
+
+		if (time_after(jiffies, timeo))
 			break;
-		
+
 		/* Latency issues. Drop the lock, wait a while and retry */
 		cfi_spin_unlock(chip->mutex);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(1);
 		cfi_spin_lock(chip->mutex);
 	}
-
-	if (status == CHIP_READY)
-		goto op_done;
-
-	if (status == CHIP_TIMEDOUT)
-		printk(KERN_WARNING "MTD %s(): flash internal timeout\n",
-		       __func__);
-	else if (ta)
-		printk(KERN_WARNING "MTD %s(): software timeout\n",
-		       __func__ );
-	else
-		printk(KERN_WARNING "MTD %s(): unexpected failure.  status = %d\n",
-		       __func__, status);
-
+	
+	printk(KERN_WARNING "MTD %s(): software timeout\n",
+	       __func__ );
+	
  op_failed:
 	/* reset on all failures. */
 	cfi_write( map, CMD(0xF0), chip->start );




More information about the linux-mtd-cvs mailing list