Как получить доступ (чтение / запись) к устройству EEPROM через SMBus / I2C в устройстве pci? (LINUX)

У меня есть устройство PCI с EEPROM, которое поддерживает SMBus / I2C. Я хотел бы создать приложение пользовательского пространства (Linux), которое может читать и писать в целевую EEPROM. Подобно тому, что делает IPMI при запросе информации VPD на каждом устройстве SSD / NVME. Однако мне сложно запрашивать целевую шину i2c и устройство i2c. Я использую i2cdetect для запроса шины i2c, но не могу определить, обнаружено ли мое целевое устройство или нет. Вопрос, мне все еще нужно знать шину / адаптер i2c, к которой подключено мое устройство? как это делается? Я искал, как создать приложение, даже думал о разработке драйвера.

Я столкнулся с этой проблемой в течение нескольких недель, и, надеюсь, кто-нибудь может мне в этом помочь. Большое Вам спасибо!!!


person starz    schedule 24.01.2018    source источник


Ответы (1)


Показывает что-то вроде ниже:

$ i2cdetect -l

i2c-0 i2c i915 gmbus dpc I2C адаптер

i2c-1 i2c i915 gmbus vga I2C адаптер

Адаптер i2c-6 smbus SMBus I801 в адаптере e000 SMBus

$ i2cdetect -y 6 #EEPROM в основном на устройстве 0x54.

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 имеет лучшее объяснение использования API.

Для работы с конкретным устройством на 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;
}
person srpatch    schedule 26.04.2018
comment
Большое спасибо srpatch. - person starz; 28.08.2020