您的位置:首页 > 其它

i2c_driver的注册及probe探测函数调用

2013-03-21 14:40 477 查看
linux I2C 驱动之----i2c_client 的注册中介绍了i2c_client的注册,现在再来说说i2c_driver的注册过程。
每一个驱动程序都有 module_init(xxxx_init) 这个语句,它代表系统启动的时候会自动执行 xxxx 这个函数,也就是说驱动的人口函数是由module_init来定义的。当然还有module_exit(XXXX),它代表系统卸载驱动时调用(linux系统允许动态加载卸载驱动),这一部分这不细说了。

上文提到的 xxxx_init 是驱动的入口函数,在此函数中,我们一般注册驱动的driver,比如我今天说的 i2c_driver:

static int __init xxxx_init(void)

{

return i2c_add_driver(&xxxx_driver);

}

其中xxxx_driver就是我们今天的主角 i2c_driver :

static struct i2c_driver xxxx_driver =

{

.driver =

{

.owner = THIS_MODULE,

.name = "xxxx",

},

.id_table = xxxx_idtable,

.probe = xxxx_probe,

}

完整的 i2c_driver 非常复杂,上面的定义只是完成了最基本的部分,当然也是必须,也就代表完成了上面的部分你的驱动就可以工作了,当然还有其他的,这里不细说了。i2c_driver 中的driver.name 要和i2c_client一致,因为这是他们配备的一个依据,id_table 是i2c_device_id结构体的一个对象,里面定义了i2c驱动对应设备的i2c地址,probe函数是个非常重要的函数,等下我再来细说。

现在我来说说 i2c_add_driver 的执行过程。

(注意:此函数是linux系统i2c 子系统已经为我们做好了的,我们完全不需要了解它的执行过程,只需要明白,当系统中已经注册了和上文提到的i2c_driver xxxx_driver 对应的i2c_client,所谓对应的是说,name一样,i2c设备的地址也一样,那么i2c_driver 与i2c_client配备成功,接着就会调用i2c_driver 的probe函数,在此函数中可以做一系列的初始化工作。)

i2c_add_driver 函数只是调用了i2c_register_driver函数,在i2c_register_driver里调用了driver_register(&i2c_driver->driver),

注意
driver_register 是linux系统设备模型里面的函数了,每一类linux设备驱动的注册最终都会调用它,传递的参数也由原来的i2c_driver 变成了 device_driver。driver_register做了一些判断,最后调用了 bus_add_driver,然后调用 driver_attach,然后调用

bus_for_each_dev,这个函数就是搜索总线上所有的device,我们这里是i2c总线,也即搜索i2c总线上的i2c_client,调用__driver_attach判断i2c_driver i2c_client是否配备,再调用driver_match_device,driver_match_device最终调用了bus的match函数,我们这也就是i2c
bus的match函数,再调用

i2c_match_id,这里到最后的id 配备了,如果配备成功则正常返回到__driver_attach函数,调用driver_probe_device,再调用really_probe,最后调用bus的probe函数,在bus的probe函数里利用to_i2c_driver 将device_driver转换成了i2c_driver,最后调用了i2c_driver的probe函数,这个部分有点复杂,其中我可能也没说的太清楚,建议用source
insight自己跟一边,因为其中有很多是公用的,跟一边后,其他驱动注册也就容易了。

1,driver_register把驱动注册到总线

[cpp] view plaincopyprint?

/**

* 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驱动,注册到总线

……………………
}

/**
* 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驱动,注册到总线
……………………
}


2,驱动注册到总线的实现函数

[cpp] view plaincopyprint?

/**

* 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);
//驱动的匹配函数
………………
}

/**
* 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);      //驱动的匹配函数
………………
}

3,driver_attach()

[cpp] view plaincopyprint?

/**

* 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);

/**
* 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);

上面真正起作用的是__driver_attach:

[cpp] view plaincopyprint?

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(structdevice_driver *drv,
struct device *dev)
{
...
//1.先是判断bus是否match:

if (drv->bus->match && !drv->bus->match(dev, drv))

goto done;

//2.再具体执行probe:

ret = really_probe(dev, drv);
...
}

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(structdevice_driver *drv, struct device *dev)
{
...
//1.先是判断bus是否match:
if (drv->bus->match && !drv->bus->match(dev, drv))
goto done;
//2.再具体执行probe:
ret = really_probe(dev, drv);
...
}

4,really_probe是我们真正要找的函数

[cpp] view plaincopyprint?

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;

………………
}

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;
………………
}


打印出的驱动设备信息如:

………………

[ 0.588087] bus: 'platform': really_probe: bound device power.0to driverpower //总线:platform 设备:power.0
驱动:power

[ 0.661226] bus: 'platform': really_probe: bound device s3c24xx-pwm.0 to driver s3c24xx-pwm

[ 0.678552] bus: 'platform': really_probe: bound device s3c24xx-pwm.1 to driver s3c24xx-pwm

[ 0.695971] bus: 'platform': really_probe: bound device s3c24xx-pwm.2 to driver s3c24xx-pwm

[ 0.713389 bus: 'platform': really_probe: bound device s3c24xx-pwm.3 to driver

……………………
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: