|
@@ -3007,6 +3007,63 @@ 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 I2C_SMBUS_BLOCK_MAX bytes
|
|
|
+ * @values: Byte array into which data will be read; big enough to hold
|
|
|
+ * the data returned by the slave. SMBus allows at most
|
|
|
+ * I2C_SMBUS_BLOCK_MAX 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.
|
|
|
+ *
|
|
|
+ * The addresses of the I2C slave device that are accessed with this function
|
|
|
+ * must be mapped to a linear region, so that a block read will have the same
|
|
|
+ * effect as a byte read. 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 = 0;
|
|
|
+ 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);
|
|
|
+
|
|
|
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) {
|
|
|
+ while ((i + 2) <= length) {
|
|
|
+ status = i2c_smbus_read_word_data(client, command + i);
|
|
|
+ if (status < 0)
|
|
|
+ return status;
|
|
|
+ values[i] = status & 0xff;
|
|
|
+ values[i + 1] = status >> 8;
|
|
|
+ i += 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ while (i < length) {
|
|
|
+ status = i2c_smbus_read_byte_data(client, command + i);
|
|
|
+ if (status < 0)
|
|
|
+ return status;
|
|
|
+ values[i] = status;
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return i;
|
|
|
+}
|
|
|
+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)
|
|
|
{
|