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

本文详细解析了平台总线设备驱动程序的分层分离机制,包括设备与驱动的匹配原理、代码实现及核心过程。通过以`s3c2410.c`文件为例,深入探讨了设备和驱动如何被注册到总线上,并解释了总线的`match`函数是如何执行匹配操作以及`probe`函数触发的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平台总线设备驱动程序采用了分层分离的机制,我们先简述一下其大体上的原理,然后在从具体代码出发进行分析。
大体原理:在内核中存在平台设备总线,我们要把设备挂载到总线设备列表中,同时也要把驱动挂在到总线驱动列表中,但是相匹配的设备和驱动的名字要保持一致,因为总线会根据设备和驱动的名字是否一致,来决定他们是否匹配,一旦设备和驱动匹配起来,就会调用驱动程序里的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
这之间的代码何时被执行?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值