我正在阅读围绕总线,设备和驱动程序构建的Linux设备模型 。我能够理解设备和驱动程序如何匹配,但不清楚总线在这里的作用,总线如何与设备匹配。
我对平台设备的名称来源更加怀疑。
“平台总线,只需将每个设备的名称与每个驱动程序的名称进行比较;如果它们相同,则设备与驱动程序匹配。”
现在我无法理解上述观点。我相信设备名称首先在dts文件中定义,然后相应的驱动程序名称在平台驱动程序代码中定义。
如果这两个名称匹配,则从驱动程序代码调用probe,这将确认设备确实存在。
任何人都可以从公交车的角度特别告诉我整个过程。
答案 0 :(得分:12)
要添加@Federico的答案,其中描述了一般情况,平台设备可以使用四个(优先级)匹配平台驱动程序。这是平台“公共汽车”的match function:
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
/* Then try ACPI style match */
if (acpi_driver_match_device(dev, drv))
return 1;
/* Then try to match against the id table */
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);
}
这是两个重要的。
使用设备树(of_driver_match_device
)进行匹配。如果您还不知道设备树概念,go read about it。在此数据结构中,每个设备在表示系统的树中具有其自己的节点。每个设备还有一个compatible
属性,它是一个字符串列表。如果任何平台驱动程序声明其中一个compatible
字符串被支持,则会匹配并且将调用驱动程序的探测。
gpio0: gpio@44e07000 {
compatible = "ti,omap4-gpio";
ti,hwmods = "gpio1";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x44e07000 0x1000>;
interrupts = <96>;
};
这描述了一个GPIO控制器。它只有一个兼容的字符串ti,omap4-gpio
。将探测声明此相同兼容字符串的任何注册平台驱动程序。这是its driver:
static const struct of_device_id omap_gpio_match[] = {
{
.compatible = "ti,omap4-gpio",
.data = &omap4_pdata,
},
{
.compatible = "ti,omap3-gpio",
.data = &omap3_pdata,
},
{
.compatible = "ti,omap2-gpio",
.data = &omap2_pdata,
},
{ },
};
MODULE_DEVICE_TABLE(of, omap_gpio_match);
static struct platform_driver omap_gpio_driver = {
.probe = omap_gpio_probe,
.driver = {
.name = "omap_gpio",
.pm = &gpio_pm_ops,
.of_match_table = of_match_ptr(omap_gpio_match),
},
};
驱动程序能够驱动三种类型的GPIO,包括前面提到的那种。
请注意,平台设备不会神奇地添加到平台总线。架构/电路板初始化将调用platform_device_add
或platform_add_devices
,在这种情况下,借助OF函数扫描树。
如果你看platform_match
,你会看到匹配回到名称匹配。在驱动程序名称和设备名称之间进行简单的字符串比较。这是旧平台驱动程序的工作方式。他们中的一些人仍然这样做,例如this one here:
static struct platform_driver imx_ssi_driver = {
.probe = imx_ssi_probe,
.remove = imx_ssi_remove,
.driver = {
.name = "imx-ssi",
.owner = THIS_MODULE,
},
};
module_platform_driver(imx_ssi_driver);
同样,特定于板的初始化将需要调用platform_device_add
或platform_add_devices
来添加平台设备,在名称匹配的情况下,这些设备完全是在C中静态创建的(名称在C中给出, IRQ和基地址等资源。)。
答案 1 :(得分:2)
在Linux内核中有不同的总线(SPI,I2C,PCI,USB,......)。
每条总线都有公交车上注册的驱动程序和设备列表。
每次将新设备或新驱动程序连接到总线时,都会启动匹配循环。
假设您注册了一个新的SPI设备。 SPI总线启动匹配循环,调用SPI匹配功能来验证您的设备是否与已在总线上注册的驱动程序匹配。如果不匹配,则无事可做。
现在,假设您注册了一个新的SPI驱动程序。总线再次启动匹配循环,以验证是否有任何已注册的设备与此新驱动程序匹配。如果匹配,则调用驱动程序probe()
。
每个总线都有自己的方法来匹配驱动程序和设备。为了实现总线,您必须编写匹配函数。因此,您可以实现一个按名称,整数值或任何您想要的匹配的总线。
每次注册驱动程序或设备时都会启动总线机制。
这是我实施ZIO bus的方式。 在这里你可以找到SPI bus 这是bus system
的核心