The protocal related code is moved to core stack. So update the host driver accordingly. Signed-off-by: Kevin Liu <kliu5@xxxxxxxxxxx> Tested-by: Tim Wang <wangtt@xxxxxxxxxxx> --- drivers/mmc/host/sdhci.c | 194 +++++++++++++++++++--------------------------- 1 files changed, 81 insertions(+), 113 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6f0bfc0..beaa233 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1608,145 +1608,99 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_unlock_irqrestore(&host->lock, flags); } -static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, - u16 ctrl) +static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, + int signal_voltage) { + u16 ctrl; int ret; - /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ - ctrl &= ~SDHCI_CTRL_VDD_180; - sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); - - if (host->vqmmc) { - ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); - if (ret) { - pr_warning("%s: Switching to 3.3V signalling voltage " - " failed\n", mmc_hostname(host->mmc)); - return -EIO; - } - } - /* Wait for 5ms */ - usleep_range(5000, 5500); - - /* 3.3V regulator output should be stable within 5 ms */ - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); - if (!(ctrl & SDHCI_CTRL_VDD_180)) + /* + * Signal Voltage Switching is only applicable for Host Controllers + * v3.00 and above. + */ + if (host->version < SDHCI_SPEC_300) return 0; - pr_warning("%s: 3.3V regulator output did not became stable\n", - mmc_hostname(host->mmc)); - - return -EIO; -} + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); -static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, - u16 ctrl) -{ - u8 pwr; - u16 clk; - u32 present_state; - int ret; + switch (signal_voltage) { - /* Stop SDCLK */ - clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - clk &= ~SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + case MMC_SIGNAL_VOLTAGE_330: + /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ + ctrl &= ~SDHCI_CTRL_VDD_180; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); - /* Check whether DAT[3:0] is 0000 */ - present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); - if (!((present_state & SDHCI_DATA_LVL_MASK) >> - SDHCI_DATA_LVL_SHIFT)) { - /* - * Enable 1.8V Signal Enable in the Host Control2 - * register - */ - if (host->vqmmc) - ret = regulator_set_voltage(host->vqmmc, - 1700000, 1950000); - else - ret = 0; + if (host->vqmmc) { + ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); + if (ret) { + pr_warning("%s: Switching to 3.3V signalling voltage " + " failed\n", mmc_hostname(host->mmc)); + return -EIO; + } + } + /* Wait for 5ms */ + usleep_range(5000, 5500); - if (!ret) { - ctrl |= SDHCI_CTRL_VDD_180; - sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + /* 3.3V regulator output should be stable within 5 ms */ + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + if (!(ctrl & SDHCI_CTRL_VDD_180)) + return 0; - /* Wait for 5ms */ - usleep_range(5000, 5500); + pr_warning("%s: 3.3V regulator output did not became stable\n", + mmc_hostname(host->mmc)); - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); - if (ctrl & SDHCI_CTRL_VDD_180) { - /* Provide SDCLK again and wait for 1ms */ - clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - clk |= SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - usleep_range(1000, 1500); + return -EAGAIN; - /* - * If DAT[3:0] level is 1111b, then the card - * was successfully switched to 1.8V signaling. - */ - present_state = sdhci_readl(host, - SDHCI_PRESENT_STATE); - if ((present_state & SDHCI_DATA_LVL_MASK) == - SDHCI_DATA_LVL_MASK) - return 0; + case MMC_SIGNAL_VOLTAGE_180: + if (host->vqmmc) { + ret = regulator_set_voltage(host->vqmmc, + 1700000, 1950000); + if (ret) { + pr_warning("%s: Switching to 1.8V signalling voltage " + " failed\n", mmc_hostname(host->mmc)); + return -EIO; } } - } - /* - * If we are here, that means the switch to 1.8V signaling - * failed. We power cycle the card, and retry initialization - * sequence by setting S18R to 0. - */ - pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); - pwr &= ~SDHCI_POWER_ON; - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); - if (host->vmmc) - regulator_disable(host->vmmc); + /* + * Enable 1.8V Signal Enable in the Host Control2 + * register + */ + ctrl |= SDHCI_CTRL_VDD_180; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); - /* Wait for 1ms as per the spec */ - usleep_range(1000, 1500); - pwr |= SDHCI_POWER_ON; - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); - if (host->vmmc) - regulator_enable(host->vmmc); + /* Wait for 5ms */ + usleep_range(5000, 5500); - pr_warning("%s: Switching to 1.8V signalling voltage failed, " - "retrying with S18R set to 0\n", mmc_hostname(host->mmc)); + /* 1.8V regulator output should be stable within 5 ms */ + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + if (ctrl & SDHCI_CTRL_VDD_180) + return 0; - return -EAGAIN; -} + pr_warning("%s: 1.8V regulator output did not became stable\n", + mmc_hostname(host->mmc)); -static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, - struct mmc_ios *ios) -{ - u16 ctrl; + return -EAGAIN; - /* - * Signal Voltage Switching is only applicable for Host Controllers - * v3.00 and above. - */ - if (host->version < SDHCI_SPEC_300) + case MMC_SIGNAL_VOLTAGE_120: + if (host->vqmmc) { + ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); + if (ret) { + pr_warning("%s: Switching to 1.2V signalling voltage " + " failed\n", mmc_hostname(host->mmc)); + return -EIO; + } + } return 0; - /* - * We first check whether the request is to set signalling voltage - * to 3.3V. If so, we change the voltage to 3.3V and return quickly. - */ - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); - if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) - return sdhci_do_3_3v_signal_voltage_switch(host, ctrl); - else if (!(ctrl & SDHCI_CTRL_VDD_180) && - (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) - return sdhci_do_1_8v_signal_voltage_switch(host, ctrl); - else + default: /* No signal voltage switch required */ return 0; + } } static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, - struct mmc_ios *ios) + int signal_voltage) { struct sdhci_host *host = mmc_priv(mmc); int err; @@ -1754,11 +1708,24 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, if (host->version < SDHCI_SPEC_300) return 0; sdhci_runtime_pm_get(host); - err = sdhci_do_start_signal_voltage_switch(host, ios); + err = sdhci_do_start_signal_voltage_switch(host, signal_voltage); sdhci_runtime_pm_put(host); return err; } +static int sdhci_card_busy(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + u32 present_state; + + sdhci_runtime_pm_get(host); + /* Check whether DAT[3:0] is 0000 */ + present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); + sdhci_runtime_pm_put(host); + + return !(present_state & SDHCI_DATA_LVL_MASK); +} + static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct sdhci_host *host; @@ -2029,6 +1996,7 @@ static const struct mmc_host_ops sdhci_ops = { .execute_tuning = sdhci_execute_tuning, .enable_preset_value = sdhci_enable_preset_value, .card_event = sdhci_card_event, + .card_busy = sdhci_card_busy, }; /*****************************************************************************\ -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html