5

我正在阅读围绕总线、设备和驱动程序构建的 Linux 设备模型。我能够了解一些关于设备和驱动程序匹配是如何发生的,但不清楚总线在这里的作用,总线如何与设备匹配。

我对平台设备的名称从何而来还有一个疑问。

“平台总线,只是将每个设备的名称与每个驱动程序的名称进行比较;如果它们相同,则设备与驱动程序匹配。”

现在我无法真正理解上述观点。我相信设备名称首先在 dts 文件中定义,然后在平台驱动程序代码中定义相应的驱动程序名称。

如果这两个名称匹配,则从驱动程序代码中调用探针,这将确认设备确实存在。

任何人都可以从巴士的角度让我知道整个过程。

4

2 回答 2

17

为了补充@Federico 的回答,它很好地描述了一般情况,平台设备可以使用四个东西(优先级)与平台驱动程序匹配。这是平台“总线”的匹配功能:

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风格搭配

使用设备树 ( ) 进行匹配of_driver_match_device。如果您还不了解设备树的概念,请阅读它。在这种数据结构中,每个设备在代表系统的树中都有自己的节点。每个设备还有一个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. 将探测任何声明相同兼容字符串的已注册平台驱动程序。这是它的驱动程序

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_addor platform_add_devices,在这种情况下,在 OF 函数的帮助下扫描树。

名称匹配

如果您查看platform_match,您将看到匹配回退到名称匹配。在驱动程序名称和设备名称之间进行简单的字符串比较。这就是旧平台驱动程序的工作方式。他们中的一些人仍然这样做,就像这里的这个:

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_addplatform_add_devices添加平台设备,在名称匹配的情况下,这些设备完全在 C 中静态创建(名称在 C 中给出,资源如 IRQ 和基地址等)。

于 2013-10-08T16:03:07.843 回答
3

在 Linux 内核中有不同的总线(SPI、I2C、PCI、USB,...)。

每条总线都有在总线上注册的驱动程序和设备的列表。

每次将新设备或新驱动程序连接到总线时,它都会启动匹配循环。

假设您注册了一个新的 SPI 设备。SPI 总线启动一个匹配循环,它调用 SPI 匹配函数来验证您的设备是否与已在总线上注册的驱动程序匹配。如果不匹配,则无事可做。

现在,假设您注册了一个新的 SPI 驱动程序。总线再次启动匹配循环,以验证是否有任何已注册设备与此新驱动程序匹配。如果匹配,probe()则调用驱动程序函数。

每条总线都有自己的方法来匹配驱动程序和设备。为了实现总线,您必须编写匹配函数。因此,您可以实现按名称、整数值或您想要的任何内容匹配的总线。

每次注册驱动程序或设备时,都会启动总线机制。

这里我是如何实现ZIO 总线的。在这里可以找到SPI 总线 这里是总线系统的核心

于 2013-10-08T13:23:07.520 回答