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

Device Tree dependency between two nodes

我有两个设备树节点,一个设置一个 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>;
  };
};

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

简答

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

节点关系

Device trees II: The harder parts LWN 文章所述:

Naturally, in each case the device which provides the interrupt or GPIO will need to be initialized before it can be found and used. It wasn't very many kernel versions ago that this was a real problem. However in the 3.4 kernel, drivers gained the ability for their initialization (or probe) routine to return the error EPROBE_DEFER which would cause the initialization to be tried again later. So if a driver finds that a GPIO line is listed in the devicetree, but no driver has registered GPIOs for the target node yet, it can fail with EPROBE_DEFER and know it can try again later. This can even be used to remove the need for callbacks and delayed registration in board files, but it is really essential for devicetree, and happily it works quite well.

唉,在你的情况下,可能无法指定节点之间的依赖关系,因此你的 i2c1gpiom1 取决于 gpio2。至少我在 Documentation/devicetree/bindings/ 中没有看到任何 I2C 控制器或 GPIO 控制器的 gpios 属性可用于引用您的 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 文件加载到 user-space 中,这完全取决于它们的加载顺序,用户必须在 rootfs 中处理它。通常 GPIO 和 I2C 控制器驱动程序是内置的,因此无需进一步讨论,仅供参考,here is 如何为 modprobe 工具定义顺序。

内核配置

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

  • CONFIG_GPIO_OMAP=y
  • CONFIG_I2C_OMAP=y

在那种情况下,两个驱动程序都是内置的,我们知道 GPIO 驱动程序比 I2C 驱动程序具有更早的 initcall。

GPIO 占用

您将 pin 声明为 gpio-hog,这是正确的做法。您可能已经知道它的含义,但我会在此处为其他感兴趣的人参考解释。来自 Documentation/devicetree/bindings/gpio/gpio.txt:

The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism providing automatic GPIO request and configuration as part of the gpio-controller's driver probe function.

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