mtd/drivers/mtd/chips cfi_cmdset_0002.c,1.55,1.56
fgiasson at infradead.org
fgiasson at infradead.org
Mon Jul 15 11:13:28 EDT 2002
Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv16436/mtd/drivers/mtd/chips
Modified Files:
cfi_cmdset_0002.c
Log Message:
Modified the way polling is made after an erase or write command is issued
to the flash in functions do_write_oneword() and do_erase_oneblock().
In the past, do_write_oneword() was reading back written value until
a timeout expired. Now, it polls toggle bits as specified in AMD
specs.
Frederic Giasson on July 15th, 2002.
Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- cfi_cmdset_0002.c 18 May 2002 07:42:03 -0000 1.55
+++ cfi_cmdset_0002.c 15 Jul 2002 15:13:25 -0000 1.56
@@ -340,7 +340,8 @@
static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast)
{
unsigned long timeo = jiffies + HZ;
- unsigned int Last[4];
+ unsigned int oldstatus, status;
+ unsigned int dq6, dq5;
unsigned long Count = 0;
struct cfi_private *cfi = map->fldrv_priv;
DECLARE_WAITQUEUE(wait, current);
@@ -389,28 +390,59 @@
cfi_udelay(chip->word_write_time);
cfi_spin_lock(chip->mutex);
- Last[0] = cfi_read(map, adr);
- // printk("Last[0] is %x\n", Last[0]);
- Last[1] = cfi_read(map, adr);
- // printk("Last[1] is %x\n", Last[1]);
- Last[2] = cfi_read(map, adr);
- // printk("Last[2] is %x\n", Last[2]);
- for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
- cfi_spin_unlock(chip->mutex);
- cfi_udelay(10);
- cfi_spin_lock(chip->mutex);
-
- Last[Count % 4] = cfi_read(map, adr);
- // printk("Last[%d%%4] is %x\n", Count, Last[Count%4]);
- }
-
- if (Last[(Count - 1) % 4] != datum){
- printk(KERN_WARNING "Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum);
- cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL);
+ /* Polling toggle bits instead of reading back many times
+ This ensures that write operation is really completed,
+ or tells us why it failed. */
+ dq6 = CMD(1<<6);
+ dq5 = CMD(1<<5);
+ timeo = jiffies + ( HZ / 1000 ); /* setting timeout to 1ms for now */
+
+ oldstatus = cfi_read(map, adr);
+ status = cfi_read(map, adr);
+ while(
+ ( (status & dq6) != (oldstatus & dq6) ) &&
+ ( (status & dq5) != dq5 ) &&
+ !time_after( jiffies, timeo )
+ )
+ {
+ oldstatus = cfi_read( map, adr );
+ status = cfi_read( map, adr );
+ udelay(1);
+ }
+
+ if( (status & dq6) != (oldstatus & dq6) )
+ {
+ /* The erasing didn't stop?? */
+ if( ( status & dq5 ) == dq5 )
+ {
+ /* When DQ5 raises, we must check once again if DQ6 is toggling.
+ If not, the erase has been completed OK. If not, reset chip. */
+ oldstatus = cfi_read( map, adr );
+ status = cfi_read( map, adr );
+
+ if( ( oldstatus & 0x00FF ) == ( status & 0x00FF ) )
+ {
+ printk( "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" );
+ }
+ else
+ {
+ /* DQ5 is active so we can do a reset and stop the erase */
+ cfi_write( map, CMD(0xF0), chip->start );
+ printk( "Internal flash device timeout occured or write operation was performed while flash was programming.\n" );
+ }
+ }
+ else
+ {
+ printk( "Waiting for write to complete timed out in do_write_oneword.");
+
+ chip->state = FL_READY;
+ wake_up(&chip->wq);
+ cfi_spin_unlock(chip->mutex);
DISABLE_VPP(map);
ret = -EIO;
- }
+ }
+ }
DISABLE_VPP(map);
chip->state = FL_READY;
wake_up(&chip->wq);
@@ -793,19 +825,39 @@
oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
}
- if ((status & dq6) != (oldstatus & dq6)) {
+ if( (status & dq6) != (oldstatus & dq6) )
+ {
/* The erasing didn't stop?? */
- if ((status & dq5) == dq5) {
- /* dq5 is active so we can do a reset and stop the erase */
- cfi_write(map, CMD(0xF0), chip->start);
+ if( ( status & dq5 ) == dq5 )
+ {
+ /* When DQ5 raises, we must check once again if DQ6 is toggling.
+ If not, the erase has been completed OK. If not, reset chip. */
+ oldstatus = cfi_read( map, adr );
+ status = cfi_read( map, adr );
+
+ if( ( oldstatus & 0x00FF ) == ( status & 0x00FF ) )
+ {
+ printk( "Warning: DQ5 raised while erase operation was in progress, but erase completed OK\n" );
+ }
+ else
+ {
+ /* DQ5 is active so we can do a reset and stop the erase */
+ cfi_write(map, CMD(0xF0), chip->start);
+ printk( KERN_WARNING "Internal flash device timeout occured or write operation was performed while flash was erasing\n" );
+ }
}
+ else
+ {
+ printk( "Waiting for erase to complete timed out in do_erase_oneblock.");
+
chip->state = FL_READY;
wake_up(&chip->wq);
cfi_spin_unlock(chip->mutex);
- printk("waiting for erase to complete timed out.");
DISABLE_VPP(map);
return -EIO;
}
+ }
+
DISABLE_VPP(map);
chip->state = FL_READY;
wake_up(&chip->wq);
@@ -1040,7 +1092,6 @@
int i;
struct flchip *chip;
int ret = 0;
-//printk("suspend\n");
for (i=0; !ret && i<cfi->numchips; i++) {
chip = &cfi->chips[i];
@@ -1093,7 +1144,6 @@
struct cfi_private *cfi = map->fldrv_priv;
int i;
struct flchip *chip;
-//printk("resume\n");
for (i=0; i<cfi->numchips; i++) {
@@ -1140,3 +1190,4 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Crossnet Co. <info at crossnet.co.jp> et al.");
MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");
+
More information about the linux-mtd-cvs
mailing list