[RFC PATCH linux dev-4.10 5/7] i2c: Add bogus I2C_SMBUS_DWORD_DATA bus protocol/transaction type
Andrew Jeffery
andrew at aj.id.au
Fri Jun 2 16:22:05 AEST 2017
Added so we can issue 4-byte read commands without invoking a block
transfer (which requires the length to be sent by the slave in the first
byte). The 0x3040 revision of the MAX31785 firmware can return a 'fast'
rotor read, and does so in this 4-byte format.
Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
---
drivers/i2c/i2c-core.c | 30 ++++++++++++++++++++++++++++++
include/linux/i2c.h | 2 ++
include/uapi/linux/i2c.h | 2 ++
3 files changed, 34 insertions(+)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 583e95042a21..4c8fe52df8ad 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -3210,6 +3210,18 @@ s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)
}
EXPORT_SYMBOL(i2c_smbus_read_word_data);
+s64 i2c_smbus_read_dword_data(const struct i2c_client *client, u8 command)
+{
+ union i2c_smbus_data data;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_DWORD_DATA, &data);
+ return (status < 0) ? status : data.dword;
+}
+EXPORT_SYMBOL(i2c_smbus_read_word_data);
+
/**
* i2c_smbus_write_word_data - SMBus "write word" protocol
* @client: Handle to slave device
@@ -3443,6 +3455,17 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
msgbuf0[i] = data->block[i];
}
break;
+ case I2C_SMBUS_DWORD_DATA:
+ if (read_write == I2C_SMBUS_READ)
+ msg[1].len = 4;
+ else {
+ msg[0].len = 5;
+ msgbuf0[1] = data->dword & 0xff;
+ msgbuf0[2] = (data->dword >> 8) & 0xff;
+ msgbuf0[3] = (data->dword >> 16) & 0xff;
+ msgbuf0[4] = (data->dword >> 24) & 0xff;
+ }
+ break;
default:
dev_err(&adapter->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
@@ -3486,6 +3509,13 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
case I2C_SMBUS_PROC_CALL:
data->word = msgbuf1[0] | (msgbuf1[1] << 8);
break;
+ case I2C_SMBUS_DWORD_DATA:
+ data->dword =
+ (msgbuf1[0] << (0 * 8)) |
+ (msgbuf1[1] << (1 * 8)) |
+ (msgbuf1[2] << (2 * 8)) |
+ (msgbuf1[3] << (3 * 8));
+ break;
case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < data->block[0]; i++)
data->block[i+1] = msgbuf1[i];
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 4b45ec46161f..ff15b25bdeda 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -95,6 +95,8 @@ extern s32 i2c_smbus_read_word_data(const struct i2c_client *client,
u8 command);
extern s32 i2c_smbus_write_word_data(const struct i2c_client *client,
u8 command, u16 value);
+extern s64 i2c_smbus_read_dword_data(const struct i2c_client *client,
+ u8 command);
static inline s32
i2c_smbus_read_word_swapped(const struct i2c_client *client, u8 command)
diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h
index 009e27bb9abe..63ab01e3faa2 100644
--- a/include/uapi/linux/i2c.h
+++ b/include/uapi/linux/i2c.h
@@ -131,6 +131,7 @@ struct i2c_msg {
union i2c_smbus_data {
__u8 byte;
__u16 word;
+ __u32 dword;
__u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
/* and one more for user-space compatibility */
};
@@ -150,5 +151,6 @@ union i2c_smbus_data {
#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
#define I2C_SMBUS_I2C_BLOCK_DATA 8
+#define I2C_SMBUS_DWORD_DATA 9
#endif /* _UAPI_LINUX_I2C_H */
--
2.11.0
More information about the openbmc
mailing list