I am working on an custom embedded device based on iMX8MP MPU. I need to read the first 16 bits of the EEPROM connected to address 0x50 on the i2c-0 bus in Linux from user space.
In the first place, I wrote on my eeprom thanks to u-boot as follow:
u-boot=> i2c mw 0x50 0x00.2 57
u-boot=> i2c mw 0x50 0x01.2 69
u-boot=> i2c mw 0x50 0x02.2 74
u-boot=> i2c mw 0x50 0x03.2 65
u-boot=> i2c mw 0x50 0x04.2 6B
u-boot=> i2c mw 0x50 0x05.2 69
u-boot=> i2c mw 0x50 0x06.2 6F
Then I checked that the value are correctly written in eeprom after a reboot as follow:
u-boot=> i2c md 0x50 0x0.2 B
0000: 57 69 74 65 6b 69 6f 20 53 41 53
I wrote a code that uses ioctls with I2C_SLAVE_FORCE and I2C_SMBUS request to communicate with EEPROM. However, values displayed are not correct and I can not figure out why.
#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <errno.h>
#include <stdlib.h>
#include <strings.h>
#define I2C_ADDRESS 0x50
#define I2C_BUS "/dev/i2c-0"
int main(void)
{
int file;
char filename[20];
int res;
unsigned char data[16];
snprintf(filename, 19, "%s", I2C_BUS);
file = open(filename, O_RDWR);
if (file < 0) {
perror("open");
exit(1);
}
res = ioctl(file, I2C_SLAVE_FORCE, I2C_ADDRESS);
if (res < 0) {
perror("ioctl");
exit(1);
}
struct i2c_smbus_ioctl_data ioctl_data = {
.read_write = I2C_SMBUS_READ,
.command = 0x00, /* read start address */
.size = I2C_SMBUS_WORD_DATA,
.data = data,
};
res = ioctl(file, I2C_SMBUS, &ioctl_data);
if (res < 0) {
perror("ioctl");
exit(1);
}
printf("Data read: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", data[i]);
}
printf("\n");
close(file);
return 0;
}
The output is:
data read : ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00
At this point I have no clue why it is not working. Any hint would be appreciated
There is a much easier way to read / write on eeprom. Indeed, If there is a file named "eeprom" for instance under
/sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0050it means that there is a kernel driver for this eeprom.A simple cat to
/sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0050/ueventindicate the corresponding driver:at24.c is the kernel driver for my eeprom. I can operate read and write operation simply by accessing the eeprom file
/sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0050/eeprom.You can find below a dummy C program that allow me to read write on eeprom.