arch_initcall(qup_i2c_init_driver);//注:该初始化的优先级别为3 .initcall3.init
下面开始分析,平台驱动如何注册驱动的。
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;//把该driver的bus类型赋值为平台总线类型
if (drv->probe)//platform的探测函数不为空,则该driver的probe函数赋值为platform_drv_probe
drv->driver.probe = platform_drv_probe;
if (drv->remove)//同上
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)//同上
drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver);
}
注册该platform中的driver成员,下面跟踪下注册的过程。
int driver_register(struct device_driver *drv)
{
other = driver_find(drv->name, drv->bus);//判读查找该驱动是否已经在该总线上注册过?
ret = bus_add_driver(drv);//如果没有注册过,就把该drv加入到总线上
}
继续分析,加入的过程:
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);//分配一个priv私有数据结构,并初始化
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;//把该私有结构挂到driver上
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
if (drv->bus->p->drivers_autoprobe) {//如果bus设置了drivers的自动探测,则执行探测绑定
error = driver_attach(drv);
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);//到处已经探测成功,把该驱动加入bus的driver的链表中
return 0;
}
继续跟踪探测,绑定函数,该函数是取出总线设备链表的每一个设备,和该驱动匹配
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
继续看_driver_attach函数
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
if (!driver_match_device(drv, dev))//该函数调用总线的match函数,进行匹配
return 0;
if (!dev->driver)//到此匹配成功,并且dev的driver为空,则执行如下探测函数
driver_probe_device(drv, dev);
return 0;
}
下面就跟踪下探测函数的实现:
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
dev->driver = drv;//关联二者
ret = really_probe(dev, drv);
}
继续跟踪:
static int really_probe(struct device *dev, struct device_driver *drv)
{
if (dev->bus->probe) {//如果总线上有probe函数,优先调用总线的该函数
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {//如果drv的不为空,则调用driver的探测函数
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);//探测成功后,绑定,也就是把该dev加入到driver的device链表
}
到处平台驱动的注册函数完毕,已经把该平台驱动加入到对应的总线中,以及和对应的平台设备绑定。
因为此处为平台设备,所以还有一点需要分析:就是探测函数
此时执行的是:drv->driver.probe = platform_drv_probe;
函数,下面分析下,该函数干了什么活:
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
return drv->probe(dev);
}
这个函数没什么东西,就是折腾下,去执行platform中的探测函数。到处算是驱动框架分析完毕,下一节开始分析具体的probe探测函数,由于注册设备和注册驱动时,都要调用对应驱动的探测函数,所以重点看的就是探测函数。