diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2015-07-30 10:56:00 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2015-08-04 09:53:13 -0400 |
commit | 43312af36f526c060f2faaba19698f5ae46eb32b (patch) | |
tree | 5307ba1998a7219b97e6da01232584fdd6579db0 /src/hw/sdcard.c | |
parent | 9637a6718c1035dcd487db9d3ee58c8aaa28f3c6 (diff) | |
download | seabios-43312af36f526c060f2faaba19698f5ae46eb32b.tar.gz |
sdcard: Improve SD card initialization command sequence
Send the initialization commands that are specified for SD cards by
the "SD Host Controller Simplified Specification Version 2.00" spec.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/hw/sdcard.c')
-rw-r--r-- | src/hw/sdcard.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index 30b0e365..7f344602 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -56,9 +56,11 @@ struct sdhci_s { } PACKED; // SDHCI commands +#define SC_GO_IDLE_STATE ((0<<8) | 0x20) #define SC_ALL_SEND_CID ((2<<8) | 0x21) #define SC_SEND_RELATIVE_ADDR ((3<<8) | 0x22) #define SC_SELECT_DESELECT_CARD ((7<<8) | 0x23) +#define SC_SEND_IF_COND ((8<<8) | 0x22) #define SC_READ_SINGLE ((17<<8) | 0x22) #define SC_READ_MULTIPLE ((18<<8) | 0x22) #define SC_WRITE_SINGLE ((24<<8) | 0x22) @@ -99,9 +101,11 @@ struct sdhci_s { #define SPC_V33 0x0e // SDHCI result flags -#define SR_OCR_CCS (1<<30) +#define SR_OCR_CCS (1<<30) +#define SR_OCR_NOTBUSY (1<<31) // SDHCI timeouts +#define SDHCI_POWERUP_TIMEOUT 1000 #define SDHCI_PIO_TIMEOUT 1000 // XXX - these are just made up #define SDHCI_TRANSFER_TIMEOUT 10000 @@ -151,6 +155,8 @@ sdcard_pio(struct sdhci_s *regs, int cmd, u32 *param) writew(®s->irq_status, SI_CMD_COMPLETE); // Read response memcpy(param, regs->response, sizeof(regs->response)); + dprintf(9, "sdcard cmd %x response %x %x %x %x\n" + , cmd, param[0], param[1], param[2], param[3]); return 0; } @@ -249,16 +255,46 @@ static int sdcard_card_setup(struct sdhci_s *regs) { // XXX - works on QEMU; probably wont on real hardware! - u32 param[4] = { 0x01 }; - int ret = sdcard_pio_app(regs, SC_APP_SEND_OP_COND, param); + + // Reset card + u32 param[4] = { }; + int ret = sdcard_pio_app(regs, SC_GO_IDLE_STATE, param); + if (ret) + return ret; + // Let card know SDHC/SDXC is supported and confirm voltage + param[0] = 0x1aa; + ret = sdcard_pio_app(regs, SC_SEND_IF_COND, param); + if (ret) + return ret; + u32 hcs = 0; + if (param[0] == 0x1aa) + hcs = 0x40000000; + // Verify SD card (instead of MMC or SDIO) + param[0] = 0x00; + ret = sdcard_pio_app(regs, SC_APP_SEND_OP_COND, param); if (ret) return ret; + // Init card + u32 end = timer_calc(SDHCI_POWERUP_TIMEOUT); + for (;;) { + param[0] = hcs | (1<<20); // SDHC support and voltage level + ret = sdcard_pio_app(regs, SC_APP_SEND_OP_COND, param); + if (ret) + return ret; + if (param[0] & SR_OCR_NOTBUSY) + break; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + } int card_type = (param[0] & SR_OCR_CCS) ? SF_SDHC : SF_SDSC; param[0] = 0x00; + // Select card ret = sdcard_pio(regs, SC_ALL_SEND_CID, param); if (ret) return ret; - param[0] = 0x01 << 16; + param[0] = 0x00; ret = sdcard_pio(regs, SC_SEND_RELATIVE_ADDR, param); if (ret) return ret; |