drivers: ipmi: Support raw i2c packet in IPMB

Many IPMB devices don't support smbus protocol and this driver
only supports the smbus protocol at the moment.

Added support for the i2c protocol as well. There will be a variable
"i2c-protocol" passed by the device tree or ACPI table which determines
whether the protocol is i2c or smbus.

Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
Reviewed-by: Asmaa Mnebhi <asmaa@mellanox.com>
Message-Id: <20191211185604.1266063-1-vijaykhemka@fb.com>
[IPMB.txt had moved to driver-api/ipmb.rst, I adjusted]
Signed-off-by: Corey Minyard <cminyard@mvista.com>
This commit is contained in:
Vijay Khemka 2019-12-11 10:56:04 -08:00 committed by Corey Minyard
parent 6794862a16
commit 042f057fe2
2 changed files with 33 additions and 0 deletions

View File

@ -71,9 +71,13 @@ b) Example for device tree::
ipmb@10 {
compatible = "ipmb-dev";
reg = <0x10>;
i2c-protocol;
};
};
If xmit of data to be done using raw i2c block vs smbus
then "i2c-protocol" needs to be defined as above.
2) Manually from Linux::
modprobe ipmb-dev-int

View File

@ -63,6 +63,7 @@ struct ipmb_dev {
spinlock_t lock;
wait_queue_head_t wait_queue;
struct mutex file_mutex;
bool is_i2c_protocol;
};
static inline struct ipmb_dev *to_ipmb_dev(struct file *file)
@ -112,6 +113,25 @@ static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count,
return ret < 0 ? ret : count;
}
static int ipmb_i2c_write(struct i2c_client *client, u8 *msg, u8 addr)
{
struct i2c_msg i2c_msg;
/*
* subtract 1 byte (rq_sa) from the length of the msg passed to
* raw i2c_transfer
*/
i2c_msg.len = msg[IPMB_MSG_LEN_IDX] - 1;
/* Assign message to buffer except first 2 bytes (length and address) */
i2c_msg.buf = msg + 2;
i2c_msg.addr = addr;
i2c_msg.flags = client->flags & I2C_CLIENT_PEC;
return i2c_transfer(client->adapter, &i2c_msg, 1);
}
static ssize_t ipmb_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@ -133,6 +153,12 @@ static ssize_t ipmb_write(struct file *file, const char __user *buf,
rq_sa = GET_7BIT_ADDR(msg[RQ_SA_8BIT_IDX]);
netf_rq_lun = msg[NETFN_LUN_IDX];
/* Check i2c block transfer vs smbus */
if (ipmb_dev->is_i2c_protocol) {
ret = ipmb_i2c_write(ipmb_dev->client, msg, rq_sa);
return (ret == 1) ? count : ret;
}
/*
* subtract rq_sa and netf_rq_lun from the length of the msg passed to
* i2c_smbus_xfer
@ -302,6 +328,9 @@ static int ipmb_probe(struct i2c_client *client,
if (ret)
return ret;
ipmb_dev->is_i2c_protocol
= device_property_read_bool(&client->dev, "i2c-protocol");
ipmb_dev->client = client;
i2c_set_clientdata(client, ipmb_dev);
ret = i2c_slave_register(client, ipmb_slave_cb);