summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2010-05-25 21:55:09 +0000
committerRafaël Carré <rafael.carre@gmail.com>2010-05-25 21:55:09 +0000
commitff9474e558a6108a3c9d42260043016ad11971ef (patch)
treea03b8a7621f33a11d826f9002fef223330803da5 /firmware
parent9112b0b1bb2501d0a038b417e7b41dc0c6bd0d14 (diff)
downloadrockbox-ff9474e558a6108a3c9d42260043016ad11971ef.tar.gz
rockbox-ff9474e558a6108a3c9d42260043016ad11971ef.tar.bz2
rockbox-ff9474e558a6108a3c9d42260043016ad11971ef.zip
as3525v1: relax a bit requirements in the SD driver
- retry failed commands up to 6 times - wait at most 5 seconds for the card to go to TRAN state - wait for the card to be in TRAN state (i.e. not programming) before disabling SD clocks (remove the workaround in sd_enable() ) should fix lockups reported on fuzev1 under heavy internal storage + µSD use (playback + database/pictureflow updating) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26291 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c79
1 files changed, 41 insertions, 38 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c
index fb1ec959e3..1e5acde727 100644
--- a/firmware/target/arm/as3525/sd-as3525.c
+++ b/firmware/target/arm/as3525/sd-as3525.c
@@ -208,48 +208,52 @@ static bool send_cmd(const int drive, const int cmd, const int arg,
{
int status;
- /* Clear old status flags */
- MCI_CLEAR(drive) = 0x7ff;
+ unsigned cmd_retries = 6;
+ while(cmd_retries--)
+ {
+ /* Clear old status flags */
+ MCI_CLEAR(drive) = 0x7ff;
- /* Load command argument or clear if none */
- MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0;
+ /* Load command argument or clear if none */
+ MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0;
- /* Construct MCI_COMMAND & enable CPSM */
- MCI_COMMAND(drive) =
- /*b0:5*/ cmd
- /* b6 */| ((flags & (MCI_RESP|MCI_LONG_RESP)) ? MCI_COMMAND_RESPONSE : 0)
- /* b7 */| ((flags & MCI_LONG_RESP) ? MCI_COMMAND_LONG_RESPONSE : 0)
- /* b8 | MCI_COMMAND_INTERRUPT */
- /* b9 | MCI_COMMAND_PENDING */ /*Only used with stream data transfer*/
- /* b10*/| MCI_COMMAND_ENABLE; /* Enables CPSM */
+ /* Construct MCI_COMMAND & enable CPSM */
+ MCI_COMMAND(drive) =
+ /*b0:5*/ cmd
+ /* b6 */| ((flags & (MCI_RESP|MCI_LONG_RESP)) ? MCI_COMMAND_RESPONSE : 0)
+ /* b7 */| ((flags & MCI_LONG_RESP) ? MCI_COMMAND_LONG_RESPONSE : 0)
+ /* b8 | MCI_COMMAND_INTERRUPT */
+ /* b9 | MCI_COMMAND_PENDING */ /*Only used with stream data transfer*/
+ /* b10*/| MCI_COMMAND_ENABLE; /* Enables CPSM */
- /* Wait while cmd completes then disable CPSM */
- while(MCI_STATUS(drive) & MCI_CMD_ACTIVE);
- MCI_COMMAND(drive) = 0;
+ /* Wait while cmd completes then disable CPSM */
+ while(MCI_STATUS(drive) & MCI_CMD_ACTIVE);
+ MCI_COMMAND(drive) = 0;
- status = MCI_STATUS(drive);
+ status = MCI_STATUS(drive);
- /* Handle command responses */
- if(flags & MCI_RESP) /* CMD expects response */
- {
- response[0] = MCI_RESP0(drive); /* Always prepare short response */
+ /* Handle command responses */
+ if(flags & MCI_RESP) /* CMD expects response */
+ {
+ response[0] = MCI_RESP0(drive); /* Always prepare short response */
- if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */
- return false;
+ if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */
+ continue;
- if(status & MCI_CMD_RESP_END) /* Response passed CRC check */
- {
- if(flags & MCI_LONG_RESP)
- { /* response[0] has already been read */
- response[1] = MCI_RESP1(drive);
- response[2] = MCI_RESP2(drive);
- response[3] = MCI_RESP3(drive);
+ if(status & MCI_CMD_RESP_END) /* Response passed CRC check */
+ {
+ if(flags & MCI_LONG_RESP)
+ { /* response[0] has already been read */
+ response[1] = MCI_RESP1(drive);
+ response[2] = MCI_RESP2(drive);
+ response[3] = MCI_RESP3(drive);
+ }
+ return true;
}
- return true;
}
+ else if(status & MCI_CMD_SENT) /* CMD sent, no response required */
+ return true;
}
- else if(status & MCI_CMD_SENT) /* CMD sent, no response required */
- return true;
return false;
}
@@ -573,7 +577,7 @@ bool sd_present(IF_MD_NONVOID(int drive))
static int sd_wait_for_tran_state(const int drive)
{
unsigned long response = 0;
- unsigned int timeout = current_tick + HZ;
+ unsigned int timeout = current_tick + 5 * HZ;
while (1)
{
@@ -815,7 +819,10 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
transfer_error[drive], drive);
}
- ret = 0; /* success */
+ /* be sure the card has finished programming */
+ ret = sd_wait_for_tran_state(drive);
+ if (ret < 0)
+ ret -= 5*20;
sd_transfer_error:
@@ -912,10 +919,6 @@ void sd_enable(bool on)
}
#endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */
- /* not sure why we have to wait, but without this, test_disk freezes
- * when closing the 300MB file which was just written to */
- udelay(100);
-
sd_enabled = false;
#ifdef HAVE_MULTIDRIVE