linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery
@ 2020-04-15  7:06 Codrin Ciubotariu
  2020-04-19 12:50 ` ludovic.desroches
  2020-05-05 15:12 ` Wolfram Sang
  0 siblings, 2 replies; 6+ messages in thread
From: Codrin Ciubotariu @ 2020-04-15  7:06 UTC (permalink / raw)
  To: linux-gpio, linux-i2c, linux-arm-kernel, linux-kernel
  Cc: ludovic.desroches, nicolas.ferre, alexandre.belloni,
	kamel.bouhara, linux, linus.walleij, alan, wsa,
	Codrin Ciubotariu

devm_gpiod_get() usually calls gpio_request_enable() for non-strict pinmux
drivers. These puts the pins in GPIO mode, whithout notifying the pinctrl
driver. At this point, the I2C bus no longer owns the pins. To mux the
pins back to the I2C bus, we use the pinctrl driver to change the state
of the pins to GPIO, before using devm_gpiod_get(). After the pins are
received as GPIOs, we switch theer pinctrl state back to the default
one,

Fixes: d3d3fdcc4c90 ("i2c: at91: implement i2c bus recovery")
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
---
 drivers/i2c/busses/i2c-at91-master.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c
index 0aba51a7df32..43d85845c897 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -845,6 +845,18 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev,
 							 PINCTRL_STATE_DEFAULT);
 	dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl,
 						      "gpio");
+	if (IS_ERR(dev->pinctrl_pins_default) ||
+	    IS_ERR(dev->pinctrl_pins_gpio)) {
+		dev_info(&pdev->dev, "pinctrl states incomplete for recovery\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * pins will be taken as GPIO, so we might as well inform pinctrl about
+	 * this and move the state to GPIO
+	 */
+	pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
+
 	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
 	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER)
 		return -EPROBE_DEFER;
@@ -855,9 +867,7 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev,
 		return -EPROBE_DEFER;
 
 	if (IS_ERR(rinfo->sda_gpiod) ||
-	    IS_ERR(rinfo->scl_gpiod) ||
-	    IS_ERR(dev->pinctrl_pins_default) ||
-	    IS_ERR(dev->pinctrl_pins_gpio)) {
+	    IS_ERR(rinfo->scl_gpiod)) {
 		dev_info(&pdev->dev, "recovery information incomplete\n");
 		if (!IS_ERR(rinfo->sda_gpiod)) {
 			gpiod_put(rinfo->sda_gpiod);
@@ -870,6 +880,9 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
+	/* change the state of the pins back to their default state */
+	pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
+
 	dev_info(&pdev->dev, "using scl, sda for recovery\n");
 
 	rinfo->prepare_recovery = at91_prepare_twi_recovery;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery
  2020-04-15  7:06 [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery Codrin Ciubotariu
@ 2020-04-19 12:50 ` ludovic.desroches
  2020-05-05 15:12 ` Wolfram Sang
  1 sibling, 0 replies; 6+ messages in thread
From: ludovic.desroches @ 2020-04-19 12:50 UTC (permalink / raw)
  To: Codrin Ciubotariu
  Cc: linux-gpio, linux-i2c, linux-arm-kernel, linux-kernel,
	nicolas.ferre, alexandre.belloni, kamel.bouhara, linux,
	linus.walleij, alan, wsa

On Wed, Apr 15, 2020 at 10:06:43AM +0300, Codrin Ciubotariu wrote:
> devm_gpiod_get() usually calls gpio_request_enable() for non-strict pinmux
> drivers. These puts the pins in GPIO mode, whithout notifying the pinctrl
> driver. At this point, the I2C bus no longer owns the pins. To mux the
> pins back to the I2C bus, we use the pinctrl driver to change the state
> of the pins to GPIO, before using devm_gpiod_get(). After the pins are
> received as GPIOs, we switch theer pinctrl state back to the default
> one,
> 
> Fixes: d3d3fdcc4c90 ("i2c: at91: implement i2c bus recovery")
> Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>

At the moment, I don't see another way to deal with this issue.

Link to the discussion:
https://lore.kernel.org/linux-arm-kernel/20191206173343.GX25745@shell.armlinux.org.uk/

Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>

> ---
>  drivers/i2c/busses/i2c-at91-master.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c
> index 0aba51a7df32..43d85845c897 100644
> --- a/drivers/i2c/busses/i2c-at91-master.c
> +++ b/drivers/i2c/busses/i2c-at91-master.c
> @@ -845,6 +845,18 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev,
>  							 PINCTRL_STATE_DEFAULT);
>  	dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl,
>  						      "gpio");
> +	if (IS_ERR(dev->pinctrl_pins_default) ||
> +	    IS_ERR(dev->pinctrl_pins_gpio)) {
> +		dev_info(&pdev->dev, "pinctrl states incomplete for recovery\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * pins will be taken as GPIO, so we might as well inform pinctrl about
> +	 * this and move the state to GPIO
> +	 */
> +	pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
> +
>  	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
>  	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER)
>  		return -EPROBE_DEFER;
> @@ -855,9 +867,7 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev,
>  		return -EPROBE_DEFER;
>  
>  	if (IS_ERR(rinfo->sda_gpiod) ||
> -	    IS_ERR(rinfo->scl_gpiod) ||
> -	    IS_ERR(dev->pinctrl_pins_default) ||
> -	    IS_ERR(dev->pinctrl_pins_gpio)) {
> +	    IS_ERR(rinfo->scl_gpiod)) {
>  		dev_info(&pdev->dev, "recovery information incomplete\n");
>  		if (!IS_ERR(rinfo->sda_gpiod)) {
>  			gpiod_put(rinfo->sda_gpiod);
> @@ -870,6 +880,9 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev,
>  		return -EINVAL;
>  	}
>  
> +	/* change the state of the pins back to their default state */
> +	pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
> +
>  	dev_info(&pdev->dev, "using scl, sda for recovery\n");
>  
>  	rinfo->prepare_recovery = at91_prepare_twi_recovery;
> -- 
> 2.20.1
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery
  2020-04-15  7:06 [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery Codrin Ciubotariu
  2020-04-19 12:50 ` ludovic.desroches
@ 2020-05-05 15:12 ` Wolfram Sang
  2020-05-13 11:07   ` Codrin.Ciubotariu
  1 sibling, 1 reply; 6+ messages in thread
From: Wolfram Sang @ 2020-05-05 15:12 UTC (permalink / raw)
  To: Codrin Ciubotariu
  Cc: linux-gpio, linux-i2c, linux-arm-kernel, linux-kernel,
	ludovic.desroches, nicolas.ferre, alexandre.belloni,
	kamel.bouhara, linux, linus.walleij, alan

[-- Attachment #1: Type: text/plain, Size: 933 bytes --]

On Wed, Apr 15, 2020 at 10:06:43AM +0300, Codrin Ciubotariu wrote:
> devm_gpiod_get() usually calls gpio_request_enable() for non-strict pinmux
> drivers. These puts the pins in GPIO mode, whithout notifying the pinctrl
> driver. At this point, the I2C bus no longer owns the pins. To mux the
> pins back to the I2C bus, we use the pinctrl driver to change the state
> of the pins to GPIO, before using devm_gpiod_get(). After the pins are
> received as GPIOs, we switch theer pinctrl state back to the default
> one,
> 
> Fixes: d3d3fdcc4c90 ("i2c: at91: implement i2c bus recovery")
> Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>

Applied to for-current, thanks!

This will do for 5.7. For 5.8 or 5.9, I can imagine to take the two
pinctrl_state pointers into bus_recovery_info and handle all this in the
core. I will try this later this week if noone is super-eager to try it
out before.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Re: [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery
  2020-05-05 15:12 ` Wolfram Sang
@ 2020-05-13 11:07   ` Codrin.Ciubotariu
  2020-05-20 16:27     ` Wolfram Sang
  0 siblings, 1 reply; 6+ messages in thread
From: Codrin.Ciubotariu @ 2020-05-13 11:07 UTC (permalink / raw)
  To: wsa
  Cc: linux-gpio, linux-i2c, linux-arm-kernel, linux-kernel,
	Ludovic.Desroches, Nicolas.Ferre, alexandre.belloni,
	kamel.bouhara, linux, linus.walleij, alan

On 05.05.2020 18:12, Wolfram Sang wrote:
> On Wed, Apr 15, 2020 at 10:06:43AM +0300, Codrin Ciubotariu wrote:
>> devm_gpiod_get() usually calls gpio_request_enable() for non-strict pinmux
>> drivers. These puts the pins in GPIO mode, whithout notifying the pinctrl
>> driver. At this point, the I2C bus no longer owns the pins. To mux the
>> pins back to the I2C bus, we use the pinctrl driver to change the state
>> of the pins to GPIO, before using devm_gpiod_get(). After the pins are
>> received as GPIOs, we switch theer pinctrl state back to the default
>> one,
>>
>> Fixes: d3d3fdcc4c90 ("i2c: at91: implement i2c bus recovery")
>> Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
> 
> Applied to for-current, thanks!

Just looked at this patch and noticed that I should change the pinctrl 
state back to default if we can't get the gpio pins. I will submit a 
patch to fix this.

> 
> This will do for 5.7. For 5.8 or 5.9, I can imagine to take the two
> pinctrl_state pointers into bus_recovery_info and handle all this in the
> core. I will try this later this week if noone is super-eager to try it
> out before.
> 

By 'all this' you mean to move the entire function in the core, right? 
Having just these two pointers bus_recinovery_info won't help much. I 
can try it, if you haven't already started...

Best regards,
Codrin


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Re: [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery
  2020-05-13 11:07   ` Codrin.Ciubotariu
@ 2020-05-20 16:27     ` Wolfram Sang
  2020-06-09 11:43       ` Codrin.Ciubotariu
  0 siblings, 1 reply; 6+ messages in thread
From: Wolfram Sang @ 2020-05-20 16:27 UTC (permalink / raw)
  To: Codrin.Ciubotariu
  Cc: linux-gpio, linux-i2c, linux-arm-kernel, linux-kernel,
	Ludovic.Desroches, Nicolas.Ferre, alexandre.belloni,
	kamel.bouhara, linux, linus.walleij, alan

[-- Attachment #1: Type: text/plain, Size: 853 bytes --]


> > This will do for 5.7. For 5.8 or 5.9, I can imagine to take the two
> > pinctrl_state pointers into bus_recovery_info and handle all this in the
> > core. I will try this later this week if noone is super-eager to try it
> > out before.
> > 
> 
> By 'all this' you mean to move the entire function in the core, right? 
> Having just these two pointers bus_recinovery_info won't help much. I 
> can try it, if you haven't already started...

I mean to add those two pointers to bus_recinovery_info and if they are
populated, then the I2C core is doing the necessary magic (or maybe just
the pinctrl handle and assume the states have fixed names?). Russell
just sent patches to add it to the PXA driver, so we could now double
check how much could be factored out.

I haven't started yet, let's keep in touch who started first :)


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Re: Re: [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery
  2020-05-20 16:27     ` Wolfram Sang
@ 2020-06-09 11:43       ` Codrin.Ciubotariu
  0 siblings, 0 replies; 6+ messages in thread
From: Codrin.Ciubotariu @ 2020-06-09 11:43 UTC (permalink / raw)
  To: wsa
  Cc: linux-gpio, linux-i2c, linux-arm-kernel, linux-kernel,
	Ludovic.Desroches, Nicolas.Ferre, alexandre.belloni,
	kamel.bouhara, linux, linus.walleij, alan

On 20.05.2020 19:27, Wolfram Sang wrote:
> 
>>> This will do for 5.7. For 5.8 or 5.9, I can imagine to take the two
>>> pinctrl_state pointers into bus_recovery_info and handle all this in the
>>> core. I will try this later this week if noone is super-eager to try it
>>> out before.
>>>
>>
>> By 'all this' you mean to move the entire function in the core, right?
>> Having just these two pointers bus_recinovery_info won't help much. I
>> can try it, if you haven't already started...
> 
> I mean to add those two pointers to bus_recinovery_info and if they are
> populated, then the I2C core is doing the necessary magic (or maybe just
> the pinctrl handle and assume the states have fixed names?). Russell
> just sent patches to add it to the PXA driver, so we could now double
> check how much could be factored out.
> 
> I haven't started yet, let's keep in touch who started first :)
> 

I started working at this. I added the pinctrl state initialization at 
the beginning of the i2c_init_recovery(). Due to the pinmux state issue 
with the GPIOs, the GPIO part needs to be also moved. The problem I ran 
in to now is the fact that, even if we can ignore if the GPIOs are not 
available, we should at least treat EPROBE_DEFER error. To do this, the 
I2C bus drivers should take into account the fact that 
i2c_register_adapter() can return -EPROBE_DEFER. Is this something to 
consider?

Thanks and best regards,
Codrin

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-06-09 11:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-15  7:06 [RFC PATCH] i2c: at91: Fix pinmux after devm_gpiod_get() for bus recovery Codrin Ciubotariu
2020-04-19 12:50 ` ludovic.desroches
2020-05-05 15:12 ` Wolfram Sang
2020-05-13 11:07   ` Codrin.Ciubotariu
2020-05-20 16:27     ` Wolfram Sang
2020-06-09 11:43       ` Codrin.Ciubotariu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).