From 534c3940039068cdc5a1b0f6010e4e259b0bbf3e Mon Sep 17 00:00:00 2001 From: Nishanth Sampath Kumar Date: Fri, 8 May 2026 14:35:27 -0700 Subject: [PATCH] regmap-i2c: add SMBus byte/word reg16 bus for adapters lacking I2C_FUNC_I2C Add a regmap-i2c bus type that supports 16-bit register addressing on adapters that have SMBUS_BYTE_DATA and SMBUS_WORD_DATA but lack I2C_FUNC_I2C and I2C_FUNC_SMBUS_I2C_BLOCK (e.g. AMD PIIX4 on AMD SP5/EPYC platforms, including Cisco 8000 series routers). This fixes at24 EEPROM probe failures on PIIX4: at24 3-0055: probe with driver at24 failed with error -524 The fix lives in the regmap-i2c core (per upstream review feedback from Bartosz Golaszewski and Mark Brown) so all drivers benefit from the fallback, not just at24. Signed-off-by: Nishanth Sampath Kumar --- ...MBus-byte-word-reg16-bus-for-adapter.patch | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100755 patches-sonic/0001-regmap-i2c-add-SMBus-byte-word-reg16-bus-for-adapter.patch diff --git a/patches-sonic/0001-regmap-i2c-add-SMBus-byte-word-reg16-bus-for-adapter.patch b/patches-sonic/0001-regmap-i2c-add-SMBus-byte-word-reg16-bus-for-adapter.patch new file mode 100755 index 000000000..13404d9de --- /dev/null +++ b/patches-sonic/0001-regmap-i2c-add-SMBus-byte-word-reg16-bus-for-adapter.patch @@ -0,0 +1,117 @@ +From 1342441971df25712dcc15d4226af7e306843073 Mon Sep 17 00:00:00 2001 +From: Nishanth Sampath Kumar +Date: Fri, 8 May 2026 14:29:23 -0700 +Subject: [PATCH] regmap-i2c: add SMBus byte/word reg16 bus for adapters + lacking I2C_FUNC_I2C + +[ upstream bad4bd28abf4d7cb2adcb39cc0de789729d2cd69 ] + +AMD PIIX4 SMBus adapters, present on AMD SP5/EPYC-based platforms +(including Cisco 8000 series routers), support SMBUS_BYTE_DATA and +SMBUS_WORD_DATA but lack I2C_FUNC_I2C and I2C_FUNC_SMBUS_I2C_BLOCK. + +When at24 (or any driver) requests a regmap with reg_bits=16 and +val_bits=8 on such an adapter, regmap_get_i2c_bus() finds no matching +bus and returns -ENOTSUPP. The existing regmap_i2c_smbus_i2c_block_reg16 +bus type already implements 16-bit addressed reads using only +write_byte_data() + read_byte() primitives, but its selection is gated +on I2C_FUNC_SMBUS_I2C_BLOCK which these adapters lack. + +Add a new regmap_smbus_byte_word_reg16 bus that: + + READ: reuses regmap_i2c_smbus_i2c_read_reg16() -- sets the 16-bit + address via write_byte_data(addr_lo, addr_hi), then reads + bytes sequentially via read_byte() (EEPROM auto-increments). + Requires only SMBUS_BYTE_DATA. + + WRITE: uses write_word_data(addr_hi, (data << 8) | addr_lo) to + encode one data byte per SMBus WORD transaction. + Requires only SMBUS_WORD_DATA. Single-byte writes only. + +The new bus is selected in regmap_get_i2c_bus() when reg_bits=16, +val_bits=8, and the adapter has SMBUS_BYTE_DATA | SMBUS_WORD_DATA but +not I2C_FUNC_I2C or SMBUS_I2C_BLOCK. The branch is placed after the +existing I2C_BLOCK_reg16 check so adapters with full block support +continue to use the faster path. + +This fixes at24 EEPROM probe failures on PIIX4: + at24 3-0055: probe with driver at24 failed with error -524 + +No driver changes are required -- at24 already passes reg_bits=16 to +devm_regmap_init_i2c(), which now succeeds. + +Signed-off-by: Nishanth Sampath Kumar +--- + drivers/base/regmap/regmap-i2c.c | 49 ++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c +index c9b39a02278e..31e30dfced19 100644 +--- a/drivers/base/regmap/regmap-i2c.c ++++ b/drivers/base/regmap/regmap-i2c.c +@@ -303,6 +303,50 @@ static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = { + .max_raw_write = I2C_SMBUS_BLOCK_MAX - 2, + }; + ++/* ++ * SMBus byte/word reg16 support for adapters that have SMBUS_BYTE_DATA ++ * and SMBUS_WORD_DATA but lack I2C_FUNC_I2C and I2C_FUNC_SMBUS_I2C_BLOCK, ++ * such as the AMD PIIX4. ++ * ++ * READ: set 16-bit EEPROM address via write_byte_data(addr_lo, addr_hi), ++ * then sequentially read bytes via read_byte() (EEPROM auto- ++ * increments the address pointer). Same as the I2C-block reg16 ++ * read path above. ++ * ++ * WRITE: encode the low address byte and data into a word transaction: ++ * write_word_data(addr_hi, (data_byte << 8) | addr_lo). ++ * Only single-byte writes are supported (one value per transaction). ++ */ ++static int regmap_smbus_word_write_reg16(void *context, const void *data, ++ size_t count) ++{ ++ struct device *dev = context; ++ struct i2c_client *i2c = to_i2c_client(dev); ++ u8 addr_hi, addr_lo, val; ++ ++ /* ++ * data layout: [addr_hi, addr_lo, val0, val1, ...]. ++ * Only single-byte value writes are supported; multi-byte would ++ * require raw I2C (or repeated word writes with incrementing address). ++ */ ++ if (count != 3) ++ return -EINVAL; ++ ++ addr_hi = ((u8 *)data)[0]; ++ addr_lo = ((u8 *)data)[1]; ++ val = ((u8 *)data)[2]; ++ ++ return i2c_smbus_write_word_data(i2c, addr_hi, ++ cpu_to_le16(((u16)val << 8) | addr_lo)); ++} ++ ++static const struct regmap_bus regmap_smbus_byte_word_reg16 = { ++ .write = regmap_smbus_word_write_reg16, ++ .read = regmap_i2c_smbus_i2c_read_reg16, ++ .max_raw_read = I2C_SMBUS_BLOCK_MAX - 2, ++ .max_raw_write = 1, ++}; ++ + static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, + const struct regmap_config *config) + { +@@ -321,6 +365,11 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, + i2c_check_functionality(i2c->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) + bus = ®map_i2c_smbus_i2c_block_reg16; ++ else if (config->val_bits == 8 && config->reg_bits == 16 && ++ i2c_check_functionality(i2c->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) ++ bus = ®map_smbus_byte_word_reg16; + else if (config->val_bits == 16 && config->reg_bits == 8 && + i2c_check_functionality(i2c->adapter, + I2C_FUNC_SMBUS_WORD_DATA)) +-- +2.25.1 +