diff options
Diffstat (limited to 'drivers/mmc/core/sd.c')
| -rw-r--r-- | drivers/mmc/core/sd.c | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cc757b850e79..948948ca9b4a 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -11,6 +11,7 @@ #include <linux/sizes.h> #include <linux/slab.h> #include <linux/stat.h> +#include <linux/string.h> #include <linux/pm_runtime.h> #include <linux/random.h> #include <linux/scatterlist.h> @@ -95,6 +96,9 @@ void mmc_decode_cid(struct mmc_card *card) card->cid.month = unstuff_bits(resp, 8, 4); card->cid.year += 2000; /* SD cards year offset */ + + /* some product names may include trailing whitespace */ + strim(card->cid.prod_name); } /* @@ -355,7 +359,7 @@ static int mmc_read_switch(struct mmc_card *card) } if (status[13] & SD_MODE_HIGH_SPEED) - card->sw_caps.hs_max_dtr = HIGH_SPEED_MAX_DTR; + card->sw_caps.hs_max_dtr = card->host->max_sd_hs_hz ?: HIGH_SPEED_MAX_DTR; if (card->scr.sda_spec3) { card->sw_caps.sd3_bus_mode = status[13]; @@ -451,7 +455,7 @@ static void sd_update_bus_speed_mode(struct mmc_card *card) * If the host doesn't support any of the UHS-I modes, fallback on * default speed. */ - if (!mmc_host_uhs(card->host)) { + if (!mmc_host_can_uhs(card->host)) { card->sd_bus_speed = 0; return; } @@ -550,7 +554,7 @@ static u32 sd_get_host_max_current(struct mmc_host *host) static int sd_set_current_limit(struct mmc_card *card, u8 *status) { - int current_limit = SD_SET_CURRENT_NO_CHANGE; + int current_limit = SD_SET_CURRENT_LIMIT_200; int err; u32 max_current; @@ -594,11 +598,8 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status) else if (max_current >= 400 && card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400) current_limit = SD_SET_CURRENT_LIMIT_400; - else if (max_current >= 200 && - card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200) - current_limit = SD_SET_CURRENT_LIMIT_200; - if (current_limit != SD_SET_CURRENT_NO_CHANGE) { + if (current_limit != SD_SET_CURRENT_LIMIT_200) { err = mmc_sd_switch(card, SD_SWITCH_SET, 3, current_limit, status); if (err) @@ -614,6 +615,29 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status) } /* + * Determine if the card should tune or not. + */ +static bool mmc_sd_use_tuning(struct mmc_card *card) +{ + /* + * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and + * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. + */ + if (mmc_host_is_spi(card->host)) + return false; + + switch (card->host->ios.timing) { + case MMC_TIMING_UHS_SDR50: + case MMC_TIMING_UHS_SDR104: + return true; + case MMC_TIMING_UHS_DDR50: + return !mmc_card_no_uhs_ddr50_tuning(card); + } + + return false; +} + +/* * UHS-I specific initialization procedure */ static int mmc_sd_init_uhs_card(struct mmc_card *card) @@ -656,14 +680,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) if (err) goto out; - /* - * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and - * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. - */ - if (!mmc_host_is_spi(card->host) && - (card->host->ios.timing == MMC_TIMING_UHS_SDR50 || - card->host->ios.timing == MMC_TIMING_UHS_DDR50 || - card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { + if (mmc_sd_use_tuning(card)) { err = mmc_execute_tuning(card); /* @@ -724,7 +741,7 @@ static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr, return sysfs_emit(buf, "0x%x\n", 0x404); } -static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL); +static DEVICE_ATTR(dsr, 0444, mmc_dsr_show, NULL); MMC_DEV_ATTR(vendor, "0x%04x\n", card->cis.vendor); MMC_DEV_ATTR(device, "0x%04x\n", card->cis.device); @@ -847,7 +864,7 @@ try_again: * to switch to 1.8V signaling level. If the card has failed * repeatedly to switch however, skip this. */ - if (retries && mmc_host_uhs(host)) + if (retries && mmc_host_can_uhs(host)) ocr |= SD_OCR_S18R; /* @@ -1489,7 +1506,7 @@ retry: * signaling. Detect that situation and try to initialize a UHS-I (1.8V) * transfer mode. */ - if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) && + if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_can_uhs(host) && mmc_sd_card_using_v18(card) && host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) { if (mmc_host_set_uhs_voltage(host) || @@ -1504,7 +1521,7 @@ retry: } /* Initialization sequence for UHS-I cards */ - if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { + if (rocr & SD_ROCR_S18A && mmc_host_can_uhs(host)) { err = mmc_sd_init_uhs_card(card); if (err) goto free_card; @@ -1593,15 +1610,6 @@ free_card: } /* - * Host is being removed. Free up the current card. - */ -static void mmc_sd_remove(struct mmc_host *host) -{ - mmc_remove_card(host->card); - host->card = NULL; -} - -/* * Card detection - card is alive. */ static int mmc_sd_alive(struct mmc_host *host) @@ -1626,7 +1634,8 @@ static void mmc_sd_detect(struct mmc_host *host) mmc_put_card(host->card, NULL); if (err) { - mmc_sd_remove(host); + mmc_remove_card(host->card); + host->card = NULL; mmc_claim_host(host); mmc_detach_bus(host); @@ -1727,6 +1736,19 @@ out: } /* + * Host is being removed. Free up the current card and do a graceful power-off. + */ +static void mmc_sd_remove(struct mmc_host *host) +{ + get_device(&host->card->dev); + mmc_remove_card(host->card); + + _mmc_sd_suspend(host); + + put_device(&host->card->dev); + host->card = NULL; +} +/* * Callback for suspend */ static int mmc_sd_suspend(struct mmc_host *host) |
