|
@@ -37,7 +37,7 @@
|
|
|
|
|
|
/* Command codes, including the leading 01 sequence */
|
|
|
enum sdcard_cmd {
|
|
|
- CMD_GO_IDLE_STATE = 0x40, /* a.k.a. reset */
|
|
|
+ CMD_GO_IDLE_STATE = 0x40, /* a.k.a. reset */
|
|
|
CMD_SEND_OP_COND = 0x41,
|
|
|
CMD_SWITCH_FUNC = 0x46,
|
|
|
CMD_SEND_IF_COND = 0x48,
|
|
@@ -136,7 +136,7 @@ static int sdcard_send_cmd(uint8_t opcode, uint32_t argument)
|
|
|
|
|
|
if (!opcode)
|
|
|
return 0; /* No command */
|
|
|
-
|
|
|
+
|
|
|
sd_writeb(opcode, SD_GO8|SD_CLEARCRC);
|
|
|
sd_writel(argument, SD_BE|SD_GO32);
|
|
|
/*
|
|
@@ -195,7 +195,7 @@ static int sdcard_read_block(void *buf, int len, int timeout,
|
|
|
int i;
|
|
|
|
|
|
p.b = buf;
|
|
|
-
|
|
|
+
|
|
|
for (;;) {
|
|
|
tok = sd_readb(SD_GO8|SD_CLEARCRC);
|
|
|
if (tok == 0xfe)
|
|
@@ -215,7 +215,7 @@ static int sdcard_read_block(void *buf, int len, int timeout,
|
|
|
* the input shift register. After dealing with alignment,
|
|
|
* use dummy reads to shift in the rest of the first longword.
|
|
|
*/
|
|
|
-
|
|
|
+
|
|
|
/* Shift in bytes if needed for alignment */
|
|
|
if (p.a & 1) {
|
|
|
*p.b++ = sd_readb(SD_GO8);
|
|
@@ -426,7 +426,7 @@ int sdcard_write_sectors(const void *buf, uint32_t lba, int count)
|
|
|
sd_writel(*p.l++, SD_GO32);
|
|
|
|
|
|
podd = -podd;
|
|
|
-
|
|
|
+
|
|
|
if (podd & 2)
|
|
|
sd_writeh(*p.w++, SD_GO16);
|
|
|
if (podd & 1)
|
|
@@ -561,22 +561,36 @@ static const char *sdcard_type_name(uint8_t type)
|
|
|
static void sdcard_try_high_speed(void)
|
|
|
{
|
|
|
int rv;
|
|
|
- uint8_t swdata[64]; /* Response from CMD6 */
|
|
|
|
|
|
if (!(sdc.csd.raw[1] & (1 << 30)))
|
|
|
return; /* Cmd group 10 = CMD6 not supported */
|
|
|
|
|
|
/* Try to switch to high speed mode */
|
|
|
rv = sdcard_send_cmd(CMD_SWITCH_FUNC, 0x80fffff1);
|
|
|
- if (rv)
|
|
|
+ if (rv) {
|
|
|
+ con_printf("sdcard: CMD6 returned %02x\n", rv);
|
|
|
return;
|
|
|
+ }
|
|
|
|
|
|
- rv = sdcard_read_block(swdata, sizeof swdata, 2000, 0, 0);
|
|
|
- if (rv)
|
|
|
- return;
|
|
|
+ if (0) {
|
|
|
+ /*
|
|
|
+ * Despite the spec, this doesn't seem to actually happen
|
|
|
+ * in SPI mode?
|
|
|
+ */
|
|
|
+ uint8_t swdata[64]; /* Response from CMD6 */
|
|
|
|
|
|
- if ((swdata[47] & 0x0f) != 1)
|
|
|
- return; /* Failed to switch to high speed mode */
|
|
|
+ rv = sdcard_read_block(swdata, sizeof swdata, 2000, 0, 0);
|
|
|
+ if (rv) {
|
|
|
+ con_printf("sdcard: CMD6 failed to return data\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((swdata[47] & 0x0f) != 1) {
|
|
|
+ con_printf("sdcard: CMD6 reported %X for high speed request\n",
|
|
|
+ swdata[47] & 0x0f);
|
|
|
+ return; /* Failed to switch to high speed mode */
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Success, now switch mode! */
|
|
|
sd_readl(SD_GO32); /* Issue at least 8 clocks; go for 32 */
|
|
@@ -689,7 +703,7 @@ DSTATUS disk_initialize(BYTE drive)
|
|
|
if (!rv) {
|
|
|
/* ACMD41 successful; this is an SD card: can switch to 25 MHz */
|
|
|
is_sd = true;
|
|
|
-
|
|
|
+
|
|
|
sd_set_mode(SD_25MHZ, true);
|
|
|
rv = sdcard_send_cmd(CMD_READ_OCR, try_sdhc);
|
|
|
if (rv) {
|
|
@@ -704,7 +718,7 @@ DSTATUS disk_initialize(BYTE drive)
|
|
|
} else {
|
|
|
/* ACMD41 unsupported, try CMD1 */
|
|
|
is_sd = false;
|
|
|
-
|
|
|
+
|
|
|
do {
|
|
|
rv = sdcard_send_cmd(CMD_SEND_OP_COND, 0);
|
|
|
if (rv & ~0x01) {
|
|
@@ -752,7 +766,7 @@ DSTATUS disk_initialize(BYTE drive)
|
|
|
*/
|
|
|
if (is_sd)
|
|
|
sdcard_try_high_speed();
|
|
|
-
|
|
|
+
|
|
|
sdc.status = 0;
|
|
|
|
|
|
sdcard_led_off();
|
|
@@ -773,4 +787,3 @@ int disk_init(void)
|
|
|
{
|
|
|
return f_mount(&sd_fs, "", 1);
|
|
|
}
|
|
|
-
|