Add 16 bit addressing EEPROM handling
Adding 16 bit eeprom addressing for reading data. First checking if
device is 8 bit or 16 bit by reading first 8 byte header and comparing
each byte. If all bytes are same then it is 8 bit or if address is auto
incremented then it is 16 bit.
Tested: Build Facebook TiogaPass board and load on the
target hardware. Ensure that Fru information are updated.
Change-Id: I1ec848764afb012562c1231f45e42f37e22334b8
Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index f879afd..fd5f5ae 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -63,12 +63,62 @@
"/sys/bus/i2c/devices/i2c-" + std::to_string(bus) + "/mux_device"));
}
+static int isDevice16Bit(int file)
+{
+ /* Get first byte */
+ int byte1 = i2c_smbus_read_byte_data(file, 0);
+ if (byte1 < 0)
+ {
+ return byte1;
+ }
+ /* Read 7 more bytes, it will read same first byte in case of
+ * 8 bit but it will read next byte in case of 16 bit
+ */
+ for (int i = 0; i < 7; i++)
+ {
+ int byte2 = i2c_smbus_read_byte_data(file, 0);
+ if (byte2 < 0)
+ {
+ return byte2;
+ }
+ if (byte2 != byte1)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int read_block_data(int flag, int file, uint16_t offset, uint8_t len,
+ uint8_t *buf)
+{
+ uint8_t low_addr = offset & 0xFF;
+ uint8_t high_addr = (offset >> 8) & 0xFF;
+
+ if (flag == 0)
+ {
+ return i2c_smbus_read_i2c_block_data(file, low_addr, len, buf);
+ }
+
+ /* This is for 16 bit addressing EEPROM device. First an offset
+ * needs to be written before read data from a offset
+ */
+ int ret = i2c_smbus_write_byte_data(file, 0, low_addr);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ return i2c_smbus_read_i2c_block_data(file, high_addr, len, buf);
+}
+
int get_bus_frus(int file, int first, int last, int bus,
std::shared_ptr<DeviceMap> devices)
{
std::future<int> future = std::async(std::launch::async, [&]() {
std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> block_data;
+
for (int ii = first; ii <= last; ii++)
{
@@ -90,8 +140,17 @@
std::cout << "something at bus " << bus << "addr " << ii
<< "\n";
}
- if (i2c_smbus_read_i2c_block_data(file, 0x0, 0x8,
- block_data.data()) < 0)
+
+ /* Check for Device type if it is 8 bit or 16 bit */
+ int flag = isDevice16Bit(file);
+ if (flag < 0)
+ {
+ std::cerr << "failed to read bus " << bus << " address " << ii
+ << "\n";
+ continue;
+ }
+
+ if (read_block_data(flag, file, 0x0, 0x8, block_data.data()) < 0)
{
std::cerr << "failed to read bus " << bus << " address " << ii
<< "\n";
@@ -117,8 +176,8 @@
if (area_offset != 0)
{
area_offset *= 8;
- if (i2c_smbus_read_i2c_block_data(
- file, area_offset, 0x8, block_data.data()) < 0)
+ if (read_block_data(flag, file, area_offset, 0x8,
+ block_data.data()) < 0)
{
std::cerr << "failed to read bus " << bus
<< " address " << ii << "\n";
@@ -133,9 +192,8 @@
while (length > 0)
{
auto to_get = std::min(0x20, length);
- if (i2c_smbus_read_i2c_block_data(
- file, area_offset, to_get,
- block_data.data()) < 0)
+ if (read_block_data(flag, file, area_offset, to_get,
+ block_data.data()) < 0)
{
std::cerr << "failed to read bus " << bus
<< " address " << ii << "\n";