一、关键结构体
1、struct i2c_adapter
i2c适配器/控制器
和cpu相关联,i2c register map相同的cpu,这块操作一般相同
结构体内包含struct i2c_algorithm指针,通信前adapter选择一个algorithm与其对应的从机进行通信
2、struct i2c_algorithm
i2c算法/操作方法
主机和从机通信的时序
与主机和从机都有关
如果是非标准i2c时序,则需要自己实现
由adapter调用
.master_xfer 负责主机对外的时序操作,例如主机发-›wait-›从机响应-›触发中断-›wake up
.functionality 告诉子系统当前algorithm支持哪些特性,就是一个值(例如:return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL)
3、struct i2c_client
i2c设备信息(从机硬件描述信息)
i2c设备描述结构体
4、struct i2c_driver
i2c设备驱动(从机驱动)
i2c驱动描述结构体
二、关联文件
1、i2c_core.c
和硬件无关
提供设备和驱动的操作接口
2、busses目录
存放各种板卡的i2c_adapter
3、algos目录
存放各种i2c_algorithm
三、i2c_core.c init简单浏览
bus_register 注册i2c总线
struct bus_type i2c_bus_type = {
.name
.match
.probe
.remove
.shutdown
.pm
};
i2c_add_driver注册一个空的i2c驱动
在device和driver匹配时调用i2c_device_probe,内部会继续调用driver-›probe
四、关键接口
1、i2c_add_adapter/i2c_add_numbered_adpter
注册前需要对struct i2c_adapter进行填充
还对相关i2c控制器的寄存器进行赋值(硬件绑定)
注册adapter
2、i2c_add_driver
注册设备驱动
3、i2c_new_device
注册设备
五、注册i2设备
1、设备树
rtc{
compatible=“nxp,pcf8563”;
reg=<0x51>;
};
2、i2c_register_board_info
->list_add_tail(&devinfo->list,&__i2c_boatd_list)
必须在i2c_register_adapter之前使用,因为注册adapter时就会遍历list,注册每一个device,不适合动态加载
3、i2c_new_device/i2c_new_probed_device
->i2c_get_adapter
->i2c_new_device
->i2c_put_adapter
i2c_new_device认为设备一定存在
i2c_new_probed_device对于已经枚举出来的设备才会new device,确认设备存在的方法就是发start和address,看有没有ack回应
4、用户态创建设备
echo "name" addr > /sys/device/platform/xxx-i2c/i2c-x/new_device
echo addr > /sys/device/platform/xxx-i2c/i2c-x/delete_device
六、i2c操作接口
1、SMbus - system manager bus
2、i2c_transfer
smbus是i2c的子集
使用方法参考
Documentation/i2c/i2c-protocol
Documentation/i2c/smbus-protocol
使用这些接口的前提是内核已经为我们实现了i2c子系统,通过调用这些接口最终调用struct i2c_adapter中algorithm的master_xfer,实现对i2c控制器的寄存器操作。
使用时对比外设芯片手册的时序图,选择合适的接口。
3、使用内核提供的i2c-dev.c驱动接口
内核配置I2C device interface
系统中会有/dev/i2c-0结点
用户态可以使用i2c-tools工具包访问i2c结点
当有其他驱动接管设备时,这个驱动不能使用
七、i2c总线驱动
总线驱动的关键是实现struct i2c_adapter->struct i2c_algorithm->master_xfer
master_xfer给寄存器写数据,然后等待i2c控制器触发中断(对于cpu来说属于外部中断),接收到中断后,按照寄存器的state值判断接下来要做的事