User Space:
/* I2C device brief definition */
#define I2C_DEV "/dev/i2c-4"
#define I2C_SLAVE_ADDR 0x16
#define TEST_I2C_REG 0x10
typedef struct
{
uint16_t slaveAddr;
uint8_t offsetAddr;
}i2c_addr;
int main(int argc, char *argv[])
{
int ret = 0;
int fd = 0;
i2c_addr i2c_dcb;
unsigned char temp = 0;
char i2c_dev[64] = {0};
uint32_t slave_addr = 0;
uint32_t test_i2c = 0;
unsigned char read_buf[2] = {0, 0};
unsigned char write_buf[2] = {0, 0};
printf("start i2c test\n");
setbuf(stdout, NULL);
memset(&i2c_dcb, 0x0, sizeof(i2c_dcb));
fd = i2c_open(I2C_DEV);
i2c_dcb.slaveAddr = I2C_SLAVE_ADDR;
i2c_dcb.ofstAddr = TEST_I2C_REG ;
if (fd < 0)
{
printf("failed to open i2c device.\n");
return -1;
}
/* read i2c, value in read_buf[0] and read_buf[1] */
ret = i2c_read(fd, &i2c_dcb, read_buf, 1);
if (ret < 0)
return ret;
/* write i2c */
ret = i2c_write(fd, &i2c_dcb, write_buf, 2);
if (ret < 0)
return ret;
return 0;
}
int32_t i2c_open(int8_t* i2c_dev_name)
{
int32_t fd = -1;
if (i2c_dev_name != NULL)
{
fd = open(I2C_DEV, O_RDWR);
if (fd < 0)
{
printf("Can't open I2C_DEVICE, open fail | error: %s \n", strerror(errno));
return -1;
}
}
return fd;
}
int32_t i2c_write(int32_t fd, i2c_addr* i2c_dcb, uint8_t* ptrData, uint16_t len)
{
int32_t ret;
uint8_t *buf = NULL;
struct i2c_rdwr_ioctl_data i2c_data;
memset(&i2c_data, 0x0, sizeof(i2c_data));
i2c_data.nmsgs = 1;
i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs *sizeof(struct i2c_msg));
if (i2c_data.msgs == NULL)
{
printf("malloc i2c struct fail\n");
}
buf = malloc((len + 1) * sizeof(uint8_t));
if (buf == NULL)
{
printf("malloc buf 0fail\n");
}
memset(buf, 0, len + 1);
buf[0] = i2c_dcb->offsetAddr;
memcpy((buf+1), ptrData, len);
i2c_data.msgs[0].len = len + 1;
i2c_data.msgs[0].addr = i2c_dcb->slaveAddr;
i2c_data.msgs[0].flags = 0;
i2c_data.msgs[0].buf = buf;
ret = ioctl(fd, I2C_RDWR, (uint64_t *)&i2c_data);
if (ret < 0)
{
printf("i2c write error! : %d \n", ret);
}
free(buf);
free(i2c_data.msgs);
return ret;
}
int32_t i2c_read(int32_t fd, i2c_addr* i2c_dcb, uint8_t* ptrBuff, uint16_t len)
{
int32_t ret ;
struct i2c_rdwr_ioctl_data i2c_data;
memset(&i2c_data, 0x0, sizeof(i2c_data));
i2c_data.nmsgs = 2;
i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct i2c_msg));
if (i2c_data.msgs == NULL)
{
printf("malloc i2c struct fail\n");
}
i2c_data.msgs[0].len = 1;
i2c_data.msgs[0].addr = i2c_dcb->slaveAddr;
i2c_data.msgs[0].flags = 0;
i2c_data.msgs[0].buf = &i2c_dcb->offsetAddr;
i2c_data.msgs[1].len = len + 1;
i2c_data.msgs[1].addr = i2c_dcb->slaveAddr;
i2c_data.msgs[1].flags = 1;
i2c_data.msgs[1].buf = ptrBuff;
ret = ioctl(fd, I2C_RDWR, (uint64_t *)&i2c_data);
if (ret < 0)
{
printf("read i2c error: %d\n", ret);
}
free(i2c_data.msgs);
return ret;
}
int32_t i2c_close(int32_t fd)
{
int32_t ret = 0;
if(fd < 0)
{
printf("fd is invalid\n");
}
ret = close(fd);
return ret;
}
Kernel Space:
kernel dtsi config,i.e:mediatek platform:
i2c2: i2c2@11c42000 {
compatible = "mediatek,i2c";
id = <2>;
reg = <0 0x11c42000 0 0x1000>,
<0 0x10217180 0 0x80>;
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&imp_iic_wrap_e_clk CLK_IMPE_AP_CLOCK_I2C2_RO>,
<&infracfg_ao_clk CLK_IFRAO_I2C3>;
clock-names = "main", "dma";
clock-div = <5>;
aed = <0x1a>;
};
&i2c2 {
pinctrl-names = "default";
pinctrl-0 = <&i2c2_pins>;
status = "okay";
nau88c22_codec@1a{
compatible = "nuvoton,nau88c22";
codec-en-gpios = <&pio 141 0>;
reg = <0x1a>;
};
};
i2c2_pins: i2c2default {
pins_bus {
pinmux = <PINMUX_GPIO109__FUNC_SDA2>,
<PINMUX_GPIO110__FUNC_SCL2>;
bias-pull-up;
mediatek,res-sel = <3>;
};
};
Kernel defconfig:
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MTK=y
CONFIG_I2C_SLAVE=y
CONFIG_INV_MPU_IIO_I2C=y
Driver:
drivers/i2c/busses/i2c-***(platform).c
in drivers/i2c/i2c-dev.c
static const struct file_operations i2cdev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
.unlocked_ioctl = i2cdev_ioctl,
.compat_ioctl = compat_i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
i2cdev_write-->i2c_master_send
i2cdev_read-->i2c_master_recv
compat_i2cdev_ioctl-->i2c_transfer
详细代码分析后续进行中。。。