Skip to contentSkip to conversation

mmc: usdhi6rol0: UHS support

PATCH Superseded Lars Persson 3 participants 5 messages Apr 18, 2016 1 message not in the archive

Subsystems (3)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Lars Persson

author maintainer
#0 lore raw

cover mmc: usdhi6rol0: UHS support

This patch set adds UHS support to the usdhi6rol0 driver, with control of the regulator and pin state settings.

Guennadi Liakhovetski (1):
mmc: usdhi6rol0: add support for UHS modes

Lars Persson (2):
mmc: dt: usdhi6rol0: add optional pinctrl binding
mmc: usdhi6rol0: add pinctrl to set pin drive strength

 .../devicetree/bindings/mmc/usdhi6rol0.txt         |  4 ++
 drivers/mmc/host/usdhi6rol0.c                      | 70 ++++++++++++++++++++++
 2 files changed, 74 insertions(+)
Signature · 1 line
2.1.4
author maintainer
#1 lore raw

PATCH 1/3 mmc: dt: usdhi6rol0: add optional pinctrl binding

Add a pinctrl binding to specify different pin settings for high speed modes and UHS modes.

---
 Documentation/devicetree/bindings/mmc/usdhi6rol0.txt | 4 ++++
 1 file changed, 4 insertions(+)
Documentation/devicetree/bindings/mmc/usdhi6rol0.txt +4 -0
index 8babdaa..9dd9478 100644
@@ -12,6 +12,10 @@ Optional properties:
 
 - vmmc-supply:	a phandle of a regulator, supplying Vcc to the card
 - vqmmc-supply:	a phandle of a regulator, supplying VccQ to the card
+- pinctrl-names: Must contain a "default" entry and optionally a "pins_uhs"
+                 entry for the UHS pin configuration.
+- pinctrl-N: One property for each name listed in pinctrl-names, see
+             ../pinctrl/pinctrl-bindings.txt.
 
 Additionally any standard mmc bindings from mmc.txt can be used.
 
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw

PATCH 2/3 mmc: usdhi6rol0: add support for UHS modes

From: Guennadi Liakhovetski <[email protected]>

The mmc core will only enable UHS modes if the host supports the .start_signal_voltage_switch() operation. Add this method to the v08r07 driver even if there's actually nothing to do in it.

---
 drivers/mmc/host/usdhi6rol0.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
drivers/mmc/host/usdhi6rol0.c +32 -0
index 807c06e..5dde31b 100644
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/time.h>
@@ -1147,12 +1148,43 @@ static void usdhi6_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	}
 }
 
+static int usdhi6_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	int ret;
+
+	if (IS_ERR(mmc->supply.vqmmc))
+		return 0;
+
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		ret = regulator_set_voltage(mmc->supply.vqmmc,
+					    2700000, 3600000);
+		break;
+	case MMC_SIGNAL_VOLTAGE_180:
+		ret = regulator_set_voltage(mmc->supply.vqmmc,
+					    1700000, 1950000);
+		break;
+	case MMC_SIGNAL_VOLTAGE_120:
+		ret = regulator_set_voltage(mmc->supply.vqmmc,
+					    1100000, 1300000);
+		break;
+	default:
+		return 0;
+	}
+
+	if (ret < 0)
+		dev_warn(mmc_dev(mmc), "Voltage switch failed: %d\n", ret);
+
+	return ret;
+}
+
 static struct mmc_host_ops usdhi6_ops = {
 	.request	= usdhi6_request,
 	.set_ios	= usdhi6_set_ios,
 	.get_cd		= usdhi6_get_cd,
 	.get_ro		= usdhi6_get_ro,
 	.enable_sdio_irq = usdhi6_enable_sdio_irq,
+	.start_signal_voltage_switch = usdhi6_sig_volt_switch,
 };
 
 /*			State machine handlers				*/
Signature · 6 lines
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#4 lore raw

Re: [PATCH 2/3] mmc: usdhi6rol0: add support for UHS modes

Quoted 42 lines · Lars Persson

From: Guennadi Liakhovetski <[email protected]>

The mmc core will only enable UHS modes if the host supports the .start_signal_voltage_switch() operation. Add this method to the v08r07 driver even if there's actually nothing to do in it.

---
 drivers/mmc/host/usdhi6rol0.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
drivers/mmc/host/usdhi6rol0.c +14 -0
index 807c06e..5dde31b 100644
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/time.h>
@@ -1147,12 +1148,43 @@ static void usdhi6_enable_sdio_irq(struct mmc_host *mmc, int enable)
        }
 }
 
+static int usdhi6_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       int ret;
+
+       if (IS_ERR(mmc->supply.vqmmc))
+               return 0;
+
+       switch (ios->signal_voltage) {
+       case MMC_SIGNAL_VOLTAGE_330:
+               ret = regulator_set_voltage(mmc->supply.vqmmc,
+                                           2700000, 3600000);
+               break;
+       case MMC_SIGNAL_VOLTAGE_180:

drivers/mmc/host/usdhi6rol0.c static void usdhi6_enable_sdio_irq(struct mmc_host *mmc, int enable) · line 1173

Quoted 10 lines
drivers/mmc/host/usdhi6rol0.c +10 -0
+               ret = regulator_set_voltage(mmc->supply.vqmmc,
+                                           1700000, 1950000);
+               break;
+       case MMC_SIGNAL_VOLTAGE_120:
+               ret = regulator_set_voltage(mmc->supply.vqmmc,
+                                           1100000, 1300000);
+               break;
+       default:
+               return 0;
+       }

Please replace this switch statement with a call to mmc_regulator_set_vqmmc() instead.

Quoted 18 lines
drivers/mmc/host/usdhi6rol0.c +8 -1
+
+       if (ret < 0)
+               dev_warn(mmc_dev(mmc), "Voltage switch failed: %d\n", ret);
+
+       return ret;
+}
+
 static struct mmc_host_ops usdhi6_ops = {
        .request        = usdhi6_request,
        .set_ios        = usdhi6_set_ios,
        .get_cd         = usdhi6_get_cd,
        .get_ro         = usdhi6_get_ro,
        .enable_sdio_irq = usdhi6_enable_sdio_irq,
+       .start_signal_voltage_switch = usdhi6_sig_volt_switch,
 };
 
 /*                     State machine handlers                          */
--
Quoted 2 lines

2.1.4

Kind regards
Uffe

author maintainer
#5 lore raw

PATCH 3/3 mmc: usdhi6rol0: add pinctrl to set pin drive strength

In reply to Lars Persson

Some boards need different pin drive strength for the UHS mode. Add an optional pinctrl setting with two pin states covering UHS speeds and other speeds.

---
 drivers/mmc/host/usdhi6rol0.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
drivers/mmc/host/usdhi6rol0.c +39 -1
index 5dde31b..4675ec0 100644
@@ -22,6 +22,7 @@
 #include <linux/mmc/sdio.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/scatterlist.h>
@@ -199,6 +200,11 @@ struct usdhi6_host {
 	struct dma_chan *chan_rx;
 	struct dma_chan *chan_tx;
 	bool dma_active;
+
+	/* Pin control */
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pins_default;
+	struct pinctrl_state *pins_uhs;
 };
 
 /*			I/O primitives					*/
@@ -1148,6 +1154,24 @@ static void usdhi6_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	}
 }
 
+static int usdhi6_set_pinstates(struct usdhi6_host *host, int voltage)
+{
+	if (IS_ERR(host->pinctrl) || IS_ERR(host->pins_default) ||
+	    IS_ERR(host->pins_uhs))
+		return 0;
+
+	switch (voltage) {
+	case MMC_SIGNAL_VOLTAGE_180:
+	case MMC_SIGNAL_VOLTAGE_120:
+		return pinctrl_select_state(host->pinctrl,
+					    host->pins_uhs);
+
+	default:
+		return pinctrl_select_state(host->pinctrl,
+					    host->pins_default);
+	}
+}
+
 static int usdhi6_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	int ret;
@@ -1172,8 +1196,15 @@ static int usdhi6_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
 		return 0;
 	}
 
-	if (ret < 0)
+	if (ret < 0) {
 		dev_warn(mmc_dev(mmc), "Voltage switch failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = usdhi6_set_pinstates(mmc_priv(mmc), ios->signal_voltage);
+	if (ret)
+		dev_warn_once(mmc_dev(mmc),
+			      "Failed to set pinstate err=%d\n", ret);
 
 	return ret;
 }
@@ -1836,6 +1867,13 @@ static int usdhi6_probe(struct platform_device *pdev)
 		mmc->f_max = host->imclk;
 	mmc->f_min = host->imclk / 512;
 
+	host->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (!IS_ERR(host->pinctrl)) {
+		host->pins_default = pinctrl_lookup_state(host->pinctrl,
+							  PINCTRL_STATE_DEFAULT);
+		host->pins_uhs     = pinctrl_lookup_state(host->pinctrl,
+							  "pins_uhs");
+	}
 	platform_set_drvdata(pdev, host);
 
 	ret = mmc_add_host(mmc);
Signature · 1 line
2.1.4