Skip to content

Commit ce69d37

Browse files
storulfcjb
authored andcommitted
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 <[email protected]> Signed-off-by: Chris Ball <[email protected]>
1 parent 6904115 commit ce69d37

File tree

4 files changed

+13
-37
lines changed

4 files changed

+13
-37
lines changed

drivers/mmc/core/core.c

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,21 +1358,20 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
13581358
int bit;
13591359

13601360
ocr &= host->ocr_avail;
1361+
if (!ocr) {
1362+
dev_warn(mmc_dev(host), "no support for card's volts\n");
1363+
return 0;
1364+
}
13611365

1362-
bit = ffs(ocr);
1363-
if (bit) {
1364-
bit -= 1;
1365-
1366+
if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
1367+
bit = ffs(ocr) - 1;
13661368
ocr &= 3 << bit;
1367-
1368-
mmc_host_clk_hold(host);
1369-
host->ios.vdd = bit;
1370-
mmc_set_ios(host);
1371-
mmc_host_clk_release(host);
1369+
mmc_power_cycle(host, ocr);
13721370
} else {
1373-
pr_warning("%s: host doesn't support card's voltages\n",
1374-
mmc_hostname(host));
1375-
ocr = 0;
1371+
bit = fls(ocr) - 1;
1372+
ocr &= 3 << bit;
1373+
if (bit != host->ios.vdd)
1374+
dev_warn(mmc_dev(host), "exceeding card's volts\n");
13761375
}
13771376

13781377
return ocr;
@@ -1571,14 +1570,6 @@ void mmc_power_off(struct mmc_host *host)
15711570
host->ios.clock = 0;
15721571
host->ios.vdd = 0;
15731572

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-
15821573
if (!mmc_host_is_spi(host)) {
15831574
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
15841575
host->ios.chip_select = MMC_CS_DONTCARE;

drivers/mmc/core/mmc.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,7 +1535,6 @@ static int mmc_resume(struct mmc_host *host)
15351535

15361536
mmc_claim_host(host);
15371537
mmc_power_up(host, host->card->ocr);
1538-
mmc_select_voltage(host, host->card->ocr);
15391538
err = mmc_init_card(host, host->card->ocr, host->card);
15401539
mmc_release_host(host);
15411540

drivers/mmc/core/sd.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,6 @@ static int mmc_sd_resume(struct mmc_host *host)
11031103

11041104
mmc_claim_host(host);
11051105
mmc_power_up(host, host->card->ocr);
1106-
mmc_select_voltage(host, host->card->ocr);
11071106
err = mmc_sd_init_card(host, host->card->ocr, host->card);
11081107
mmc_release_host(host);
11091108

drivers/mmc/core/sdio.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
987987
/* Restore power if needed */
988988
if (!mmc_card_keep_power(host)) {
989989
mmc_power_up(host, host->card->ocr);
990-
mmc_select_voltage(host, host->card->ocr);
991990
/*
992991
* Tell runtime PM core we just powered up the card,
993992
* since it still believes the card is powered off.
@@ -1045,7 +1044,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
10451044
static int mmc_sdio_power_restore(struct mmc_host *host)
10461045
{
10471046
int ret;
1048-
u32 ocr, rocr;
10491047

10501048
BUG_ON(!host);
10511049
BUG_ON(!host->card);
@@ -1067,28 +1065,17 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
10671065
* for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
10681066
* harmless in other situations.
10691067
*
1070-
* With these steps taken, mmc_select_voltage() is also required to
1071-
* restore the correct voltage setting of the card.
10721068
*/
10731069

10741070
sdio_reset(host);
10751071
mmc_go_idle(host);
10761072
mmc_send_if_cond(host, host->ocr_avail);
10771073

1078-
ret = mmc_send_io_op_cond(host, 0, &ocr);
1074+
ret = mmc_send_io_op_cond(host, 0, NULL);
10791075
if (ret)
10801076
goto out;
10811077

1082-
if (host->ocr_avail_sdio)
1083-
host->ocr_avail = host->ocr_avail_sdio;
1084-
1085-
rocr = mmc_select_voltage(host, ocr & ~0x7F);
1086-
if (!rocr) {
1087-
ret = -EINVAL;
1088-
goto out;
1089-
}
1090-
1091-
ret = mmc_sdio_init_card(host, rocr, host->card,
1078+
ret = mmc_sdio_init_card(host, host->card->ocr, host->card,
10921079
mmc_card_keep_power(host));
10931080
if (!ret && host->sdio_irqs)
10941081
mmc_signal_sdio_irq(host);

0 commit comments

Comments
 (0)