diff --git a/doc/device-tree-bindings/i2c/i2c-gpio.txt b/doc/device-tree-bindings/i2c/i2c-gpio.txt index e29eeba9e6..b06b829933 100644 --- a/doc/device-tree-bindings/i2c/i2c-gpio.txt +++ b/doc/device-tree-bindings/i2c/i2c-gpio.txt @@ -18,6 +18,8 @@ Optional: It not defined, then default is 5us (~50KHz). * i2c-gpio,deblock Run deblocking sequence when the driver gets probed. +* 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 e3a21ad3b2..07fdd343f2 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; @@ -328,7 +346,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: