Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/sdcard.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index 053f8de..45f19a7 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -264,7 +264,7 @@ sdcard_process_op(struct disk_op_s *op)
// Initialize an SD card static int -sdcard_card_setup(struct sdhci_s *regs) +sdcard_card_setup(struct sdhci_s *regs, int volt) { // XXX - works on QEMU; probably wont on real hardware!
@@ -274,12 +274,13 @@ sdcard_card_setup(struct sdhci_s *regs) if (ret) return ret; // Let card know SDHC/SDXC is supported and confirm voltage - param[0] = 0x1aa; + u32 vrange = (volt >= (1<<15) ? 0x100 : 0x200) | 0xaa; + param[0] = vrange; ret = sdcard_pio(regs, SC_SEND_IF_COND, param); if (ret) return ret; u32 hcs = 0; - if (param[0] == 0x1aa) + if (param[0] == vrange) hcs = 0x40000000; // Verify SD card (instead of MMC or SDIO) param[0] = 0x00; @@ -289,7 +290,7 @@ sdcard_card_setup(struct sdhci_s *regs) // Init card u32 end = timer_calc(SDHCI_POWERUP_TIMEOUT); for (;;) { - param[0] = hcs | (1<<20); // SDHC support and voltage level + param[0] = hcs | volt; // SDHC support and voltage level ret = sdcard_pio_app(regs, SC_APP_SEND_OP_COND, param); if (ret) return ret; @@ -319,6 +320,21 @@ sdcard_card_setup(struct sdhci_s *regs) }
static int +sdcard_set_power(struct sdhci_s *regs) +{ + u32 cap = readl(®s->cap_lo); + if (!(cap & SD_CAPLO_V33)) { + dprintf(1, "SD controller does not support 3.3V power\n"); + return -1; + } + writeb(®s->power_control, 0); + msleep(SDHCI_POWER_OFF_TIME); + writeb(®s->power_control, SPC_V33 | SPC_POWER_ON); + msleep(SDHCI_POWER_ON_TIME); + return 1<<20; +} + +static int sdcard_set_frequency(struct sdhci_s *regs, u32 khz) { u16 ver = readw(®s->controller_version); @@ -328,10 +344,6 @@ sdcard_set_frequency(struct sdhci_s *regs, u32 khz) dprintf(1, "Unknown base frequency for SD controller\n"); return -1; } - if (!(cap & SD_CAPLO_V33)) { - dprintf(1, "SD controller does not support 3.3V power\n"); - return -1; - } // Set new frequency u32 divisor = DIV_ROUND_UP(base_freq * 1000, khz); u16 creg; @@ -382,17 +394,16 @@ sdcard_controller_setup(void *data) writew(®s->irq_enable, 0xffff); writew(®s->error_signal, 0); writeb(®s->timeout_control, 0x0e); // Set to max timeout - writeb(®s->power_control, 0); - msleep(SDHCI_POWER_OFF_TIME); - writeb(®s->power_control, SPC_V33 | SPC_POWER_ON); - msleep(SDHCI_POWER_ON_TIME); + int volt = sdcard_set_power(regs); + if (volt < 0) + return; int ret = sdcard_set_frequency(regs, 400); if (ret) return; msleep(SDHCI_CLOCK_ON_TIME);
// Initialize card - int card_type = sdcard_card_setup(regs); + int card_type = sdcard_card_setup(regs, volt); if (card_type < 0) return; ret = sdcard_set_frequency(regs, 25000);