How to use Linux kernel to control LEDs connected to GPIOs on Colibri i.MX6?

We would like to control LEDs connected to GPIOs on Colibri i.MX6 using LED support in Linux kernel. Unfortunately the kernel does not export LEDs via sysfs API (/sys/class/leds/) while the device tree seems to parsed correctly.

Related part of DTS file:

/dts-v1/;

#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include "imx6dl.dtsi"
#include "imx6qdl-colibri.dtsi"

/ {
	...

	leds {
		compatible = "gpio-leds";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_gpio_leds>;

		led0: heartbeat {
			label = "heartbeat";
			gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
			default-state = "off";
			linux,default-trigger = "heartbeat";
		};		
	};
};

...

&iomuxc {
	imx6dl-colibri {
		pinctrl_gpio_leds: gpio_leds {
			fsl,pins = <
				MX6QDL_PAD_GPIO_2__GPIO1_IO02			PAD_CTRL_HYS_PD		/* heartbeat */
			>;
		};
	};
};

...

Related kernel configuration:

root@colibri-imx6:~# zcat /proc/config.gz | grep LEDS | grep -v "not set"
CONFIG_RFKILL_LEDS=y
CONFIG_RT2X00_LIB_LEDS=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_GPIO=y

Device tree is parsed correctly (as far as I can tell):

root@colibri-imx6:/proc/device-tree/leds# ls -l
-r--r--r--    1 root     root            10 Jan 15 14:34 compatible
dr-xr-xr-x    2 root     root             0 Jan 15 14:34 heartbeat
-r--r--r--    1 root     root             5 Jan 15 14:34 name
-r--r--r--    1 root     root             4 Jan 15 14:34 pinctrl-0
-r--r--r--    1 root     root             8 Jan 15 14:34 pinctrl-names
root@colibri-imx6:/proc/device-tree/leds# ls -l heartbeat/
-r--r--r--    1 root     root             4 Jan 15 14:34 default-state
-r--r--r--    1 root     root            12 Jan 15 14:34 gpios
-r--r--r--    1 root     root            10 Jan 15 14:34 label
-r--r--r--    1 root     root            10 Jan 15 14:34 linux,default-trigger
-r--r--r--    1 root     root            10 Jan 15 14:34 name
root@colibri-imx6:/proc/device-tree/leds# echo $(cat compatible)
gpio-leds

But the /sys/class/leds/ directory is missing expected folder (heartbeat). There is only mmc0::, which I suppose comes from MMC driver:

root@colibri-imx6:/sys/class/leds# ls -l
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mmc0:: -> ../../devices/soc0/soc.0/2100000.aips-bus/2198000.usdhc/leds/mmc0::

There is nothing related to LEDs, GPIOs, etc, in the dmesg, so I really have no idea why the kernel did not export control directory for the LED.

If you know what is wrong with the configuration, please tell me.

Thanks

If you started with our default device tree then resp. pin will already be claimed for regular GPIO use:

imx6dl-colibri-eval-v3.dts
...
&iomuxc {
        /*
         * Mux all pins which are unused to be GPIOs
         * so they are ready for export to user space
         */
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_weim_gpio_1 &pinctrl_weim_gpio_2
                     &pinctrl_weim_gpio_3 &pinctrl_weim_gpio_4
...

So you will have to remove it from there first.

A good working example for LEDs use would be our Apalis iMX6 on Ixora combination e.g. have a look at imx6qdl-apalis-ixora.dtsi for reference.

You found a bug in our kernel. The regression happened when we backported the extcon subsystem which we need to switch the USB host/gadget role on the Colibri USBC port.

This patch made the gpio-leds work for me again. Likely we will have to do additional stuff to resolve the issue cleanly.

I opened an internal ticket how we want to handle ‘big’ comments in the future. Feel free to create an answer to workaround such limitations.

@max.krummenacher
Thanks for the patch, it fixed the issue for us.

Since you are talking about fixing it cleanly, is there something I should be aware of right now?

No.
I’m just not through with finding other places were the same bug kicks in.
I already know of drivers/of/pdt.c (unused in probably all sensible configurations for a i.MX6 module), maybe there are others.

Yes, I started with imx6dl-colibri-eval-v3.dts file, but I removed pinctrl for unused GPIOs. I just tried to add default pinctrl to see if the pin conflict would be reported in dmesg as I assume, and it does fail with errors:

[    1.552925] imx6dl-pinctrl 20e0000.iomuxc: pin MX6DL_PAD_GPIO_2 already requested by 20e0000.iomuxc; cannot claim for leds.25
[    1.564327] imx6dl-pinctrl 20e0000.iomuxc: pin-137 (leds.25) status -22
[    1.570972] imx6dl-pinctrl 20e0000.iomuxc: could not request pin 137 (MX6DL_PAD_GPIO_2) from group gpio_leds  on device 20e0000.iomuxc
[    1.583105] leds-gpio leds.25: Error applying setting, reverse things back

Thanks for the tip for Ixora board DTS file, I must have missed it as I only looked at Colibri related boards. Unfortunately I am afraid that it will not help me, as I copied pinctrl and leds section from that file into my DTS file, and it seems to be just same. There are parsed device tree entries for the LEDs in /proc/device-tree/leds/, but there are no directories in /sys/class/leds/.

I have attached complete DTS file for our board, maybe you will find something wrong in there which is not obvious from snippet in first post.

I suspect that the issue may not be device tree related at all and is maybe caused by some sort of kernel misconfiguration, but I have no idea what could be wrong as I just recompiled kernel with colibri-imx6_defconfig and it does not work.


Note: I am bit confused if I should add this as comment, or as answer. I am not answering the original question, but it is way too long to post it as comment.