[PATCH v3 2/2] i2c: cadence: Add support for Axiado AX3000
Swark Yang <[email protected]> Tue, 30 Jun 2026 21:48:59 -0700
| Newsgroups | org.ozlabs.lists.openbmc,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-i2c,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260630-axiado-ax3000-cadence-i2c-support-v3-2-4e217cfe5904@axiado.com> |
The Axiado AX3000 SoC integrates a Cadence I2C controller that supports SMBus Quick commands. Introduce the "axiado,ax3000-i2c" compatible string and add a new quirk CDNS_I2C_ENABLE_SMBUS_QUICK to enable this functionality. This allows the controller to support I2C_FUNC_SMBUS_QUICK, enabling features such as bus scanning via quick write commands. Additionally, enabling SMBus Quick emulation in the I2C core exposes the controller to potential 0-length reads. Because the Cadence IP does not natively support 0-length reads (writing 0 to the transfer size register leaves the hardware in an unsupported state), this patch also populates the adapter quirks with I2C_AQ_NO_ZERO_LEN_READ. This ensures 0-length reads are safely rejected by the core, preventing potential bus hangs. Signed-off-by: Swark Yang <[email protected]> --- drivers/i2c/busses/i2c-cadence.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 0fb728ade92e..1964ea1650c5 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -128,6 +128,7 @@ #define CDNS_I2C_TIMEOUT_MAX 0xFF #define CDNS_I2C_BROKEN_HOLD_BIT BIT(0) +#define CDNS_I2C_ENABLE_SMBUS_QUICK BIT(1) #define CDNS_I2C_POLL_US 100000 #define CDNS_I2C_POLL_US_ATOMIC 10 #define CDNS_I2C_TIMEOUT_US 500000 @@ -1175,10 +1176,14 @@ static int cdns_i2c_master_xfer_atomic(struct i2c_adapter *adap, struct i2c_msg */ static u32 cdns_i2c_func(struct i2c_adapter *adap) { + struct cdns_i2c *id = adap->algo_data; u32 func = I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_SMBUS_BLOCK_DATA; + if (id->quirks & CDNS_I2C_ENABLE_SMBUS_QUICK) + func |= I2C_FUNC_SMBUS_QUICK; + #if IS_ENABLED(CONFIG_I2C_SLAVE) func |= I2C_FUNC_SLAVE; #endif @@ -1442,9 +1447,24 @@ static const struct cdns_platform_data r1p10_i2c_def = { .quirks = CDNS_I2C_BROKEN_HOLD_BIT, }; +static const struct cdns_platform_data ax3000_i2c_def = { + .quirks = CDNS_I2C_ENABLE_SMBUS_QUICK, +}; + +/* + * The controller does not support zero-length reads. Enabling SMBus Quick + * commands would otherwise let the core emulate a Quick read as a zero-length + * read message, which writes 0 to the transfer size register and leaves the + * hardware in an unsupported state. Reject such transfers in the core. + */ +static const struct i2c_adapter_quirks cdns_i2c_quirks = { + .flags = I2C_AQ_NO_ZERO_LEN_READ, +}; + static const struct of_device_id cdns_i2c_of_match[] = { { .compatible = "cdns,i2c-r1p10", .data = &r1p10_i2c_def }, { .compatible = "cdns,i2c-r1p14",}, + { .compatible = "axiado,ax3000-i2c", .data = &ax3000_i2c_def }, { /* end of table */ } }; MODULE_DEVICE_TABLE(of, cdns_i2c_of_match); @@ -1510,6 +1530,9 @@ static int cdns_i2c_probe(struct platform_device *pdev) id->quirks = data->quirks; } + if (id->quirks & CDNS_I2C_ENABLE_SMBUS_QUICK) + id->adap.quirks = &cdns_i2c_quirks; + id->rinfo.pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(id->rinfo.pinctrl)) { int err = PTR_ERR(id->rinfo.pinctrl); -- 2.34.1