]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
misc: amd-sbi: Move protocol functionality to core file
authorAkshay Gupta <akshay.gupta@amd.com>
Mon, 28 Apr 2025 06:30:26 +0000 (06:30 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 May 2025 12:44:40 +0000 (14:44 +0200)
- 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>
drivers/misc/amd-sbi/Kconfig
drivers/misc/amd-sbi/Makefile
drivers/misc/amd-sbi/rmi-core.c [new file with mode: 0644]
drivers/misc/amd-sbi/rmi-core.h [new file with mode: 0644]
drivers/misc/amd-sbi/rmi-i2c.c [moved from drivers/misc/amd-sbi/sbrmi.c with 53% similarity]

index be2d9e495eb72b491303d7118b30c88a04d3cfc3..0c8981f97f25bef6336971d8b192313f29e77892 100644 (file)
@@ -1,9 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config AMD_SBRMI_I2C
-        tristate "AMD side band RMI support"
-        depends on I2C
-        help
-          Side band RMI over I2C support for AMD out of band management.
+       tristate "AMD side band RMI support"
+       depends on I2C
+       depends on HWMON
+       help
+         Side band RMI over I2C support for AMD out of band management.
 
          This driver can also be built as a module. If so, the module will
          be called sbrmi-i2c.
index 304394bf5e59a1cccd6d27c62ab2a4e5678969c3..7cd8e0a1aa5df7a4c9d1be2f4343ece85cce4b64 100644 (file)
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_AMD_SBRMI_I2C)    += sbrmi.o
+sbrmi-i2c-objs                 := rmi-i2c.o rmi-core.o
+obj-$(CONFIG_AMD_SBRMI_I2C)    += sbrmi-i2c.o
diff --git a/drivers/misc/amd-sbi/rmi-core.c b/drivers/misc/amd-sbi/rmi-core.c
new file mode 100644 (file)
index 0000000..7445675
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * sbrmi-core.c - file defining SB-RMI protocols compliant
+ *               AMD SoC device.
+ *
+ * Copyright (C) 2025 Advanced Micro Devices, Inc.
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include "rmi-core.h"
+
+/* Mask for Status Register bit[1] */
+#define SW_ALERT_MASK  0x2
+
+/* Software Interrupt for triggering */
+#define START_CMD      0x80
+#define TRIGGER_MAILBOX        0x01
+
+int rmi_mailbox_xfer(struct sbrmi_data *data,
+                    struct sbrmi_mailbox_msg *msg)
+{
+       int i, ret, retry = 10;
+       int sw_status;
+       u8 byte;
+
+       mutex_lock(&data->lock);
+
+       /* Indicate firmware a command is to be serviced */
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       SBRMI_INBNDMSG7, START_CMD);
+       if (ret < 0)
+               goto exit_unlock;
+
+       /* Write the command to SBRMI::InBndMsg_inst0 */
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       SBRMI_INBNDMSG0, msg->cmd);
+       if (ret < 0)
+               goto exit_unlock;
+
+       /*
+        * For both read and write the initiator (BMC) writes
+        * Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1]
+        * SBRMI_x3C(MSB):SBRMI_x39(LSB)
+        */
+       for (i = 0; i < 4; i++) {
+               byte = (msg->data_in >> i * 8) & 0xff;
+               ret = i2c_smbus_write_byte_data(data->client,
+                                               SBRMI_INBNDMSG1 + i, byte);
+               if (ret < 0)
+                       goto exit_unlock;
+       }
+
+       /*
+        * Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to
+        * perform the requested read or write command
+        */
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX);
+       if (ret < 0)
+               goto exit_unlock;
+
+       /*
+        * Firmware will write SBRMI::Status[SwAlertSts]=1 to generate
+        * an ALERT (if enabled) to initiator (BMC) to indicate completion
+        * of the requested command
+        */
+       do {
+               sw_status = i2c_smbus_read_byte_data(data->client,
+                                                    SBRMI_STATUS);
+               if (sw_status < 0) {
+                       ret = sw_status;
+                       goto exit_unlock;
+               }
+               if (sw_status & SW_ALERT_MASK)
+                       break;
+               usleep_range(50, 100);
+       } while (retry--);
+
+       if (retry < 0) {
+               dev_err(&data->client->dev,
+                       "Firmware fail to indicate command completion\n");
+               ret = -EIO;
+               goto exit_unlock;
+       }
+
+       /*
+        * For a read operation, the initiator (BMC) reads the firmware
+        * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1]
+        * {SBRMI_x34(MSB):SBRMI_x31(LSB)}.
+        */
+       if (msg->read) {
+               for (i = 0; i < 4; i++) {
+                       ret = i2c_smbus_read_byte_data(data->client,
+                                                      SBRMI_OUTBNDMSG1 + i);
+                       if (ret < 0)
+                               goto exit_unlock;
+                       msg->data_out |= ret << i * 8;
+               }
+       }
+
+       /*
+        * BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the
+        * ALERT to initiator
+        */
+       ret = i2c_smbus_write_byte_data(data->client, SBRMI_STATUS,
+                                       sw_status | SW_ALERT_MASK);
+
+exit_unlock:
+       mutex_unlock(&data->lock);
+       return ret;
+}
diff --git a/drivers/misc/amd-sbi/rmi-core.h b/drivers/misc/amd-sbi/rmi-core.h
new file mode 100644 (file)
index 0000000..8e30a43
--- /dev/null
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SBRMI_CORE_H_
+#define _SBRMI_CORE_H_
+
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+
+/* SB-RMI registers */
+enum sbrmi_reg {
+       SBRMI_CTRL              = 0x01,
+       SBRMI_STATUS,
+       SBRMI_OUTBNDMSG0        = 0x30,
+       SBRMI_OUTBNDMSG1,
+       SBRMI_OUTBNDMSG2,
+       SBRMI_OUTBNDMSG3,
+       SBRMI_OUTBNDMSG4,
+       SBRMI_OUTBNDMSG5,
+       SBRMI_OUTBNDMSG6,
+       SBRMI_OUTBNDMSG7,
+       SBRMI_INBNDMSG0,
+       SBRMI_INBNDMSG1,
+       SBRMI_INBNDMSG2,
+       SBRMI_INBNDMSG3,
+       SBRMI_INBNDMSG4,
+       SBRMI_INBNDMSG5,
+       SBRMI_INBNDMSG6,
+       SBRMI_INBNDMSG7,
+       SBRMI_SW_INTERRUPT,
+};
+
+/*
+ * SB-RMI supports soft mailbox service request to MP1 (power management
+ * firmware) through SBRMI inbound/outbound message registers.
+ * SB-RMI message IDs
+ */
+enum sbrmi_msg_id {
+       SBRMI_READ_PKG_PWR_CONSUMPTION = 0x1,
+       SBRMI_WRITE_PKG_PWR_LIMIT,
+       SBRMI_READ_PKG_PWR_LIMIT,
+       SBRMI_READ_PKG_MAX_PWR_LIMIT,
+};
+
+/* Each client has this additional data */
+struct sbrmi_data {
+       struct i2c_client *client;
+       struct mutex lock;
+       u32 pwr_limit_max;
+};
+
+struct sbrmi_mailbox_msg {
+       u8 cmd;
+       bool read;
+       u32 data_in;
+       u32 data_out;
+};
+
+int rmi_mailbox_xfer(struct sbrmi_data *data, struct sbrmi_mailbox_msg *msg);
+#endif /*_SBRMI_CORE_H_*/
similarity index 53%
rename from drivers/misc/amd-sbi/sbrmi.c
rename to drivers/misc/amd-sbi/rmi-i2c.c
index d48d8e5460ff6e3cc4538bdd88ddb648da53078b..6412f00eb3810fad4ce451b37611e41e3ed21e60 100644 (file)
@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * sbrmi.c - hwmon driver for a SB-RMI mailbox
- *           compliant AMD SoC device.
+ * rmi-i2c.c - Side band RMI over I2C support for AMD out
+ *             of band management
  *
- * Copyright (C) 2020-2021 Advanced Micro Devices, Inc.
+ * Copyright (C) 2024 Advanced Micro Devices, Inc.
  */
 
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include "rmi-core.h"
 
 /* Do not allow setting negative power limit */
 #define SBRMI_PWR_MIN  0
-/* Mask for Status Register bit[1] */
-#define SW_ALERT_MASK  0x2
-
-/* Software Interrupt for triggering */
-#define START_CMD      0x80
-#define TRIGGER_MAILBOX        0x01
-
-/*
- * SB-RMI supports soft mailbox service request to MP1 (power management
- * firmware) through SBRMI inbound/outbound message registers.
- * SB-RMI message IDs
- */
-enum sbrmi_msg_id {
-       SBRMI_READ_PKG_PWR_CONSUMPTION = 0x1,
-       SBRMI_WRITE_PKG_PWR_LIMIT,
-       SBRMI_READ_PKG_PWR_LIMIT,
-       SBRMI_READ_PKG_MAX_PWR_LIMIT,
-};
-
-/* SB-RMI registers */
-enum sbrmi_reg {
-       SBRMI_CTRL              = 0x01,
-       SBRMI_STATUS,
-       SBRMI_OUTBNDMSG0        = 0x30,
-       SBRMI_OUTBNDMSG1,
-       SBRMI_OUTBNDMSG2,
-       SBRMI_OUTBNDMSG3,
-       SBRMI_OUTBNDMSG4,
-       SBRMI_OUTBNDMSG5,
-       SBRMI_OUTBNDMSG6,
-       SBRMI_OUTBNDMSG7,
-       SBRMI_INBNDMSG0,
-       SBRMI_INBNDMSG1,
-       SBRMI_INBNDMSG2,
-       SBRMI_INBNDMSG3,
-       SBRMI_INBNDMSG4,
-       SBRMI_INBNDMSG5,
-       SBRMI_INBNDMSG6,
-       SBRMI_INBNDMSG7,
-       SBRMI_SW_INTERRUPT,
-};
-
-/* Each client has this additional data */
-struct sbrmi_data {
-       struct i2c_client *client;
-       struct mutex lock;
-       u32 pwr_limit_max;
-};
-
-struct sbrmi_mailbox_msg {
-       u8 cmd;
-       bool read;
-       u32 data_in;
-       u32 data_out;
-};
 
 static int sbrmi_enable_alert(struct i2c_client *client)
 {
@@ -94,100 +40,6 @@ static int sbrmi_enable_alert(struct i2c_client *client)
        return 0;
 }
 
-static int rmi_mailbox_xfer(struct sbrmi_data *data,
-                           struct sbrmi_mailbox_msg *msg)
-{
-       int i, ret, retry = 10;
-       int sw_status;
-       u8 byte;
-
-       mutex_lock(&data->lock);
-
-       /* Indicate firmware a command is to be serviced */
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       SBRMI_INBNDMSG7, START_CMD);
-       if (ret < 0)
-               goto exit_unlock;
-
-       /* Write the command to SBRMI::InBndMsg_inst0 */
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       SBRMI_INBNDMSG0, msg->cmd);
-       if (ret < 0)
-               goto exit_unlock;
-
-       /*
-        * For both read and write the initiator (BMC) writes
-        * Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1]
-        * SBRMI_x3C(MSB):SBRMI_x39(LSB)
-        */
-       for (i = 0; i < 4; i++) {
-               byte = (msg->data_in >> i * 8) & 0xff;
-               ret = i2c_smbus_write_byte_data(data->client,
-                                               SBRMI_INBNDMSG1 + i, byte);
-               if (ret < 0)
-                       goto exit_unlock;
-       }
-
-       /*
-        * Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to
-        * perform the requested read or write command
-        */
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX);
-       if (ret < 0)
-               goto exit_unlock;
-
-       /*
-        * Firmware will write SBRMI::Status[SwAlertSts]=1 to generate
-        * an ALERT (if enabled) to initiator (BMC) to indicate completion
-        * of the requested command
-        */
-       do {
-               sw_status = i2c_smbus_read_byte_data(data->client,
-                                                    SBRMI_STATUS);
-               if (sw_status < 0) {
-                       ret = sw_status;
-                       goto exit_unlock;
-               }
-               if (sw_status & SW_ALERT_MASK)
-                       break;
-               usleep_range(50, 100);
-       } while (retry--);
-
-       if (retry < 0) {
-               dev_err(&data->client->dev,
-                       "Firmware fail to indicate command completion\n");
-               ret = -EIO;
-               goto exit_unlock;
-       }
-
-       /*
-        * For a read operation, the initiator (BMC) reads the firmware
-        * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1]
-        * {SBRMI_x34(MSB):SBRMI_x31(LSB)}.
-        */
-       if (msg->read) {
-               for (i = 0; i < 4; i++) {
-                       ret = i2c_smbus_read_byte_data(data->client,
-                                                      SBRMI_OUTBNDMSG1 + i);
-                       if (ret < 0)
-                               goto exit_unlock;
-                       msg->data_out |= ret << i * 8;
-               }
-       }
-
-       /*
-        * BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the
-        * ALERT to initiator
-        */
-       ret = i2c_smbus_write_byte_data(data->client, SBRMI_STATUS,
-                                       sw_status | SW_ALERT_MASK);
-
-exit_unlock:
-       mutex_unlock(&data->lock);
-       return ret;
-}
-
 static int sbrmi_read(struct device *dev, enum hwmon_sensor_types type,
                      u32 attr, int channel, long *val)
 {
@@ -297,7 +149,7 @@ static int sbrmi_get_max_pwr_limit(struct sbrmi_data *data)
        return ret;
 }
 
-static int sbrmi_probe(struct i2c_client *client)
+static int sbrmi_i2c_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
        struct device *hwmon_dev;
@@ -323,12 +175,11 @@ static int sbrmi_probe(struct i2c_client *client)
 
        hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
                                                         &sbrmi_chip_info, NULL);
-
        return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id sbrmi_id[] = {
-       {"sbrmi"},
+       {"sbrmi-i2c"},
        {}
 };
 MODULE_DEVICE_TABLE(i2c, sbrmi_id);
@@ -343,15 +194,16 @@ MODULE_DEVICE_TABLE(of, sbrmi_of_match);
 
 static struct i2c_driver sbrmi_driver = {
        .driver = {
-               .name = "sbrmi",
+               .name = "sbrmi-i2c",
                .of_match_table = of_match_ptr(sbrmi_of_match),
        },
-       .probe = sbrmi_probe,
+       .probe = sbrmi_i2c_probe,
        .id_table = sbrmi_id,
 };
 
 module_i2c_driver(sbrmi_driver);
 
 MODULE_AUTHOR("Akshay Gupta <akshay.gupta@amd.com>");
+MODULE_AUTHOR("Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>");
 MODULE_DESCRIPTION("Hwmon driver for AMD SB-RMI emulated sensor");
 MODULE_LICENSE("GPL");