Linux驱动学习之---平台驱动的注册过程(转载)


注:基于Linux-2.6.38

       上一篇说了平台设备是怎么注册进内核的,这一篇要说平台驱动(platform driver)的注册过程,看看当平台驱动注册进内核时是怎么与平台设备“联系”起来的。知道这些之后,以后想移植到新的内核或者添加其他平台设备(如SPI,IIC设备)或者编写平台设备驱动(如SPI,IIC驱动)就知道该怎么下手了。

       这里以s3c处理器的framebuffer驱动为例进行说明(其他的平台驱动原理一样)。找到/drivers/video/samsung/s3cfb.c,首先看模块的初始化函数:

1 int __devinit s3cfb_init(void)
2 {
3         return platform_driver_register(&s3cfb_driver);
4 }

第3行调用platform_driver_register(),参数s3cfb_driver的类型为struct platform_driver,看看它的定义:

复制代码
 1 static struct platform_driver s3cfb_driver = {
 2         .probe          = s3cfb_probe,
 3         .remove         = s3cfb_remove,
 4         .suspend        = s3cfb_suspend,
 5         .resume         = s3cfb_resume,
 6         .driver         = {
 7                 .name   = "s3c-fb",
 8                 .owner  = THIS_MODULE,
 9         },
10 };
复制代码

第2~5行给一些函数指针赋值,记住第7行这个name成员的值,后面会再提到;下面看platform_driver_register()在drivers/base/platform.c里的定义:

复制代码
 1 int platform_driver_register(struct platform_driver *drv)
 2 {       
 3         drv->driver.bus = &platform_bus_type;
 4         if (drv->probe)
 5                 drv->driver.probe = platform_drv_probe;
 6         if (drv->remove)
 7                 drv->driver.remove = platform_drv_remove;
 8         if (drv->shutdown)
 9                 drv->driver.shutdown = platform_drv_shutdown;
10 
11         return driver_register(&drv->driver);
12 }
复制代码

第3行,设置当前驱动所在的总线,从这里可以看出,平台设备和平台驱动处在同一条总线上;第4~9行,也是一些函数指针赋值操作;关键看第11行调用的在drivers/base/driver.c里定义的driver_register():

复制代码
 1 int driver_register(struct device_driver *drv)
 2 {
 3         int ret;
 4         struct device_driver *other;
 5 
 6         BUG_ON(!drv->bus->p);
 7         
 8         if ((drv->bus->probe && drv->probe) ||
 9             (drv->bus->remove && drv->remove) ||
10             (drv->bus->shutdown && drv->shutdown))
11                 printk(KERN_WARNING "Driver '%s' needs updating - please use "
12                         "bus_type methods\n", drv->name);
13                 
14         other = driver_find(drv->name, drv->bus);
15         if (other) {
16                 put_driver(other);
17                 printk(KERN_ERR "Error: Driver '%s' is already registered, "
18                         "aborting...\n", drv->name);
19                 return -EBUSY;
20         }
21 
22         ret = bus_add_driver(drv);
23         if (ret)
24                 return ret;
25         ret = driver_add_groups(drv, drv->groups);
26         if (ret)
27                 bus_remove_driver(drv);
28         return ret;
29 }
复制代码

看第14行的driver_find():

复制代码
 1 struct device_driver *driver_find(const char *name, struct bus_type *bus)
 2 {
 3         struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
 4         struct driver_private *priv;
 5 
 6         if (k) {
 7                 priv = to_driver(k);
 8                 return priv->driver;
 9         }
10         return NULL;
11 }
复制代码

通过函数的2个参数就可以知道,意思就是在bus总线上通过name找到它所对应的驱动。其实这里是不会找得到的,如果能找到就说明当前驱动之前已经注册过,就会返回出错信息。

回到driver_register()第22行的bus_add_driver(),这个函数有点长,只给出关键部分:

复制代码
1 int bus_add_driver(struct device_driver *drv)
2 {
3 ...........................................
4         if (drv->bus->p->drivers_autoprobe) {
5                 error = driver_attach(drv);
6                 if (error)
7                         goto out_unregister;
8         }
9 .......................................
复制代码

第4行的if条件一般会成立,因此看第5行的driver_attach():

1 int driver_attach(struct device_driver *drv)
2 {       
3         return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
4 }

遍历总线上每一个已经注册了的设备,每找到一个就调用__driver_attach()来判断是否与当前驱动匹配(怎么样才算匹配?答案即将揭晓),因此有必要看看__driver_attach()的定义:

复制代码
 1 static int __driver_attach(struct device *dev, void *data)
 2 {
 3         struct device_driver *drv = data;
 4 
 5         /*
 6          * Lock device and try to bind to it. We drop the error
 7          * here and always return 0, because we need to keep trying
 8          * to bind to devices and some drivers will return an error
 9          * simply if it didn't support the device.
10          *
11          * driver_probe_device() will spit a warning if there
12          * is an error.
13          */
14 
15         if (!driver_match_device(drv, dev))
16                 return 0;
17 
18         if (dev->parent)        /* Needed for USB */
19                 device_lock(dev->parent);
20         device_lock(dev);
21         if (!dev->driver)
22                 driver_probe_device(drv, dev);
23         device_unlock(dev);
24         if (dev->parent)
25                 device_unlock(dev->parent);
26 
27         return 0;
28 }
复制代码

如果第15行的driver_match_device()返回0的话后面的都不用执行了,看看它的定义:

 

1 static inline int driver_match_device(struct device_driver *drv,
2                                       struct device *dev)
3 {
4         return drv->bus->match ? drv->bus->match(dev, drv) : 1;
5 }

 

第4行,如果drv->bus->match这个函数有定义,就调用drv->bus->match函数,否则返回1。在这里可以告诉你,drv->bus->match是有定义的,不信?那去看看。

复制代码
1 struct bus_type platform_bus_type = {
2         .name           = "platform",
3         .dev_attrs      = platform_dev_attrs,
4         .match          = platform_match,
5         .uevent         = platform_uevent,
6         .pm             = &platform_dev_pm_ops,
7 };
复制代码

是吧,再去看看match函数:

复制代码
 1 static int platform_match(struct device *dev, struct device_driver *drv)
 2 {
 3         struct platform_device *pdev = to_platform_device(dev);
 4         struct platform_driver *pdrv = to_platform_driver(drv);
 5 
 6         /* Attempt an OF style match first */
 7         if (of_driver_match_device(dev, drv))
 8                 return 1;
 9 
10         /* Then try to match against the id table */
11         if (pdrv->id_table)
12                 return platform_match_id(pdrv->id_table, pdev) != NULL;
13 
14         /* fall-back to driver name match */
15         //
16         return (strcmp(pdev->name, drv->name) == 0);
17 }
复制代码

第8行和第12行,这两条返回语句对于当前来说都不会被执行,因此重点在第16行,drv->name的值在本篇的最前面可以看到是"s3c-fb",接下来看pdev->name的值:

复制代码
1 struct platform_device s3c_device_fb = {
2     .name          = "s3c-fb",
3     .id          = -1,
4     .num_resources      = ARRAY_SIZE(s3c_fb_resource),
5     .resource      = s3c_fb_resource,
6     .dev.dma_mask      = &s3c_device_fb.dev.coherent_dma_mask,
7     .dev.coherent_dma_mask = 0xffffffffUL,
8 };
复制代码

第2行,看到了吧,也是"s3c-fb",事实上在这里看来这两个值一定要相同,驱动靠它来找到对应的设备。

好了,回到__driver_attach()第18行以后的内容,其中第22行的driver_probe_device()会被执行,看它的定义:

 

复制代码
 1 int driver_probe_device(struct device_driver *drv, struct device *dev)
 2 {
 3         int ret = 0;
 4 
 5         if (!device_is_registered(dev))
 6                 return -ENODEV;
 7 
 8         pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
 9                  drv->bus->name, __func__, dev_name(dev), drv->name);
10 
11         pm_runtime_get_noresume(dev);
12         pm_runtime_barrier(dev);
13         ret = really_probe(dev, drv);
14         pm_runtime_put_sync(dev);
15 
16         return ret;
17 }
复制代码

 

关键在第13行,really_probe()实现了真正的探测:

复制代码
 1 static int really_probe(struct device *dev, struct device_driver *drv)
 2 {
 3         int ret = 0;
 4 
 5         atomic_inc(&probe_count);
 6         pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
 7                  drv->bus->name, __func__, drv->name, dev_name(dev));
 8         WARN_ON(!list_empty(&dev->devres_head));
 9 
10         dev->driver = drv;
11         if (driver_sysfs_add(dev)) {
12                 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
13                         __func__, dev_name(dev));
14                 goto probe_failed;
15         }
16 
17         
18         if (dev->bus->probe) {
19                 ret = dev->bus->probe(dev);
20                 if (ret)
21                         goto probe_failed;
22         } else if (drv->probe) {
23                 ret = drv->probe(dev);
24                 if (ret)
25                         goto probe_failed;
26         }
27 ...................................
复制代码

第10行,把驱动和设备对应起来;第18~26行,意思很明显,从目前来看,第18行的条件不成立而第22行的条件会成立,因此会执行驱动里定义的probe()函数,在这里已经知道了驱动程序里的probe()是什么时候被调用的,后面那些内容是“收尾”工作了。

到这里已经找到了我想要的东西了,也就告一段落了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值