1

I have a PCI device with EEPROM in it that supports SMBus/I2C. I would like to create a userspace application (Linux) that can read and write to target EEPROM. Similar to what IPMI is doing in querying VPD information on every SSD/NVME device. However, I am having a hard time querying target i2c bus and i2c device. I am using i2cdetect to query i2c bus, but I can't locate if my target device is detected or not. Question, do I still need to know i2c bus/adapter where my device is connected? how is this done? I've been researching on how to create the application, I even thinking of developing a driver.

I've been in this problem for weeks and hopefully someone can help me on this. Thank you very much!!!

starz
  • 11
  • 1
  • 5

1 Answers1

-1

Shows something like below:

$i2cdetect -l

i2c-0 i2c i915 gmbus dpc I2C adapter

i2c-1 i2c i915 gmbus vga I2C adapter

i2c-6 smbus SMBus I801 adapter at e000 SMBus adapter

$i2cdetect -y 6 #EEPROM on 0x54 device location mostly.

0 1 2 3 4 5 6 7 8 9 a b c d e f

00: -- -- -- -- -- 08 -- -- -- -- -- -- --

10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

20: -- -- -- -- -- -- -- -- -- -- -- -- -- 2d -- --

30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

50: 50 -- -- -- 54 55 56 57 -- -- -- -- -- -- -- --

60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

70: -- -- -- -- -- -- -- --

https://www.kernel.org/doc/Documentation/i2c/dev-interface has the better explanation on API Usage.

To work with a particular device on SMBus :

static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, int size, union i2c_smbus_data *data)
{
          struct i2c_smbus_ioctl_data args;

          args.read_write = read_write;
          args.command = command;
          args.size = size;
          args.data = data;

        return ioctl(file,I2C_SMBUS,&args);
}

static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
        union i2c_smbus_data data;
        if (i2c_smbus_access(file, I2C_SMBUS_READ, command, I2C_SMBUS_WORD_DATA,&data))
                return -1;
        else
         {       printf("word before returning%x\n",data.word);
                return 0x0FFFF & data.word;
         }
}

int main( void)
{
        uint8_t data=0x55 , addr = 0x54, reg = 0x0d;
        const char *path = "/dev/i2c-6";  // SmBus
        int file;
        if ( (file=open( path , O_RDWR)) < 0)
                err(errno, "Tried to open but not working'%s'", path);

        if ( ioctl(file, I2C_SLAVE, addr ) < 0)
                err(errno, "Tried to set device address '0x%02x'", 0x01);
        data = i2c_smbus_read_byte_data(file, reg);
        printf("%s: device at address 0x%02x: date : 0x%02x\n", path, reg, data);

    return 0;
}
srpatch
  • 407
  • 5
  • 4