平台总线设备驱动模型——基础知识

平台总线设备驱动程序采用了分层分离的机制,我们先简述一下其大体上的原理,然后在从具体代码出发进行分析。
大体原理:在内核中存在平台设备总线,我们要把设备挂载到总线设备列表中,同时也要把驱动挂在到总线驱动列表中,但是相匹配的设备和驱动的名字要保持一致,因为总线会根据设备和驱动的名字是否一致,来决定他们是否匹配,一旦设备和驱动匹配起来,就会调用驱动程序里的probe函数进行处理。
代码分析,以/dirvers/mtd/nand/s3c2410.c为例来分析:
platform_driver_register(&s3c2410_nand_driver); //驱动名为s3c2410-nand
          drv->driver.bus = &platform_bus_type; //platform_bus_type里存在match函数,待会会分析
          driver_register(&drv->driver);
                     bus_add_driver(drv); //将驱动添加到平台总线驱动列表中
我们搜索名“s3c2410-nand”的设备,最终在/arch/arm/plat-s3c24xx/devs.c中发现了线索:
struct platform_device s3c_device_nand = {
.name  = "s3c2410-nand",
.id  = -1,
.num_resources  = ARRAY_SIZE(s3c_nand_resource),
.resource  = s3c_nand_resource,
};
那么这个设备是如何添加到总线上的呢?
.init_machine = osiris_init,
         platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));// 关于osiris_devices的定义见注释1
                   platform_device_register(devs[i]);
                             platform_device_add(pdev);
                                      device_add(&pdev->dev); //将设备添加到总线

这样设备和驱动都注册到了总线上面,那么总线要做什么呢?
我们还记得注册驱动的时候有这么一句吧:
drv->driver.bus = &platform_bus_type;
我们来看看 platform_bus_type的定义:
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.suspend = platform_suspend,
.suspend_late = platform_suspend_late,
.resume_early = platform_resume_early,
.resume = platform_resume,
};
这里面有match函数,总线就是根据这个函数来判断设备和驱动是否匹配的,我们来看一下代码:
static int platform_match(struct device * dev, struct device_driver * drv)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);

return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}
我们看到了,确实是根据驱动和设备的名字是否一致,来判断是否匹配的。
一旦匹配就会调用probe函数。
注释1:
static struct platform_device *osiris_devices[] __initdata = {
&s3c_device_i2c,
&s3c_device_wdt,
&s3c_device_nand,
&osiris_pcmcia,
};

疑问?
我水比较差,只能分析到这个地步了,下面是我的几点疑问,希望大家帮我一下好吗:
(1)我搜遍了代码也没有发现有谁调用了match函数,那么这个函数怎么被执行呢?
(2)为什么match成功后会调用probe函数呢?它也没有在哪个函数里面被调用啊!
(3)
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (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;
if (drv->suspend)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
return driver_register(&drv->driver);
}
为什么一旦设置了 drv->probe就要自动设置 drv->driver.probe = platform_drv_probe;?drv.probe和drv->driver.probe两个probe有什么区别啊?
(4)
MACHINE_START(OSIRIS, "Simtec-OSIRIS")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = osiris_map_io,
.init_machine = osiris_init,
.init_irq = s3c24xx_init_irq,
.init_machine = osiris_init,
.timer = &s3c24xx_timer,
MACHINE_END
这之间的代码何时被执行?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值