Linux设备管理模型将device、driver以链表的形式绑定在总线Bus上,向总线注册一个驱动时会去匹配相应设备,这里梳理下一个驱动注册的流程:
1.驱动模块初始化函数module_init()被调用流程:
start_kernel();
rest_init();
kernel_init();
kernel_init_freeable();
do_basic_setup();
do_initcalls();//
do_initcall_level();
.....
module_init();
2.以I2C设备为例,modul_init()会调用你自己的初始化函数:
static struct i2c_driver your_driver = {
.driver = {
.owner = THIS_MODULE,
.name = YOUR_DRIVER_NAME_UP,
.of_match_table = your_driver_of_match,
},
.probe = your_probe_func,
.remove = your_i2c_drv_remove,
.id_table = your_i2c_drv_id_table,
//.suspend = your_i2c_drv_suspend,
//.resume = your_i2c_drv_resume,
};
static int __int your_init_func(void)
{
…
i2c_add_driver(&your_i2c_driver);
…
}
modul_init(your_init_func);
3.注册驱动流程:
i2c_register_driver()
driver_register()
bus_add_driver()
driver_attach()
bus_for_each_dev()
__driver_attach (for your device)
driver_probe_device()
really_probe()
i2c_device_probe (this is what dev->bus->probe is for an i2c driver)
your_probe_func()
4.以下分析具体函数:
(1)i2c_register_driver(): 位置:drivers/i2c/i2c-core.c
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
int res;
/* Can't register until after driver model init */
if (WARN_ON(!is_registered)) {
printk("unlikely(WARN_ON(!i2c_bus_type.p and return -EAGAIN.\n");
return -EAGAIN;
}
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type; //赋值bus type
INIT_LIST_HEAD(&driver->clients);
/* When registration returns, the driver core
* will have called probe() for all matching-but-unbound devices.
*/
res = driver_register(&driver->driver); // 这里进入
if (res){
printk("driver_register return res : %d\n", res);
return res;
}
pr_debug("driver [%s] registered\n", driver->driver.name);
/* iWalk the adapters that are already present */
i2c_for_each_dev(driver, __process_new_driver);
return 0;
}
type定义如下:
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
};
(2)driver_register把驱动注册到总线: 位置:drivers/base/driver.c
/**
* driver_register - register driver with bus
* @drv: driver to register
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*/
int driver_register(struct device_driver *drv)
{
......
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
ret = bus_add_driver(drv); //把drv驱动,注册到总线
.......
}
(3)驱动注册到总线的实现函数: 位置:drivers/base/bus.c
/**
* bus_add_driver - Add a driver to the bus. -----在总线上加入一个驱动
* @drv: driver.
*/
int bus_add_driver(struct device_driver *drv)
{
......
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv); //驱动的匹配函数
......
}
(4)driver_attach(): 位置:drivers/base/dd.c
/**
* driver_attach - try to bind driver to devices.
* @drv: driver.
*
* Walk the list of devices that the bus has on it and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*/
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);//注意这里__driver_attach
}
EXPORT_SYMBOL_GPL(driver_attach);
(5)bus_for_each_dev()将会遍历总线上的每个设备,并调用__driver_attach() : 位置:drivers/base/bus.c
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus || !bus->p)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data); //实际调用__driver_attach()
klist_iter_exit(&i);
return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);
(6)上面调用的是__driver_attach(): 位置:drivers/base/dd.c
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
/*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/
if (!driver_match_device(drv, dev)) //驱动与设备匹配
return 0;
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev); //看下这个函数的实现过程
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev)) //检查是否已注册过
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv); //入口
pm_request_idle(dev);
return ret;
}
(7)really_probe()函数: 位置:drivers/base/dd.c
static int really_probe(struct device *dev, struct device_driver *drv)
{
......
//1.驱动所属总线的probe函数:
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
}
//2.驱动中的probe函数:
else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);//这个可以看到我们注册的总 驱动、设备和总线信息
goto done;
......
}
(8)i2c_device_probe()里将调用your_probe_func(): 位置:driver/i2c/i2c-core.c
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;
if (!client->irq && dev->of_node) {
int irq = of_irq_get(dev->of_node, 0);
if (irq == -EPROBE_DEFER)
return irq;
if (irq < 0)
irq = 0;
client->irq = irq;
}
driver = to_i2c_driver(dev->driver);
if (!driver->probe || !driver->id_table)
return -ENODEV;
if (!device_can_wakeup(&client->dev))
device_init_wakeup(&client->dev,
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
status = of_clk_set_defaults(dev->of_node, false);
if (status < 0)
return status;
status = dev_pm_domain_attach(&client->dev, true);
if (status != -EPROBE_DEFER) {
status = driver->probe(client, i2c_match_id(driver->id_table,
client)); //调用你自己的probe函数
if (status)
dev_pm_domain_detach(&client->dev, true);
}
return status;
}
(9)至此,就调用到你自己在驱动里边实现的your_probe_func()了