mirror of https://gitee.com/openkylin/linux.git
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:
parent
6794862a16
commit
042f057fe2
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue