On 19.08.20 16:19, Pali Rohár wrote:
From: Evan Wang <xsw...@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 <xsw...@marvell.com>
Reviewed-on: http://vgitil04.il.marvell.com:8080/53589
Reviewed-by: Hua Jing <jing...@marvell.com>
Tested-by: Hua Jing <jing...@marvell.com>
[pali: Amended fixup patch]
Signed-off-by: Pali Rohár <p...@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: s...@denx.de

Reply via email to