i2c: Add i2c block transaction support
The previous code always uses SMBus block read/write.
On some PSU (e.g. FP5280G2's PSU) the I2C block read/write is
required, so add that support.
Specifically, add a Mode enum class and add the parameter for block
read/write to indicate whether SMBus or I2C block read/write is to be
called.
Tested: Verify the code works on FP5280G2 with I2C block write.
Note: Currently there is no case for I2C block read, so that function is
not tested.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I5f77ffe6900d14f3703dae7241799a7b37c5a726
diff --git a/tools/i2c/i2c.cpp b/tools/i2c/i2c.cpp
index 76756be..624bc60 100644
--- a/tools/i2c/i2c.cpp
+++ b/tools/i2c/i2c.cpp
@@ -76,6 +76,13 @@
devAddr);
}
break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+ {
+ throw I2CException("Missing I2C_FUNC_SMBUS_READ_I2C_BLOCK",
+ busStr, devAddr);
+ }
+ break;
default:
fprintf(stderr, "Unexpected read size type: %d\n", type);
assert(false);
@@ -123,6 +130,13 @@
devAddr);
}
break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
+ {
+ throw I2CException("Missing I2C_FUNC_SMBUS_WRITE_I2C_BLOCK",
+ busStr, devAddr);
+ }
+ break;
default:
fprintf(stderr, "Unexpected read size type: %d\n", type);
assert(false);
@@ -164,11 +178,25 @@
data = static_cast<uint16_t>(ret);
}
-void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data)
+void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data, Mode mode)
{
- checkReadFuncs(I2C_SMBUS_BLOCK_DATA);
-
- int ret = i2c_smbus_read_block_data(fd, addr, data);
+ int ret;
+ switch (mode)
+ {
+ case Mode::SMBUS:
+ checkReadFuncs(I2C_SMBUS_BLOCK_DATA);
+ ret = i2c_smbus_read_block_data(fd, addr, data);
+ break;
+ case Mode::I2C:
+ checkReadFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
+ ret = i2c_smbus_read_i2c_block_data(fd, addr, size, data);
+ if (ret != size)
+ {
+ throw I2CException("Failed to read i2c block data", busStr,
+ devAddr, errno);
+ }
+ break;
+ }
if (ret < 0)
{
throw I2CException("Failed to read block data", busStr, devAddr, errno);
@@ -206,11 +234,22 @@
}
}
-void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data)
+void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data,
+ Mode mode)
{
- checkWriteFuncs(I2C_SMBUS_BLOCK_DATA);
-
- if (i2c_smbus_write_block_data(fd, addr, size, data) < 0)
+ int ret;
+ switch (mode)
+ {
+ case Mode::SMBUS:
+ checkWriteFuncs(I2C_SMBUS_BLOCK_DATA);
+ ret = i2c_smbus_write_block_data(fd, addr, size, data);
+ break;
+ case Mode::I2C:
+ checkWriteFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
+ ret = i2c_smbus_write_i2c_block_data(fd, addr, size, data);
+ break;
+ }
+ if (ret < 0)
{
throw I2CException("Failed to write block data", busStr, devAddr,
errno);