Commit 152b5245 authored by Paul Cercueil's avatar Paul Cercueil Committed by Ulf Hansson

mmc: jz4740: Add support for vqmmc power supply

Support enabling / disabling the vqmmc power supply if it was provided
by the firmware.

Provide the .start_signal_voltage_switch callback to change the voltage
of the external vqmmc power supply.
Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20230131210229.68129-2-paul@crapouillou.netSigned-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent fe3e137c
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -158,6 +159,8 @@ struct jz4740_mmc_host { ...@@ -158,6 +159,8 @@ struct jz4740_mmc_host {
struct mmc_request *req; struct mmc_request *req;
struct mmc_command *cmd; struct mmc_command *cmd;
bool vqmmc_enabled;
unsigned long waiting; unsigned long waiting;
uint32_t cmdat; uint32_t cmdat;
...@@ -935,6 +938,8 @@ static void jz4740_mmc_request(struct mmc_host *mmc, struct mmc_request *req) ...@@ -935,6 +938,8 @@ static void jz4740_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{ {
struct jz4740_mmc_host *host = mmc_priv(mmc); struct jz4740_mmc_host *host = mmc_priv(mmc);
int ret;
if (ios->clock) if (ios->clock)
jz4740_mmc_set_clock_rate(host, ios->clock); jz4740_mmc_set_clock_rate(host, ios->clock);
...@@ -947,12 +952,25 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -947,12 +952,25 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
clk_prepare_enable(host->clk); clk_prepare_enable(host->clk);
break; break;
case MMC_POWER_ON: case MMC_POWER_ON:
if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
ret = regulator_enable(mmc->supply.vqmmc);
if (ret)
dev_err(&host->pdev->dev, "Failed to set vqmmc power!\n");
else
host->vqmmc_enabled = true;
}
break; break;
default: case MMC_POWER_OFF:
if (!IS_ERR(mmc->supply.vmmc)) if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 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;
}
clk_disable_unprepare(host->clk); clk_disable_unprepare(host->clk);
break; break;
default:
break;
} }
switch (ios->bus_width) { switch (ios->bus_width) {
...@@ -978,6 +996,23 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) ...@@ -978,6 +996,23 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable); jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
} }
static int jz4740_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
{
int ret;
/* vqmmc regulator is available */
if (!IS_ERR(mmc->supply.vqmmc)) {
ret = mmc_regulator_set_vqmmc(mmc, ios);
return ret < 0 ? ret : 0;
}
/* no vqmmc regulator, assume fixed regulator at 3/3.3V */
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
return 0;
return -EINVAL;
}
static const struct mmc_host_ops jz4740_mmc_ops = { static const struct mmc_host_ops jz4740_mmc_ops = {
.request = jz4740_mmc_request, .request = jz4740_mmc_request,
.pre_req = jz4740_mmc_pre_request, .pre_req = jz4740_mmc_pre_request,
...@@ -986,6 +1021,7 @@ static const struct mmc_host_ops jz4740_mmc_ops = { ...@@ -986,6 +1021,7 @@ static const struct mmc_host_ops jz4740_mmc_ops = {
.get_ro = mmc_gpio_get_ro, .get_ro = mmc_gpio_get_ro,
.get_cd = mmc_gpio_get_cd, .get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = jz4740_mmc_enable_sdio_irq, .enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
.start_signal_voltage_switch = jz4740_voltage_switch,
}; };
static const struct of_device_id jz4740_mmc_of_match[] = { static const struct of_device_id jz4740_mmc_of_match[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment