aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci-xenon-phy.c110
-rw-r--r--drivers/mmc/host/sdhci-xenon.c2
-rw-r--r--drivers/mmc/host/sdhci-xenon.h2
3 files changed, 113 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c
index b14544e91b65..4bdbcd3f2645 100644
--- a/drivers/mmc/host/sdhci-xenon-phy.c
+++ b/drivers/mmc/host/sdhci-xenon-phy.c
@@ -143,6 +143,21 @@ enum xenon_phy_type_enum {
143 NR_PHY_TYPES 143 NR_PHY_TYPES
144}; 144};
145 145
146enum soc_pad_ctrl_type {
147 SOC_PAD_SD,
148 SOC_PAD_FIXED_1_8V,
149};
150
151struct soc_pad_ctrl {
152 /* Register address of SoC PHY PAD ctrl */
153 void __iomem *reg;
154 /* SoC PHY PAD ctrl type */
155 enum soc_pad_ctrl_type pad_type;
156 /* SoC specific operation to set SoC PHY PAD */
157 void (*set_soc_pad)(struct sdhci_host *host,
158 unsigned char signal_voltage);
159};
160
146static struct xenon_emmc_phy_regs xenon_emmc_5_0_phy_regs = { 161static struct xenon_emmc_phy_regs xenon_emmc_5_0_phy_regs = {
147 .timing_adj = XENON_EMMC_5_0_PHY_TIMING_ADJUST, 162 .timing_adj = XENON_EMMC_5_0_PHY_TIMING_ADJUST,
148 .func_ctrl = XENON_EMMC_5_0_PHY_FUNC_CONTROL, 163 .func_ctrl = XENON_EMMC_5_0_PHY_FUNC_CONTROL,
@@ -176,6 +191,8 @@ struct xenon_emmc_phy_params {
176 u8 nr_tun_times; 191 u8 nr_tun_times;
177 /* Divider for calculating Tuning Step */ 192 /* Divider for calculating Tuning Step */
178 u8 tun_step_divider; 193 u8 tun_step_divider;
194
195 struct soc_pad_ctrl pad_ctrl;
179}; 196};
180 197
181static int xenon_alloc_emmc_phy(struct sdhci_host *host) 198static int xenon_alloc_emmc_phy(struct sdhci_host *host)
@@ -254,6 +271,45 @@ static int xenon_emmc_phy_init(struct sdhci_host *host)
254 return 0; 271 return 0;
255} 272}
256 273
274#define ARMADA_3700_SOC_PAD_1_8V 0x1
275#define ARMADA_3700_SOC_PAD_3_3V 0x0
276
277static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host,
278 unsigned char signal_voltage)
279{
280 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
281 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
282 struct xenon_emmc_phy_params *params = priv->phy_params;
283
284 if (params->pad_ctrl.pad_type == SOC_PAD_FIXED_1_8V) {
285 writel(ARMADA_3700_SOC_PAD_1_8V, params->pad_ctrl.reg);
286 } else if (params->pad_ctrl.pad_type == SOC_PAD_SD) {
287 if (signal_voltage == MMC_SIGNAL_VOLTAGE_180)
288 writel(ARMADA_3700_SOC_PAD_1_8V, params->pad_ctrl.reg);
289 else if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
290 writel(ARMADA_3700_SOC_PAD_3_3V, params->pad_ctrl.reg);
291 }
292}
293
294/*
295 * Set SoC PHY voltage PAD control register,
296 * according to the operation voltage on PAD.
297 * The detailed operation depends on SoC implementation.
298 */
299static void xenon_emmc_phy_set_soc_pad(struct sdhci_host *host,
300 unsigned char signal_voltage)
301{
302 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
303 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
304 struct xenon_emmc_phy_params *params = priv->phy_params;
305
306 if (!params->pad_ctrl.reg)
307 return;
308
309 if (params->pad_ctrl.set_soc_pad)
310 params->pad_ctrl.set_soc_pad(host, signal_voltage);
311}
312
257/* 313/*
258 * Enable eMMC PHY HW DLL 314 * Enable eMMC PHY HW DLL
259 * DLL should be enabled and stable before HS200/SDR104 tuning, 315 * DLL should be enabled and stable before HS200/SDR104 tuning,
@@ -562,6 +618,51 @@ phy_init:
562 dev_dbg(mmc_dev(host->mmc), "eMMC PHY setting completes\n"); 618 dev_dbg(mmc_dev(host->mmc), "eMMC PHY setting completes\n");
563} 619}
564 620
621static int get_dt_pad_ctrl_data(struct sdhci_host *host,
622 struct device_node *np,
623 struct xenon_emmc_phy_params *params)
624{
625 int ret = 0;
626 const char *name;
627 struct resource iomem;
628
629 if (of_device_is_compatible(np, "marvell,armada-3700-sdhci"))
630 params->pad_ctrl.set_soc_pad = armada_3700_soc_pad_voltage_set;
631 else
632 return 0;
633
634 if (of_address_to_resource(np, 1, &iomem)) {
635 dev_err(mmc_dev(host->mmc), "Unable to find SoC PAD ctrl register address for %s\n",
636 np->name);
637 return -EINVAL;
638 }
639
640 params->pad_ctrl.reg = devm_ioremap_resource(mmc_dev(host->mmc),
641 &iomem);
642 if (IS_ERR(params->pad_ctrl.reg)) {
643 dev_err(mmc_dev(host->mmc), "Unable to get SoC PHY PAD ctrl register for %s\n",
644 np->name);
645 return PTR_ERR(params->pad_ctrl.reg);
646 }
647
648 ret = of_property_read_string(np, "marvell,pad-type", &name);
649 if (ret) {
650 dev_err(mmc_dev(host->mmc), "Unable to determine SoC PHY PAD ctrl type\n");
651 return ret;
652 }
653 if (!strcmp(name, "sd")) {
654 params->pad_ctrl.pad_type = SOC_PAD_SD;
655 } else if (!strcmp(name, "fixed-1-8v")) {
656 params->pad_ctrl.pad_type = SOC_PAD_FIXED_1_8V;
657 } else {
658 dev_err(mmc_dev(host->mmc), "Unsupported SoC PHY PAD ctrl type %s\n",
659 name);
660 return -EINVAL;
661 }
662
663 return ret;
664}
665
565static int xenon_emmc_phy_parse_param_dt(struct sdhci_host *host, 666static int xenon_emmc_phy_parse_param_dt(struct sdhci_host *host,
566 struct device_node *np, 667 struct device_node *np,
567 struct xenon_emmc_phy_params *params) 668 struct xenon_emmc_phy_params *params)
@@ -590,7 +691,14 @@ static int xenon_emmc_phy_parse_param_dt(struct sdhci_host *host,
590 &value)) 691 &value))
591 params->tun_step_divider = value & 0xFF; 692 params->tun_step_divider = value & 0xFF;
592 693
593 return 0; 694 return get_dt_pad_ctrl_data(host, np, params);
695}
696
697/* Set SoC PHY Voltage PAD */
698void xenon_soc_pad_ctrl(struct sdhci_host *host,
699 unsigned char signal_voltage)
700{
701 xenon_emmc_phy_set_soc_pad(host, signal_voltage);
594} 702}
595 703
596/* 704/*
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
index 36e22bd2b8cc..8e56b9ccfb39 100644
--- a/drivers/mmc/host/sdhci-xenon.c
+++ b/drivers/mmc/host/sdhci-xenon.c
@@ -280,6 +280,8 @@ static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
280 */ 280 */
281 xenon_enable_internal_clk(host); 281 xenon_enable_internal_clk(host);
282 282
283 xenon_soc_pad_ctrl(host, ios->signal_voltage);
284
283 /* 285 /*
284 * If Vqmmc is fixed on platform, vqmmc regulator should be unavailable. 286 * If Vqmmc is fixed on platform, vqmmc regulator should be unavailable.
285 * Thus SDHCI_CTRL_VDD_180 bit might not work then. 287 * Thus SDHCI_CTRL_VDD_180 bit might not work then.
diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h
index b29d45358de8..6e6523ea01ce 100644
--- a/drivers/mmc/host/sdhci-xenon.h
+++ b/drivers/mmc/host/sdhci-xenon.h
@@ -96,4 +96,6 @@ int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios);
96void xenon_clean_phy(struct sdhci_host *host); 96void xenon_clean_phy(struct sdhci_host *host);
97int xenon_phy_parse_dt(struct device_node *np, 97int xenon_phy_parse_dt(struct device_node *np,
98 struct sdhci_host *host); 98 struct sdhci_host *host);
99void xenon_soc_pad_ctrl(struct sdhci_host *host,
100 unsigned char signal_voltage);
99#endif 101#endif