i2c: i2c-gpio: Fix GPIO output

The dm_gpio_set_dir_flags function cannot be used to update the configuration of a GPIO pin because it does a bitwise OR with the existing flags. Looks like commit 788ea834124b ("gpio: add function _dm_gpio_set_dir_flags") has introduced this behaviour and the i2c-gpio driver has been broken since.
Signed-off-by: Harm Berntsen harm.berntsen@nedap.com CC: Heiko Schocher hs@denx.de CC: Patrick Delaunay patrick.delaunay@st.com ---
drivers/i2c/i2c-gpio.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/i2c-gpio.c b/drivers/i2c/i2c-gpio.c index 381938c956..9c5e0d4d68 100644 --- a/drivers/i2c/i2c-gpio.c +++ b/drivers/i2c/i2c-gpio.c @@ -50,9 +50,10 @@ static void i2c_gpio_sda_set(struct i2c_gpio_bus *bus, int bit) struct gpio_desc *sda = &bus->gpios[PIN_SDA];
if (bit) - dm_gpio_set_dir_flags(sda, GPIOD_IS_IN); + sda->flags = (sda->flags & ~GPIOD_IS_OUT) | GPIOD_IS_IN; else - dm_gpio_set_dir_flags(sda, GPIOD_IS_OUT); + sda->flags = (sda->flags & (~GPIOD_IS_IN & ~GPIOD_IS_OUT_ACTIVE)) | GPIOD_IS_OUT; + dm_gpio_set_dir(sda); }
static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit) @@ -61,14 +62,16 @@ static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit) int count = 0;
if (bit) { - dm_gpio_set_dir_flags(scl, GPIOD_IS_IN); + scl->flags = (scl->flags & ~GPIOD_IS_OUT) | GPIOD_IS_IN; + dm_gpio_set_dir(scl); 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); + scl->flags = (scl->flags & (~GPIOD_IS_IN & ~GPIOD_IS_OUT_ACTIVE)) | GPIOD_IS_OUT; + dm_gpio_set_dir(scl); } }
@@ -76,11 +79,11 @@ static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit) 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; + scl->flags = (scl->flags & (~GPIOD_IS_IN & ~GPIOD_IS_OUT_ACTIVE)) | GPIOD_IS_OUT;
if (bit) - flags |= GPIOD_IS_OUT_ACTIVE; - dm_gpio_set_dir_flags(scl, flags); + scl->flags |= GPIOD_IS_OUT_ACTIVE; + dm_gpio_set_dir(scl); }
static void i2c_gpio_write_bit(struct i2c_gpio_bus *bus, int delay, uchar bit)

Hello Harm
On 29.11.20 10:47, Harm Berntsen wrote:
The dm_gpio_set_dir_flags function cannot be used to update the configuration of a GPIO pin because it does a bitwise OR with the existing flags. Looks like commit 788ea834124b ("gpio: add function _dm_gpio_set_dir_flags") has introduced this behaviour and the i2c-gpio driver has been broken since.
Signed-off-by: Harm Berntsen harm.berntsen@nedap.com CC: Heiko Schocher hs@denx.de CC: Patrick Delaunay patrick.delaunay@st.com
drivers/i2c/i2c-gpio.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
Applied to u-boot-i2c.git master
Thanks!
bye, Heiko
participants (2)
-
Harm Berntsen
-
Heiko Schocher