Skip to content

Commit

Permalink
mmc: sunxi: Support vqmmc regulator
Browse files Browse the repository at this point in the history
eMMC chips require 2 power supplies, vmmc for internal logic, and vqmmc
for driving output buffers. vqmmc also controls signaling voltage. Most
boards we've seen use the same regulator for both, nevertheless the 2
have different usages, and should be set separately.

This patch adds support for vqmmc regulator supply, including voltage
switching. The MMC core can use this to try different signaling voltages
for eMMC.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
Chen-Yu Tsai authored and Ulf Hansson committed Feb 29, 2016
1 parent 4159215 commit f771f6e
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions drivers/mmc/host/sunxi-mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/reset.h>
#include <linux/regulator/consumer.h>

#include <linux/of_address.h>
#include <linux/of_gpio.h>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
};
Expand Down

0 comments on commit f771f6e

Please sign in to comment.