i2c中probe函数实现必须要传统匹配和设备树匹配同时实现
引用:引用参考原文——linux3.0以后自己实现i2c驱动probe探测函数不执行原因
正点原子i2c驱动实验,读写ap3216c,只有传统匹配表和设备树匹配表同时存在,i2c设备才能匹配成功,注释掉其中一个都会匹配失败。导致不会进入probe函数。(同platform)
这是内核中的问题并不是代码问题。
原因是在 i2c_device_probe 函数中存在
static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
int status;
if (!client)
return 0;
... ...
driver = to_i2c_driver(dev->driver);
if (!driver->probe || !driver->id_table)
return -ENODEV;
... ...
status = driver->probe(client, i2c_match_id(driver->id_table, client));
... ...
}
if (!driver->probe || !driver->id_table)
return -ENODEV
其中|| 逻辑或 判断规则:一真则真,两假才假,即
如果driver->id_table为空或者driver->probe为空则无法实现probe函数
所以,在新内核的dts设备树表述设备时,注册i2c_driver时,一定要将i2c_driver中的id_table实现!!!
其实也是根据设备树匹配成功的,只不过传统匹配表(i2c_device_id)也必须实现。如果只使用传统匹配表匹配应该是不需要设备树匹配表的。
附:设备树中ap3216c模块下面除了compatible,reg没有其他内容
reg查看ap3216c中的i2c从机地址 i2c slave address
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
ap3216c@1e {
compatible = "alientek,ap3216c";
reg = <0x1e>;
};
};
这是因为ap3216c是挂在在i2c下面的从机,所以设备树需要配置的其实只有i2c的I2C_SCL: UART4_TXD,I2C_SDA:UART4_RXD。(复用为ALT2)而这已经在父文件中配置过了,所以设备树中只需要配置compatible即可
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
>;
};
而ap3216c.h中定义的宏只是ap3216c内部寄存器的位置,和设备树无关。也可以讲内容直接移到.c文件或者不定义宏。
#define AP3216C_SYSTEMCONG 0x00 /* 配置寄存器 */
#define AP3216C_INTSTATUS 0X01 /* 中断状态寄存器 */
#define AP3216C_INTCLEAR 0X02 /* 中断清除寄存器 */
#define AP3216C_IRDATALOW 0x0A /* IR数据低字节 */
#define AP3216C_IRDATAHIGH 0x0B /* IR数据高字节 */
#define AP3216C_ALSDATALOW 0x0C /* ALS数据低字节 */
#define AP3216C_ALSDATAHIGH 0X0D /* ALS数据高字节 */
#define AP3216C_PSDATALOW 0X0E /* PS数据低字节 */
#define AP3216C_PSDATAHIGH 0X0F /* PS数据高字节 */