platform_device和platform_driver的匹配

来源:互联网 发布:mac 桌面文件的路径 编辑:程序博客网 时间:2024/05/06 09:21

说句老实话,我不太喜欢现在Linux 2.6这套bus, platform, device,device driver 的模式。我觉得这种模式破坏了Linux的“简单就是美”的哲学,原来那套驱动已经可以包容所有驱动,也可以直接注册驱动文件和管理,而且以前的驱动在现在的结构上也还可以使用,把它在注册到bus这棵树上又有什么用呢?虽然可以看到一点对于移植性和平台管理方面的优点,但是我认为现在这种驱动编程的风格越来越像Windows的风格,很不直观和简约,让人理解起来相当的困惑。

牢骚发完了,bus结构还得继续,说说platform_device和platform_driver的匹配吧!一般来说系统上来在init_init_machine的对应函数ap_init中注册一些这个平台的设备,如下:

static struct resource cbp_sdmmc_resource[]=
{
   [0]={
         .start=HWD_MMC_BASE,
         .end=HWD_MMC_BASE+0xff0,
         .flags=IORESOURCE_MEM
       },
   [1]={
         .start=IRQ_SDMMC,
         .end=IRQ_SDMMC,
         .flags=IORESOURCE_IRQ
       },
   [2]={
         .start=IRQ_SDMMC_CD,
         .end=IRQ_SDMMC_CD,
         .flags=IORESOURCE_IRQ
       }
};

struct platform_device cbp_device_sdmmc = {
 .name    = "cbp-sdmmc",
 .id    = -1,
 .num_resources   = ARRAY_SIZE(cbp_sdmmc_resource),
 .resource   = cbp_sdmmc_resource,
        .dev              = {
                .coherent_dma_mask = 0xffffffffUL
        }
};
static struct platform_device * cbp_devices[] __initdata = {
   &cbp_device_sdmmc
};
static void __init ap_init(void)
{
   platform_add_devices(cbp_devices,ARRAY_SIZE(cbp_devices));

}
说明这个平台使用的SD/MMC驱动的名字叫"cbp-sdmmc",然后在驱动中用platform_driver_register声明对应的platform_driver来使用上面声明的平台资源,如下:

static int __init cbpmci_init(void)
{
    return platform_driver_register(&cbpmci_driver);
}
platform_driver和platform_driver的匹配方式有两种:

1)直接根据名字来进行匹配,这种方式是比较常用的方式,比如如下申明cbpmci_driver:

static struct platform_driver cbpmci_driver = {
 .probe = cbpmci_probe,
 .driver = {
  .name = "cbp-sdmmc",
 },
};
2)通过id_talbe来实现,这种实现的最终还是通过名字对应来匹配,但是匹配的名字被列在一个表中,platform_device的name和这个表中的每一个值进行比较,知道找到相同的那一个,如下申明:

 static struct platform_device_id cbpmci_driver_ids[] = {
 {
  .name = "other-sdmmc",
  .driver_data = 0,
 }, 
 {
  .name = "cbp-sdmmc",
  .driver_data = 1,
 }, 
 { }
};

static struct platform_driver cbpmci_driver = {
 .driver = {
  .name = "vtc_sdmmc",
  .owner = THIS_MODULE,
  .pm = &cbpmci_pm_ops,
 },
 .id_table = cbpmci_driver_ids,
 .probe  = cbpmci_probe,
 .remove  = __devexit_p(cbpmci_remove),
 .shutdown = cbpmci_shutdown,
};
当id_table不为空的时候,.driver.name中的名字“vtc_sdmmc”就不管用了,会按照id_table中的内容进行匹配,同时匹配后的会把匹配上的platform_device_id保存在platform_device结构的id_entry中,在probe的时候就可以通过id_entry中的driver_data判断匹配的到底是cbpmci_driver_ids中的哪一组ID,

比如上面例子中的"cbp-sdmmc"中匹配的是第二组,这样就可以再Probe的判断到底是什么平台了

if(platform_get_device_id(pdev)->driver_data==1) printk("cgp SD/MMC support/n");

这种匹配方式在三星的SD/MMC中有使用,由于2412和2440的地址是一样的,而2410不一样,所以通过driver_data 是否为1来区分。

static struct platform_device_id s3cmci_driver_ids[] = {
 {
  .name = "s3c2410-sdi",
  .driver_data = 0,
 }, {
  .name = "s3c2412-sdi",
  .driver_data = 1,
 }, {
  .name = "s3c2440-sdi",
  .driver_data = 1,
 },
 { }
};

 

一下是Linux匹配的源代码,在platform.c中,一看就一目了然了,当然要跟到这步,中间还有好多指针要走:

static int platform_match(struct device *dev, struct device_driver *drv)
{
 struct platform_device *pdev = to_platform_device(dev);
 struct platform_driver *pdrv = to_platform_driver(drv);

 /* match against the id table first */
 if (pdrv->id_table)
  return platform_match_id(pdrv->id_table, pdev) != NULL;

 /* fall-back to driver name match */
 return (strcmp(pdev->name, drv->name) == 0);
}

此外platform_add_devices最终会调用platform_device_register,而platform_device_register和platform_driver_register应该先调用哪一个理论上讲是先调用device然后driver,但其实是无所谓的,最后都会调用device_attach()来probe。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买二手苹果手机没有账号怎么办 手机淘宝足迹不更新怎么办 淘宝申请退款不想退了怎么办 荣耀3c主板坏了怎么办 荣耀10天气删了怎么办 荣耀7i手机卡顿怎么办 荣耀v9总是自己拨号怎么办 华为荣耀5x很卡怎么办 华为荣耀6plus卡怎么办 华为手机触屏不灵敏怎么办 华为荣耀6x太卡怎么办 华为荣耀7太卡怎么办 荣耀手机开不开机怎么办 华为g750手机开不了机怎么办 华为手机开不了机怎么办 小米手机刷机后激活不了帐号怎么办 魅蓝note5卡顿怎么办 魅蓝note5卡了怎么办 魅蓝note5很卡怎么办 魅蓝note5锁了怎么办 荣耀9开不开机怎么办 4s更新后用不了怎么办 魅蓝3开不了机怎么办 手机不支持联通4g网络怎么办 华为手机出现emui界面怎么办 华为畅玩4x内存不足怎么办 手机电源键掉了怎么办 手机电源键坏了怎么办 小米5s听筒声音小怎么办 荣耀8电源键失灵怎么办 华为荣耀3c卡怎么办 大王卡是2g网络怎么办 联通停用2g副卡怎么办 华为荣耀8忘记解锁密码怎么办 华为手机内存满了怎么办 华为手机无限重启怎么办 华为3c重启怎么办 荣耀6 无限重启怎么办 手机进水无法开机了怎么办 华为手机不停重启怎么办 华为手机反复重启怎么办