Skip to content

Commit 4347059

Browse files
akky16gregkh
authored andcommitted
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 <[email protected]> Signed-off-by: Akshay Gupta <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e156586 commit 4347059

File tree

5 files changed

+192
-162
lines changed

5 files changed

+192
-162
lines changed

drivers/misc/amd-sbi/Kconfig

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
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.
78

89
This driver can also be built as a module. If so, the module will
910
be called sbrmi-i2c.

drivers/misc/amd-sbi/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# 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

drivers/misc/amd-sbi/rmi-core.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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+
}

drivers/misc/amd-sbi/rmi-core.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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_*/

0 commit comments

Comments
 (0)