Loading drivers/mmc/host/sdhci.c +78 −114 Original line number Diff line number Diff line Loading @@ -1615,11 +1615,23 @@ 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; /* * Signal Voltage Switching is only applicable for Host Controllers * v3.00 and above. */ if (host->version < SDHCI_SPEC_300) return 0; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); switch (signal_voltage) { 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); Loading @@ -1643,117 +1655,55 @@ static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, pr_warning("%s: 3.3V regulator output did not became stable\n", mmc_hostname(host->mmc)); return -EAGAIN; 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; } } static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, u16 ctrl) { u8 pwr; u16 clk; u32 present_state; int ret; /* Stop SDCLK */ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); clk &= ~SDHCI_CLOCK_CARD_EN; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); /* 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 (!ret) { ctrl |= SDHCI_CTRL_VDD_180; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); /* Wait for 5ms */ usleep_range(5000, 5500); /* 1.8V regulator output should be stable within 5 ms */ 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); /* * 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) if (ctrl & SDHCI_CTRL_VDD_180) return 0; } } } /* * 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); /* 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); pr_warning("%s: Switching to 1.8V signalling voltage failed, " "retrying with S18R set to 0\n", mmc_hostname(host->mmc)); pr_warning("%s: 1.8V regulator output did not became stable\n", mmc_hostname(host->mmc)); return -EAGAIN; case MMC_SIGNAL_VOLTAGE_120: if (host->vqmmc) { ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000); if (ret) { pr_warning("%s: Switching to 1.2V signalling voltage " " failed\n", mmc_hostname(host->mmc)); return -EIO; } } static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, struct mmc_ios *ios) { u16 ctrl; /* * Signal Voltage Switching is only applicable for Host Controllers * v3.00 and above. */ if (host->version < SDHCI_SPEC_300) 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; Loading @@ -1761,11 +1711,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; Loading Loading @@ -2036,6 +1999,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, }; /*****************************************************************************\ Loading Loading
drivers/mmc/host/sdhci.c +78 −114 Original line number Diff line number Diff line Loading @@ -1615,11 +1615,23 @@ 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; /* * Signal Voltage Switching is only applicable for Host Controllers * v3.00 and above. */ if (host->version < SDHCI_SPEC_300) return 0; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); switch (signal_voltage) { 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); Loading @@ -1643,117 +1655,55 @@ static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, pr_warning("%s: 3.3V regulator output did not became stable\n", mmc_hostname(host->mmc)); return -EAGAIN; 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; } } static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, u16 ctrl) { u8 pwr; u16 clk; u32 present_state; int ret; /* Stop SDCLK */ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); clk &= ~SDHCI_CLOCK_CARD_EN; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); /* 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 (!ret) { ctrl |= SDHCI_CTRL_VDD_180; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); /* Wait for 5ms */ usleep_range(5000, 5500); /* 1.8V regulator output should be stable within 5 ms */ 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); /* * 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) if (ctrl & SDHCI_CTRL_VDD_180) return 0; } } } /* * 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); /* 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); pr_warning("%s: Switching to 1.8V signalling voltage failed, " "retrying with S18R set to 0\n", mmc_hostname(host->mmc)); pr_warning("%s: 1.8V regulator output did not became stable\n", mmc_hostname(host->mmc)); return -EAGAIN; case MMC_SIGNAL_VOLTAGE_120: if (host->vqmmc) { ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000); if (ret) { pr_warning("%s: Switching to 1.2V signalling voltage " " failed\n", mmc_hostname(host->mmc)); return -EIO; } } static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, struct mmc_ios *ios) { u16 ctrl; /* * Signal Voltage Switching is only applicable for Host Controllers * v3.00 and above. */ if (host->version < SDHCI_SPEC_300) 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; Loading @@ -1761,11 +1711,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; Loading Loading @@ -2036,6 +1999,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, }; /*****************************************************************************\ Loading