2
votes

I'm working with a Freescale MX6 and a 3.10.31 Freescale modified kernel. I have a Maxim MAX7325 used as an IO expander, which has pushbuttons attached to P0-P2. The interrupt line from the 7325 is attached to the GPIO_3 pad (which I believe is GPIO1_3...)

I set up the 7325 and gpio-keys in the device tree like this:

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;
  };
};

and

&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>;
   };
};

What appears to happen is when probe for the MAX7325 driver is called, client->dev.platform_data is NULL. Because of this, when max732x_irq_setup is called later, it doesn't set up the chip->gpio_chip.to_irq pointer to point at max732x_gpio_to_irq function (presumably because it doesn't have the right info for this to work.) Later, when gpio_keys tries to config the first input, it fails when it tries to set up the interrupt and none of the other keys get set up.

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

I did determine using the /sys interface that P0 maps to GPIO 240, so yeah, GPIO 242 is the sw2 GPIO-KEY I was trying to set up.

I'm wondering, does this driver not work with a device tree? I don't see it trying to get any device tree properties, but other IO expander drivers I looked at didn't either, so I thought maybe the I2C core is reading the device tree and supposed to fill in the platform_data from there somehow before it calls the driver's probe function (?)

I'm fairly new at this, so any help would be appreciated. =) I did read a few of the Device Tree docs online, but I'm thinking this is something fairly specific that I'm not doing correctly, which they don't cover... (?)

I do have CONFIG_GPIO_MAX732X_IRQ configured in the kernel... and I did at one point try setting the interrupt-controller property for the max7325 I2c1 node, but I wasn't sure that was needed (?)

1

1 Answers

5
votes

MAX732x device tree support

Driver you are using won't work with data from device tree. I have added device tree support to this driver and sent it to kernel mailing lists for review, but they are not merged yet. See this thread (total 4 patches):

You can either apply those patches to your branch or wait for them to get into upstream kernel and then cherry-pick them from there (into your branch).

Bindings documentation (see patches above) shows how to create device tree declaration for MAX732x. In your case it may look like this:

&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>;
    };
};

Another way for you to use this driver (without patches above) is to specify platform data in board file for your board. I believe it should be one of next files:

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

You can find an example how to do so here: arch/arm/mach-pxa/littleton.c, line 394.

But it may be not reliable way: I tried to do so and had some issues with i2c buses numbers (didn't look too much in that way though). It also looks bad to scatter devices' definitions between board file and dts file. So I strongly recommend you to use patches above.

Answers to questions

What appears to happen is when probe for the MAX7325 driver is called, client->dev.platform_data is NULL.

It happens because driver was binded with device declaration from device tree file rather than from board file. In that case driver should use client->dev.of_node instead of client->dev.platform_data. Just see how it's done in my patch above.

You can read more about how binding/matching/instantiating happens in kernel documentation here:

  • Documentation/i2c/instantiating-devices
  • Documentation/devicetree/usage-model.txt

I thought maybe the I2C core is reading the device tree and supposed to fill in the platform_data from there somehow before it calls the driver's probe function (?)

No. When binding is happening, client->irq being automatically populated in I2C core (before driver's probe function being called). Properties like gpio_base and irq_base -- you don't need them in case when data came from device tree.

I did at one point try setting the interrupt-controller property for the max7325 I2c1 node, but I wasn't sure that was needed (?)

MAX7325 issues interrupt to your SoC when it detects changes on input lines (more specifically, on open-drain I/O ports configured as inputs). So if you want your driver to generate separate interrupts for each input I/O line (so that other drivers can consume them), you should specify "interrupt-controller" and "#interrupt-cells" properties. But for this you need all patches mentioned above to be applied.

Patches status

Now all mentioned patches were merged into upstream kernel (v4.0 and later):

  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

Also notice that there are some new patches were made on top of my patches. You can watch them here.