diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525.c | 79 |
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, | |||
208 | { | 208 | { |
209 | int status; | 209 | int status; |
210 | 210 | ||
211 | /* Clear old status flags */ | 211 | unsigned cmd_retries = 6; |
212 | MCI_CLEAR(drive) = 0x7ff; | 212 | while(cmd_retries--) |
213 | { | ||
214 | /* Clear old status flags */ | ||
215 | MCI_CLEAR(drive) = 0x7ff; | ||
213 | 216 | ||
214 | /* Load command argument or clear if none */ | 217 | /* Load command argument or clear if none */ |
215 | MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0; | 218 | MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0; |
216 | 219 | ||
217 | /* Construct MCI_COMMAND & enable CPSM */ | 220 | /* Construct MCI_COMMAND & enable CPSM */ |
218 | MCI_COMMAND(drive) = | 221 | MCI_COMMAND(drive) = |
219 | /*b0:5*/ cmd | 222 | /*b0:5*/ cmd |
220 | /* b6 */| ((flags & (MCI_RESP|MCI_LONG_RESP)) ? MCI_COMMAND_RESPONSE : 0) | 223 | /* b6 */| ((flags & (MCI_RESP|MCI_LONG_RESP)) ? MCI_COMMAND_RESPONSE : 0) |
221 | /* b7 */| ((flags & MCI_LONG_RESP) ? MCI_COMMAND_LONG_RESPONSE : 0) | 224 | /* b7 */| ((flags & MCI_LONG_RESP) ? MCI_COMMAND_LONG_RESPONSE : 0) |
222 | /* b8 | MCI_COMMAND_INTERRUPT */ | 225 | /* b8 | MCI_COMMAND_INTERRUPT */ |
223 | /* b9 | MCI_COMMAND_PENDING */ /*Only used with stream data transfer*/ | 226 | /* b9 | MCI_COMMAND_PENDING */ /*Only used with stream data transfer*/ |
224 | /* b10*/| MCI_COMMAND_ENABLE; /* Enables CPSM */ | 227 | /* b10*/| MCI_COMMAND_ENABLE; /* Enables CPSM */ |
225 | 228 | ||
226 | /* Wait while cmd completes then disable CPSM */ | 229 | /* Wait while cmd completes then disable CPSM */ |
227 | while(MCI_STATUS(drive) & MCI_CMD_ACTIVE); | 230 | while(MCI_STATUS(drive) & MCI_CMD_ACTIVE); |
228 | MCI_COMMAND(drive) = 0; | 231 | MCI_COMMAND(drive) = 0; |
229 | 232 | ||
230 | status = MCI_STATUS(drive); | 233 | status = MCI_STATUS(drive); |
231 | 234 | ||
232 | /* Handle command responses */ | 235 | /* Handle command responses */ |
233 | if(flags & MCI_RESP) /* CMD expects response */ | 236 | if(flags & MCI_RESP) /* CMD expects response */ |
234 | { | 237 | { |
235 | response[0] = MCI_RESP0(drive); /* Always prepare short response */ | 238 | response[0] = MCI_RESP0(drive); /* Always prepare short response */ |
236 | 239 | ||
237 | if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */ | 240 | if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */ |
238 | return false; | 241 | continue; |
239 | 242 | ||
240 | if(status & MCI_CMD_RESP_END) /* Response passed CRC check */ | 243 | if(status & MCI_CMD_RESP_END) /* Response passed CRC check */ |
241 | { | 244 | { |
242 | if(flags & MCI_LONG_RESP) | 245 | if(flags & MCI_LONG_RESP) |
243 | { /* response[0] has already been read */ | 246 | { /* response[0] has already been read */ |
244 | response[1] = MCI_RESP1(drive); | 247 | response[1] = MCI_RESP1(drive); |
245 | response[2] = MCI_RESP2(drive); | 248 | response[2] = MCI_RESP2(drive); |
246 | response[3] = MCI_RESP3(drive); | 249 | response[3] = MCI_RESP3(drive); |
250 | } | ||
251 | return true; | ||
247 | } | 252 | } |
248 | return true; | ||
249 | } | 253 | } |
254 | else if(status & MCI_CMD_SENT) /* CMD sent, no response required */ | ||
255 | return true; | ||
250 | } | 256 | } |
251 | else if(status & MCI_CMD_SENT) /* CMD sent, no response required */ | ||
252 | return true; | ||
253 | 257 | ||
254 | return false; | 258 | return false; |
255 | } | 259 | } |
@@ -573,7 +577,7 @@ bool sd_present(IF_MD_NONVOID(int drive)) | |||
573 | static int sd_wait_for_tran_state(const int drive) | 577 | static int sd_wait_for_tran_state(const int drive) |
574 | { | 578 | { |
575 | unsigned long response = 0; | 579 | unsigned long response = 0; |
576 | unsigned int timeout = current_tick + HZ; | 580 | unsigned int timeout = current_tick + 5 * HZ; |
577 | 581 | ||
578 | while (1) | 582 | while (1) |
579 | { | 583 | { |
@@ -815,7 +819,10 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
815 | transfer_error[drive], drive); | 819 | transfer_error[drive], drive); |
816 | } | 820 | } |
817 | 821 | ||
818 | ret = 0; /* success */ | 822 | /* be sure the card has finished programming */ |
823 | ret = sd_wait_for_tran_state(drive); | ||
824 | if (ret < 0) | ||
825 | ret -= 5*20; | ||
819 | 826 | ||
820 | sd_transfer_error: | 827 | sd_transfer_error: |
821 | 828 | ||
@@ -912,10 +919,6 @@ void sd_enable(bool on) | |||
912 | } | 919 | } |
913 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | 920 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ |
914 | 921 | ||
915 | /* not sure why we have to wait, but without this, test_disk freezes | ||
916 | * when closing the 300MB file which was just written to */ | ||
917 | udelay(100); | ||
918 | |||
919 | sd_enabled = false; | 922 | sd_enabled = false; |
920 | 923 | ||
921 | #ifdef HAVE_MULTIDRIVE | 924 | #ifdef HAVE_MULTIDRIVE |