platform驱动注册中为什么要使用不同的函数注册两次驱动匹配?

在阅读Linux平台驱动代码时,会发现会分别使用MODULE_DEVICE_TABLE进行一次驱动匹配,随后在module_platform_driver中定义的struct platform_driver结构中再次对.driver..of_match_table赋值了进行了驱动匹配的注册,像下面这样:

static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume);

static const struct of_device_id rk_gmac_dwmac_match[] = {
#ifdef CONFIG_CPU_PX30
	{ .compatible = "rockchip,px30-gmac", .data = &px30_ops },
#endif
#ifdef CONFIG_CPU_RK1808
	{ .compatible = "rockchip,rk1808-gmac", .data = &rk1808_ops },
#endif

//…省略部分型号定义…//

#ifdef CONFIG_CPU_RK3588
	{ .compatible = "rockchip,rk3588-gmac", .data = &rk3588_ops },
#endif
    
//…省略部分型号定义…//
    
	{}
};
MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);

static struct platform_driver rk_gmac_dwmac_driver = {
	.probe  = rk_gmac_probe,
	.remove = rk_gmac_remove,
	.driver = {
		.name           = "rk_gmac-dwmac",
		.pm		= &rk_gmac_pm_ops,
		.of_match_table = rk_gmac_dwmac_match,
	},
};
module_platform_driver(rk_gmac_dwmac_driver);

这是为什么呢?是不是重复注册呢?是为了保险起见而进行的重复操作吗?
事实上并不是这样,这两个地方虽然都进行了驱动的匹配,但是意义却并不相同,原因如下:

  1. MODULE_DEVICE_TABLE
    • 作用:这个宏用于将设备匹配表导出到用户空间。它会生成一个特殊的节(section),其中包含设备ID表。这些信息在内核模块加载时由depmod工具读取,并用于设备和驱动程序的自动匹配。例如:
MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
 这行代码会将`rk_gmac_dwmac_match`表中的设备ID信息导出,以便在模块加载时进行匹配。
  1. module_platform_driver
    • 作用:这个宏用于注册平台驱动程序。它会调用platform_driver_register函数,将驱动程序注册到内核中,使其能够响应设备的探测和移除事件。例如:
module_platform_driver(rk_gmac_dwmac_driver);
 这行代码会注册`rk_gmac_dwmac_driver`驱动程序,使其能够处理与平台设备相关的操作,如探测(probe)和移除(remove)。

总结来说,MODULE_DEVICE_TABLE用于导出设备ID表以便在模块加载时进行匹配,而module_platform_driver用于注册驱动程序,使其能够处理设备的探测和移除事件。这两个步骤是相互补充的,确保驱动程序能够正确加载和运行。

在这里插入图片描述

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
驱动程序的初始化是在内核加载驱动程序时进行的。当内核检测到有新的硬件设备插入或者需要加载特定的驱动程序时,它会调用对应的驱动程序的初始化函数来初始化该驱动程序。 对于Platform设备,驱动程序的初始化通常在注册`platform_driver`时进行。`platform_driver`是注册Platform设备驱动程序的数据结构,它包含了驱动程序的一些属性信息,如驱动程序的名称、设备ID、与设备匹配的`of_device_id`表等。在注册`platform_driver`时,内核会自动调用驱动程序的初始化函数来完成驱动程序的初始化。 以下是一个Platform设备驱动程序的示例: ```c #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> static int my_platform_probe(struct platform_device *pdev) { // 驱动程序的初始化代码 return 0; } static int my_platform_remove(struct platform_device *pdev) { // 驱动程序的卸载代码 return 0; } static struct platform_driver my_platform_driver = { .probe = my_platform_probe, .remove = my_platform_remove, .driver = { .name = "my-platform-driver", .owner = THIS_MODULE, }, }; static int __init my_platform_init(void) { return platform_driver_register(&my_platform_driver); } static void __exit my_platform_exit(void) { platform_driver_unregister(&my_platform_driver); } module_init(my_platform_init); module_exit(my_platform_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("My Platform Driver"); ``` 在该示例,`my_platform_probe()`和`my_platform_remove()`函数分别为驱动程序的初始化和卸载函数。在`my_platform_driver`结构体使用`.probe`和`.remove`字段分别指定了驱动程序的初始化和卸载函数。在`my_platform_init()`函数使用`platform_driver_register()`函数注册驱动程序。在`my_platform_exit()`函数使用`platform_driver_unregister()`函数来卸载驱动程序。 当内核检测到需要加载该驱动程序时,就会调用`my_platform_probe()`函数来初始化驱动程序。当需要卸载该驱动程序时,就会调用`my_platform_remove()`函数来卸载驱动程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值