diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2015-08-11 13:29:55 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2015-08-17 12:11:24 -0400 |
commit | d501de1c2299707fe9b1b28a12e024e93894ee40 (patch) | |
tree | d9f1f9d91faa82f9ff62cbb11f88967cfd841b53 /src/hw/sdcard.c | |
parent | bf8f26666ff0f36b53c1570744b6eb2c2b2098b7 (diff) | |
download | seabios-d501de1c2299707fe9b1b28a12e024e93894ee40.tar.gz |
sdcard: Initial support for MMC cards
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/hw/sdcard.c')
-rw-r--r-- | src/hw/sdcard.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index 1f262912..68888bfa 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -63,6 +63,7 @@ struct sdhci_s { #define SCB_R48o 0x02 // Response R3, R4 #define SCB_R136 0x09 // Response R2 #define SC_GO_IDLE_STATE ((0<<8) | SCB_R0) +#define SC_SEND_OP_COND ((1<<8) | SCB_R48o) #define SC_ALL_SEND_CID ((2<<8) | SCB_R136) #define SC_SEND_RELATIVE_ADDR ((3<<8) | SCB_R48) #define SC_SELECT_DESELECT_CARD ((7<<8) | SCB_R48b) @@ -138,9 +139,8 @@ struct sddrive_s { }; // SD card types -#define SF_MMC 0 -#define SF_SDSC 1 -#define SF_SDHC 2 +#define SF_SC 1 +#define SF_HC 2 // Repeatedly read a u16 register until any bit in a given mask is set static int @@ -228,7 +228,7 @@ sdcard_pio_transfer(struct sddrive_s *drive, int cmd, u32 addr u16 tmode = ((count > 1 ? ST_MULTIPLE|ST_AUTO_CMD12|ST_BLOCKCOUNT : 0) | (isread ? ST_READ : 0)); writew(&drive->regs->transfer_mode, tmode); - if (drive->card_type < SF_SDHC) + if (drive->card_type < SF_HC) addr *= DISK_SECTOR_SIZE; u32 param[4] = { addr }; int ret = sdcard_pio(drive->regs, cmd, param); @@ -305,24 +305,32 @@ sdcard_card_setup(struct sdhci_s *regs, int volt) if (ret) return ret; // Let card know SDHC/SDXC is supported and confirm voltage + u32 isMMC = 0, hcs = 0; 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] == vrange) - hcs = 0x40000000; + if (!ret && param[0] == vrange) + hcs = (1<<30); // 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; + if (ret) { + // Check for MMC card + param[0] = 0x00; + ret = sdcard_pio(regs, SC_SEND_OP_COND, param); + if (ret) + return ret; + isMMC = 1; + hcs = (1<<30); + } // Init card u32 end = timer_calc(SDHCI_POWERUP_TIMEOUT); for (;;) { - param[0] = hcs | volt; // SDHC support and voltage level - ret = sdcard_pio_app(regs, SC_APP_SEND_OP_COND, param); + param[0] = hcs | volt; // high-capacity support and voltage level + if (isMMC) + ret = sdcard_pio(regs, SC_SEND_OP_COND, param); + else + ret = sdcard_pio_app(regs, SC_APP_SEND_OP_COND, param); if (ret) return ret; if (param[0] & SR_OCR_NOTBUSY) @@ -331,18 +339,19 @@ sdcard_card_setup(struct sdhci_s *regs, int volt) warn_timeout(); return -1; } + msleep(5); // Avoid flooding log when debugging } - int card_type = (param[0] & SR_OCR_CCS) ? SF_SDHC : SF_SDSC; - param[0] = 0x00; + int card_type = (param[0] & SR_OCR_CCS) ? SF_HC : SF_SC; // Select card + param[0] = 0x00; ret = sdcard_pio(regs, SC_ALL_SEND_CID, param); if (ret) return ret; - param[0] = 0x00; + param[0] = isMMC ? 0x0001 << 16 : 0x00; ret = sdcard_pio(regs, SC_SEND_RELATIVE_ADDR, param); if (ret) return ret; - u16 rca = param[0] >> 16; + u16 rca = isMMC ? 0x0001 : param[0] >> 16; param[0] = rca << 16; ret = sdcard_pio(regs, SC_SELECT_DESELECT_CARD, param); if (ret) |