diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 790f01662b4e6af7ed6cdb941cac5dd34af6c91e..765dfb9f77ec42f675a684b0d88a2d2e682e5b5b 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -256,6 +257,9 @@ struct sunxi_mmc_host { struct mmc_request *mrq; struct mmc_request *manual_stop_mrq; int ferror; + + /* vqmmc */ + bool vqmmc_enabled; }; static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) @@ -716,6 +720,16 @@ static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->ferror) return; + if (!IS_ERR(mmc->supply.vqmmc)) { + host->ferror = regulator_enable(mmc->supply.vqmmc); + if (host->ferror) { + dev_err(mmc_dev(mmc), + "failed to enable vqmmc\n"); + return; + } + host->vqmmc_enabled = true; + } + host->ferror = sunxi_mmc_init_host(mmc); if (host->ferror) return; @@ -727,6 +741,9 @@ static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) dev_dbg(mmc_dev(mmc), "power off!\n"); sunxi_mmc_reset_host(host); mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) + regulator_disable(mmc->supply.vqmmc); + host->vqmmc_enabled = false; break; } @@ -758,6 +775,19 @@ static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } +static int sunxi_mmc_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) +{ + /* vqmmc regulator is available */ + if (!IS_ERR(mmc->supply.vqmmc)) + return mmc_regulator_set_vqmmc(mmc, ios); + + /* no vqmmc regulator, assume fixed regulator at 3/3.3V */ + if (mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) + return 0; + + return -EINVAL; +} + static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct sunxi_mmc_host *host = mmc_priv(mmc); @@ -909,6 +939,7 @@ static struct mmc_host_ops sunxi_mmc_ops = { .get_ro = mmc_gpio_get_ro, .get_cd = mmc_gpio_get_cd, .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, + .start_signal_voltage_switch = sunxi_mmc_volt_switch, .hw_reset = sunxi_mmc_hw_reset, .card_busy = sunxi_mmc_card_busy, };