
From: Carlo Caione carlo@endlessm.com
Add support for pin voltage configuration. Besides to support UHS mode this is useful when the IO lines are connected to a configurable regulator not enabled at boot or always on.
Signed-off-by: Carlo Caione carlo@endlessm.com --- drivers/mmc/dw_mmc.c | 34 ++++++++++++++++++++++++++++++++++ include/dwmmc.h | 26 ++++++++++++++------------ 2 files changed, 48 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 13180fc0d6..0841d516d2 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -12,6 +12,7 @@ #include <memalign.h> #include <mmc.h> #include <dwmmc.h> +#include <power/regulator.h>
#define PAGE_SIZE 4096
@@ -382,6 +383,34 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) return 0; }
+#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE) && CONFIG_IS_ENABLED(DM_REGULATOR) +static int dwmci_set_io_regulators(struct mmc *mmc) +{ + struct dwmci_host *host = (struct dwmci_host *)mmc->priv; + int uv = mmc_voltage_to_mv(mmc->signal_voltage) * 1000; + int ret = 0; + + if (!mmc->vqmmc_supply) + return 0; + + host->signal_voltage = mmc->signal_voltage; + + ret = regulator_set_enable(mmc->vqmmc_supply, false); + if (ret && ret != -ENOSYS) + return ret; + + ret = regulator_set_value(mmc->vqmmc_supply, uv); + if (ret) + return ret; + + ret = regulator_set_enable(mmc->vqmmc_supply, true); + if (ret && ret != -ENOSYS) + return ret; + + return 0; +} +#endif + #ifdef CONFIG_DM_MMC static int dwmci_set_ios(struct udevice *dev) { @@ -421,6 +450,11 @@ static int dwmci_set_ios(struct mmc *mmc) if (host->clksel) host->clksel(host);
+#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE) && CONFIG_IS_ENABLED(DM_REGULATOR) + if (host->signal_voltage != mmc->signal_voltage) + return dwmci_set_io_regulators(mmc); +#endif + return 0; }
diff --git a/include/dwmmc.h b/include/dwmmc.h index bc1d6e3abb..461141af54 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -133,18 +133,19 @@ /** * struct dwmci_host - Information about a designware MMC host * - * @name: Device name - * @ioaddr: Base I/O address of controller - * @quirks: Quick flags - see DWMCI_QUIRK_... - * @caps: Capabilities - see MMC_MODE_... - * @bus_hz: Bus speed in Hz, if @get_mmc_clk() is NULL - * @div: Arbitrary clock divider value for use by controller - * @dev_index: Arbitrary device index for use by controller - * @dev_id: Arbitrary device ID for use by controller - * @buswidth: Bus width in bits (8 or 4) - * @fifoth_val: Value for FIFOTH register (or 0 to leave unset) - * @mmc: Pointer to generic MMC structure for this device - * @priv: Private pointer for use by controller + * @name: Device name + * @ioaddr: Base I/O address of controller + * @quirks: Quick flags - see DWMCI_QUIRK_... + * @caps: Capabilities - see MMC_MODE_... + * @bus_hz: Bus speed in Hz, if @get_mmc_clk() is NULL + * @div: Arbitrary clock divider value for use by controller + * @signal_voltage: Current voltage for the IO lines + * @dev_index: Arbitrary device index for use by controller + * @dev_id: Arbitrary device ID for use by controller + * @buswidth: Bus width in bits (8 or 4) + * @fifoth_val: Value for FIFOTH register (or 0 to leave unset) + * @mmc: Pointer to generic MMC structure for this device + * @priv: Private pointer for use by controller */ struct dwmci_host { const char *name; @@ -155,6 +156,7 @@ struct dwmci_host { unsigned int clock; unsigned int bus_hz; unsigned int div; + unsigned int signal_voltage; int dev_index; int dev_id; int buswidth;