diff options
| author | Akshay Gupta <akshay.gupta@amd.com> | 2025-09-15 10:36:46 +0000 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-10-22 07:59:57 +0200 |
| commit | 45392fd4394cb8d4b39ba0f144651aba05b7b2a7 (patch) | |
| tree | 01fcdc26545e8cee4d506747ed43ad0b9994bc95 /drivers/misc | |
| parent | 5c7dddd7360b9f24d535c34dcd4101fe41b35aa1 (diff) | |
misc: amd-sbi: Add support for Turin platform
- RMI registers addresses in AMD new platforms are 2 bytes,
on previous processors the address size is 1 byte.
- Implement logic to identify register address size at runtime.
- The identification is done in first transaction using the
Revision register.
- The revision register can be read using 1 byte in both, older and
newer platforms.
- However, sending 1 byte on later platform can cause unrecoverable error.
Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Signed-off-by: Akshay Gupta <akshay.gupta@amd.com>
Link: https://patch.msgid.link/20250915103649.1705078-3-akshay.gupta@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
| -rw-r--r-- | drivers/misc/amd-sbi/rmi-i2c.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/misc/amd-sbi/rmi-i2c.c b/drivers/misc/amd-sbi/rmi-i2c.c index 087c57bb0f37..f0cc99000b69 100644 --- a/drivers/misc/amd-sbi/rmi-i2c.c +++ b/drivers/misc/amd-sbi/rmi-i2c.c @@ -18,6 +18,8 @@ #include <linux/regmap.h> #include "rmi-core.h" +#define REV_TWO_BYTE_ADDR 0x21 + static int sbrmi_enable_alert(struct sbrmi_data *data) { int ctrl, ret; @@ -89,15 +91,40 @@ static struct regmap_config sbrmi_regmap_config = { .val_bits = 8, }; +static struct regmap_config sbrmi_regmap_config_ext = { + .reg_bits = 16, + .val_bits = 8, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, +}; + static int sbrmi_i2c_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct regmap *regmap; + int rev, ret; regmap = devm_regmap_init_i2c(client, &sbrmi_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); + ret = regmap_read(regmap, SBRMI_REV, &rev); + if (ret) + return ret; + + /* + * For Turin and newer platforms, revision is 0x21 or later. This is + * to identify the two byte register address size. However, one + * byte transaction can be successful. + * Verify if revision is 0x21 or later, if yes, switch to 2 byte + * address size. + * Continuously using 1 byte address for revision 0x21 or later can lead + * to bus corruption. + */ + if (rev >= REV_TWO_BYTE_ADDR) { + regmap = devm_regmap_init_i2c(client, &sbrmi_regmap_config_ext); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + } return sbrmi_common_probe(dev, regmap, client->addr); } @@ -141,11 +168,31 @@ static int sbrmi_i3c_probe(struct i3c_device *i3cdev) { struct device *dev = i3cdev_to_dev(i3cdev); struct regmap *regmap; + int rev, ret; regmap = devm_regmap_init_i3c(i3cdev, &sbrmi_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); + ret = regmap_read(regmap, SBRMI_REV, &rev); + if (ret) + return ret; + + /* + * For Turin and newer platforms, revision is 0x21 or later. This is + * to identify the two byte register address size. However, one + * byte transaction can be successful. + * Verify if revision is 0x21 or later, if yes, switch to 2 byte + * address size. + * Continuously using 1 byte address for revision 0x21 or later can lead + * to bus corruption. + */ + if (rev >= REV_TWO_BYTE_ADDR) { + regmap = devm_regmap_init_i3c(i3cdev, &sbrmi_regmap_config_ext); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + } + /* * AMD APML I3C devices support static address. * If static address is defined, dynamic address is same as static address. |
