changeset 1766:5783e8dbedf5

Fix support for parallel devices giving 32-bit wide access
author bartv
date Wed, 23 Feb 2005 15:49:27 +0000
parents bfd6d67dba43
children 2ca70385b0f4
files packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c
diffstat 3 files changed, 32 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog
+++ b/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog
@@ -1,3 +1,13 @@
+2005-01-19  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/am29xxxxx_aux.c (am29_hw_erase): Handle interleaved
+	(parallel) flash correctly when one device finishes before another.
+	(am29_hw_program): Similar.
+	(cyg_am29xxxxx_program): Use assert correctly.
+	
+	* src/am29xxxxx.c (AM29_NEXT_DATUM_32): Use cyg_uint32, not
+	cyg_uint16.
+	
 2004-12-02  Bart Veer  <bartv@ecoscentric.com>
 
 	* src/am29xxxxx.c, include/am29xxxxx_dev.h: <cyg/io/flash_priv.h>
--- a/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c
+++ b/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c
@@ -168,7 +168,7 @@
 
 # define AM29_NEXT_DATUM_32(_ptr_)                                                      \
     ({                                                                                  \
-        cyg_uint16 _result_;                                                            \
+        cyg_uint32 _result_;                                                            \
         _result_  = (_ptr_[3] << 24) | (_ptr_[2] << 16) | (_ptr_[1] << 8) | _ptr_[0];   \
         _ptr_    += 4;                                                                  \
         _result_; })
@@ -182,7 +182,7 @@
 
 # define AM29_NEXT_DATUM_32(_ptr_)                                                      \
     ({                                                                                  \
-        cyg_uint16 _result_;                                                            \
+        cyg_uint32 _result_;                                                            \
         _result_  = (_ptr_[0] << 24) | (_ptr_[1] << 16) | (_ptr_[2] << 8) | _ptr_[3];   \
         _ptr_    += 4;                                                                  \
         _result_; })
--- a/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c
+++ b/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c
@@ -252,7 +252,14 @@ AM29_FNNAME(am29_hw_erase)(volatile AM29
             // The bits have stopped toggling, so finished.
             break;
         }
-        if (0 != ((datum1 | datum2) & AM29_STATUS_DQ5)) {
+        // 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;
         }
@@ -275,7 +282,7 @@ AM29_FNNAME(am29_hw_program)(volatile AM
     
     for (i = 0; i < count; i++) {
         AM29_TYPE   datum;
-        AM29_TYPE   current, masked_datum;
+        AM29_TYPE   current, current2, masked_datum;
         
         // We can only clear bits, not set them, so any bits that were
         // already clear need to be preserved.
@@ -303,11 +310,16 @@ AM29_FNNAME(am29_hw_program)(volatile AM
                 break;
             }
             if (0 != (current & AM29_STATUS_DQ5)) {
-                current = addr[i];
-                if (current == datum) {
-                    // Race condition, but the operation did succeed.
-                    break;
-                } else {
+                // 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.
@@ -446,7 +458,7 @@ AM29_FNNAME(cyg_am29xxxxx_program)(struc
     int                 i;
 
     CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required");
-    CYG_ASSERT((dest >= dev->start) && (addr <= dev->end), "flash address out of device range");
+    CYG_ASSERT((dest >= dev->start) && (dest <= dev->end), "flash address out of device range");
 
     // Only support writes that are aligned to the bus boundary. This
     // may be more restrictive than what the hardware is capable of.