summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/sd-as3525.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525.c')
-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,
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))
573static int sd_wait_for_tran_state(const int drive) 577static 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
820sd_transfer_error: 827sd_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