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