linux内核platform,Linux内核中的platform机制

五、platform_device与platform_driver匹配的过程

27609387_2 

追踪__driver_attach这个函数,在这个函数里面分别调driver_match_device,driver_probe_device函数。如果匹配成功就调用probe函数,否则返回。

drivers/base/dd.c, line 255255 static int __driver_attach(struct device *dev, void *data)

256 {

257         struct device_driver *drv = data;

258

259         /*

260          * Lock device and try to bind to it. We drop the error

261          * here and always return 0, because we need to keep trying

262          * to bind to devices and some drivers will return an error

263          * simply if it didn\'t support the device.

264          *

265          * driver_probe_device() will spit a warning if there

266          * is an error.

267          */

268

269         if (!driver_match_device(drv, dev))

270                 return 0;

271

272         if (dev->parent)        /* Needed for USB */

273                 down(&dev->parent->sem);

274         down(&dev->sem);

275         if (!dev->driver)

276                 driver_probe_device(drv, dev);

277         up(&dev->sem);

278         if (dev->parent)

279                 up(&dev->parent->sem);

280

281         return 0;

282 }匹配的过程中调用了bus的match函数,我们在第二部分platform的初始化里,有platform_bus_type.match = platform_match,这里的platform_match函数定义在drivers/base/platform.c, line 619.619 static int platform_match(struct device *dev, struct device_driver *drv)

620 {

621         struct platform_device *pdev = to_platform_device(dev);

622         struct platform_driver *pdrv = to_platform_driver(drv);

623

624         /* match against the id table first */

625         if (pdrv->id_table)

626                 return platform_match_id(pdrv->id_table, pdev) != NULL;

627

628         /* fall-back to driver name match */

629         return (strcmp(pdev->name, drv->name) == 0); //从此处可以看到,内核是按照name来匹配的630 }六、实例在kernel/arch/arm/mach-pxa/pxa27x.c定义了

static struct resource pxa27x_ohci_resources[] = {

[0] = {

.start  = 0x4C000000,

.end    = 0x4C00ff6f,

.flags  = IORESOURCE_MEM, //表示第1组描述的是内存类型的资源信息

}, [1] = {

.start  = IRQ_USBH1,

.end    = IRQ_USBH1,

.flags  = IORESOURCE_IRQ, //表示第2组描述的是中断资源信息},};

这里定义了两组resource,它描述了一个usb host设备的资源,第1组描述了这个usb host设备所占用的总线地址范围,IORESOURCE_MEM表示第1组描述的是内存类型的资源信息,第2组描述了这个usb host设备的中断号,IORESOURCE_IRQ表示第2组描述的是中断资源信息。设备驱动会根据flags来获取相应的资源信息。有了resource信息,就可以定义platform_device了:static struct platform_device ohci_device = {.name  = \"pxa27x-ohci\",.id  = -1,.dev  = {.dma_mask = &pxa27x_dmamask,.coherent_dma_mask = 0xffffffff,},.num_resources  = ARRAY_SIZE(pxa27x_ohci_resources),.resource       = pxa27x_ohci_resources,};有了platform_device就可以调用函数platform_add_devices向系统中添加该设备了,这里的实现是static int __init pxa27x_init(void){return platform_add_devices(devices, ARRAY_SIZE(devices));}这里的pxa27x_init必须在设备驱动加载之前被调用,可以把它放到subsys_initcall(pxa27x_init);驱动程序需要实现结构体struct platform_driver,参考kernel/driver/usb/host/ohci-pxa27.c,static structplatform_driver ohci_hcd_pxa27x_driver = {.probe  = ohci_hcd_pxa27x_drv_probe,.remove =ohci_hcd_pxa27x_drv_remove,#ifdef CONFIG_PM.suspend = ohci_hcd_pxa27x_drv_suspend,.resume  =ohci_hcd_pxa27x_drv_resume,#endif.driver  = {.name = \"pxa27x-ohci\",},};在驱动初始化函数中调用函数platform_driver_register()注册platform_driver,需要注意的是ohci_device结构中name元素和ohci_hcd_pxa27x_driver结构中driver.name必须是相同的,这样在platform_driver_register()注册时会对所有已注册的所有platform_device中的name和当前注册的platform_driver的driver.name进行比较,只有找到相同的名称的platfomr_device才能注册成功,当注册成功时会调用platform_driver结构元素probe函数指针,这里就是ohci_hcd_pxa27x_drv_probe。当进入probe函数后,需要获取设备的资源信息,获取资源的函数有:struct resource * platform_get_resource(struct platform_device *dev,unsigned int type,unsignedint num);根据参数type所指定类型,例如IORESOURCE_MEM,来获取指定的资源。struct intplatform_get_irq(struct platform_device *dev, unsigned int num);获取资源中的中断号。structresource * platform_get_resource_byname(struct platform_device *dev,unsigned int type,char*name);根据参数name所指定的名称,来获取指定的资源。int platform_get_irq_byname(structplatform_device *dev, char *name);根据参数name所指定的名称,来获取资源中的中断号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值