diff mbox series

[v2,04/15] mmc: mmci: Add support for setting pad type via pinctrl

Message ID 1516105859-3525-5-git-send-email-patrice.chotard@st.com
State New
Headers show
Series Add MMCI support for STM32F SoCs family | expand

Commit Message

Patrice CHOTARD Jan. 16, 2018, 12:30 p.m. UTC
From: Patrice Chotard <patrice.chotard@st.com>

If variant hasn't the control bit to switch pads in opendrain mode,
we can achieve the same result by asking to the pinmux driver to
configure pins for us.

This patch make the mmci driver able to do this whenever needed.

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
---

v2: _ Add pinctrl pin management when open drain bit is not available


 drivers/mmc/host/mmci.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
 drivers/mmc/host/mmci.h |  5 +++++
 2 files changed, 45 insertions(+), 5 deletions(-)

Comments

Ulf Hansson Jan. 17, 2018, 9:34 a.m. UTC | #1
[...]

>         /*
> @@ -1616,6 +1625,32 @@ static int mmci_probe(struct amba_device *dev,
>         host = mmc_priv(mmc);
>         host->mmc = mmc;
>
> +       /*
> +        * Some variant (STM32) doesn't have opendrain bit, nevertheless
> +        * pins can be set accordingly using pinctrl
> +        */
> +       if (!variant->opendrain) {
> +               host->pinctrl = devm_pinctrl_get(&dev->dev);
> +               if (IS_ERR(host->pinctrl)) {
> +                       dev_err(&dev->dev, "failed to get pinctrl");
> +                       goto host_free;
> +               }
> +
> +               host->pins_default = pinctrl_lookup_state(host->pinctrl,
> +                                                         PINCTRL_STATE_DEFAULT);
> +               if (IS_ERR(host->pins_default)) {
> +                       dev_warn(mmc_dev(mmc), "Can't select default pins\n");
> +                       host->pins_default = NULL;

This is wrong, I think you should bail out and return the error code instead.

Moreover, calling pinctrl_select_state() from ->set_ios by using a
NULL state, will likely trigger a NULL pointer deference bug in the
pinctrl layer.

> +               }
> +
> +               host->pins_opendrain = pinctrl_lookup_state(host->pinctrl,
> +                                                           MMCI_PINCTRL_STATE_OPENDRAIN);
> +               if (IS_ERR(host->pins_opendrain)) {
> +                       dev_warn(mmc_dev(mmc), "Can't select opendrain pins\n");
> +                       host->pins_opendrain = NULL;

Ditto.

> +               }
> +       }
> +

[...]

Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrice CHOTARD Jan. 18, 2018, 1:35 p.m. UTC | #2
SGkgVWxmDQoNCk9uIDAxLzE3LzIwMTggMTA6MzQgQU0sIFVsZiBIYW5zc29uIHdyb3RlOg0KPiBb
Li4uXQ0KPiANCj4+ICAgICAgICAgIC8qDQo+PiBAQCAtMTYxNiw2ICsxNjI1LDMyIEBAIHN0YXRp
YyBpbnQgbW1jaV9wcm9iZShzdHJ1Y3QgYW1iYV9kZXZpY2UgKmRldiwNCj4+ICAgICAgICAgIGhv
c3QgPSBtbWNfcHJpdihtbWMpOw0KPj4gICAgICAgICAgaG9zdC0+bW1jID0gbW1jOw0KPj4NCj4+
ICsgICAgICAgLyoNCj4+ICsgICAgICAgICogU29tZSB2YXJpYW50IChTVE0zMikgZG9lc24ndCBo
YXZlIG9wZW5kcmFpbiBiaXQsIG5ldmVydGhlbGVzcw0KPj4gKyAgICAgICAgKiBwaW5zIGNhbiBi
ZSBzZXQgYWNjb3JkaW5nbHkgdXNpbmcgcGluY3RybA0KPj4gKyAgICAgICAgKi8NCj4+ICsgICAg
ICAgaWYgKCF2YXJpYW50LT5vcGVuZHJhaW4pIHsNCj4+ICsgICAgICAgICAgICAgICBob3N0LT5w
aW5jdHJsID0gZGV2bV9waW5jdHJsX2dldCgmZGV2LT5kZXYpOw0KPj4gKyAgICAgICAgICAgICAg
IGlmIChJU19FUlIoaG9zdC0+cGluY3RybCkpIHsNCj4+ICsgICAgICAgICAgICAgICAgICAgICAg
IGRldl9lcnIoJmRldi0+ZGV2LCAiZmFpbGVkIHRvIGdldCBwaW5jdHJsIik7DQo+PiArICAgICAg
ICAgICAgICAgICAgICAgICBnb3RvIGhvc3RfZnJlZTsNCj4+ICsgICAgICAgICAgICAgICB9DQo+
PiArDQo+PiArICAgICAgICAgICAgICAgaG9zdC0+cGluc19kZWZhdWx0ID0gcGluY3RybF9sb29r
dXBfc3RhdGUoaG9zdC0+cGluY3RybCwNCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQSU5DVFJMX1NUQVRFX0RFRkFVTFQpOw0KPj4g
KyAgICAgICAgICAgICAgIGlmIChJU19FUlIoaG9zdC0+cGluc19kZWZhdWx0KSkgew0KPj4gKyAg
ICAgICAgICAgICAgICAgICAgICAgZGV2X3dhcm4obW1jX2RldihtbWMpLCAiQ2FuJ3Qgc2VsZWN0
IGRlZmF1bHQgcGluc1xuIik7DQo+PiArICAgICAgICAgICAgICAgICAgICAgICBob3N0LT5waW5z
X2RlZmF1bHQgPSBOVUxMOw0KPiANCj4gVGhpcyBpcyB3cm9uZywgSSB0aGluayB5b3Ugc2hvdWxk
IGJhaWwgb3V0IGFuZCByZXR1cm4gdGhlIGVycm9yIGNvZGUgaW5zdGVhZC4NCg0KT2sNCg0KPiAN
Cj4gTW9yZW92ZXIsIGNhbGxpbmcgcGluY3RybF9zZWxlY3Rfc3RhdGUoKSBmcm9tIC0+c2V0X2lv
cyBieSB1c2luZyBhDQo+IE5VTEwgc3RhdGUsIHdpbGwgbGlrZWx5IHRyaWdnZXIgYSBOVUxMIHBv
aW50ZXIgZGVmZXJlbmNlIGJ1ZyBpbiB0aGUNCj4gcGluY3RybCBsYXllci4NCg0KUmVnYXJkaW5n
IHBpbmN0cmxfc2VsZWN0X3N0YXRlKCkgY2FsbCB3aXRoIGEgTlVMTCBzdGF0ZSwgdGhpcyBjYXNl
IGlzIA0KbWFuYWdlZCBpbnNpZGUgcGluY3RybF9zdGF0ZSgpLCBidXQgb2ssIGl0IHdpbGwgYmUg
bW9yZSBlbGVnYW50IHRvIGV4aXQgDQpkaXJlY3RseSBpbiBjYXNlIG9mIG5vIERUIHBpbnMgZGVm
aW5pdGlvbiBmb3VuZC4NCg0KPiANCj4+ICsgICAgICAgICAgICAgICB9DQo+PiArDQo+PiArICAg
ICAgICAgICAgICAgaG9zdC0+cGluc19vcGVuZHJhaW4gPSBwaW5jdHJsX2xvb2t1cF9zdGF0ZSho
b3N0LT5waW5jdHJsLA0KPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgTU1DSV9QSU5DVFJMX1NUQVRFX09QRU5EUkFJTik7DQo+PiAr
ICAgICAgICAgICAgICAgaWYgKElTX0VSUihob3N0LT5waW5zX29wZW5kcmFpbikpIHsNCj4+ICsg
ICAgICAgICAgICAgICAgICAgICAgIGRldl93YXJuKG1tY19kZXYobW1jKSwgIkNhbid0IHNlbGVj
dCBvcGVuZHJhaW4gcGluc1xuIik7DQo+PiArICAgICAgICAgICAgICAgICAgICAgICBob3N0LT5w
aW5zX29wZW5kcmFpbiA9IE5VTEw7DQo+IA0KPiBEaXR0by4NCg0Kb2sNCg0KVGhhbmtzDQoNClBh
dHJpY2UNCj4gDQo+PiArICAgICAgICAgICAgICAgfQ0KPj4gKyAgICAgICB9DQo+PiArDQo+IA0K
PiBbLi4uXQ0KPiANCj4gS2luZCByZWdhcmRzDQo+IFVmZmUNCj4g
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox series

Patch

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index eb5fcfe..2a7aea7 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1465,13 +1465,22 @@  static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 				~MCI_ST_DATA2DIREN);
 	}
 
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN &&
-	    host->variant->opendrain) {
+	if (host->variant->opendrain) {
+		if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+			/*
+			 * The ST Micro variant use the ROD bit for
+			 * something else and only has OD (Open Drain).
+			 */
+			pwr |= host->variant->opendrain;
+	} else {
 		/*
-		 * The ST Micro variant use the ROD bit for
-		 * something else and only has OD (Open Drain).
+		 * If the variant cannot configure the pads by its own, then we
+		 * expect the pinctrl to be able to do that for us
 		 */
-		pwr |= host->variant->opendrain;
+		if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+			pinctrl_select_state(host->pinctrl, host->pins_opendrain);
+		else
+			pinctrl_select_state(host->pinctrl, host->pins_default);
 	}
 
 	/*
@@ -1616,6 +1625,32 @@  static int mmci_probe(struct amba_device *dev,
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 
+	/*
+	 * Some variant (STM32) doesn't have opendrain bit, nevertheless
+	 * pins can be set accordingly using pinctrl
+	 */
+	if (!variant->opendrain) {
+		host->pinctrl = devm_pinctrl_get(&dev->dev);
+		if (IS_ERR(host->pinctrl)) {
+			dev_err(&dev->dev, "failed to get pinctrl");
+			goto host_free;
+		}
+
+		host->pins_default = pinctrl_lookup_state(host->pinctrl,
+							  PINCTRL_STATE_DEFAULT);
+		if (IS_ERR(host->pins_default)) {
+			dev_warn(mmc_dev(mmc), "Can't select default pins\n");
+			host->pins_default = NULL;
+		}
+
+		host->pins_opendrain = pinctrl_lookup_state(host->pinctrl,
+							    MMCI_PINCTRL_STATE_OPENDRAIN);
+		if (IS_ERR(host->pins_opendrain)) {
+			dev_warn(mmc_dev(mmc), "Can't select opendrain pins\n");
+			host->pins_opendrain = NULL;
+		}
+	}
+
 	host->hw_designer = amba_manf(dev);
 	host->hw_revision = amba_rev(dev);
 	dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 83160a9..f91cdf7 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -192,6 +192,8 @@ 
 
 #define NR_SG		128
 
+#define MMCI_PINCTRL_STATE_OPENDRAIN "opendrain"
+
 struct clk;
 struct variant_data;
 struct dma_chan;
@@ -227,6 +229,9 @@  struct mmci_host {
 	bool			vqmmc_enabled;
 	struct mmci_platform_data *plat;
 	struct variant_data	*variant;
+	struct pinctrl		*pinctrl;
+	struct pinctrl_state	*pins_default;
+	struct pinctrl_state	*pins_opendrain;
 
 	u8			hw_designer;
 	u8			hw_revision:4;