// 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!
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;
// 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;
return card_type;
}
+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)
{
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;
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);