[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