在阅读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);
这是为什么呢?是不是重复注册呢?是为了保险起见而进行的重复操作吗?
事实上并不是这样,这两个地方虽然都进行了驱动的匹配,但是意义却并不相同,原因如下:
- MODULE_DEVICE_TABLE:
- 作用:这个宏用于将设备匹配表导出到用户空间。它会生成一个特殊的节(section),其中包含设备ID表。这些信息在内核模块加载时由
depmod
工具读取,并用于设备和驱动程序的自动匹配。例如:
- 作用:这个宏用于将设备匹配表导出到用户空间。它会生成一个特殊的节(section),其中包含设备ID表。这些信息在内核模块加载时由
MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
这行代码会将`rk_gmac_dwmac_match`表中的设备ID信息导出,以便在模块加载时进行匹配。
- 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
用于注册驱动程序,使其能够处理设备的探测和移除事件。这两个步骤是相互补充的,确保驱动程序能够正确加载和运行。