Search code examples
linuxarmembedded-linuxgpiodevice-tree

How to set value of i2c PCA9570 gpio expander as early as possible during Linux boot?


I have written a working driver for the PCA9570. Its four outputs are set (and read back) via Linux's GPIO subsystem. e.g.

root@armbox:/sys/class/gpio# echo 508 > export
root@armbox:/sys/class/gpio# echo 509 > export
root@armbox:/sys/class/gpio# echo 510 > export
root@armbox:/sys/class/gpio# echo 511 > export

The problem is that the chip starts with its outputs high. https://www.nxp.com/docs/en/data-sheet/PCA9570.pdf section 8.1.

root@armbox:/sys/class/gpio# cat gpio508/value 
1
root@armbox:/sys/class/gpio# cat gpio509/value 
1
root@armbox:/sys/class/gpio# cat gpio510/value 
1
root@armbox:/sys/class/gpio# cat gpio511/value 
1

I can manually set them low from userspace, after boot. e.g.

root@armbox:/sys/class/gpio# echo 0 > gpio510/value 
root@armbox:/sys/class/gpio# cat gpio510/value 
0

How can I set the chip's outputs low as early as possible during the boot sequence?

I can hack my own driver to do this, during pca9570_probe(), but that feels very hacky. pca9570_probe() currently reads the values from the chip.

static int pca9570_probe(struct i2c_client *client,
                   const struct i2c_device_id *id)
{
    ...

    ret = pca9570_readb(chip, &chip->reg);
    if (ret)
        goto out_failed;

    return 0;

out_failed:
    if (chip->client)
        i2c_unregister_device(chip->client);

    return -1;
}

Is there a correct way in Linux to specify GPIO values during boot, rather than hacking a driver?

P.S. The dts clause is:

            pca9570: pca9570@48 {
                            compatible = "pca9570";
                            reg = <0x24>;
                            gpio-controller;
                            #gpio-cells = <4>;
            };

Solution

  • You can use 'GPIO hogging' mechanism as described in DeviceTree gpio binding documentation. Quoting basic information:

    GPIO hogging is a mechanism providing automatic GPIO request and configuration as part of the gpio-controller's driver probe function.

    For example, we have this definition in our device tree for our gpio expander:

    gpio_expander: tca6424a@22 {
            compatible = "ti,tca6424";
            reg = <0x22>;
            [...] /* some other gpio expander configuration */
    
            lcd-rst {
                    gpio-hog;
                    gpios = <7 GPIO_ACTIVE_LOW>;
                    output-low;
            };
    };
    

    You don't need to extend your driver, it is part of the gpio subsystem.