* [PATCH v2 0/2] Add support for best effort block read emulation
@ 2015-04-17 19:17 Irina Tirdea
2015-04-17 19:17 ` [PATCH v2 1/2] i2c: core: " Irina Tirdea
2015-04-17 19:17 ` [PATCH v2 2/2] eeprom: at24: use i2c_smbus_read_i2c_block_data_or_emulated Irina Tirdea
0 siblings, 2 replies; 3+ messages in thread
From: Irina Tirdea @ 2015-04-17 19:17 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c; +Cc: linux-kernel, Irina Tirdea
This is the second version for adding i2c_smbus_read_i2c_block_data_or_emulated
to i2c-core. It contains mostly fixes suggested by Wolfram.
Changes since v1:
- dropped the RFC tag
- changed at24 to use i2c_smbus_read_i2c_block_data_or_emulated
- when reading an odd number of bytes using word emulation, read an even
number of bytes and drop the last one
- add a comment that this might not be suitable for all I2C slaves
Irina Tirdea (2):
i2c: core: Add support for best effort block read emulation
eeprom: at24: use i2c_smbus_read_i2c_block_data_or_emulated
drivers/i2c/i2c-core.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/misc/eeprom/at24.c | 40 +++++++------------------------
include/linux/i2c.h | 3 +++
3 files changed, 72 insertions(+), 31 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/2] i2c: core: Add support for best effort block read emulation
2015-04-17 19:17 [PATCH v2 0/2] Add support for best effort block read emulation Irina Tirdea
@ 2015-04-17 19:17 ` Irina Tirdea
2015-04-17 19:17 ` [PATCH v2 2/2] eeprom: at24: use i2c_smbus_read_i2c_block_data_or_emulated Irina Tirdea
1 sibling, 0 replies; 3+ messages in thread
From: Irina Tirdea @ 2015-04-17 19:17 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c; +Cc: linux-kernel, Irina Tirdea
There are devices that need to handle block transactions
regardless of the capabilities exported by the adapter.
For performance reasons, they need to use i2c read blocks
if available, otherwise emulate the block transaction with word
or byte transactions.
Add support for a helper function that would read a data block
using the best transfer available: I2C_FUNC_SMBUS_READ_I2C_BLOCK,
I2C_FUNC_SMBUS_READ_WORD_DATA or I2C_FUNC_SMBUS_READ_BYTE_DATA.
Signed-off-by: Irina Tirdea <irina.tirdea@intel.com>
---
drivers/i2c/i2c-core.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/i2c.h | 3 +++
2 files changed, 63 insertions(+)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 098f698..5ceebc4 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -2907,6 +2907,66 @@ trace:
}
EXPORT_SYMBOL(i2c_smbus_xfer);
+/**
+ * i2c_smbus_read_i2c_block_data_or_emulated - read block or emulate
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @length: Size of data block; SMBus allows at most 32 bytes
+ * @values: Byte array into which data will be read; big enough to hold
+ * the data returned by the slave. SMBus allows at most 32 bytes.
+ *
+ * This executes the SMBus "block read" protocol if supported by the adapter.
+ * If block read is not supported, it emulates it using either word or byte
+ * read protocols depending on availability.
+ *
+ * Before using this function you must double-check if the I2C slave does
+ * support exchanging a block transfer with a byte transfer.
+ */
+s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
+ u8 command, u8 length, u8 *values)
+{
+ u8 i;
+ int status;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ return i2c_smbus_read_i2c_block_data(client, command,
+ length, values);
+ } else if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA)) {
+ for (i = 0; i < length; i += 2) {
+ status = i2c_smbus_read_word_data(client, command + i);
+ if (status < 0)
+ return status;
+ values[i] = status & 0xff;
+ if ((i + 1) < length)
+ values[i + 1] = status >> 8;
+ }
+ if (i > length)
+ return length;
+ return i;
+ } else if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
+ for (i = 0; i < length; i++) {
+ status = i2c_smbus_read_byte_data(client, command + i);
+ if (status < 0)
+ return status;
+ values[i] = status;
+ }
+ return i;
+ }
+
+ dev_err(&client->adapter->dev, "Unsupported transactions: %d,%d,%d\n",
+ I2C_SMBUS_I2C_BLOCK_DATA, I2C_SMBUS_WORD_DATA,
+ I2C_SMBUS_BYTE_DATA);
+
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated);
+
#if IS_ENABLED(CONFIG_I2C_SLAVE)
int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
{
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index e83a738..faf518d 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -121,6 +121,9 @@ extern s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client,
extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
u8 command, u8 length,
const u8 *values);
+extern s32
+i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
+ u8 command, u8 length, u8 *values);
#endif /* I2C */
/**
--
1.9.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] eeprom: at24: use i2c_smbus_read_i2c_block_data_or_emulated
2015-04-17 19:17 [PATCH v2 0/2] Add support for best effort block read emulation Irina Tirdea
2015-04-17 19:17 ` [PATCH v2 1/2] i2c: core: " Irina Tirdea
@ 2015-04-17 19:17 ` Irina Tirdea
1 sibling, 0 replies; 3+ messages in thread
From: Irina Tirdea @ 2015-04-17 19:17 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c; +Cc: linux-kernel, Irina Tirdea
For i2c busses that support only SMBUS extensions, the eeprom at24
driver reads data from the device using the SMBus block, word or byte
read protocols depending on availability.
Replace the block read emulation from the driver with the
i2c_smbus_read_i2c_block_data_or_emulated call from i2c core.
Signed-off-by: Irina Tirdea <irina.tirdea@intel.com>
---
drivers/misc/eeprom/at24.c | 40 +++++++++-------------------------------
1 file changed, 9 insertions(+), 31 deletions(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 2d3db81..d13795a 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -186,19 +186,11 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
if (count > io_limit)
count = io_limit;
- switch (at24->use_smbus) {
- case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (at24->use_smbus) {
/* Smaller eeproms can work given some SMBus extension calls */
if (count > I2C_SMBUS_BLOCK_MAX)
count = I2C_SMBUS_BLOCK_MAX;
- break;
- case I2C_SMBUS_WORD_DATA:
- count = 2;
- break;
- case I2C_SMBUS_BYTE_DATA:
- count = 1;
- break;
- default:
+ } else {
/*
* When we have a better choice than SMBus calls, use a
* combined I2C message. Write address; then read up to
@@ -229,27 +221,13 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
timeout = jiffies + msecs_to_jiffies(write_timeout);
do {
read_time = jiffies;
- switch (at24->use_smbus) {
- case I2C_SMBUS_I2C_BLOCK_DATA:
- status = i2c_smbus_read_i2c_block_data(client, offset,
- count, buf);
- break;
- case I2C_SMBUS_WORD_DATA:
- status = i2c_smbus_read_word_data(client, offset);
- if (status >= 0) {
- buf[0] = status & 0xff;
- buf[1] = status >> 8;
- status = count;
- }
- break;
- case I2C_SMBUS_BYTE_DATA:
- status = i2c_smbus_read_byte_data(client, offset);
- if (status >= 0) {
- buf[0] = status;
- status = count;
- }
- break;
- default:
+ if (at24->use_smbus) {
+ status =
+ i2c_smbus_read_i2c_block_data_or_emulated(client,
+ offset,
+ count,
+ buf);
+ } else {
status = i2c_transfer(client->adapter, msg, 2);
if (status == 2)
status = count;
--
1.9.1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-04-17 19:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-17 19:17 [PATCH v2 0/2] Add support for best effort block read emulation Irina Tirdea
2015-04-17 19:17 ` [PATCH v2 1/2] i2c: core: " Irina Tirdea
2015-04-17 19:17 ` [PATCH v2 2/2] eeprom: at24: use i2c_smbus_read_i2c_block_data_or_emulated Irina Tirdea
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®