[PATCH v5] i2c: designware: Enable SAR in slave mode for Multiple SAR controllers
Umesh Kumar <[email protected]>
| 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 v2.03a (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]> --- Changes in v5: - Fixed missing spaces in commit message (Andy Shevchenko). Changes in v4: - Added DataBook version (v2.03a) to commit message and code comment. - Removed duplicate comment from core.h; kept only in the .c file. - Added changelog. Changes in v3: - Referenced the Synopsys DW_apb_i2c DataBook (Andy Shevchenko). Changes in v2: - Dropped RFC tag; added Mika's Acked-by. v1 (RFC): https://lore.kernel.org/linux-i2c/[email protected]/ drivers/i2c/busses/i2c-designware-common.c | 10 +++++++++- drivers/i2c/busses/i2c-designware-core.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 4dc57fd56170..880b9a74b3ff 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 v2.03a (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..1390c8862a68 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -125,6 +125,7 @@ #define DW_IC_ENABLE_ENABLE BIT(0) #define DW_IC_ENABLE_ABORT BIT(1) +#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