概述:
i2c是很流行的串行半双工通信协议,主从架构。
linux 中有关于i2c子系统的实现支持,其和平台无关的,具体实现需要驱动工程师自己实现。
linux i2c中核心代码是i2c-core.c 其有i2c适配器、i2c算法、i2c驱动以及i2c设备注册、注销以及数据处理的实现。
再介绍下i2c子系统各部分的关系:i2c适配器是设备,是i2c具体外设(外部或芯片内部)的抽象,i2c算法是i2c适配器的驱动,i2c设备是挂载到i2c外设的设备抽象,i2c驱动是i2c设备的驱动。
1、首先介绍i2c子系统的重要的数据结构(也是各模块的代表)
在kernel/include/linux/i2c.h头文件中
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
上面是i2c总线的实例化,其目录在/sys/bus/i2c
.name = "i2c" 总线名称,就是bus下目录名称。
.match = i2c_device_match 是总线的设备、驱动匹配函数,在设备注册或者驱动注册时调用。
.probe = i2c_device_probe 是总线的设备探测函数,其实最终调用的是驱动的probe函数。
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
* with the access algorithms necessary to access it.
*/
struct i2c_adapter {
struct module *owner;
unsigned int class; /* classes to allow probing for */
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
void *algo_data;
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
int timeout; /* in jiffies */
int retries;
struct device dev; /* the adapter device */
int nr;
char name[48];
struct completion dev_released;
struct mutex userspace_clients_lock;
struct list_head userspace_clients;
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
i2c_adapter i2c适配器抽象(其实算上相关操作函数才是真正的抽象),代表i2c外设设备,其需要由相关的algorithms才能工作。
struct module *owner; 内核模块指针。
unsigned int class; 代表哪类设备,不需要具体class指针,只是标记是哪类设备,用来匹配用的。
const struct i2c_algorithm *algo; 其用来操作设备的算法,是其驱动,没有算法适配器无法工作。
void *algo_data; 算法用到的数据。
struct rt_mutex bus_lock; 实时互斥锁,用来防止优先级翻转的,是实时进程需要的锁。
int timeout; 操作超时时间。
int retries;
struct device dev; 设备驱动模型的代表。
int nr; 适配器号,即总线号,linux idr模块使用的,用来所以适配器其指针的。
char name[48]; 名称
struct completion dev_released; linux完成量
struct mutex userspace_clients_lock; 互斥量
struct list_head userspace_clients; 设备链表