diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2007-02-18 12:07:47 +0100 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-03-06 13:26:55 +0100 |
commit | cd9277c011a99769fa371521b460ed57f6d280b1 (patch) | |
tree | 8ae2566bf8c9dac5a01a7f4f04457596ca42465a /drivers/mmc/mmc.c | |
parent | c5f93cf19df633a8dbd7adf8130d604eec96e145 (diff) | |
download | op-kernel-dev-cd9277c011a99769fa371521b460ed57f6d280b1.zip op-kernel-dev-cd9277c011a99769fa371521b460ed57f6d280b1.tar.gz |
mmc: require explicit support for high-speed
The new high-speed timings are similar to each other and the old
system, but not identical. And although things "just work" most of
the time, sometimes it does not. So we need to start marking which
hosts are known to fully comply with the new timings.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/mmc.c')
-rw-r--r-- | drivers/mmc/mmc.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 5046a16..4a73e8b 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -376,10 +376,11 @@ static inline void mmc_set_ios(struct mmc_host *host) { struct mmc_ios *ios = &host->ios; - pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", + pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u " + "width %u timing %u\n", mmc_hostname(host), ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, ios->vdd, - ios->bus_width); + ios->bus_width, ios->timing); host->ops->set_ios(host, ios); } @@ -809,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host) host->ios.chip_select = MMC_CS_DONTCARE; host->ios.power_mode = MMC_POWER_UP; host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); mmc_delay(1); @@ -828,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host) host->ios.chip_select = MMC_CS_DONTCARE; host->ios.power_mode = MMC_POWER_OFF; host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); } @@ -1112,46 +1115,50 @@ static void mmc_process_ext_csds(struct mmc_host *host) continue; } - /* Activate highspeed support. */ - cmd.opcode = MMC_SWITCH; - cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_HS_TIMING << 16) | - (1 << 8) | - EXT_CSD_CMD_SET_NORMAL; - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + if (host->caps & MMC_CAP_MMC_HIGHSPEED) { + /* Activate highspeed support. */ + cmd.opcode = MMC_SWITCH; + cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (1 << 8) | + EXT_CSD_CMD_SET_NORMAL; + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); - if (err != MMC_ERR_NONE) { - printk("%s: failed to switch card to mmc v4 " - "high-speed mode.\n", - mmc_hostname(card->host)); - continue; - } + err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); + if (err != MMC_ERR_NONE) { + printk("%s: failed to switch card to mmc v4 " + "high-speed mode.\n", + mmc_hostname(card->host)); + continue; + } - mmc_card_set_highspeed(card); + mmc_card_set_highspeed(card); - /* Check for host support for wide-bus modes. */ - if (!(host->caps & MMC_CAP_4_BIT_DATA)) { - continue; + host->ios.timing = MMC_TIMING_SD_HS; + mmc_set_ios(host); } - /* Activate 4-bit support. */ - cmd.opcode = MMC_SWITCH; - cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_BUS_WIDTH << 16) | - (EXT_CSD_BUS_WIDTH_4 << 8) | - EXT_CSD_CMD_SET_NORMAL; - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + /* Check for host support for wide-bus modes. */ + if (host->caps & MMC_CAP_4_BIT_DATA) { + /* Activate 4-bit support. */ + cmd.opcode = MMC_SWITCH; + cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_BUS_WIDTH << 16) | + (EXT_CSD_BUS_WIDTH_4 << 8) | + EXT_CSD_CMD_SET_NORMAL; + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); - if (err != MMC_ERR_NONE) { - printk("%s: failed to switch card to " - "mmc v4 4-bit bus mode.\n", - mmc_hostname(card->host)); - continue; - } + err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); + if (err != MMC_ERR_NONE) { + printk("%s: failed to switch card to " + "mmc v4 4-bit bus mode.\n", + mmc_hostname(card->host)); + continue; + } - host->ios.bus_width = MMC_BUS_WIDTH_4; + host->ios.bus_width = MMC_BUS_WIDTH_4; + mmc_set_ios(host); + } } kfree(ext_csd); @@ -1241,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) unsigned char *status; struct scatterlist sg; + if (!(host->caps & MMC_CAP_SD_HIGHSPEED)) + return; + status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_WARNING "%s: Unable to allocate buffer for " @@ -1332,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) } mmc_card_set_highspeed(card); + + host->ios.timing = MMC_TIMING_SD_HS; + mmc_set_ios(host); } kfree(status); |