Re: [PATCH RFC 04/15] mmc: sunxi: Support vqmmc regulator
From: Ulf Hansson
Date: Fri Jan 29 2016 - 06:44:00 EST
On 21 January 2016 at 06:26, Chen-Yu Tsai <wens@xxxxxxxx> wrote:
> 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@xxxxxxxx>
Thanks, applied for next!
Kind regards
Uffe
> ---
> drivers/mmc/host/sunxi-mmc.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> index 0495ae7da6d6..4bec87458317 100644
> --- a/drivers/mmc/host/sunxi-mmc.c
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -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>
> @@ -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);
> @@ -923,6 +953,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,
> };
> --
> 2.7.0.rc3
>