# HG changeset patch # User bartv # Date 1109173767 0 # Node ID 5783e8dbedf5d7119afe950c5f70b79626a2e359 # Parent bfd6d67dba43a9461b4efefaccdda90a5c5e6611 Fix support for parallel devices giving 32-bit wide access diff --git a/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog b/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog --- 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 + + * 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 * src/am29xxxxx.c, include/am29xxxxx_dev.h: diff --git a/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c b/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c --- 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_; }) diff --git a/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c b/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c --- 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.