|
@@ -132,7 +132,6 @@ static void sdcard_led_off(void)
|
|
|
|
|
|
static int sdcard_send_cmd(uint8_t opcode, uint32_t argument)
|
|
|
{
|
|
|
- uint8_t crc7;
|
|
|
int i;
|
|
|
|
|
|
if (!opcode)
|
|
@@ -140,12 +139,15 @@ static int sdcard_send_cmd(uint8_t opcode, uint32_t argument)
|
|
|
|
|
|
sd_writeb(opcode, SD_GO8|SD_CLEARCRC);
|
|
|
sd_writel(argument, SD_BE|SD_GO32);
|
|
|
- crc7 = sd_crc7_wr();
|
|
|
- sd_writeb(crc7, SD_GO8);
|
|
|
+ /*
|
|
|
+ * GO16 here is to shift in the first byte after into the read
|
|
|
+ * shift register.
|
|
|
+ */
|
|
|
+ sd_writeb(sd_crc7_wr(), SD_GO16);
|
|
|
|
|
|
/* The spec says a reply within 8 cycles, cut it some slack */
|
|
|
for (i = 16; i; i--) {
|
|
|
- int8_t status = sd_readb(0);
|
|
|
+ int8_t status = sd_readb(SD_GO8);
|
|
|
if (status >= 0) /* Bit 7 = 0 for a valid reply */
|
|
|
return status;
|
|
|
}
|
|
@@ -588,7 +590,7 @@ DSTATUS disk_initialize(BYTE drive)
|
|
|
uint16_t status;
|
|
|
uint32_t try_sdhc;
|
|
|
bool is_sd;
|
|
|
- int i, rv;
|
|
|
+ int i, j, rv;
|
|
|
|
|
|
if (drive != 0)
|
|
|
return STA_NOINIT;
|
|
@@ -606,18 +608,31 @@ DSTATUS disk_initialize(BYTE drive)
|
|
|
|
|
|
sdcard_led_on();
|
|
|
|
|
|
- /* Generate 256 clock cycles in slow mode, with CS# high */
|
|
|
- sd_set_mode(SD_SLOW, false);
|
|
|
- for (i = 0; i < 8; i++)
|
|
|
- sd_writel(~0, SD_GO32);
|
|
|
+ /* This doesn't work for MMC, but speeds up debugging */
|
|
|
+#undef SD_SLOW
|
|
|
+#define SD_SLOW SD_20MHZ
|
|
|
|
|
|
- /* Assert CS# and send reset command; if no response assume no disk */
|
|
|
- sd_set_mode(SD_SLOW, true);
|
|
|
- rv = sdcard_send_cmd(CMD_GO_IDLE_STATE, 0);
|
|
|
- if (rv != 0x01) {
|
|
|
- con_printf("sdcard: CMD0 error %02x\n", rv);
|
|
|
- sdcard_led_off();
|
|
|
- return sdc.status = STA_NOINIT | STA_NODISK;
|
|
|
+ /* Allow 4 retries in case the card is in a funky state */
|
|
|
+ i = 4;
|
|
|
+ while (1) {
|
|
|
+ /* Generate 256 clock cycles in slow mode, with CS# high */
|
|
|
+ sd_set_mode(SD_SLOW, false);
|
|
|
+ for (j = 0; j < 8; j++)
|
|
|
+ sd_writel(~0, SD_GO32);
|
|
|
+
|
|
|
+ /* Assert CS# and send reset command */
|
|
|
+ sd_set_mode(SD_SLOW, true);
|
|
|
+ sd_writeb(~0, SD_GO8); /* Dummy byte after CS# assert */
|
|
|
+ rv = sdcard_send_cmd(CMD_GO_IDLE_STATE, 0);
|
|
|
+
|
|
|
+ if (rv == 0x01)
|
|
|
+ break; /* Success! */
|
|
|
+
|
|
|
+ if (!--i) {
|
|
|
+ con_printf("sdcard: CMD0 error %02x\n", rv);
|
|
|
+ sdcard_led_off();
|
|
|
+ return sdc.status = STA_NOINIT | STA_NODISK;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Switch to 20 MHz */
|