diff options
author | Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> | 2013-04-23 14:27:07 (GMT) |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-05-26 18:23:18 (GMT) |
commit | 60443712195bbcbbff9af189bdd9d2c1ef0a5cae (patch) | |
tree | 8556da51a7cc4f852f49cca47dff38bec7bee1a6 /drivers/mmc/core | |
parent | 07a682160866e302d696f5c76d74024d575fb79d (diff) | |
download | linux-fsl-qoriq-60443712195bbcbbff9af189bdd9d2c1ef0a5cae.tar.xz |
mmc: core: Fix select power class after resume
Use the saved values in card->ext_csd when selecting power class.
By doing this the power class will be selected even if mmc_init_card
is called with oldcard != NULL, which is the case after a suspend/resume.
Today ext_csd is NULL if mmc_init_card is called with oldcard != NULL
and power class will not be selected.
According to the eMMC specification the POWER_CLASS value is reset after
power failure, H/W reset assertion and any CMD0 reset.
Signed-off-by: Fredrik Soderstedt <fredrik.soderstedt@stericsson.com>
Reviewed-by: Johan Rudholm <jrudholm@gmail.com>
Acked By: Girish K S <girish.shivananjappa@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/mmc.c | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index dd6810e..3a69b94 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -461,6 +461,24 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) */ card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; card->ext_csd.boot_ro_lockable = true; + + /* Save power class values */ + card->ext_csd.raw_pwr_cl_52_195 = + ext_csd[EXT_CSD_PWR_CL_52_195]; + card->ext_csd.raw_pwr_cl_26_195 = + ext_csd[EXT_CSD_PWR_CL_26_195]; + card->ext_csd.raw_pwr_cl_52_360 = + ext_csd[EXT_CSD_PWR_CL_52_360]; + card->ext_csd.raw_pwr_cl_26_360 = + ext_csd[EXT_CSD_PWR_CL_26_360]; + card->ext_csd.raw_pwr_cl_200_195 = + ext_csd[EXT_CSD_PWR_CL_200_195]; + card->ext_csd.raw_pwr_cl_200_360 = + ext_csd[EXT_CSD_PWR_CL_200_360]; + card->ext_csd.raw_pwr_cl_ddr_52_195 = + ext_csd[EXT_CSD_PWR_CL_DDR_52_195]; + card->ext_csd.raw_pwr_cl_ddr_52_360 = + ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; } if (card->ext_csd.rev >= 5) { @@ -607,7 +625,23 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) (card->ext_csd.raw_sectors[2] == bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && (card->ext_csd.raw_sectors[3] == - bw_ext_csd[EXT_CSD_SEC_CNT + 3])); + bw_ext_csd[EXT_CSD_SEC_CNT + 3]) && + (card->ext_csd.raw_pwr_cl_52_195 == + bw_ext_csd[EXT_CSD_PWR_CL_52_195]) && + (card->ext_csd.raw_pwr_cl_26_195 == + bw_ext_csd[EXT_CSD_PWR_CL_26_195]) && + (card->ext_csd.raw_pwr_cl_52_360 == + bw_ext_csd[EXT_CSD_PWR_CL_52_360]) && + (card->ext_csd.raw_pwr_cl_26_360 == + bw_ext_csd[EXT_CSD_PWR_CL_26_360]) && + (card->ext_csd.raw_pwr_cl_200_195 == + bw_ext_csd[EXT_CSD_PWR_CL_200_195]) && + (card->ext_csd.raw_pwr_cl_200_360 == + bw_ext_csd[EXT_CSD_PWR_CL_200_360]) && + (card->ext_csd.raw_pwr_cl_ddr_52_195 == + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) && + (card->ext_csd.raw_pwr_cl_ddr_52_360 == + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360])); if (err) err = -EINVAL; @@ -676,11 +710,10 @@ static struct device_type mmc_type = { * mmc_switch command. */ static int mmc_select_powerclass(struct mmc_card *card, - unsigned int bus_width, u8 *ext_csd) + unsigned int bus_width) { int err = 0; - unsigned int pwrclass_val; - unsigned int index = 0; + unsigned int pwrclass_val = 0; struct mmc_host *host; BUG_ON(!card); @@ -688,9 +721,6 @@ static int mmc_select_powerclass(struct mmc_card *card, host = card->host; BUG_ON(!host); - if (ext_csd == NULL) - return 0; - /* Power class selection is supported for versions >= 4.0 */ if (card->csd.mmca_vsn < CSD_SPEC_VER_4) return 0; @@ -702,13 +732,13 @@ static int mmc_select_powerclass(struct mmc_card *card, switch (1 << host->ios.vdd) { case MMC_VDD_165_195: if (host->ios.clock <= 26000000) - index = EXT_CSD_PWR_CL_26_195; + pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; else if (host->ios.clock <= 52000000) - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? - EXT_CSD_PWR_CL_52_195 : - EXT_CSD_PWR_CL_DDR_52_195; + pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? + card->ext_csd.raw_pwr_cl_52_195 : + card->ext_csd.raw_pwr_cl_ddr_52_195; else if (host->ios.clock <= 200000000) - index = EXT_CSD_PWR_CL_200_195; + pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; break; case MMC_VDD_27_28: case MMC_VDD_28_29: @@ -720,13 +750,13 @@ static int mmc_select_powerclass(struct mmc_card *card, case MMC_VDD_34_35: case MMC_VDD_35_36: if (host->ios.clock <= 26000000) - index = EXT_CSD_PWR_CL_26_360; + pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; else if (host->ios.clock <= 52000000) - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? - EXT_CSD_PWR_CL_52_360 : - EXT_CSD_PWR_CL_DDR_52_360; + pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? + card->ext_csd.raw_pwr_cl_52_360 : + card->ext_csd.raw_pwr_cl_ddr_52_360; else if (host->ios.clock <= 200000000) - index = EXT_CSD_PWR_CL_200_360; + pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; break; default: pr_warning("%s: Voltage range not supported " @@ -734,8 +764,6 @@ static int mmc_select_powerclass(struct mmc_card *card, return -EINVAL; } - pwrclass_val = ext_csd[index]; - if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> EXT_CSD_PWR_CL_8BIT_SHIFT; @@ -1131,7 +1159,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; - err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits); if (err) pr_warning("%s: power class selection to bus width %d" " failed\n", mmc_hostname(card->host), @@ -1164,8 +1192,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, bus_width = bus_widths[idx]; if (bus_width == MMC_BUS_WIDTH_1) ddr = 0; /* no DDR for 1-bit width */ - err = mmc_select_powerclass(card, ext_csd_bits[idx][0], - ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits[idx][0]); if (err) pr_warning("%s: power class selection to " "bus width %d failed\n", @@ -1195,8 +1222,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } if (!err && ddr) { - err = mmc_select_powerclass(card, ext_csd_bits[idx][1], - ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits[idx][1]); if (err) pr_warning("%s: power class selection to " "bus width %d ddr %d failed\n", |