[i.MX8M Plus] Config an i2c io-expansion device and set one pin to leds-gpio

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

[i.MX8M Plus] Config an i2c io-expansion device and set one pin to leds-gpio

Jump to solution
4,902 Views
sophiehu
Contributor III

Hi NXP,

We have a custom board with i2c io-expansion PCAL6408. There are 8 gpios. I config it in dts and all the gpios work well.

&i2c3 {
    clock-frequency = <400000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c3>;
    status = "okay"

    pcal6408: pcal6408@20 {
    compatible = "nxp,pcal6408";
    reg = <0x20>;
    gpio-controller;
    #gpio-cells = <2>;
};

We connect one gpio to led and wish to config the gpio as led. Is it possible?

I try to config like this:

&i2c3 {
    clock-frequency = <400000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c3>;
    status = "okay"

    pcal6408: pcal6408@20 {
        compatible = "nxp,pcal6408";
        reg = <0x20>;
        gpio-controller;
        #gpio-cells = <2>;

        pwr_led: led@6 {
            label = "green:pwr";
            gpios = <6 GPIO_ACTIVE_HIGH>;
            default-state = "on";
        };
    };
};

It shows error:

[ 0.071647] OF: /soc@0/bus@30800000/i2c@30a40000/pcal6408@20/led@4: could not get #gpio-cells for /soc@0/bus@30000000/efuse@30350000/speed-grade@10
[ 0.071700] OF: /soc@0/bus@30800000/i2c@30a40000/pcal6408@20/led@5: could not get #gpio-cells for /cpus/l2-cache0
[ 0.071738] OF: /soc@0/bus@30800000/i2c@30a40000/pcal6408@20/led@6: could not get #gpio-cells for /cpus/idle-states/cpu-pd-wait
[ 0.071777] OF: /soc@0/bus@30800000/i2c@30a40000/pcal6408@20/led@7: could not get #gpio-cells for /soc@0/bus@30800000/i2c@30a20000/pmic@25/regulators/BUCK2

I also try this:

/ {
    leds {
      compatible = "gpio-leds";
        pwr_led {
          label = "pwr";
          gpios = <&pcal6408 6 GPIO_ACTIVE_HIGH>;
          default-state = "on";
      };
};

It compiles error:

ERROR (phandle_references): /leds/wifi_led: Reference to non-existent node or label "pcal6408"

Would you give me some suggestion?
Thank you.

Best Regards,

Sophie

0 Kudos
Reply
1 Solution
4,843 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

Hello @sophiehu 

The orignal pcaxxx driver can only support common gpio control, it can't support embed led driver. You can use libgpio to control in/out, high/low in userspace.

 

https://stackoverflow.com/questions/66106568/how-to-programmatically-use-gpio-expander-driver-in-lin...

View solution in original post

0 Kudos
Reply
6 Replies
4,885 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

Hello @sophiehu 

Please refer the kernel docuement to config dts node: Documentation/devicetree/bindings/gpio/gpio-pca95xx.yaml The gpio-hog and gpios is required.

 

patternProperties:
  "^(hog-[0-9]+|.+-hog(-[0-9]+)?)$":
    type: object
    properties:
      gpio-hog: true
      gpios: true
      input: true
      output-high: true
      output-low: true
      line-name: true

    required:
      - gpio-hog
      - gpios

    additionalProperties: false

 

0 Kudos
Reply
4,876 Views
sophiehu
Contributor III

Hi Qmiller,

I moldify dts like this:
pcal6408: pcal6408@20 {
    compatible = "nxp,pcal6408";
    reg = <0x20>;
    gpio-controller;
    #gpio-cells = <2>;
    pwr_led {
        compatible = "gpio-leds";
        label = "green:pwr";
        gpio-hog;
        gpios = <6 GPIO_ACTIVE_HIGH>;
        output-high;
        default-state = "on";
    };
};

It will be set to gpio not led. The kernel log:
[ 2.161174] gpio-509 (wifi_led): hogged as output/low
The gpioinfo:
gpiochip5 - 8 lines:
line 0: unnamed unused input active-high
line 1: unnamed unused input active-high
line 2: unnamed unused input active-high
line 3: unnamed unused input active-high
line 4: unnamed unused input active-high
line 5: unnamed unused input active-high
line 6: unnamed "pwr_led" output active-high [used]
line 7: unnamed unused input active-high

It cannot be a "led" in /sys/class/led and control it like a led. Would you give me some succestion?
Thank you.

Best Regards,
Sophie

0 Kudos
Reply
4,862 Views
sophiehu
Contributor III

Hi Qmiller,

Any updated?
I also try to set dts like this:

&i2c3 {
    pcal6408: pcal6408@20 {
        compatible = "nxp,pcal6408";
        reg = <0x20>;
        gpio-controller;
        #gpio-cells = <2>;
        leds {
            compatible = "gpio-leds";
            led0: led0 {
                gpios = <&pcal6408 0 GPIO_ACTIVE_HIGH>;
                label = "pcal6408:led0";
            };
            led1: led1 {
                gpios = <&pcal6408 1 GPIO_ACTIVE_HIGH>;
                label = "pcal6408:led1";
            };
        };
    };
};

And it still not works. I add some debug message in drivers/leds/leds_gpio.c and it fail in calling device_get_child_node_count of gpio_leds_create of gpio_led_probe.

[    1.682012] gpio_led_probe
[    1.684745] gpio_leds_create
[    1.687639] gpio_leds_create: device_get_child_node_count 1
[    1.693235] gpio_leds_create: devm_fwnode_get_gpiod_from_child fail
[    1.699512] gpio_led_probe: gpio_leds_create fail

[    2.099153] nxp-pca9450 0-0025: pca9450bc probed.
[    2.157122] pca953x 2-0020: using no AI

Best Regards,
Sophie

0 Kudos
Reply
4,844 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

Hello @sophiehu 

The orignal pcaxxx driver can only support common gpio control, it can't support embed led driver. You can use libgpio to control in/out, high/low in userspace.

 

https://stackoverflow.com/questions/66106568/how-to-programmatically-use-gpio-expander-driver-in-lin...

0 Kudos
Reply
4,835 Views
sophiehu
Contributor III

Hi @Zhiming_Liu ,

Thank you.

Since I cannot config pca6408 gpio as led device by gpio-pca953x driver and leds-gpio driver, how about leds-pca* driver? I see some leds-pca* drivers in kernel/drivers/leds/, such as leds-pca9532.c, leds-pca955x.c and leds-pca963x.c. Is there any leds-pca* driver compatible with pcal6408 just like gpio-pca953x driver?

I have tried to insert pcal6408 in leds-pca9532.c 

enum {
    ...
    pcal6408,
};

static const struct i2c_device_id pca9532_id[] = {
    ...
    { "pcal6408", pcal6408 },
    { }
};

static const struct pca9532_chip_info pca9532_chip_info_tbl[] = {
    ...
    [pcal6408] = {
        .num_leds = 8,
    },
};
static const struct of_device_id of_pca9532_leds_match[] = {
    ...
    { .compatible = "nxp,pcal6408", .data = (void *)pcal6408 },
    {},
};

And also leds-pca955x.c

enum pca955x_type {
   ...
    pcal6408,
};

static struct pca955x_chipdef pca955x_chipdefs[] = {
   ...
    [pcal6408] = {
        .bits = 8,
        .slv_addr = 0x20,
        .slv_addr_shift = 3,
    },
};

static const struct i2c_device_id pca955x_id[] = {
   ...
    { "pcal6408", pcal6408 },
    { }
};
static const struct of_device_id of_pca955x_match[] = {
   ...
    { .compatible = "nxp,pcal6408", .data = (void *)pcal6408 },
    {},
};

But they don't work.

0 Kudos
Reply
4,823 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

Hello @sophiehu 

It's possible to porting pca6408 refering these  leds-pca9xxx driver. But you can't just add such codes in original driver and change the register definition. The codes is designed to probe led drivers(pca95xx), this means some structure members in these driver is not suitable for pca6408. Conclusion is that you need write a new led-xxx driver for pca6408 refering these leds-pca9xxx driver.

Here is the pca6408 spec:

https://www.nxp.com.cn/docs/en/data-sheet/PCAL6408A.pdf

0 Kudos
Reply