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