参考文档:
https://blog.csdn.net/wq690968346/article/details/50921039(i2c_client的四中方法)
https://blog.csdn.net/pengliang528/article/details/78262441
1:最新的I2c模型:设备,总线,驱动模型。
分层模型(1):核心层:提供统一的I2C接口操作函数,
(2):适配器:基于板卡的I2c的硬件操作。基于某个芯片的硬件操作。
bus:I2C_bus_type提供了注册接口函数。
设备层(device):i2c_clinet 注册: i2c_new_device 结构体:i2c_adapter(i2c_board_info)
驱动层(driver):i2c_driver 注册:i2c_add_driver() 结构体:i2c_driver 比较(i2c_device_id)
比较如果名称相同,则调用i2c_driver 的probe函数
第一层:i2c adapter的硬件驱动,探测,初始化i2c_adapter(申请i2c的io地址和中断号),驱动soc控制控制adapter产生的硬件信号以及I2c中断。
第二层:提供i2c_adapter的algorithm,用适配器xxx_xferf()填充i2c_algorithm的master_xfer函数指针,并把i2c_algorithm赋给algo指针,覆盖图中的抽象层,i2c核心层。
第三层:i2c_driver接口,用具体的i2c device设备的attach_adapter()、detach_adapter()方法赋值给i2c_driver的成员函数指针。实现设备device与总线(或者叫adapter)的挂接
第四层:具体device的驱动,i2c_driver只是实现设备与总线的挂接,所以要实现具体设备device的write()、read()、ioctl()等方法,赋值给file_operations,然后注册字符设备(多数是字符设备)
与之相关的c文件:i2c-core.c这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口。
i2c-dev.c实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过适配器访设备时的主设备号都为89,次设备号为0-255。I2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read(),write(),和ioctl()等接口,应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器,并控制I2C设备的工作方式。
busses文件夹这个文件中包含了一些I2C总线的驱动,如针对S3C2410,S3C2440,S3C6410等处理器的I2C控制器驱动为i2c-s3c2410.c.
algos文件夹实现了一些I2C总线适配器的algorithm.
先看一些结构体:(从下到上)
- struct i2c_algorithm { //i2c传输
- int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);//I2C传输函数指针
- int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union
- i2c_smbus_data *data);//smbus传输函数指针
- u32 (*functionality) (struct i2c_adapter *);//返回适配器支持的功能
- };
- struct i2c_adapter { //i2c物理上的适配器,一个适配器上有多个i2c_client ,所以i2c_adapter中包含依附于它的i2c_clinet
- 的链表。
- struct module *owner;//所属模块
- unsigned int id;//algorithm的类型,定义于i2c-id.h,
- unsigned int class;
- const struct i2c_algorithm *algo; //总线通信方法结构体指针
- void *algo_data;//algorithm数据
- struct rt_mutex bus_lock;//控制并发访问的自旋锁
- int timeout;
- int retries;//重试次数
- struct device dev; //适配器设备
- int nr;
- char name[48];//适配器名称
- struct completion dev_released;//用于同步
- struct list_head userspace_clients;//client链表头
- };
- struct i2c_client { //对应真是的i2c的物理设备,每个i2c设备东欧要有一个i2c-client来描述
- unsigned short flags;//标志
- unsigned short addr; //低7位为芯片地址
- char name[I2C_NAME_SIZE];//设备名称
- struct i2c_adapter *adapter;//依附的i2c_adapter
- struct i2c_driver *driver;//依附的i2c_driver
- struct device dev;//设备结构体
- int irq;//设备所使用的结构体
- struct list_head detected;//链表头
- };
- struct i2c_driver { //与i2c_client 是一对多,一个i2c_driver 可以支持多个同等类型的i2c_client
- unsigned int class;
- int (*attach_adapter)(struct i2c_adapter *);//依附i2c_adapter函数指针
- int (*detach_adapter)(struct i2c_adapter *);//脱离i2c_adapter函数指针
- int (*probe)(struct i2c_client *, const struct i2c_device_id *);
- int (*remove)(struct i2c_client *);
- void (*shutdown)(struct i2c_client *);
- int (*suspend)(struct i2c_client *, pm_message_t mesg);
- int (*resume)(struct i2c_client *);
- void (*alert)(struct i2c_client *, unsigned int data);
- int (*command)(struct i2c_client *client, unsigned int cmd, void*arg);//命令列表
- struct device_driver driver;
- const struct i2c_device_id *id_table;//该驱动所支持的设备ID表
- int (*detect)(struct i2c_client *, struct i2c_board_info *);
- const unsigned short *address_list;
- struct list_head clients;
- };
主要函数
i2c_transfer()只是用来找到i2c_adapter对应的i2c_algorithm,并使用i2c_algorithm的master_xfer()函数真正的驱动硬件流程
s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)从i2cbus中读取字节。
- //增加/删除i2c_adapter
- int i2c_add_adapter(struct i2c_adapter *adapter)
- int i2c_del_adapter(struct i2c_adapter *adap)
- //增加/删除i2c_driver
- int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
- void i2c_del_driver(struct i2c_driver *driver)
- //i2c_client依附/脱离
- int i2c_attach_client(struct i2c_client *client)
- //I2C传输,发送和接收
- int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
- int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
- int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)