Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ulf Hansson and committed by
Chris Ball
ce69d37b 69041150

+13 -37
+11 -20
drivers/mmc/core/core.c
··· 1358 1358 int bit; 1359 1359 1360 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); 1363 - if (bit) { 1364 - bit -= 1; 1365 - 1366 + if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { 1367 + bit = ffs(ocr) - 1; 1366 1368 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); 1372 1370 } 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"); 1376 1375 } 1377 1376 1378 1377 return ocr; ··· 1569 1570 1570 1571 host->ios.clock = 0; 1571 1572 host->ios.vdd = 0; 1572 - 1573 - 1574 - /* 1575 - * Reset ocr mask to be the highest possible voltage supported for 1576 - * this card. This value will be used at next power up. 1577 - */ 1578 - if (host->card) 1579 - host->card->ocr = 1 << (fls(host->ocr_avail) - 1); 1580 1573 1581 1574 if (!mmc_host_is_spi(host)) { 1582 1575 host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-1
drivers/mmc/core/mmc.c
··· 1535 1535 1536 1536 mmc_claim_host(host); 1537 1537 mmc_power_up(host, host->card->ocr); 1538 - mmc_select_voltage(host, host->card->ocr); 1539 1538 err = mmc_init_card(host, host->card->ocr, host->card); 1540 1539 mmc_release_host(host); 1541 1540
-1
drivers/mmc/core/sd.c
··· 1103 1103 1104 1104 mmc_claim_host(host); 1105 1105 mmc_power_up(host, host->card->ocr); 1106 - mmc_select_voltage(host, host->card->ocr); 1107 1106 err = mmc_sd_init_card(host, host->card->ocr, host->card); 1108 1107 mmc_release_host(host); 1109 1108
+2 -15
drivers/mmc/core/sdio.c
··· 987 987 /* Restore power if needed */ 988 988 if (!mmc_card_keep_power(host)) { 989 989 mmc_power_up(host, host->card->ocr); 990 - mmc_select_voltage(host, host->card->ocr); 991 990 /* 992 991 * Tell runtime PM core we just powered up the card, 993 992 * since it still believes the card is powered off. ··· 1044 1045 static int mmc_sdio_power_restore(struct mmc_host *host) 1045 1046 { 1046 1047 int ret; 1047 - u32 ocr, rocr; 1048 1048 1049 1049 BUG_ON(!host); 1050 1050 BUG_ON(!host->card); ··· 1065 1067 * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and 1066 1068 * harmless in other situations. 1067 1069 * 1068 - * With these steps taken, mmc_select_voltage() is also required to 1069 - * restore the correct voltage setting of the card. 1070 1070 */ 1071 1071 1072 1072 sdio_reset(host); 1073 1073 mmc_go_idle(host); 1074 1074 mmc_send_if_cond(host, host->ocr_avail); 1075 1075 1076 - ret = mmc_send_io_op_cond(host, 0, &ocr); 1076 + ret = mmc_send_io_op_cond(host, 0, NULL); 1077 1077 if (ret) 1078 1078 goto out; 1079 1079 1080 - if (host->ocr_avail_sdio) 1081 - host->ocr_avail = host->ocr_avail_sdio; 1082 - 1083 - rocr = mmc_select_voltage(host, ocr & ~0x7F); 1084 - if (!rocr) { 1085 - ret = -EINVAL; 1086 - goto out; 1087 - } 1088 - 1089 - ret = mmc_sdio_init_card(host, rocr, host->card, 1080 + ret = mmc_sdio_init_card(host, host->card->ocr, host->card, 1090 1081 mmc_card_keep_power(host)); 1091 1082 if (!ret && host->sdio_irqs) 1092 1083 mmc_signal_sdio_irq(host);