[PATCH] i2c: designware: fix i2c probe error
Heiko Schocher
hs at nabladev.com
Wed Jun 10 12:34:43 CEST 2026
Hello Coben,
On 30.05.26 17:24, Coben Han wrote:
> Probing i2c slave device just needs its device address.
>
> A certain type of chipsets such as RTC S35390A have no offset,
> which means address length should be 0.
>
> But the current designware_i2c_probe_chip function requires
> offset 0 and its length 1.
>
> This causes the designware-i2c to be initialized again and again.
>
> Furthermore, after booting into kernel, the designware-i2c kernel
> driver complains its controller timeout.
>
> This patch fixes this misbehaviour in such way that only device
> address is issued, no reinitialization needs when target device
> not detected, the designware-i2c kernel driver continues working.
>
> Signed-off-by: Coben Han <cobenhan at mediastek.com>
> ---
> drivers/i2c/designware_i2c.c | 52 +++++++++++++++++++++++++++++-------
> 1 file changed, 42 insertions(+), 10 deletions(-)
Sounds valid to me, it would be good to have some Tested by tags
from other users, that this change does not break.
>
> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> index 8ad716f410e..a7d3b609aca 100644
> --- a/drivers/i2c/designware_i2c.c
> +++ b/drivers/i2c/designware_i2c.c
> @@ -672,18 +672,50 @@ static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
> }
>
> /* dw_i2c_probe - Probe the i2c chip */
> -static int dw_i2c_probe(struct i2c_adapter *adap, u8 dev)
> +static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr, uint chip_flags)
> {
> - struct i2c_regs *i2c_base = i2c_get_base(adap);
> - u32 tmp;
> - int ret;
> + struct dw_i2c *i2c = dev_get_priv(bus);
> + struct i2c_regs *i2c_base = i2c->regs;
> + u32 start_time, ic_status;
> + int ret = 0;
>
> - /*
> - * Try to read the first location of the chip.
> - */
> - ret = __dw_i2c_read(i2c_base, dev, 0, 1, (uchar *)&tmp, 1);
> - if (ret)
> - dw_i2c_init(adap, adap->speed, adap->slaveaddr);
> + if (i2c_wait_for_bb(i2c_base) < 0)
> + return 1;
Why not returning -ETIMEDOUT ? (or better the return code from i2c_wait_for_bb()
which -ETIMEDOUT, but may in future it changes...
> +
> + dw_i2c_enable(i2c_base, false);
> + writel(chip_addr, &i2c_base->ic_tar);
> + dw_i2c_enable(i2c_base, true);
> +
> + writel(IC_STOP, &i2c_base->ic_cmd_data);
> +
> + start_time = get_timer(0);
> + while (1) {
> + ic_status = readl(&i2c_base->ic_status);
> +
> + if ((ic_status & IC_STATUS_TFE) && !(ic_status & IC_STATUS_MA))
> + break;
> +
> + if (readl(&i2c_base->ic_raw_intr_stat) & IC_TX_ABRT) {
> + readl(&i2c_base->ic_clr_tx_abrt);
> + ret = -EREMOTEIO;
> + break;
> + }
> +
> + if (get_timer(start_time) > I2C_BYTE_TO) {
> + ret = -ETIMEDOUT;
> + break;
> + }
> + }
> +
> + start_time = get_timer(0);
> + while (1) {
> + if ((readl(&i2c_base->ic_raw_intr_stat) & IC_STOP_DET)) {
> + readl(&i2c_base->ic_clr_stop_det);
> + break;
> + } else if (get_timer(start_time) > I2C_STOPDET_TO) {
> + break;
> + }
> + }
>
> return ret;
> }
>
bye,
Heiko
--
Nabla Software Engineering
HRB 40522 Augsburg
Phone: +49 821 45592596
E-Mail: office at nabladev.com
Geschäftsführer : Stefano Babic
More information about the U-Boot
mailing list