Commit 013f7e71 authored by Akshay Gupta's avatar Akshay Gupta Committed by Greg Kroah-Hartman
Browse files

misc: amd-sbi: Use regmap subsystem



- regmap subsystem provides multiple benefits over direct smbus APIs
- subsystem adds another abstraction layer on top of struct i2c_client to
  make it easy to read or write registers.
- The subsystem can be helpful in following cases
  - Different types of bus (i2c/i3c), we have plans to support i3c.
  - Different Register address size (1byte/2byte)

Reviewed-by: default avatarNaveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Signed-off-by: default avatarAkshay Gupta <akshay.gupta@amd.com>
Link: https://lore.kernel.org/r/20250428063034.2145566-5-akshay.gupta@amd.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f4dc6406
Loading
Loading
Loading
Loading
+12 −17
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include "rmi-core.h"

/* Mask for Status Register bit[1] */
@@ -21,6 +22,7 @@
int rmi_mailbox_xfer(struct sbrmi_data *data,
		     struct sbrmi_mailbox_msg *msg)
{
	unsigned int bytes;
	int i, ret, retry = 10;
	int sw_status;
	u8 byte;
@@ -28,14 +30,12 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	mutex_lock(&data->lock);

	/* Indicate firmware a command is to be serviced */
	ret = i2c_smbus_write_byte_data(data->client,
					SBRMI_INBNDMSG7, START_CMD);
	ret = regmap_write(data->regmap, 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);
	ret = regmap_write(data->regmap, SBRMI_INBNDMSG0, msg->cmd);
	if (ret < 0)
		goto exit_unlock;

@@ -46,8 +46,7 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	 */
	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);
		ret = regmap_write(data->regmap, SBRMI_INBNDMSG1 + i, byte);
		if (ret < 0)
			goto exit_unlock;
	}
@@ -56,8 +55,7 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	 * 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);
	ret = regmap_write(data->regmap, SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX);
	if (ret < 0)
		goto exit_unlock;

@@ -67,8 +65,7 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	 * of the requested command
	 */
	do {
		sw_status = i2c_smbus_read_byte_data(data->client,
						     SBRMI_STATUS);
		ret = regmap_read(data->regmap, SBRMI_STATUS, &sw_status);
		if (sw_status < 0) {
			ret = sw_status;
			goto exit_unlock;
@@ -79,8 +76,6 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	} while (retry--);

	if (retry < 0) {
		dev_err(&data->client->dev,
			"Firmware fail to indicate command completion\n");
		ret = -EIO;
		goto exit_unlock;
	}
@@ -92,11 +87,11 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	 */
	if (msg->read) {
		for (i = 0; i < 4; i++) {
			ret = i2c_smbus_read_byte_data(data->client,
						       SBRMI_OUTBNDMSG1 + i);
			ret = regmap_read(data->regmap,
					  SBRMI_OUTBNDMSG1 + i, &bytes);
			if (ret < 0)
				goto exit_unlock;
			msg->data_out |= ret << i * 8;
			msg->data_out |= bytes << i * 8;
		}
	}

@@ -104,7 +99,7 @@ int rmi_mailbox_xfer(struct sbrmi_data *data,
	 * 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,
	ret = regmap_write(data->regmap, SBRMI_STATUS,
			   sw_status | SW_ALERT_MASK);

exit_unlock:
+2 −1
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/mutex.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

/* SB-RMI registers */
enum sbrmi_reg {
@@ -47,7 +48,7 @@ enum sbrmi_msg_id {

/* Each client has this additional data */
struct sbrmi_data {
	struct i2c_client *client;
	struct regmap *regmap;
	struct mutex lock;
	u32 pwr_limit_max;
};
+16 −9
Original line number Diff line number Diff line
@@ -13,24 +13,24 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include "rmi-core.h"

static int sbrmi_enable_alert(struct i2c_client *client)
static int sbrmi_enable_alert(struct sbrmi_data *data)
{
	int ctrl;
	int ctrl, ret;

	/*
	 * Enable the SB-RMI Software alert status
	 * by writing 0 to bit 4 of Control register(0x1)
	 */
	ctrl = i2c_smbus_read_byte_data(client, SBRMI_CTRL);
	if (ctrl < 0)
		return ctrl;
	ret = regmap_read(data->regmap, SBRMI_CTRL, &ctrl);
	if (ret < 0)
		return ret;

	if (ctrl & 0x10) {
		ctrl &= ~0x10;
		return i2c_smbus_write_byte_data(client,
						 SBRMI_CTRL, ctrl);
		return regmap_write(data->regmap, SBRMI_CTRL, ctrl);
	}

	return 0;
@@ -55,17 +55,24 @@ static int sbrmi_i2c_probe(struct i2c_client *client)
{
	struct device *dev = &client->dev;
	struct sbrmi_data *data;
	struct regmap_config sbrmi_i2c_regmap_config = {
		.reg_bits = 8,
		.val_bits = 8,
	};
	int ret;

	data = devm_kzalloc(dev, sizeof(struct sbrmi_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->client = client;
	mutex_init(&data->lock);

	data->regmap = devm_regmap_init_i2c(client, &sbrmi_i2c_regmap_config);
	if (IS_ERR(data->regmap))
		return PTR_ERR(data->regmap);

	/* Enable alert for SB-RMI sequence */
	ret = sbrmi_enable_alert(client);
	ret = sbrmi_enable_alert(data);
	if (ret < 0)
		return ret;