diff mbox series

dm: i2c-gpio: add support for clock stretching

Message ID 20200123223009.213180-1-michael.auchter@ni.com
State Changes Requested
Delegated to: Heiko Schocher
Headers show
Series dm: i2c-gpio: add support for clock stretching | expand

Commit Message

Michael Auchter Jan. 23, 2020, 10:30 p.m. UTC
This adds support for clock stretching to the i2c-gpio driver. This is
accomplished by switching the GPIO used for the SCL line to an input
when it should be driven high, and polling on the SCL line value until
it goes high (indicating that the I2C slave is no longer pulling it
low).

Signed-off-by: Michael Auchter <michael.auchter@ni.com>
Cc: Heiko Schocher <hs@denx.de>
---
 drivers/i2c/i2c-gpio.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Comments

Heiko Schocher Jan. 27, 2020, 7 a.m. UTC | #1
Hello Michael,

Am 23.01.2020 um 23:30 schrieb Michael Auchter:
> This adds support for clock stretching to the i2c-gpio driver. This is
> accomplished by switching the GPIO used for the SCL line to an input
> when it should be driven high, and polling on the SCL line value until
> it goes high (indicating that the I2C slave is no longer pulling it
> low).
> 
> Signed-off-by: Michael Auchter <michael.auchter@ni.com>
> Cc: Heiko Schocher <hs@denx.de>
> ---
>   drivers/i2c/i2c-gpio.c | 15 +++++++++++----
>   1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/i2c/i2c-gpio.c b/drivers/i2c/i2c-gpio.c
> index 4e8fa21473..80ac26e583 100644
> --- a/drivers/i2c/i2c-gpio.c
> +++ b/drivers/i2c/i2c-gpio.c
> @@ -49,11 +49,18 @@ static void i2c_gpio_sda_set(struct gpio_desc *sda, int bit)
>   
>   static void i2c_gpio_scl_set(struct gpio_desc *scl, int bit)
>   {
> -	ulong flags = GPIOD_IS_OUT;
> +	int count = 0;
>   
> -	if (bit)
> -		flags |= GPIOD_IS_OUT_ACTIVE;
> -	dm_gpio_set_dir_flags(scl, flags);
> +	if (bit) {
> +		dm_gpio_set_dir_flags(scl, GPIOD_IS_IN);
> +		while (!dm_gpio_get_value(scl) && count++ < 100000)
> +			udelay(1);
> +
> +		if (!dm_gpio_get_value(scl))
> +			pr_err("timeout waiting on slave to release scl\n");
> +	} else {
> +		dm_gpio_set_dir_flags(scl, GPIOD_IS_OUT);
> +	}
>   }
>   
>   static void i2c_gpio_write_bit(struct gpio_desc *scl, struct gpio_desc *sda,
> 

In principle I would say Ok, but your patch changes behaviour for
all boards which use this driver currently ...

May they cannot reread the gpio ... we have no scl_get() yet!

So please, make this change dependend on linux property "i2c-gpio,scl-output-only"
see:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/i2c/i2c-gpio.yaml#n36

As an example in linux:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/i2c/busses/i2c-gpio.c#n317

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/i2c/algos/i2c-algo-bit.c#n75

So at least, we have the chance to switch back to old behaviour by adding
this (new for U-Boot) property.

Thanks!

bye,
Heiko
diff mbox series

Patch

diff --git a/drivers/i2c/i2c-gpio.c b/drivers/i2c/i2c-gpio.c
index 4e8fa21473..80ac26e583 100644
--- a/drivers/i2c/i2c-gpio.c
+++ b/drivers/i2c/i2c-gpio.c
@@ -49,11 +49,18 @@  static void i2c_gpio_sda_set(struct gpio_desc *sda, int bit)
 
 static void i2c_gpio_scl_set(struct gpio_desc *scl, int bit)
 {
-	ulong flags = GPIOD_IS_OUT;
+	int count = 0;
 
-	if (bit)
-		flags |= GPIOD_IS_OUT_ACTIVE;
-	dm_gpio_set_dir_flags(scl, flags);
+	if (bit) {
+		dm_gpio_set_dir_flags(scl, GPIOD_IS_IN);
+		while (!dm_gpio_get_value(scl) && count++ < 100000)
+			udelay(1);
+
+		if (!dm_gpio_get_value(scl))
+			pr_err("timeout waiting on slave to release scl\n");
+	} else {
+		dm_gpio_set_dir_flags(scl, GPIOD_IS_OUT);
+	}
 }
 
 static void i2c_gpio_write_bit(struct gpio_desc *scl, struct gpio_desc *sda,