diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index 40392b35b2..9bfb2a9412 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include "ata_idle_notify.h" | 45 | #include "ata_idle_notify.h" |
46 | #include "sd.h" | 46 | #include "sd.h" |
47 | #include "usb.h" | 47 | #include "usb.h" |
48 | /*#define LOGF_ENABLE*/ | ||
49 | #include "logf.h" | ||
48 | 50 | ||
49 | #ifdef HAVE_HOTSWAP | 51 | #ifdef HAVE_HOTSWAP |
50 | #include "disk.h" | 52 | #include "disk.h" |
@@ -56,6 +58,8 @@ | |||
56 | #define MCI_NO_RESP (0<<0) | 58 | #define MCI_NO_RESP (0<<0) |
57 | #define MCI_RESP (1<<0) | 59 | #define MCI_RESP (1<<0) |
58 | #define MCI_LONG_RESP (1<<1) | 60 | #define MCI_LONG_RESP (1<<1) |
61 | #define MCI_ACMD (1<<2) | ||
62 | #define MCI_NOCRC (1<<3) | ||
59 | 63 | ||
60 | /* ARM PL180 registers */ | 64 | /* ARM PL180 registers */ |
61 | #define MCI_POWER(i) (*(volatile unsigned char *) (pl180_base[i]+0x00)) | 65 | #define MCI_POWER(i) (*(volatile unsigned char *) (pl180_base[i]+0x00)) |
@@ -210,6 +214,10 @@ static bool send_cmd(const int drive, const int cmd, const int arg, | |||
210 | unsigned cmd_retries = 6; | 214 | unsigned cmd_retries = 6; |
211 | while(cmd_retries--) | 215 | while(cmd_retries--) |
212 | { | 216 | { |
217 | if ((flags & MCI_ACMD) && /* send SD_APP_CMD before each try */ | ||
218 | !send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_RESP, response)) | ||
219 | return false; | ||
220 | |||
213 | /* Clear old status flags */ | 221 | /* Clear old status flags */ |
214 | MCI_CLEAR(drive) = 0x7ff; | 222 | MCI_CLEAR(drive) = 0x7ff; |
215 | 223 | ||
@@ -236,8 +244,21 @@ static bool send_cmd(const int drive, const int cmd, const int arg, | |||
236 | { | 244 | { |
237 | response[0] = MCI_RESP0(drive); /* Always prepare short response */ | 245 | response[0] = MCI_RESP0(drive); /* Always prepare short response */ |
238 | 246 | ||
239 | if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */ | 247 | if(status & MCI_RESPONSE_ERROR) {/* timeout or crc failure */ |
248 | if ((status & MCI_CMD_CRC_FAIL) && | ||
249 | (flags & MCI_NOCRC)) | ||
250 | break; | ||
251 | logf("sd cmd error: drive %d cmd %d arg %08x sd_status %08x resp0 %08lx", | ||
252 | drive, cmd, arg, status, response[0]); | ||
240 | continue; | 253 | continue; |
254 | } | ||
255 | |||
256 | if((flags & MCI_RESP) && | ||
257 | !(flags & MCI_LONG_RESP) && | ||
258 | (response[0] & SD_R1_CARD_ERROR)) { | ||
259 | logf("sd card error: drive %d cmd %d arg %08x r1 %08lx", | ||
260 | drive, cmd, arg, response[0]); | ||
261 | } | ||
241 | 262 | ||
242 | if(status & MCI_CMD_RESP_END) /* Response passed CRC check */ | 263 | if(status & MCI_CMD_RESP_END) /* Response passed CRC check */ |
243 | { | 264 | { |
@@ -268,6 +289,8 @@ static int sd_init_card(const int drive) | |||
268 | long init_timeout; | 289 | long init_timeout; |
269 | bool sd_v2 = false; | 290 | bool sd_v2 = false; |
270 | 291 | ||
292 | card_info[drive].rca = 0; | ||
293 | |||
271 | /* MCLCK on and set to 400kHz ident frequency */ | 294 | /* MCLCK on and set to 400kHz ident frequency */ |
272 | MCI_CLOCK(drive) = MCI_IDENTSPEED; | 295 | MCI_CLOCK(drive) = MCI_IDENTSPEED; |
273 | 296 | ||
@@ -293,12 +316,9 @@ static int sd_init_card(const int drive) | |||
293 | if(TIME_AFTER(current_tick, init_timeout)) | 316 | if(TIME_AFTER(current_tick, init_timeout)) |
294 | return -2; | 317 | return -2; |
295 | 318 | ||
296 | /* app_cmd */ | ||
297 | send_cmd(drive, SD_APP_CMD, 0, MCI_RESP, &response); | ||
298 | |||
299 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ | 319 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ |
300 | send_cmd(drive, SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), | 320 | send_cmd(drive, SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), |
301 | MCI_RESP, &card_info[drive].ocr); | 321 | MCI_ACMD|MCI_NOCRC|MCI_RESP, &card_info[drive].ocr); |
302 | 322 | ||
303 | } while(!(card_info[drive].ocr & (1<<31))); | 323 | } while(!(card_info[drive].ocr & (1<<31))); |
304 | 324 | ||
@@ -365,17 +385,11 @@ static int sd_init_card(const int drive) | |||
365 | /* Switch to to 4 bit widebus mode */ | 385 | /* Switch to to 4 bit widebus mode */ |
366 | if(sd_wait_for_tran_state(drive) < 0) | 386 | if(sd_wait_for_tran_state(drive) < 0) |
367 | return -11; | 387 | return -11; |
368 | /* CMD55 */ /* Response is requested due to timing issue */ | ||
369 | if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_RESP, &response)) | ||
370 | return -14; | ||
371 | /* ACMD42 */ | 388 | /* ACMD42 */ |
372 | if(!send_cmd(drive, SD_SET_CLR_CARD_DETECT, 0, MCI_RESP, &response)) | 389 | if(!send_cmd(drive, SD_SET_CLR_CARD_DETECT, 0, MCI_ACMD|MCI_RESP, &response)) |
373 | return -15; | 390 | return -15; |
374 | /* CMD55 */ /* Response is requested due to timing issue */ | ||
375 | if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_RESP, &response)) | ||
376 | return -12; | ||
377 | /* ACMD6 */ | 391 | /* ACMD6 */ |
378 | if(!send_cmd(drive, SD_SET_BUS_WIDTH, 2, MCI_RESP, &response)) | 392 | if(!send_cmd(drive, SD_SET_BUS_WIDTH, 2, MCI_ACMD|MCI_RESP, &response)) |
379 | return -13; | 393 | return -13; |
380 | /* Now that card is widebus make controller aware */ | 394 | /* Now that card is widebus make controller aware */ |
381 | MCI_CLOCK(drive) |= MCI_CLOCK_WIDEBUS; | 395 | MCI_CLOCK(drive) |= MCI_CLOCK_WIDEBUS; |