i2c_adapter
struct i2c_adapter代表一个i2c控制器,本质上也是一个设备,所以包含struct device,其中包含重要成员struct i2c_algorithm,i2c_algorithm 中的master_xfer()用来实现i2c数据通信方法。
i2c_driver
代表i2c设备的驱动,包含struct device_driver,device_driver中包含of_device_id,match()函数用于匹配驱动和设备。还包含两个函数指针,int (*probe)(struct i2c_client *),int (*remove)(struct i2c_client *)。
i2c_client
代表i2c从设备,其中包含struct device,用于和i2c_driver进行匹配,还包含i2c_adapter,用于指定此设备挂载在哪个i2c控制器上,i2c从设备地址由其中的addr保存。
i2c_msg
struct i2c_msg {
__u16 addr; /* slave address */
__u16 flags;
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
#define I2C_M_RD 0x0001 /* read data, from slave to master */
#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
};
linux中i2c信号的传输以i2c_msg为单位,i2c_msg包含addr,flag,buf,len。
从机驱动中使用i2c_transfer()来实现寄存器的读写,一般写函数中定义一个i2c_msg,读函数定义两个i2c_msg,调用i2c_transfer()本质上是调用i2c_algorithm中的master_xfer(),适配器中调用i2c_master_recv()和i2c_master_send()来实现数据传输。
i2c_driver实现要点
- probe(struct *client)中一般实现字符设备驱动的基本框架并需要将参数client的值赋给驱动文件中定义的xxx_client。xxx_client赋值成功后需要将xxx_client传递给i2c_msg。
- __init 中需要i2c_add_driver(),__exit函数中需要i2c_del_driver()。
i2c_adapter驱动
RK3399 i2c适配器驱动采用platform框架,驱动中定义rk3x_i2c,其中包含i2c_adapter,regs,驱动头部定义寄存器。probe函数中初始化i2c_adapter,包括algorithm、device.of_node、platform_get_resource(),并将返回值赋给rk3x_i2c->regs(regs保存i2c控制器的首地址,其他寄存器的地址为该地址加头部定义的偏移量)。
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &rk3x_i2c_algorithm;
i2c->adap.retries = 3;
i2c->adap.dev.of_node = np;
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &pdev->dev;
执行i2c_add_adapter。
remove函数中i2c_del_adapter。
rk3x_i2c_xfer
i2c_adapter和i2c_client通信的底层都是调用i2c_transfer(),i2c_transfer()调用i2c_adapter驱动中的rk3x_i2c_xfer。再底层就是调用readl(),writel()来实现。readl(),writerl()为内存映射的 I/O 空间读取或写入数据。