i2c: designware: fix i2c probe error

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@mediastek.com>
This commit is contained in:
Coben Han
2026-07-08 11:23:25 +02:00
committed by Heiko Schocher
parent a8d40f922d
commit b8487e7e2d
+39 -5
View File
@@ -740,13 +740,47 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
{
struct dw_i2c *i2c = dev_get_priv(bus);
struct i2c_regs *i2c_base = i2c->regs;
u32 tmp;
int ret;
u32 start_time, ic_status;
int ret = 0;
/* Try to read the first location of the chip */
ret = __dw_i2c_read(i2c_base, chip_addr, 0, 1, (uchar *)&tmp, 1);
ret = i2c_wait_for_bb(i2c_base);
if (ret)
__dw_i2c_init(i2c_base, 0, 0);
return ret;
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;
}