1、I2C_Adapter驱动框架
1)i2c_adapter结构体:
结构体中的i2c_algorithm是指进入这个总线的算法。
- master_xfer:这是最重要的函数,它实现了一般的I2C传输,用来传输一个或者多个i2c_msg
- master_xfer_atomic:
- 可选的函数,功能跟master_xfer一样,在atomic context环境下使用
- 比如关机之前。所有中断都关闭的情况下,用来访问电源管理芯片
- smbus__xfer:实现SMBus传输,如果不提供这个函数,SMBus传输会使用master_xfer来模拟
- smbus_xfer_atomic:
- 可选函数,功能跟smbus_xfer一样,在atomic context 环境下使用
- 比如在关机之前、所有中断都关闭的情况下,用来访问电源管理芯片
- functionality:返回值所支持的flags:各类I2C_FUNC_*
- reg_slave/unreg_slave:
- 有些I2C Adapter也可以工作于Slave模式,用来实现或模拟一个i2c设备
- reg_slave就是把一个i2c_client注册到I2C Adapter,换句话说就是让这个I2C Adapter模拟该I2C_client
- unreg_slave:反注册
2、驱动程序框架
分配、设置、注册一个i2c_adapter结构体:
i2c_adapter的核心是i2c_algorithm
i2c_algorithm的核心是master_xfer函数
分配函数:
struct i2c_adapter *adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
设置:
adap->owner = THIS_MODULE;
adap->algp = i2c_imx_algo;
注册:
ret = i2c_add_adapter(adap); //不管adap->nr原来是什么,都动态设置adap->nr
ret = i2c_add_numbered_adapter(adap); //如果adap->nr == -1则动态分配nr;否则使用该nr
反注册:
i2c_del_adapter(adap);
3、i2c_algorithm示例
Linux-5.4中使用GPIO模拟I2C
Linux-4.9.88中IMX6ULL的I2C驱动
4、编写一个驱动框架
1、设备数
在设备树里构造I2C Bus节点:
i2c_bus_virtual{
compatible = “imx6ull,i2c-bus-virtual”;
};
2、platform_driver
分配、设置、注册platform_driver结构体。
核心是probe函数
- 根据设备树信息设置硬件(引脚、时钟等)
- 分配、设置、注册i2c_adapter
3、i2c_adapter
i2c_adapter的核心是master_xfer函数。它的实现取决于硬件,大概代码如下:
static int xxx_master_xfer(struct i2c_adapter *adapter,
struct i2c_msg *msgs, int num)
{
for (i = 0; i < num; i++) {
struct i2c_msg *msg = msgs[i];
{
// 1. 发出S信号: 设置寄存器发出S信号
CTLREG = S;
// 2. 根据Flag发出设备地址和R/W位: 把这8位数据写入某个DATAREG即可发出信号
// 判断是否有ACK
if (!ACK)
return ERROR;
else {
// 3. read / write
if (read) {
STATUS = XXX; // 这决定读到一个数据后是否发出ACK给对方
val = DATAREG; // 这会发起I2C读操作
} else if(write) {
DATAREG = val; // 这会发起I2C写操作
val = STATUS; // 判断是否收到ACK
if (!ACK)
return ERROR;
}
}
// 4. 发出P信号
CTLREG = P;
}
}
return i;
}
至此,I2C_Adapter驱动框架的学习就到此为止了。如果对大家有收获的话,希望大家多多点赞,收藏,关注。