According to Fig. 3-35 in "SD Host Controller Simplified Spec. Ver4.20": - Prepare vdd1, vdd2 and ios.timing for using after/in step (2) - chip_select is not used in UHS-II, used to return to the legacy flow Signed-off-by: Ben Chuang <ben.chuang@xxxxxxxxxxxxxxxxxxx> Signed-off-by: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx> --- drivers/mmc/core/core.c | 61 +++++++++++++++++++++++++----------- drivers/mmc/core/regulator.c | 14 +++++++++ 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f194940c5974..722b61811f1e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1318,33 +1318,52 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) if (host->ios.power_mode == MMC_POWER_ON) return; - mmc_pwrseq_pre_power_on(host); + if (host->flags & MMC_UHS2_SUPPORT) { + /* TODO: handle 'ocr' parameter */ + host->ios.vdd = fls(host->ocr_avail) - 1; + host->ios.vdd2 = fls(host->ocr_avail_uhs2) - 1; + if (mmc_host_is_spi(host)) + host->ios.chip_select = MMC_CS_HIGH; + else + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.timing = MMC_TIMING_UHS2; + } else { + mmc_pwrseq_pre_power_on(host); - host->ios.vdd = fls(ocr) - 1; - host->ios.power_mode = MMC_POWER_UP; - /* Set initial state and call mmc_set_ios */ - mmc_set_initial_state(host); + host->ios.vdd = fls(ocr) - 1; + host->ios.power_mode = MMC_POWER_UP; + /* Set initial state and call mmc_set_ios */ + mmc_set_initial_state(host); - mmc_set_initial_signal_voltage(host); + mmc_set_initial_signal_voltage(host); - /* - * This delay should be sufficient to allow the power supply - * to reach the minimum voltage. - */ - mmc_delay(host->ios.power_delay_ms); + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + mmc_delay(host->ios.power_delay_ms); - mmc_pwrseq_post_power_on(host); + mmc_pwrseq_post_power_on(host); + } host->ios.clock = host->f_init; - host->ios.power_mode = MMC_POWER_ON; + mmc_set_ios(host); - /* - * This delay must be at least 74 clock sizes, or 1 ms, or the - * time required to reach a stable voltage. - */ - mmc_delay(host->ios.power_delay_ms); + if (host->flags & MMC_UHS2_SUPPORT) + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + /* TODO: avoid an immediate value */ + mmc_delay(10); + else + /* + * This delay must be at least 74 clock sizes, or 1 ms, or the + * time required to reach a stable voltage. + */ + mmc_delay(host->ios.power_delay_ms); } void mmc_power_off(struct mmc_host *host) @@ -2233,7 +2252,11 @@ void mmc_start_host(struct mmc_host *host) if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) { mmc_claim_host(host); - mmc_power_up(host, host->ocr_avail); + + /* Power up here will make UHS2 init ugly. */ + if (!(host->caps & MMC_CAP_UHS2)) + mmc_power_up(host, host->ocr_avail); + mmc_release_host(host); } diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c index 609201a467ef..629e25bc8cb7 100644 --- a/drivers/mmc/core/regulator.c +++ b/drivers/mmc/core/regulator.c @@ -249,6 +249,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); + mmc->supply.vmmc2 = devm_regulator_get_optional(dev, "vmmc2"); if (IS_ERR(mmc->supply.vmmc)) { if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) @@ -268,6 +269,19 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) dev_dbg(dev, "No vqmmc regulator found\n"); } + if (IS_ERR(mmc->supply.vmmc2)) { + if (PTR_ERR(mmc->supply.vmmc2) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(dev, "No vmmc2 regulator found\n"); + } else { + ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc2); + if (ret > 0) + mmc->ocr_avail_uhs2 = ret; + else + dev_warn(dev, "Failed getting UHS2 OCR mask: %d\n", + ret); + } + return 0; } EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); -- 2.32.0