Commit 13cae4a1 authored by Matt Johnston's avatar Matt Johnston Committed by David S. Miller

i2c: core: Allow 255 byte transfers for SMBus 3.x

SMBus 3.0 increased the maximum block transfer size from 32 bytes to
255 bytes. We increase the size of struct i2c_smbus_data's block[]
member.

i2c_smbus_xfer() and i2c_smbus_xfer_emulated() now support 255 byte
block operations, other block functions remain limited to 32 bytes for
compatibility with existing callers.

We allow adapters to indicate support for the larger size with
I2C_FUNC_SMBUS_V3_BLOCK. Most emulated drivers should be able to use 255
byte blocks by replacing I2C_SMBUS_BLOCK_MAX with I2C_SMBUS_V3_BLOCK_MAX
though some will have hardware limitations that need testing.
Signed-off-by: default avatarMatt Johnston <matt@codeconstruct.com.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cc0be1ad
...@@ -303,7 +303,8 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val) ...@@ -303,7 +303,8 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)
bool is_read = msg->flags & I2C_M_RD; bool is_read = msg->flags & I2C_M_RD;
unsigned char *dma_buf; unsigned char *dma_buf;
dma_buf = kzalloc(I2C_SMBUS_BLOCK_MAX + (is_read ? 2 : 3), GFP_KERNEL); dma_buf = kzalloc(I2C_SMBUS_V3_BLOCK_MAX + (is_read ? 2 : 3),
GFP_KERNEL);
if (!dma_buf) if (!dma_buf)
return; return;
...@@ -329,9 +330,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, ...@@ -329,9 +330,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
* initialize most things with sane defaults, to keep the code below * initialize most things with sane defaults, to keep the code below
* somewhat simpler. * somewhat simpler.
*/ */
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; unsigned char msgbuf0[I2C_SMBUS_V3_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; unsigned char msgbuf1[I2C_SMBUS_V3_BLOCK_MAX+2];
int nmsgs = read_write == I2C_SMBUS_READ ? 2 : 1; int nmsgs = read_write == I2C_SMBUS_READ ? 2 : 1;
u16 block_max;
u8 partial_pec = 0; u8 partial_pec = 0;
int status; int status;
struct i2c_msg msg[2] = { struct i2c_msg msg[2] = {
...@@ -350,6 +352,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, ...@@ -350,6 +352,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
bool wants_pec = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK bool wants_pec = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
&& size != I2C_SMBUS_I2C_BLOCK_DATA); && size != I2C_SMBUS_I2C_BLOCK_DATA);
/* Drivers must opt in to 255 byte max block size */
block_max = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_V3_BLOCK)
? I2C_SMBUS_V3_BLOCK_MAX : I2C_SMBUS_BLOCK_MAX;
msgbuf0[0] = command; msgbuf0[0] = command;
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
...@@ -399,7 +405,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, ...@@ -399,7 +405,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
i2c_smbus_try_get_dmabuf(&msg[1], 0); i2c_smbus_try_get_dmabuf(&msg[1], 0);
} else { } else {
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { if (msg[0].len > block_max + 2) {
dev_err(&adapter->dev, dev_err(&adapter->dev,
"Invalid block write size %d\n", "Invalid block write size %d\n",
data->block[0]); data->block[0]);
...@@ -413,7 +419,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, ...@@ -413,7 +419,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
case I2C_SMBUS_BLOCK_PROC_CALL: case I2C_SMBUS_BLOCK_PROC_CALL:
nmsgs = 2; /* Another special case */ nmsgs = 2; /* Another special case */
read_write = I2C_SMBUS_READ; read_write = I2C_SMBUS_READ;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { if (data->block[0] > block_max) {
dev_err(&adapter->dev, dev_err(&adapter->dev,
"Invalid block write size %d\n", "Invalid block write size %d\n",
data->block[0]); data->block[0]);
...@@ -430,7 +436,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, ...@@ -430,7 +436,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
i2c_smbus_try_get_dmabuf(&msg[1], 0); i2c_smbus_try_get_dmabuf(&msg[1], 0);
break; break;
case I2C_SMBUS_I2C_BLOCK_DATA: case I2C_SMBUS_I2C_BLOCK_DATA:
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { if (data->block[0] > block_max) {
dev_err(&adapter->dev, "Invalid block %s size %d\n", dev_err(&adapter->dev, "Invalid block %s size %d\n",
read_write == I2C_SMBUS_READ ? "read" : "write", read_write == I2C_SMBUS_READ ? "read" : "write",
data->block[0]); data->block[0]);
...@@ -498,7 +504,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, ...@@ -498,7 +504,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL: case I2C_SMBUS_BLOCK_PROC_CALL:
if (msg[1].buf[0] > I2C_SMBUS_BLOCK_MAX) { if (msg[1].buf[0] > block_max) {
dev_err(&adapter->dev, dev_err(&adapter->dev,
"Invalid block size returned: %d\n", "Invalid block size returned: %d\n",
msg[1].buf[0]); msg[1].buf[0]);
......
...@@ -52,6 +52,19 @@ typedef int (*i2c_slave_cb_t)(struct i2c_client *client, ...@@ -52,6 +52,19 @@ typedef int (*i2c_slave_cb_t)(struct i2c_client *client,
struct module; struct module;
struct property_entry; struct property_entry;
/* SMBus 3.0 extends the maximum block read/write size to 255 (from 32).
* The larger size is only supported by some drivers, indicated by
* the I2C_FUNC_SMBUS_V3_BLOCK functionality bit.
*/
#define I2C_SMBUS_V3_BLOCK_MAX 255 /* As specified in SMBus 3.0 standard */
/* Note compatibility definition in uapi header with 32 byte block */
union i2c_smbus_data {
__u8 byte;
__u16 word;
__u8 block[I2C_SMBUS_V3_BLOCK_MAX + 1]; /* block[0] is used for length */
};
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
/* Return the Frequency mode string based on the bus frequency */ /* Return the Frequency mode string based on the bus frequency */
const char *i2c_freq_mode_string(u32 bus_freq_hz); const char *i2c_freq_mode_string(u32 bus_freq_hz);
......
...@@ -108,6 +108,7 @@ struct i2c_msg { ...@@ -108,6 +108,7 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ #define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000 /* SMBus 2.0 or later */ #define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000 /* SMBus 2.0 or later */
#define I2C_FUNC_SMBUS_V3_BLOCK 0x20000000 /* Device supports 255 byte block */
#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \ #define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE) I2C_FUNC_SMBUS_WRITE_BYTE)
...@@ -137,13 +138,15 @@ struct i2c_msg { ...@@ -137,13 +138,15 @@ struct i2c_msg {
/* /*
* Data for SMBus Messages * Data for SMBus Messages
*/ */
#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ #define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus 2.0 standard */
#ifndef __KERNEL__
union i2c_smbus_data { union i2c_smbus_data {
__u8 byte; __u8 byte;
__u16 word; __u16 word;
__u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
/* and one more for user-space compatibility */ /* and one more for user-space compatibility */
}; };
#endif
/* i2c_smbus_xfer read or write markers */ /* i2c_smbus_xfer read or write markers */
#define I2C_SMBUS_READ 1 #define I2C_SMBUS_READ 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment