summaryrefslogtreecommitdiff
path: root/drivers/i2c/i2c-uclass.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-03-17 11:33:59 -0400
committerTom Rini <trini@konsulko.com>2020-03-17 11:33:59 -0400
commitb180e32ea39d03021655a31a19d527529a2eb980 (patch)
tree518505ebb4914d2e54f1ef898ad9ecb651355718 /drivers/i2c/i2c-uclass.c
parent552c3d4c2d3a98658158fdb7213515d631f5e181 (diff)
parent80e8b8add057d2c947394d9d57fc2dcc7ff886d1 (diff)
Merge tag '20200316-for-next' of https://gitlab.denx.de/u-boot/custodians/u-boot-i2c into next
i2c: for next - i2c-gpio: make it possible to run deblock sequence on driver probe - i2c-gpio: add clock stretching support - updates the Designware I2C driver for high speed mode, fix a bug and add some improvements. - add DM support for memory based bootcounter driver
Diffstat (limited to 'drivers/i2c/i2c-uclass.c')
-rw-r--r--drivers/i2c/i2c-uclass.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 2aa3efe8aaa..e9ec3885767 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -501,35 +501,53 @@ static int i2c_gpio_get_pin(struct gpio_desc *pin)
return dm_gpio_get_value(pin);
}
-static int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin,
- struct gpio_desc *scl_pin)
+int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin,
+ struct gpio_desc *scl_pin,
+ unsigned int scl_count,
+ unsigned int start_count,
+ unsigned int delay)
{
- int counter = 9;
- int ret = 0;
+ int i, ret = -EREMOTEIO;
i2c_gpio_set_pin(sda_pin, 1);
i2c_gpio_set_pin(scl_pin, 1);
- udelay(5);
+ udelay(delay);
/* Toggle SCL until slave release SDA */
- while (counter-- >= 0) {
+ while (scl_count-- >= 0) {
i2c_gpio_set_pin(scl_pin, 1);
- udelay(5);
+ udelay(delay);
i2c_gpio_set_pin(scl_pin, 0);
- udelay(5);
- if (i2c_gpio_get_pin(sda_pin))
+ udelay(delay);
+ if (i2c_gpio_get_pin(sda_pin)) {
+ ret = 0;
break;
+ }
+ }
+
+ if (!ret && start_count) {
+ for (i = 0; i < start_count; i++) {
+ /* Send start condition */
+ udelay(delay);
+ i2c_gpio_set_pin(sda_pin, 1);
+ udelay(delay);
+ i2c_gpio_set_pin(scl_pin, 1);
+ udelay(delay);
+ i2c_gpio_set_pin(sda_pin, 0);
+ udelay(delay);
+ i2c_gpio_set_pin(scl_pin, 0);
+ }
}
/* Then, send I2C stop */
i2c_gpio_set_pin(sda_pin, 0);
- udelay(5);
+ udelay(delay);
i2c_gpio_set_pin(scl_pin, 1);
- udelay(5);
+ udelay(delay);
i2c_gpio_set_pin(sda_pin, 1);
- udelay(5);
+ udelay(delay);
if (!i2c_gpio_get_pin(sda_pin) || !i2c_gpio_get_pin(scl_pin))
ret = -EREMOTEIO;
@@ -561,7 +579,7 @@ static int i2c_deblock_gpio(struct udevice *bus)
goto out_no_pinctrl;
}
- ret0 = i2c_deblock_gpio_loop(&gpios[PIN_SDA], &gpios[PIN_SCL]);
+ ret0 = i2c_deblock_gpio_loop(&gpios[PIN_SDA], &gpios[PIN_SCL], 9, 0, 5);
ret = pinctrl_select_state(bus, "default");
if (ret) {