platform总线注册过程及platform_driver与platform_device的匹配

16 篇文章 0 订阅
11 篇文章 0 订阅

我们知道,按platform结构写驱动,我们只需注册platform_device和platform_driver而不需要我们自己去注册platform总线,因为系统启动就有那条总线,那么它是怎么得到的呢?这里进行具体跟踪一下:

start_kernel——>rest_init——>kernel_thread(这个线程创建很重要)——>kernel_init——>do_basic_setup——>driver_init——>platform_bus_init

int __init platform_bus_init(void)
{
 int error;

 early_platform_cleanup();

 error = device_register(&platform_bus);
 if (error)
  return error;
 error =  bus_register(&platform_bus_type);
 if (error)
  device_unregister(&platform_bus);
 return error;
}

根据platform_bus_type总线类型得

struct bus_type platform_bus_type = {
 .name  = "platform",
 .dev_attrs = platform_dev_attrs,
 .match  = platform_match,//永远记住总线的match函数才是最终的设备与驱动的匹配函数,成功后会调用驱动的probe函数
 .uevent  = platform_uevent,
 .pm  = &platform_dev_pm_ops,
};

这里继续分析匹配过程:

platform_driver_register——>driver_register——>bus_add_driver——>driver_attach——>bus_for_each_dev——>__driver_attach——>driver_match_device——>drv->bus->match——>(*match)(struct device *dev, struct device_driver *drv);
这里找到总线类型中的match函数,这里只是个函数指针,很明显platform_bus_type结构下有具体match的实现,匹配后会自动调用驱动下的probe函数

struct bus_type {
 const char  *name;
 struct bus_attribute *bus_attrs;
 struct device_attribute *dev_attrs;
 struct driver_attribute *drv_attrs;
 do_basic_setup

 int (*match)(struct device *dev, struct device_driver *drv);
 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
 int (*probe)(struct device *dev);
 int (*remove)(struct device *dev);
 void (*shutdown)(struct device *dev);

 int (*suspend)(struct device *dev, pm_message_t state);
 int (*resume)(struct device *dev);

 const struct dev_pm_ops *pm;

 struct bus_type_private *p;
};

static int platform_match(struct device *dev, struct device_driver *drv)//platform_bustype匹配函数
{
 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);
}

接下来看driver的probe函数是如何被调用的:

platform_driver_register——>driver_register——>bus_add_driver——>driver_attach——>bus_for_each_dev——>__driver_attach——>driver_probe_device——>really_probe——>drv->probe——>int (*probe) (struct device *dev)(这个函数指针就指向我们真正填写的device+driver下的probe)

注意:总线、设备、驱动结构中,总线的match函数负责匹配驱动与设备;然后匹配成功后会调用驱动中的probe函数,卸载驱动或设备的时候后调用release函数

同样对于platform_device_register中也会去调用bus中的match

platform_device_register——>platform_device_add——>device_add——>bus_probe_device-------->device_attach——>bus_for_each_drv——>__device_attach——>driver_match_device——>bus->match----->driver_probe_device---->really_probe----->bus->probe---->drv->probe——>int (*probe) (struct device *dev)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux内核中,platform_driver中的.driver是一个device_driver结构体,用于实现设备驱动模型的一些通用功能。device_driver结构体包含了一些驱动的元数据,例如驱动的名称、ID等信息,以及与设备驱动模型相关的函数指针,例如probe、remove、suspend和resume等函数,用于初始化设备和释放设备资源。 device_driver结构体的定义如下: ``` struct device_driver { const char *name; struct bus_type *bus; struct module *owner; const char *mod_name; bool suppress_bind_attrs; const struct of_device_id *of_match_table; int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; const struct dev_pm_ops *pm; const struct driver_sysfs_ops *sysfs_ops; }; ``` 其中,name表示驱动的名称,bus表示驱动所在的总线类型,owner表示驱动所属的模块,mod_name表示驱动所在模块的名称,suppress_bind_attrs表示是否禁用设备绑定属性,of_match_table表示用于匹配设备节点的设备树表格,probe、remove、shutdown、suspend和resume等函数指针用于初始化设备和释放设备资源,groups表示与设备相关的属性组,pm表示与设备电源管理相关的操作,sysfs_ops表示与sysfs文件系统相关的操作。 device_driver结构体中的函数指针与platform_driver结构体中的probe、remove、shutdown、suspend和resume函数指针相对应,不同之处在于device_driver结构体中的函数是设备驱动模型的通用函数,可以被不同类型的设备驱动所使用。 总之,platform_driver中的.driver是一个device_driver结构体,用于实现设备驱动模型的一些通用功能,包含了驱动的元数据和与设备驱动模型相关的函数指针。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值