【问题标题】:max732x.c I2C IO Expander + GPIO Keys w/ Linux Device Tree not working带 Linux 设备树的 max732x.c I2C IO 扩展器 + GPIO 键不工作
【发布时间】:2014-10-31 03:23:52
【问题描述】:

我正在使用飞思卡尔 MX6 和飞思卡尔 3.10.31 修改内核。我有一个用作 IO 扩展器的 Maxim MAX7325,它的按钮连接到 P0-P2。 7325 的中断线连接到 GPIO_3 焊盘(我相信是 GPIO1_3...)

我在设备树中设置了 7325 和 gpio-keys,如下所示:

max7325_reset: max7325-reset {
  compatible = "gpio-reset";
  reset-gpios = <&gpio5 16 GPIO_ACTIVE_LOW>;
  reset-delay-us = <1>;
  #reset-cells = <0>;
};


gpio-keys {
  compatible = "gpio-keys";

  sw2 {
     gpios = <&max7325 2 GPIO_ACTIVE_LOW>;
     linux,code = <30>;    //a
     gpio-key,wakeup;
  };
};

&i2c1 {
   clock-frequency = <100000>;
   pinctrl-names = "default";
   pinctrl-0 = <&pinctrl_i2c1_2>;
   status = "okay";

   max7325: gpio@68 {
      compatible = "maxim,max7325";
      reg = <0x68>;
      gpio-controller;
      #gpio-cells = <2>;
      resets = <&max7325_reset>;

      gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
      interrupt-parent = <&gpio1>;
      interrupts = <3 2>;
   };
};

似乎发生的情况是当调用 MAX7325 驱动程序的探针时,client->dev.platform_data 为 NULL。正因为如此,稍后调用 max732x_irq_setup 时,它并没有设置 chip->gpio_chip.to_irq 指针指向 max732x_gpio_to_irq 函数(可能是因为它没有正确的信息来使其工作。)后来,当 gpio_keys 尝试配置第一个输入,当它尝试设置中断并且没有设置其他键时失败。

gpio-keys gpio-keys.20: Unable to get irq number for GPIO 242, error -6

我确实确定使用 P0 映射到 GPIO 240 的 /sys 接口,所以是的,GPIO 242 是我尝试设置的 sw2 GPIO-KEY。

我想知道,这个驱动程序不适用于设备树吗?我没有看到它试图获取任何设备树属性,但我查看的其他 IO 扩展器驱动程序也没有,所以我认为 I2C 内核可能正在读取设备树并应该以某种方式从那里填写 platform_data它调用驱动程序的探测函数(?)

我在这方面还很陌生,所以任何帮助都将不胜感激。 =) 我确实在线阅读了一些设备树文档,但我认为这是相当具体的事情,我没有正确执行,他们没有涵盖......(?)

我确实在内核中配置了 CONFIG_GPIO_MAX732X_IRQ...我曾尝试为 max7325 I2c1 节点设置中断控制器属性,但我不确定是否需要(?)

【问题讨论】:

    标签: linux-device-driver gpio device-tree max732x.c


    【解决方案1】:

    MAX732x 设备树支持

    您正在使用的驱动程序无法处理设备树中的数据。我已向该驱动程序添加了设备树支持并将其发送到内核邮件列表以供审查,但它们尚未合并。见this thread(共4个补丁):

    您可以将这些补丁应用到您的分支或等待它们进入上游内核,然后从那里挑选它们(进入您的分支)。

    绑定文档(参见上面的补丁)展示了如何为 MAX732x 创建设备树声明。在您的情况下,它可能如下所示:

    &i2c1 {
        expander: max7325@68 {
            compatible = "maxim,max7325";
            reg = <0x68>;
            gpio-controller;
            #gpio-cells = <2>;
            interrupt-controller;
            #interrupt-cells = <2>;
            interrupt-parent = <&gpio1>;
            interrupts = <3 2>;
        };
    };
    

    您使用此驱动程序的另一种方法(没有上面的补丁)是在板文件中为您的板指定平台数据。我相信它应该是下一个文件之一:

    • arch/arm/mach-imx/mach-imx6q.c
    • arch/arm/mach-imx/mach-imx6sl.c
    • arch/arm/mach-imx/mach-imx6sx.c

    您可以在此处找到如何执行此操作的示例:arch/arm/mach-pxa/littleton.c,第 394 行。

    但这可能不是可靠的方法:我尝试这样做并且在 i2c 总线编号方面遇到了一些问题(虽然看起来不太像)。在板文件和 dts 文件之间分散设备定义看起来也很糟糕。所以我强烈推荐你使用上面的补丁。

    问题解答

    似乎发生的情况是当调用 MAX7325 驱动程序的探针时,client->dev.platform_data 为 NULL。

    发生这种情况是因为驱动程序绑定了来自设备树文件而不是来自板文件的设备声明。在这种情况下,驱动程序应该使用 client->dev.of_node 而不是 client->dev.platform_data。看看我上面的补丁是怎么做的。

    您可以在此处阅读内核文档中有关绑定/匹配/实例化如何发生的更多信息:

    • 文档/i2c/instantiating-devices
    • 文档/devicetree/usage-model.txt

    我想也许 I2C 内核正在读取设备树并应该在调用驱动程序的探测函数之前从那里以某种方式填充 platform_data (?)

    没有。发生绑定时,client->irq 会自动填充到 I2C 内核中(在调用驱动程序的探测函数之前)。 gpio_baseirq_base 等属性——如果数据来自设备树,则不需要它们。

    我曾尝试为 max7325 I2c1 节点设置中断控制器属性,但我不确定是否需要这样做 (?)

    当 MAX7325 检测到输入线路上的变化时(更具体地说,在配置为输入的开漏 I/O 端口上),它会向您的 SoC 发出中断。 因此,如果您希望您的驱动程序为每个输入 I/O 线生成单独的中断(以便其他驱动程序可以使用它们),您应该指定“interrupt-controller”和“#interrupt-cells”属性。但为此,您需要应用上述所有补丁。

    补丁状态

    现在所有提到的补丁都被合并到上游内核(v4.0 及更高版本):

    1. gpio: max732x: Add device tree support
    2. gpio: max732x: Rewrite IRQ code to use irq_domain API
    3. gpio: max732x: Fix possible deadlock
    4. gpio: max732x: Add DT binding documentation

    另外请注意,在我的补丁之上制作了一些新补丁。你可以看他们here

    【讨论】:

    • 这些更改是否已进入内核?如果是这样,你能告诉我他们登陆的是哪个版本吗?如果没有,你有补丁吗?lkml.org/lkml/2015/1/13/305 不让我下载补丁?
    • @chrisdew 我在回答末尾添加了“补丁状态”部分,回答您的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 2020-07-06
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    相关资源
    最近更新 更多