chrisdew chrisdew - 1 month ago 10
C Question

I've added a MAX7320 i2c output chip. How can I get the kernel to load the driver for it?

I've added a MAX7320 i2c expander chip to i2c bus 0 on my ARM Linux board.

The chip works correctly from userspace with commands such as

/usr/sbin/i2cset -y 0 0x5d 0x02
and
/usr/sbin/i2cget -y 0 0x5d
.

There is a
drivers/gpio/gpio-max732x.c
file in the kernel source, which is compiled into the kernel that I'm running. (I've built it from source.)

How do I tell the kernel that it should instantiate the gpio-max732x driver on "i2c bus 0, chip id 0x5d"?

Do I need to modify the device tree
.dts
file and put a new
.dtb
file in
/boot/dtbs/
?

What would the clause for instantiating a
gpio-max732x
module look like?

P.S. I've seen https://lkml.org/lkml/2015/1/13/305 but I can't figure out how to get the patch files.

Answer

Device Tree

There must be appropriate Device Tree definition for your chip, in order for driver to instantiate. There are 2 ways to do so:

  1. Modify .dts Device Tree file for your board (look in arch/arm/boot/dts/), then recompile it and re-flash it to your device.

    This way is preferred in case when you have access you kernel sources for your board and you are able to re-flash .dtb file to your device.

  2. Create Device Tree Overlay file, compile it and load it on your device.

    This way is preferred when you don't have access to kernel sources for your board, or you are unable to flash new device tree blob to your device.

Your device definition in Device Tree should look like (according to Documentation/devicetree/bindings/gpio/gpio-max732x.txt):

&i2c0 {
    expander: max7320@5d {
        compatible = "maxim,max7320";
        reg = <0x5d>;
        gpio-controller;
        #gpio-cells = <2>;
    };
};

Kernel configuration

As your expander chip (MAX7320) has no input GPIOs, you don't need IRQ support for MAX732x. So you can disable CONFIG_GPIO_MAX732X_IRQ in your kernel configuration.

Matching device with driver

Once you have your Device Tree loaded (with definition for MAX7320), MAX732x driver will be matched with device definition, and instantiated. Below is explained how matching happens.

In Device Tree file you have compatible property:

compatible = "maxim,max7320";

In MAX732x driver you can see this table:

static const struct of_device_id max732x_of_table[] = {
    ...
    { .compatible = "maxim,max7320" },
    ...

When driver is being loaded, and when Device Tree blob is being loaded, kernel tries to find the match for each driver and Device Tree definition. Just by comparing strings above. If strings are matched -- kernel instantiates driver, passing corresponding device parameters to it. Look at i2c_device_match() function for details.

Obtaining patches

The best way is to use kernel sources that already have Device Tree support of MAX732x (v4.2+). But if it's not the case, then...

You can cherry-pick patches from upstream kernel to your kernel:

$ git remote add upstream git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ git fetch --all
$ git cherry-pick 43c4bcf9425e
$ git cherry-pick 479f8a5744d8
$ git cherry-pick 09afa276d52e
$ git cherry-pick 996bd13f28e6

And if you still want to apply patches manually (worst option, actually), here you can find direct links to patches. Click (patch) link to get a raw patch.

Hardware concerns

To be sure that your chip has 0x5d I2C address, check that configuration pins are tied to next lines (as per datasheet):

Pin    Line
-----------
AD2     V+
AD0     V+
Comments