[EXT] [PATCH 1/2] mmc: xenon: set signal voltage and max base clock

Kostya Porotchkin kostap at marvell.com
Wed Aug 19 19:58:28 CEST 2020



> -----Original Message-----
> From: Pali Rohár <pali at kernel.org>
> Sent: Wednesday, August 19, 2020 17:20
> To: Peng Fan <peng.fan at nxp.com>; Kostya Porotchkin
> <kostap at marvell.com>; Stefan Roese <sr at denx.de>
> Cc: u-boot at lists.denx.de
> Subject: [EXT] [PATCH 1/2] mmc: xenon: set signal voltage and max base
> clock
> 
> External Email
> 
> ----------------------------------------------------------------------
> From: Evan Wang <xswang at marvell.com>
> 
> - The SDIO signal voltage and max base clock frequency
>   setting are missing in driver, which causes SDIO
>   not working.
> - The patch adds SDIO signal voltage switch support,
>   which is based on regulator-gpio of vqmmc-supply, and
>   sets the max base clock frequency.
> - Fix the zero clock value in call to sdhci_setup_cfg()
>   function.
> 
> Change-Id: I79c8860c65b8db166f4f70db56ede4097f71f1fa
> Signed-off-by: Evan Wang <xswang at marvell.com>
> Reviewed-on: http://vgitil04.il.marvell.com:8080/53589
> Reviewed-by: Hua Jing <jinghua at marvell.com>
> Tested-by: Hua Jing <jinghua at marvell.com>
> [pali: Amended fixup patch]
> Signed-off-by: Pali Rohár <pali at kernel.org>
Reviewed-by: Konstantin Porotchkin <kostap at marvell.com>

> ---
>  drivers/mmc/xenon_sdhci.c | 79
> ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 78 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c index
> 356dd9846d..7f9a579c83 100644
> --- a/drivers/mmc/xenon_sdhci.c
> +++ b/drivers/mmc/xenon_sdhci.c
> @@ -22,6 +22,7 @@
>  #include <linux/libfdt.h>
>  #include <malloc.h>
>  #include <sdhci.h>
> +#include <power/regulator.h>
> 
>  DECLARE_GLOBAL_DATA_PTR;
> 
> @@ -42,6 +43,14 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define SDHC_SYS_EXT_OP_CTRL			0x010C
>  #define MASK_CMD_CONFLICT_ERROR			BIT(8)
> 
> +#define SDHC_SLOT_EMMC_CTRL			0x0130
> +#define ENABLE_DATA_STROBE_SHIFT		24
> +#define SET_EMMC_RSTN_SHIFT			16
> +#define EMMC_VCCQ_MASK				0x3
> +#define EMMC_VCCQ_1_8V				0x1
> +#define EMMC_VCCQ_1_2V				0x2
> +#define	EMMC_VCCQ_3_3V				0x3
> +
>  #define SDHC_SLOT_RETUNING_REQ_CTRL		0x0144
>  /* retuning compatible */
>  #define RETUNING_COMPATIBLE			0x1
> @@ -108,6 +117,8 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define MMC_TIMING_MMC_HS400	10
> 
>  #define XENON_MMC_MAX_CLK	400000000
> +#define XENON_MMC_3V3_UV	3300000
> +#define XENON_MMC_1V8_UV	1800000
> 
>  enum soc_pad_ctrl_type {
>  	SOC_PAD_SD,
> @@ -128,6 +139,8 @@ struct xenon_sdhci_priv {
> 
>  	void *pad_ctrl_reg;
>  	int pad_type;
> +
> +	struct udevice *vqmmc;
>  };
> 
>  static int xenon_mmc_phy_init(struct sdhci_host *host) @@ -208,6 +221,51
> @@ static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host)
>  		writel(ARMADA_3700_SOC_PAD_3_3V, priv->pad_ctrl_reg);
> }
> 
> +static int xenon_mmc_start_signal_voltage_switch(struct sdhci_host
> +*host) {
> +	struct xenon_sdhci_priv *priv = host->mmc->priv;
> +	u8 voltage;
> +	u32 ctrl;
> +	int ret = 0;
> +
> +	/* If there is no vqmmc regulator, return */
> +	if (!priv->vqmmc)
> +		return 0;
> +
> +	if (priv->pad_type == SOC_PAD_FIXED_1_8V) {
> +		/* Switch to 1.8v */
> +		ret = regulator_set_value(priv->vqmmc,
> +					  XENON_MMC_1V8_UV);
> +	} else if (priv->pad_type == SOC_PAD_SD) {
> +		/* Get voltage info */
> +		voltage = sdhci_readb(host, SDHCI_POWER_CONTROL);
> +		voltage &= ~SDHCI_POWER_ON;
> +
> +		if (voltage == SDHCI_POWER_330) {
> +			/* Switch to 3.3v */
> +			ret = regulator_set_value(priv->vqmmc,
> +						  XENON_MMC_3V3_UV);
> +		} else {
> +			/* Switch to 1.8v */
> +			ret = regulator_set_value(priv->vqmmc,
> +						  XENON_MMC_1V8_UV);
> +		}
> +	}
> +
> +	/* Set VCCQ, eMMC mode: 1.8V; SD/SDIO mode: 3.3V */
> +	ctrl = sdhci_readl(host, SDHC_SLOT_EMMC_CTRL);
> +	if (IS_SD(host->mmc))
> +		ctrl |= EMMC_VCCQ_3_3V;
> +	else
> +		ctrl |= EMMC_VCCQ_1_8V;
> +	sdhci_writel(host, ctrl, SDHC_SLOT_EMMC_CTRL);
> +
> +	if (ret)
> +		printf("Signal voltage switch fail\n");
> +
> +	return ret;
> +}
> +
>  static void xenon_mmc_phy_set(struct sdhci_host *host)  {
>  	struct xenon_sdhci_priv *priv = host->mmc->priv; @@ -334,6
> +392,13 @@ static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
>  	uint speed = host->mmc->tran_speed;
>  	int pwr_18v = 0;
> 
> +	/*
> +	 * Signal Voltage Switching is only applicable for Host Controllers
> +	 * v3.00 and above.
> +	 */
> +	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
> +		xenon_mmc_start_signal_voltage_switch(host);
> +
>  	if ((sdhci_readb(host, SDHCI_POWER_CONTROL) &
> ~SDHCI_POWER_ON) ==
>  	    SDHCI_POWER_180)
>  		pwr_18v = 1;
> @@ -394,6 +459,18 @@ static int xenon_sdhci_probe(struct udevice *dev)
>  	/* Set default timing */
>  	priv->timing = MMC_TIMING_LEGACY;
> 
> +	/* Get the vqmmc regulator if there is */
> +	device_get_supply_regulator(dev, "vqmmc-supply", &priv-
> >vqmmc);
> +	/* Set the initial voltage value to 3.3V if there is regulator */
> +	if (priv->vqmmc) {
> +		ret = regulator_set_value(priv->vqmmc,
> +					  XENON_MMC_3V3_UV);
> +		if (ret) {
> +			printf("Failed to set VQMMC regulator to 3.3V\n");
> +			return ret;
> +		}
> +	}
> +
>  	/* Disable auto clock gating during init */
>  	xenon_mmc_set_acg(host, false);
> 
> @@ -426,7 +503,7 @@ static int xenon_sdhci_probe(struct udevice *dev)
>  	host->ops = &xenon_sdhci_ops;
> 
>  	host->max_clk = XENON_MMC_MAX_CLK;
> -	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
> +	ret = sdhci_setup_cfg(&plat->cfg, host, XENON_MMC_MAX_CLK, 0);
>  	if (ret)
>  		return ret;
> 
> --
> 2.20.1



More information about the U-Boot mailing list