diff mbox

[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 (mailing list archive)
State New, archived
Headers show

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
Patrice CHOTARD Jan. 18, 2018, 1:35 p.m. UTC | #2
Hi Ulf

On 01/17/2018 10:34 AM, Ulf Hansson wrote:
> [...]
> 
>>          /*
>> @@ -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.

Ok

> 
> 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.

Regarding pinctrl_select_state() call with a NULL state, this case is 
managed inside pinctrl_state(), but ok, it will be more elegant to exit 
directly in case of no DT pins definition found.

> 
>> +               }
>> +
>> +               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.

ok

Thanks

Patrice
> 
>> +               }
>> +       }
>> +
> 
> [...]
> 
> Kind regards
> Uffe
>
diff mbox

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;