两个节点之间的设备树依赖关系

Mih*_*Pop 3 linux-device-driver linux-kernel device-tree

我有两个设备树节点,一个设置 GPIO 引脚,另一个配置一个 i2c 总线,例如:

&gpio2 {
  en-gpio {
    gpio-hog;
    gpios = <5 0>;
    output-high;
  };
};

&i2c1 {
  gpiom1: gpio@27 {
    compatible = "microchip,mcp23008";
    gpio-controller;
    #gpio-cells = <2>;
    reg = <0x27>;
  };
};
Run Code Online (Sandbox Code Playgroud)

如何在 i2c 节点和 GPIO 节点之间添加依赖关系?我想要实现的是,应该在初始化 i2c 上的设备之前设置 GPIO 引脚。

Sam*_*nko 8

简短回答

在这种情况下,您无法提供节点之间的依赖关系。但很可能在您的情况下已经考虑了正确的顺序,并且 GPIO 引脚将在 I2C 设备初始化之前设置,这要归功于早期用于 GPIO 控制器驱动程序的 initcall,并且因为gpio-hog使用了。如果您想检查一下您的平台以确定 - 以下是详细信息。

节点关系

如设备树 II:较难的部分LWN 文章中所述:

当然,在每种情况下,提供中断或 GPIO 的设备都需要在被发现和使用之前进行初始化。在没有很多内核版本之前,这是一个真正的问题。probe然而,在 3.4 内核中,驱动程序获得了其初始化(或)例程返回错误的能力EPROBE_DEFER,这将导致稍后再次尝试初始化。因此,如果驱动程序发现设备树中列出了 GPIO 线,但还没有驱动程序为目标节点注册 GPIO,则它可能会失败EPROBE_DEFER并知道可以稍后重试。这甚至可以用来消除对回调和板文件中延迟注册的需要,但这对于 devicetree 来说确实很重要,而且令人高兴的是它工作得很好。

唉,在您的情况下,可能无法指定节点之间的依赖关系,因此您的i2c1orgpiom1依赖于gpio2. 至少我gpios在 中没有看到任何Documentation/devicetree/bindings/可用于引用您的en-gpio. 所以看来你应该依赖驱动程序的加载顺序。

驱动程序依赖

驱动程序之间有两种可能的依赖关系:

  1. 如果驱动程序是内置的(在内核映像内部):驱动程序可以在不同的initcalls中初始化,从而以正确的顺序加载
  2. 如果驱动程序可加载.ko文件):驱动程序可以具有在内核构建系统中定义的依赖项

由于您没有提及您的平台,让我们看看它如何使用 BeagleBone Black board 来工作。您可以使用它作为模板来了解它在您的平台上是如何完成的。

静态依赖

让我们检查一下驱动程序的初始化顺序:

  1. am33xx-l4.dtsi文件中我们可以看到:
    • GPIO 控制器:compatible = "ti,omap4-gpio"
    • I2C控制器:compatible = "ti,omap4-i2c"
    • I2C设备:compatible = "microchip,mcp23008"
  2. 这些兼容字符串的相应驱动程序是:
    • GPIO 控制器:drivers/gpio/gpio-omap.c
    • I2C控制器:drivers/i2c/busses/i2c-omap.c
    • I2C设备:drivers/pinctrl/pinctrl-mcp23s08.c
  3. 这些驱动程序在下一个 initcalls 上初始化:
    • GPIO 控制器:postcore_initcall(=2)
    • I2C 控制器:subsys_initcall(=4)
    • I2C 设备:subsys_initcall(=4)

因此 GPIO 控制器驱动程序将在 I2C 驱动程序之前初始化。

动态依赖

那么动态依赖呢?从相应的MakefileKconfig文件中我们可以看到配置选项和依赖项:

  • GPIO 控制器:CONFIG_GPIO_OMAP,三态,不依赖于 I2C 东西
  • I2C 控制器:CONFIG_I2C_OMA三态,不依赖于 GPIO 的东西
  • I2C设备:CONFIG_PINCTRL_MCP23S08,三态,取决于I2C

因此,如果驱动程序作为文件加载到用户空间.ko,则完全取决于加载顺序,用户必须在 rootfs 中处理它。通常 GPIO 和 I2C 控制器驱动程序是内置的,因此无需进一步讨论,仅供参考,以下是工具的顺序定义方式modprobe

内核配置

要检查驱动程序是如何构建的(内置的或可加载的),可以检查.config文件。例如,如果multi_v7_defconfig使用:

  • CONFIG_GPIO_OMAP=y
  • CONFIG_I2C_OMAP=y

在这种情况下,两个驱动程序都是内置的,并且我们知道 GPIO 驱动程序的 initcall 早于 I2C 驱动程序。

GPIO 占用

通过将您的 PIN 声明为 ,您做了正确的事情gpio-hog。您可能已经知道它的含义,但我会为其他感兴趣的人参考此处的解释。来自Documentation/devicetree/bindings/gpio/gpio.txt

GPIO 芯片可能包含 GPIO hog 定义。GPIO 占用是一种提供自动 GPIO 请求和配置的机制,作为 GPIO 控制器驱动程序探测功能的一部分

所以这是你能尽早得到的。如果您的 GPIO 控制器驱动程序是内置的,并且 initcall 编号小于 I2C 驱动程序的 1,您可以认为您的en-gpio引脚将在 I2C 设备驱动程序初始化之前设置。