[PATCH v3] i2c: designware: Enable SAR in slave mode for Multiple SAR controllers
Umesh Kumar <[email protected]> Wed, 12 Aug 2026 17:15:14 +0530
| Newsgroups | org.kernel.vger.linux-i2c,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
DesignWare controllers synthesised with the Multiple SAR feature (e.g. Marvell CN20K) gate the primary slave address behind IC_ENABLE.SAR_EN (bit 19). Per the Synopsys DW_apb_i2c DataBook (Multiple SAR feature), when this bit is set the core acknowledges the address matching IC_SAR; otherwise the address is NACKed. The slave enable path writes only IC_ENABLE.ENABLE (bit 0), so on such controllers the target never ACKs its address and a remote master cannot reach it. Set SAR_EN together with ENABLE when entering slave mode. The bit is reserved (and ignored) on single-SAR controllers, so existing users are unaffected. Signed-off-by: Umesh Kumar <[email protected]> Acked-by: Mika Westerberg <[email protected]> --- drivers/i2c/busses/i2c-designware-common.c | 10 +++++++++- drivers/i2c/busses/i2c-designware-core.h | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 4dc57fd56170..8ed0b588d67b 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -374,7 +374,15 @@ static void i2c_dw_configure_mode(struct dw_i2c_dev *dev, int mode) regmap_write(dev->map, DW_IC_CON, dev->slave_cfg); regmap_write(dev->map, DW_IC_SAR, dev->slave->addr); regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_SLAVE_MASK); - __i2c_dw_enable(dev); + /* + * Per the Synopsys DW_apb_i2c DataBook (Multiple SAR feature), + * controllers synthesised with multiple SARs only acknowledge + * traffic to IC_SAR when IC_ENABLE.SAR_EN is set; a plain enable + * is not enough. The bit is reserved (ignored) on single-SAR + * controllers. + */ + regmap_write(dev->map, DW_IC_ENABLE, + DW_IC_ENABLE_ENABLE | DW_IC_ENABLE_SAR_EN); break; default: WARN(1, "Invalid mode %d\n", mode); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 9d8d104cc391..b237d093c562 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -125,6 +125,14 @@ #define DW_IC_ENABLE_ENABLE BIT(0) #define DW_IC_ENABLE_ABORT BIT(1) +/* + * IC_ENABLE.SAR_EN, per the Synopsys DW_apb_i2c DataBook (Multiple SAR + * feature): on controllers synthesised with multiple SARs (e.g. Marvell + * CN20K) the primary slave address (IC_SAR) is only acknowledged when this + * bit is set. Must be programmed while IC_ENABLE.ENABLE is 0. Reserved on + * single-SAR controllers. + */ +#define DW_IC_ENABLE_SAR_EN BIT(19) #define DW_IC_STATUS_ACTIVITY BIT(0) #define DW_IC_STATUS_TFE BIT(2) -- 2.43.0