[PATCH 1/2] mmc: xenon: set signal voltage and max base clock
Stefan Roese
sr at denx.de
Mon Aug 31 15:04:01 CEST 2020
On 19.08.20 16:19, Pali Rohár wrote:
> 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>
Applied to u-boot-marvell/master
Thanks,
Stefan
> ---
> 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;
>
>
Viele Grüße,
Stefan
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de
More information about the U-Boot
mailing list