diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2013-09-16 05:28:42 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-10-30 20:26:30 -0400 |
commit | ce69d37b7d8fa692c45d71d94aa0c921859b82ce (patch) | |
tree | aef1e93b62424f07b72ddd322a64e6435b27d932 /drivers/mmc/core/core.c | |
parent | 6904115095ad60ced638eb1e36e0e4e5e7de00b0 (diff) |
mmc: core: Prevent violation of specs while initializing cards
According to eMMC/SD/SDIO specs, the VDD (VCC) voltage level must be
maintained during the initialization sequence. If we want/need to tune
the voltage level, a complete power cycle of the card must be executed.
Most host drivers conforms to the specifications by only allowing to
change VDD voltage level at the MMC_POWER_UP state, but some also cares
about MMC_POWER_ON state, which they should'nt. This patch will not
break those drivers, but they could clean up code to better reflect
what is expected from the protocol layer.
A big re-work of the mmc_select_voltage function is done to only change
VDD voltage level if the host supports MMC_CAP2_FULL_PWR_CYCLE.
Otherwise only validation of the host and card ocr mask will be done.
A very nice side-effect of this patch is that we now don't need to
reset the negotiated ocr mask at the mmc_power_off function, since now
it will actually reflect the present voltage level, which safely can be
used at the next power up and re-initialization. Moreover, we then only
need to execute mmc_select_voltage from the attach sequence.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 529d2eff6095..63672aba0e98 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1358,21 +1358,20 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) | |||
1358 | int bit; | 1358 | int bit; |
1359 | 1359 | ||
1360 | ocr &= host->ocr_avail; | 1360 | ocr &= host->ocr_avail; |
1361 | if (!ocr) { | ||
1362 | dev_warn(mmc_dev(host), "no support for card's volts\n"); | ||
1363 | return 0; | ||
1364 | } | ||
1361 | 1365 | ||
1362 | bit = ffs(ocr); | 1366 | if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { |
1363 | if (bit) { | 1367 | bit = ffs(ocr) - 1; |
1364 | bit -= 1; | ||
1365 | |||
1366 | ocr &= 3 << bit; | 1368 | ocr &= 3 << bit; |
1367 | 1369 | mmc_power_cycle(host, ocr); | |
1368 | mmc_host_clk_hold(host); | ||
1369 | host->ios.vdd = bit; | ||
1370 | mmc_set_ios(host); | ||
1371 | mmc_host_clk_release(host); | ||
1372 | } else { | 1370 | } else { |
1373 | pr_warning("%s: host doesn't support card's voltages\n", | 1371 | bit = fls(ocr) - 1; |
1374 | mmc_hostname(host)); | 1372 | ocr &= 3 << bit; |
1375 | ocr = 0; | 1373 | if (bit != host->ios.vdd) |
1374 | dev_warn(mmc_dev(host), "exceeding card's volts\n"); | ||
1376 | } | 1375 | } |
1377 | 1376 | ||
1378 | return ocr; | 1377 | return ocr; |
@@ -1571,14 +1570,6 @@ void mmc_power_off(struct mmc_host *host) | |||
1571 | host->ios.clock = 0; | 1570 | host->ios.clock = 0; |
1572 | host->ios.vdd = 0; | 1571 | host->ios.vdd = 0; |
1573 | 1572 | ||
1574 | |||
1575 | /* | ||
1576 | * Reset ocr mask to be the highest possible voltage supported for | ||
1577 | * this card. This value will be used at next power up. | ||
1578 | */ | ||
1579 | if (host->card) | ||
1580 | host->card->ocr = 1 << (fls(host->ocr_avail) - 1); | ||
1581 | |||
1582 | if (!mmc_host_is_spi(host)) { | 1573 | if (!mmc_host_is_spi(host)) { |
1583 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 1574 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
1584 | host->ios.chip_select = MMC_CS_DONTCARE; | 1575 | host->ios.chip_select = MMC_CS_DONTCARE; |