From 7231522a5ed1545d3206f5204676897d62a24f5f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 7 Feb 2020 16:57:50 +0100 Subject: i2c: Export i2c_deblock_gpio_loop() Export the i2c_deblock_gpio_loop() so it can be used in other places in U-Boot. In particular, this is useful in the GPIO I2C driver, which claims the SDA/SCL GPIOs and thus prevents the i2c_deblock() implementation from claiming the pins as GPIOs again. Signed-off-by: Marek Vasut Reviewed-by: Heiko Schocher --- include/i2c.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include') diff --git a/include/i2c.h b/include/i2c.h index 0faf8542e28..7c92042c584 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -330,6 +330,22 @@ uint i2c_get_chip_addr_offset_mask(struct udevice *dev); */ int i2c_deblock(struct udevice *bus); +/** + * i2c_deblock_gpio_loop() - recover a bus from an unknown state by toggling SDA/SCL + * + * This is the inner logic used for toggling I2C SDA/SCL lines as GPIOs + * for deblocking the I2C bus. + * + * @sda_pin: SDA GPIO + * @scl_pin: SCL GPIO + * @scl_count: Number of SCL clock cycles generated to deblock SDA + * @delay: Delay between SCL clock line changes + * @return 0 if OK, -ve on error + */ +struct gpio_desc; +int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin, struct gpio_desc *scl_pin, + unsigned int scl_count, unsigned int delay); + /** * struct dm_i2c_ops - driver operations for I2C uclass * -- cgit v1.3.1 From a19172863335dcaa1b2a98009f0bfef2a61ab4a2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 7 Feb 2020 16:57:51 +0100 Subject: i2c: Add option to send start condition after deblocking Add option to send start condition after deblocking SDA. Signed-off-by: Marek Vasut Reviewed-by: Heiko Schocher --- drivers/i2c/i2c-uclass.c | 23 ++++++++++++++++++++--- include/i2c.h | 4 +++- 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 86f529241f4..e9ec3885767 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -504,9 +504,10 @@ static int i2c_gpio_get_pin(struct gpio_desc *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 ret = 0; + int i, ret = -EREMOTEIO; i2c_gpio_set_pin(sda_pin, 1); i2c_gpio_set_pin(scl_pin, 1); @@ -518,8 +519,24 @@ int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin, udelay(delay); i2c_gpio_set_pin(scl_pin, 0); udelay(delay); - if (i2c_gpio_get_pin(sda_pin)) + 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 */ @@ -562,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], 9, 5); + ret0 = i2c_deblock_gpio_loop(&gpios[PIN_SDA], &gpios[PIN_SCL], 9, 0, 5); ret = pinctrl_select_state(bus, "default"); if (ret) { diff --git a/include/i2c.h b/include/i2c.h index 7c92042c584..059200115a8 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -339,12 +339,14 @@ int i2c_deblock(struct udevice *bus); * @sda_pin: SDA GPIO * @scl_pin: SCL GPIO * @scl_count: Number of SCL clock cycles generated to deblock SDA + * @start_count:Number of I2C start conditions sent after deblocking SDA * @delay: Delay between SCL clock line changes * @return 0 if OK, -ve on error */ struct gpio_desc; int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin, struct gpio_desc *scl_pin, - unsigned int scl_count, unsigned int delay); + unsigned int scl_count, unsigned int start_count, + unsigned int delay); /** * struct dm_i2c_ops - driver operations for I2C uclass -- cgit v1.3.1 From ed6dd4e460bd94150dc09fce547a27e2fcca66eb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 28 Feb 2020 22:04:13 +0900 Subject: misc: i2c_eeprom: remove pagewidth field from i2c_eeprom This struct member is not used in any effective way. Remove it. Signed-off-by: Masahiro Yamada --- drivers/misc/i2c_eeprom.c | 8 +++----- include/i2c_eeprom.h | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index 6c0459dc555..728e0fd79ab 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -99,13 +99,11 @@ static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev) u32 pagesize; u32 size; - if (dev_read_u32(dev, "pagesize", &pagesize) == 0) { + if (dev_read_u32(dev, "pagesize", &pagesize) == 0) priv->pagesize = pagesize; - } else { + else /* 6 bit -> page size of up to 2^63 (should be sufficient) */ - priv->pagewidth = data->pagewidth; - priv->pagesize = (1 << priv->pagewidth); - } + priv->pagesize = 1 << data->pagewidth; if (dev_read_u32(dev, "size", &size) == 0) priv->size = size; diff --git a/include/i2c_eeprom.h b/include/i2c_eeprom.h index b96254ae79f..cd620d519fc 100644 --- a/include/i2c_eeprom.h +++ b/include/i2c_eeprom.h @@ -16,8 +16,6 @@ struct i2c_eeprom_ops { struct i2c_eeprom { /* The EEPROM's page size in byte */ unsigned long pagesize; - /* The EEPROM's page width in bits (pagesize = 2^pagewidth) */ - unsigned pagewidth; /* The EEPROM's capacity in bytes */ unsigned long size; }; -- cgit v1.3.1