From patchwork Fri Feb 7 15:57:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 236048 List-Id: U-Boot discussion From: marex at denx.de (Marek Vasut) Date: Fri, 7 Feb 2020 16:57:51 +0100 Subject: [PATCH 3/4] i2c: Add option to send start condition after deblocking In-Reply-To: <20200207155752.40930-1-marex@denx.de> References: <20200207155752.40930-1-marex@denx.de> Message-ID: <20200207155752.40930-3-marex@denx.de> 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(-) diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 86f529241f..e9ec388576 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 7c92042c58..059200115a 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