No direct results, let me talk about it.
I. Review:
In Note 5: i2c subsystem learning under linux It is based on Linux 2.6. kernel. In Linux 3.0, the device representation of I2C is implemented by board-level program, and I2C device is represented by i2c_client, the device information is loaded by struct i2c_board_info, and the device is loaded into I2C bus by i2c_new_device function.
exp: device.c
static struct i2c_board_info xxx_info = { I2C_BOARD_INFO("xxx", 0x48), //xxx is the matching name!!! };
driver.c
const struct i2c_device_id xxx_id[] = { { "xxx", 0 }, //The xxx in the i2c_device_id structure is the matching name!!! { } }; static struct i2c_driver it6801_drv = { .driver = { .name = "xxx", .owner = THIS_MODULE, }, .probe = xxx_drv_probe, .remove = xxx_drv_remove, .id_table = xxx_id, };
Secondly, the new kernel (after Linux 3.0) is introduced into DTS device tree. The description of equipment is all expressed by DTS device tree.
The reason why I implemented the i2c driver and the probe function did not execute - > Problem code:
exp: dts
&i2cN { //N represents the first N-way i2c bus status = "okay"; xxx@48 { status = "okay"; compatible = "xxx"; //compatible variable is the matching name reg = <0x48>; }; }
driver:
static const struct of_device_id of_xxx_match[] = { { .compatible = "xxx" }, //As you can see, this matches the device in dts { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, of_xxx_match); static struct i2c_driver xxx_drv = { .driver = { .name = "xxx", .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_xxx_match), }, .probe = xxx_drv_probe, .remove = xxx_drv_remove, };
After writing the code quickly, I found that my xxx_drv_probe function was not executed. The other two I2C drivers I wrote were also mounted on the first bus, and the other two drivers were running well, emmm... Why not this one? Analysis of the reasons: First, it is suspected that dts is not written correctly, compatible variable name is inconsistent; second, look at / sys/bus/i2c/devices / device, device exists, look at / sys/bus/i2c/drivers / below, my xxx_i2c_driver also exists! That's strange; then I use the arm-linux-nm command to look at my driver and show that xxx_drv_probe is compiled... In the end, the driver is compared with the two drivers, and it is found that the id_table in struct i2c_driver is missing.
driver:
static const struct of_device_id of_xxx_match[] = { { .compatible = "xxx" }, //As you can see, this matches the device in dts { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, of_xxx_match); const struct i2c_device_id xxx_id[] = { { "xxx", 0 }, { } }; static struct i2c_driver xxx_drv = { .driver = { .name = "xxx", .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_xxx_match), }, .probe = xxx_drv_probe, .remove = xxx_drv_remove, .id_table = xxx_id, //Although not used, but must be implemented, otherwise the probe function will not be called!!! };
After adding id_table in struct i2c_driver, the probe function is successfully called, my God!!! Look at the source code with questions, as follows.
i2c bus matching process
Call process: i2c_add_driver -->i2c_register_driver -->driver->driver.bus = &i2c_bus_type; -->driver_register -->bus_add_driver -->driver_attach -->bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); // Polling for devices on i2c bus -->__driver_attach -->driver_match_device -->driver_probe_device -->really_probe -->dev->bus->probe(dev); -->i2c_device_probe<i2c_bus_type;Realization in Structures> -->if (!driver->probe || !driver->id_table) -->driver->probe(client, i2c_match_id(driver->id_table, client)); -->xxx_drv_probe<i2c_driver Our driver implements in the architecture probe>
Finally in the true_probe function:
static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; ... ...//Eliminate irrelevant code if (dev->bus->probe) { ret = dev->bus->probe(dev); if (ret) goto probe_failed; } else if (drv->probe) { ret = drv->probe(dev); if (ret) goto probe_failed; } ... ... }
When registering I2C bus, bus - > probe function has been implemented and i2c_device_probe function has been implemented.
In the i2c_device_probe function:
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)//Judgment shows that if driver - > id_table is empty, direct return will not be executed further. So id_table must be implemented!!! Only then will the probe function be called return -ENODEV; ... ... status = driver->probe(client, i2c_match_id(driver->id_table, client)); ... ... }
4. Summarize the reasons why the i2c driver probe written by myself does not execute.
If the id_table of i2c_driver is not implemented in its own driver, it will eventually be in the i2c_device_probe function.
if (!driver->probe || !driver->id_table) return -ENODEV;
The statement returns directly, so that the xxx_drv_probe function implemented by ourselves can not be invoked!
Therefore, when registering i2c_driver, the id_table in i2c_driver must be implemented!!!