diff mbox series

[2/2] dm: i2c-gpio: add support for clock stretching

Message ID 20200207165532.219139-2-michael.auchter@ni.com
State New
Headers show
Series [1/2] dm: i2c-gpio: rework gpio get/set functions | expand

Commit Message

Michael Auchter Feb. 7, 2020, 4:55 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).

This is enabled by default; for gpios which cannot be configured as
inputs, the i2c-gpio,scl-output-only property can be used to fall back
to the previous behavior.

Signed-off-by: Michael Auchter <michael.auchter at ni.com>
Cc: Heiko Schocher <hs at denx.de>
---
 doc/device-tree-bindings/i2c/i2c-gpio.txt |  2 ++
 drivers/i2c/i2c-gpio.c                    | 23 ++++++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

Comments

Heiko Schocher Feb. 18, 2020, 7:20 a.m. UTC | #1
Hello Michael,

Am 07.02.2020 um 17:55 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).
> 
> This is enabled by default; for gpios which cannot be configured as
> inputs, the i2c-gpio,scl-output-only property can be used to fall back
> to the previous behavior.
> 
> Signed-off-by: Michael Auchter <michael.auchter at ni.com>
> Cc: Heiko Schocher <hs at denx.de>
> ---
>   doc/device-tree-bindings/i2c/i2c-gpio.txt |  2 ++
>   drivers/i2c/i2c-gpio.c                    | 23 ++++++++++++++++++++++-
>   2 files changed, 24 insertions(+), 1 deletion(-)

Reviewed-by: Heiko Schocher <hs at denx.de>

bye,
Heiko
Heiko Schocher March 17, 2020, 5:12 a.m. UTC | #2
Hello Michael,

Am 07.02.2020 um 17:55 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).
> 
> This is enabled by default; for gpios which cannot be configured as
> inputs, the i2c-gpio,scl-output-only property can be used to fall back
> to the previous behavior.
> 
> Signed-off-by: Michael Auchter <michael.auchter at ni.com>
> Cc: Heiko Schocher <hs at denx.de>
> ---
>   doc/device-tree-bindings/i2c/i2c-gpio.txt |  2 ++
>   drivers/i2c/i2c-gpio.c                    | 23 ++++++++++++++++++++++-
>   2 files changed, 24 insertions(+), 1 deletion(-)

Applied to u-boot-i2c next, thanks!

bye,
Heiko
diff mbox series

Patch

diff --git a/doc/device-tree-bindings/i2c/i2c-gpio.txt b/doc/device-tree-bindings/i2c/i2c-gpio.txt
index ba56ed5dea..36910d26a9 100644
--- a/doc/device-tree-bindings/i2c/i2c-gpio.txt
+++ b/doc/device-tree-bindings/i2c/i2c-gpio.txt
@@ -16,6 +16,8 @@  Optional:
    The resulting transfer speed can be adjusted by setting the delay[us]
    between gpio-toggle operations. Speed [Hz] = 1000000 / 4 * udelay[us],
    It not defined, then default is 5us (~50KHz).
+* i2c-gpio,scl-output-only;
+   Set if SCL is an output only
 
 Example:
 
diff --git a/drivers/i2c/i2c-gpio.c b/drivers/i2c/i2c-gpio.c
index d989449513..8a8d1ff21b 100644
--- a/drivers/i2c/i2c-gpio.c
+++ b/drivers/i2c/i2c-gpio.c
@@ -56,6 +56,24 @@  static void i2c_gpio_sda_set(struct i2c_gpio_bus *bus, int bit)
 }
 
 static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit)
+{
+	struct gpio_desc *scl = &bus->gpios[PIN_SCL];
+	int count = 0;
+
+	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);
+	}
+}
+
+/* variant for output only gpios which cannot support clock stretching */
+static void i2c_gpio_scl_set_output_only(struct i2c_gpio_bus *bus, int bit)
 {
 	struct gpio_desc *scl = &bus->gpios[PIN_SCL];
 	ulong flags = GPIOD_IS_OUT;
@@ -313,7 +331,10 @@  static int i2c_gpio_ofdata_to_platdata(struct udevice *dev)
 
 	bus->get_sda = i2c_gpio_sda_get;
 	bus->set_sda = i2c_gpio_sda_set;
-	bus->set_scl = i2c_gpio_scl_set;
+	if (fdtdec_get_bool(blob, node, "i2c-gpio,scl-output-only"))
+		bus->set_scl = i2c_gpio_scl_set_output_only;
+	else
+		bus->set_scl = i2c_gpio_scl_set;
 
 	return 0;
 error: