Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

misc: amd-sbi: Move protocol functionality to core file

- This is done to utilize the protocol functionality into
other domains.
- Increase the scalability of the module with different bus(i2c/i3c)

Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Signed-off-by: Akshay Gupta <akshay.gupta@amd.com>
Link: https://lore.kernel.org/r/20250428063034.2145566-3-akshay.gupta@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Akshay Gupta and committed by
Greg Kroah-Hartman
43470595 e1565867

+192 -162
+5 -4
drivers/misc/amd-sbi/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config AMD_SBRMI_I2C 3 - tristate "AMD side band RMI support" 4 - depends on I2C 5 - help 6 - Side band RMI over I2C support for AMD out of band management. 3 + tristate "AMD side band RMI support" 4 + depends on I2C 5 + depends on HWMON 6 + help 7 + Side band RMI over I2C support for AMD out of band management. 7 8 8 9 This driver can also be built as a module. If so, the module will 9 10 be called sbrmi-i2c.
+2 -1
drivers/misc/amd-sbi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - obj-$(CONFIG_AMD_SBRMI_I2C) += sbrmi.o 2 + sbrmi-i2c-objs := rmi-i2c.o rmi-core.o 3 + obj-$(CONFIG_AMD_SBRMI_I2C) += sbrmi-i2c.o
+113
drivers/misc/amd-sbi/rmi-core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * sbrmi-core.c - file defining SB-RMI protocols compliant 4 + * AMD SoC device. 5 + * 6 + * Copyright (C) 2025 Advanced Micro Devices, Inc. 7 + */ 8 + #include <linux/delay.h> 9 + #include <linux/err.h> 10 + #include <linux/i2c.h> 11 + #include <linux/mutex.h> 12 + #include "rmi-core.h" 13 + 14 + /* Mask for Status Register bit[1] */ 15 + #define SW_ALERT_MASK 0x2 16 + 17 + /* Software Interrupt for triggering */ 18 + #define START_CMD 0x80 19 + #define TRIGGER_MAILBOX 0x01 20 + 21 + int rmi_mailbox_xfer(struct sbrmi_data *data, 22 + struct sbrmi_mailbox_msg *msg) 23 + { 24 + int i, ret, retry = 10; 25 + int sw_status; 26 + u8 byte; 27 + 28 + mutex_lock(&data->lock); 29 + 30 + /* Indicate firmware a command is to be serviced */ 31 + ret = i2c_smbus_write_byte_data(data->client, 32 + SBRMI_INBNDMSG7, START_CMD); 33 + if (ret < 0) 34 + goto exit_unlock; 35 + 36 + /* Write the command to SBRMI::InBndMsg_inst0 */ 37 + ret = i2c_smbus_write_byte_data(data->client, 38 + SBRMI_INBNDMSG0, msg->cmd); 39 + if (ret < 0) 40 + goto exit_unlock; 41 + 42 + /* 43 + * For both read and write the initiator (BMC) writes 44 + * Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1] 45 + * SBRMI_x3C(MSB):SBRMI_x39(LSB) 46 + */ 47 + for (i = 0; i < 4; i++) { 48 + byte = (msg->data_in >> i * 8) & 0xff; 49 + ret = i2c_smbus_write_byte_data(data->client, 50 + SBRMI_INBNDMSG1 + i, byte); 51 + if (ret < 0) 52 + goto exit_unlock; 53 + } 54 + 55 + /* 56 + * Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to 57 + * perform the requested read or write command 58 + */ 59 + ret = i2c_smbus_write_byte_data(data->client, 60 + SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX); 61 + if (ret < 0) 62 + goto exit_unlock; 63 + 64 + /* 65 + * Firmware will write SBRMI::Status[SwAlertSts]=1 to generate 66 + * an ALERT (if enabled) to initiator (BMC) to indicate completion 67 + * of the requested command 68 + */ 69 + do { 70 + sw_status = i2c_smbus_read_byte_data(data->client, 71 + SBRMI_STATUS); 72 + if (sw_status < 0) { 73 + ret = sw_status; 74 + goto exit_unlock; 75 + } 76 + if (sw_status & SW_ALERT_MASK) 77 + break; 78 + usleep_range(50, 100); 79 + } while (retry--); 80 + 81 + if (retry < 0) { 82 + dev_err(&data->client->dev, 83 + "Firmware fail to indicate command completion\n"); 84 + ret = -EIO; 85 + goto exit_unlock; 86 + } 87 + 88 + /* 89 + * For a read operation, the initiator (BMC) reads the firmware 90 + * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1] 91 + * {SBRMI_x34(MSB):SBRMI_x31(LSB)}. 92 + */ 93 + if (msg->read) { 94 + for (i = 0; i < 4; i++) { 95 + ret = i2c_smbus_read_byte_data(data->client, 96 + SBRMI_OUTBNDMSG1 + i); 97 + if (ret < 0) 98 + goto exit_unlock; 99 + msg->data_out |= ret << i * 8; 100 + } 101 + } 102 + 103 + /* 104 + * BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the 105 + * ALERT to initiator 106 + */ 107 + ret = i2c_smbus_write_byte_data(data->client, SBRMI_STATUS, 108 + sw_status | SW_ALERT_MASK); 109 + 110 + exit_unlock: 111 + mutex_unlock(&data->lock); 112 + return ret; 113 + }
+63
drivers/misc/amd-sbi/rmi-core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright (C) 2025 Advanced Micro Devices, Inc. 4 + */ 5 + 6 + #ifndef _SBRMI_CORE_H_ 7 + #define _SBRMI_CORE_H_ 8 + 9 + #include <linux/mutex.h> 10 + #include <linux/i2c.h> 11 + #include <linux/platform_device.h> 12 + 13 + /* SB-RMI registers */ 14 + enum sbrmi_reg { 15 + SBRMI_CTRL = 0x01, 16 + SBRMI_STATUS, 17 + SBRMI_OUTBNDMSG0 = 0x30, 18 + SBRMI_OUTBNDMSG1, 19 + SBRMI_OUTBNDMSG2, 20 + SBRMI_OUTBNDMSG3, 21 + SBRMI_OUTBNDMSG4, 22 + SBRMI_OUTBNDMSG5, 23 + SBRMI_OUTBNDMSG6, 24 + SBRMI_OUTBNDMSG7, 25 + SBRMI_INBNDMSG0, 26 + SBRMI_INBNDMSG1, 27 + SBRMI_INBNDMSG2, 28 + SBRMI_INBNDMSG3, 29 + SBRMI_INBNDMSG4, 30 + SBRMI_INBNDMSG5, 31 + SBRMI_INBNDMSG6, 32 + SBRMI_INBNDMSG7, 33 + SBRMI_SW_INTERRUPT, 34 + }; 35 + 36 + /* 37 + * SB-RMI supports soft mailbox service request to MP1 (power management 38 + * firmware) through SBRMI inbound/outbound message registers. 39 + * SB-RMI message IDs 40 + */ 41 + enum sbrmi_msg_id { 42 + SBRMI_READ_PKG_PWR_CONSUMPTION = 0x1, 43 + SBRMI_WRITE_PKG_PWR_LIMIT, 44 + SBRMI_READ_PKG_PWR_LIMIT, 45 + SBRMI_READ_PKG_MAX_PWR_LIMIT, 46 + }; 47 + 48 + /* Each client has this additional data */ 49 + struct sbrmi_data { 50 + struct i2c_client *client; 51 + struct mutex lock; 52 + u32 pwr_limit_max; 53 + }; 54 + 55 + struct sbrmi_mailbox_msg { 56 + u8 cmd; 57 + bool read; 58 + u32 data_in; 59 + u32 data_out; 60 + }; 61 + 62 + int rmi_mailbox_xfer(struct sbrmi_data *data, struct sbrmi_mailbox_msg *msg); 63 + #endif /*_SBRMI_CORE_H_*/
+9 -157
drivers/misc/amd-sbi/sbrmi.c drivers/misc/amd-sbi/rmi-i2c.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * sbrmi.c - hwmon driver for a SB-RMI mailbox 4 - * compliant AMD SoC device. 3 + * rmi-i2c.c - Side band RMI over I2C support for AMD out 4 + * of band management 5 5 * 6 - * Copyright (C) 2020-2021 Advanced Micro Devices, Inc. 6 + * Copyright (C) 2024 Advanced Micro Devices, Inc. 7 7 */ 8 8 9 9 #include <linux/delay.h> ··· 14 14 #include <linux/module.h> 15 15 #include <linux/mutex.h> 16 16 #include <linux/of.h> 17 + #include "rmi-core.h" 17 18 18 19 /* Do not allow setting negative power limit */ 19 20 #define SBRMI_PWR_MIN 0 20 - /* Mask for Status Register bit[1] */ 21 - #define SW_ALERT_MASK 0x2 22 - 23 - /* Software Interrupt for triggering */ 24 - #define START_CMD 0x80 25 - #define TRIGGER_MAILBOX 0x01 26 - 27 - /* 28 - * SB-RMI supports soft mailbox service request to MP1 (power management 29 - * firmware) through SBRMI inbound/outbound message registers. 30 - * SB-RMI message IDs 31 - */ 32 - enum sbrmi_msg_id { 33 - SBRMI_READ_PKG_PWR_CONSUMPTION = 0x1, 34 - SBRMI_WRITE_PKG_PWR_LIMIT, 35 - SBRMI_READ_PKG_PWR_LIMIT, 36 - SBRMI_READ_PKG_MAX_PWR_LIMIT, 37 - }; 38 - 39 - /* SB-RMI registers */ 40 - enum sbrmi_reg { 41 - SBRMI_CTRL = 0x01, 42 - SBRMI_STATUS, 43 - SBRMI_OUTBNDMSG0 = 0x30, 44 - SBRMI_OUTBNDMSG1, 45 - SBRMI_OUTBNDMSG2, 46 - SBRMI_OUTBNDMSG3, 47 - SBRMI_OUTBNDMSG4, 48 - SBRMI_OUTBNDMSG5, 49 - SBRMI_OUTBNDMSG6, 50 - SBRMI_OUTBNDMSG7, 51 - SBRMI_INBNDMSG0, 52 - SBRMI_INBNDMSG1, 53 - SBRMI_INBNDMSG2, 54 - SBRMI_INBNDMSG3, 55 - SBRMI_INBNDMSG4, 56 - SBRMI_INBNDMSG5, 57 - SBRMI_INBNDMSG6, 58 - SBRMI_INBNDMSG7, 59 - SBRMI_SW_INTERRUPT, 60 - }; 61 - 62 - /* Each client has this additional data */ 63 - struct sbrmi_data { 64 - struct i2c_client *client; 65 - struct mutex lock; 66 - u32 pwr_limit_max; 67 - }; 68 - 69 - struct sbrmi_mailbox_msg { 70 - u8 cmd; 71 - bool read; 72 - u32 data_in; 73 - u32 data_out; 74 - }; 75 21 76 22 static int sbrmi_enable_alert(struct i2c_client *client) 77 23 { ··· 38 92 } 39 93 40 94 return 0; 41 - } 42 - 43 - static int rmi_mailbox_xfer(struct sbrmi_data *data, 44 - struct sbrmi_mailbox_msg *msg) 45 - { 46 - int i, ret, retry = 10; 47 - int sw_status; 48 - u8 byte; 49 - 50 - mutex_lock(&data->lock); 51 - 52 - /* Indicate firmware a command is to be serviced */ 53 - ret = i2c_smbus_write_byte_data(data->client, 54 - SBRMI_INBNDMSG7, START_CMD); 55 - if (ret < 0) 56 - goto exit_unlock; 57 - 58 - /* Write the command to SBRMI::InBndMsg_inst0 */ 59 - ret = i2c_smbus_write_byte_data(data->client, 60 - SBRMI_INBNDMSG0, msg->cmd); 61 - if (ret < 0) 62 - goto exit_unlock; 63 - 64 - /* 65 - * For both read and write the initiator (BMC) writes 66 - * Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1] 67 - * SBRMI_x3C(MSB):SBRMI_x39(LSB) 68 - */ 69 - for (i = 0; i < 4; i++) { 70 - byte = (msg->data_in >> i * 8) & 0xff; 71 - ret = i2c_smbus_write_byte_data(data->client, 72 - SBRMI_INBNDMSG1 + i, byte); 73 - if (ret < 0) 74 - goto exit_unlock; 75 - } 76 - 77 - /* 78 - * Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to 79 - * perform the requested read or write command 80 - */ 81 - ret = i2c_smbus_write_byte_data(data->client, 82 - SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX); 83 - if (ret < 0) 84 - goto exit_unlock; 85 - 86 - /* 87 - * Firmware will write SBRMI::Status[SwAlertSts]=1 to generate 88 - * an ALERT (if enabled) to initiator (BMC) to indicate completion 89 - * of the requested command 90 - */ 91 - do { 92 - sw_status = i2c_smbus_read_byte_data(data->client, 93 - SBRMI_STATUS); 94 - if (sw_status < 0) { 95 - ret = sw_status; 96 - goto exit_unlock; 97 - } 98 - if (sw_status & SW_ALERT_MASK) 99 - break; 100 - usleep_range(50, 100); 101 - } while (retry--); 102 - 103 - if (retry < 0) { 104 - dev_err(&data->client->dev, 105 - "Firmware fail to indicate command completion\n"); 106 - ret = -EIO; 107 - goto exit_unlock; 108 - } 109 - 110 - /* 111 - * For a read operation, the initiator (BMC) reads the firmware 112 - * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1] 113 - * {SBRMI_x34(MSB):SBRMI_x31(LSB)}. 114 - */ 115 - if (msg->read) { 116 - for (i = 0; i < 4; i++) { 117 - ret = i2c_smbus_read_byte_data(data->client, 118 - SBRMI_OUTBNDMSG1 + i); 119 - if (ret < 0) 120 - goto exit_unlock; 121 - msg->data_out |= ret << i * 8; 122 - } 123 - } 124 - 125 - /* 126 - * BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the 127 - * ALERT to initiator 128 - */ 129 - ret = i2c_smbus_write_byte_data(data->client, SBRMI_STATUS, 130 - sw_status | SW_ALERT_MASK); 131 - 132 - exit_unlock: 133 - mutex_unlock(&data->lock); 134 - return ret; 135 95 } 136 96 137 97 static int sbrmi_read(struct device *dev, enum hwmon_sensor_types type, ··· 149 297 return ret; 150 298 } 151 299 152 - static int sbrmi_probe(struct i2c_client *client) 300 + static int sbrmi_i2c_probe(struct i2c_client *client) 153 301 { 154 302 struct device *dev = &client->dev; 155 303 struct device *hwmon_dev; ··· 175 323 176 324 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, 177 325 &sbrmi_chip_info, NULL); 178 - 179 326 return PTR_ERR_OR_ZERO(hwmon_dev); 180 327 } 181 328 182 329 static const struct i2c_device_id sbrmi_id[] = { 183 - {"sbrmi"}, 330 + {"sbrmi-i2c"}, 184 331 {} 185 332 }; 186 333 MODULE_DEVICE_TABLE(i2c, sbrmi_id); ··· 194 343 195 344 static struct i2c_driver sbrmi_driver = { 196 345 .driver = { 197 - .name = "sbrmi", 346 + .name = "sbrmi-i2c", 198 347 .of_match_table = of_match_ptr(sbrmi_of_match), 199 348 }, 200 - .probe = sbrmi_probe, 349 + .probe = sbrmi_i2c_probe, 201 350 .id_table = sbrmi_id, 202 351 }; 203 352 204 353 module_i2c_driver(sbrmi_driver); 205 354 206 355 MODULE_AUTHOR("Akshay Gupta <akshay.gupta@amd.com>"); 356 + MODULE_AUTHOR("Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>"); 207 357 MODULE_DESCRIPTION("Hwmon driver for AMD SB-RMI emulated sensor"); 208 358 MODULE_LICENSE("GPL");