This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Spansion Flash Chips Type N/M


Hi !

I am using Spansion Flash SG29GLXXXM types with Flash V2 branche on redboot 
for a while now. At changing to the N Type (has other sector size 0x20000, M 
has 0x10000) of this flashes, I found some problems with the bit-toggle 
algorithms. Can someone verify if this patch for FLASH V2 branche can go up 
to cvs, or mybe it helps someone with spansion flashes? The code is from the 
spansion homepage.

The biggest problems i found were when 2 Flash Chips with 16 bit bus are on a 
32 bit databus. Maybe someone can test the patch on AM29XXX chips how it 
works?

I tested it here on:
1x SG29GL256N  (16bit on 16 bit bus)
2x SG29GL128M (2x16bit on 32 bit bus)
2x SG29GL128M (2x16bit on 32 bit bus)

thanks regards manfred


 

 

  
Index: ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c
===================================================================
--- ecos.orig/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c	2006-11-06 20:00:26.660773335 +0100
+++ ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c	2006-11-06 20:00:47.856654298 +0100
@@ -100,6 +100,11 @@
 # define AM29_PARALLEL(_cmd_)    (_cmd_)
 #endif
 
+// for spansion bit-toggle code
+#define DQ6_TGL_DQ1_MASK (dq6_toggles >> 5)
+#define DQ6_TGL_DQ3_MASK (dq6_toggles >> 3)
+#define DQ6_TGL_DQ5_MASK (dq6_toggles >> 1)
+
 // ----------------------------------------------------------------------------
 // When performing the various low-level operations like erase the flash
 // chip can no longer support ordinary data reads. Obviously this is a
@@ -216,6 +221,7 @@
 // each sector, so there is no opportunity inside the driver for
 // erasing multiple sectors in a single call. The address argument
 // points at the start of the sector.
+
 static void
 AM29_FNNAME(am29_hw_erase)(volatile AM29_TYPE* addr)
 {
@@ -230,41 +236,34 @@
     // There is now a 50us window in which we could send additional
     // ERASE_SECTOR commands, but the driver API does not allow this
 
-    // All chips are now erasing in parallel. Loop until all have
-    // completed. This can be detected in a number of ways. The DQ7
-    // bit will be 0 until the erase is complete, but there is a
-    // problem if something went wrong (e.g. the sector is locked),
-    // the erase has not actually started, and the relevant bit was 0
-    // already. More useful is DQ6. This will toggle during the 50us
-    // window and while the erase is in progress, then stop toggling.
-    // If the erase does not actually start then the bit won't toggle
-    // at all so the operation completes rather quickly.
-    //
-    // If at any time DQ5 is set (indicating a timeout inside the
-    // chip) then a reset command must be issued and the erase is
-    // aborted. It is not clear this can actually happen during an
-    // erase, but just in case.
     do {
-        AM29_TYPE   datum1, datum2;
+        AM29_TYPE   datum1, datum2, dq6_toggles = 0;
         datum1  = addr[AM29_OFFSET_COMMAND];
         datum2  = addr[AM29_OFFSET_COMMAND];
         if ((datum1 & AM29_STATUS_DQ6) == (datum2 & AM29_STATUS_DQ6)) {
             // The bits have stopped toggling, so finished.
             break;
         }
-        // If DQ6 toggled, then check if DQ5 was set in datum1
-        // (not datum2 as that may indicate a successful 0->1 transition
-        // which can happen for one part of parallel devices before they
-        // all complete the erase)
-        if ((((datum1 ^ datum2) & AM29_STATUS_DQ6) >> 1) & datum1) {
-            // Hardware error. The calling code will always verify
-            // that the erase really was successful, so we don't need
-            // to distinguish
-            addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET;
-            break;
-        }
-    } while (retries-- > 0);
 
+	/* Checking Timeout condition: only check on the device that has DQ6 toggling */
+	if (DQ6_TGL_DQ5_MASK & datum2)
+	{
+    	    /* read again to make sure Timeout Error is correct */
+    	    datum1  = addr[AM29_OFFSET_COMMAND];
+    	    datum2  = addr[AM29_OFFSET_COMMAND];
+
+    	    dq6_toggles = (datum1 ^ datum2) & AM29_STATUS_DQ6;
+
+    	    if ((dq6_toggles && (DQ6_TGL_DQ5_MASK & datum2)) &&
+            !(DQ6_TGL_DQ5_MASK ^ (datum2 & AM29_STATUS_DQ5))) {
+        	// Hardware error. The calling code will always verify
+        	// that the erase really was successful, so we don't need
+        	// to distinguish
+        	addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET;
+        	break;
+	    }
+	}
+    } while (retries-- > 0);
     // The calling code will verify that the erase was successful,
     // and generate an error code.
 }
@@ -281,9 +280,10 @@
     int     i;
     
     for (i = 0; i < count; i++) {
-        AM29_TYPE   datum;
-        AM29_TYPE   current, current2, masked_datum;
-        
+        AM29_TYPE   datum, datum1, datum2;
+    	 AM29_TYPE   dq6_toggles = 0;
+	 AM29_TYPE   current;
+
         // We can only clear bits, not set them, so any bits that were
         // already clear need to be preserved.
         current = addr[i];
@@ -298,36 +298,32 @@
         block_start[AM29_OFFSET_COMMAND]    = AM29_COMMAND_PROGRAM;
         addr[i] = datum;
 
-        // The data is now being written. While the write is in progress
-        // DQ7 will have an inverted value from what was written, so we
-        // can poll, comparing just this bit. Again, if DQ5 is set then
-        // an error has occurred.
-        masked_datum = datum & AM29_STATUS_DQ7;
         retries = CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_TIMEOUT;
-        do {
-            current = addr[i];
-            if ((current & AM29_STATUS_DQ7) == masked_datum) {
-                break;
-            }
-            if (0 != (current & AM29_STATUS_DQ5)) {
-                // It's possible that one device can finish before
-                // another. To deal with this we look at the DQ6
-                // toggle bit, and only consider this to be an error
-                // if it is still toggling for the device that's
-                // reporting DQ5 set. This is similar to the checking
-                // for erase timeouts above. This is unnecessary
-                // before DQ5 gets set, so we don't do the double read
-                // all the time.
-                current2 = addr[i];
-                if ((((current ^ current2) & AM29_STATUS_DQ6) >> 1) & current) {
-                    // A timeout has occurred inside the hardware and
-                    // the system is in a strange state. Reset but don't
-                    // try to write any more of the data.
+	do
+	{
+    	    datum1  = addr[AM29_OFFSET_COMMAND];
+    	    datum2  = addr[AM29_OFFSET_COMMAND];
+    	    if ((datum1 & AM29_STATUS_DQ6) == (datum2 & AM29_STATUS_DQ6)) {
+        	// The bits have stopped toggling, so finished.
+        	break;
+    	    }
+
+	    /* only check on the device that has DQ6 toggling */
+	    if (DQ6_TGL_DQ1_MASK & datum2)
+	    {
+    		/* read again to make sure error is correct */
+    		datum1  = addr[AM29_OFFSET_COMMAND];
+    		datum2  = addr[AM29_OFFSET_COMMAND];
+
+    		dq6_toggles = (datum1 ^ datum2) & AM29_STATUS_DQ6;
+
+    		if ((dq6_toggles && (DQ6_TGL_DQ1_MASK & datum2)) &&
+        	!(DQ6_TGL_DQ1_MASK ^ (datum2 & AM29_STATUS_DQ1))) {
                     block_start[AM29_OFFSET_COMMAND]    = AM29_COMMAND_RESET;
                     return;
-                }
-            }
-        } while (retries-- > 0);
+		}
+	    }
+	} while (retries-- > 0);
 
         if (0 == retries) {
             // Failed to write this word, no point in trying to write the rest.

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]