Can't get any gpio to work in userspace on BeagleBoneBlack with latest Debian 12 kernel 6.[12-15].x images

I’ve been trying to update my setup to work on the new kernels that only accept libgpiod.
It seems that it is only possible to ‘activate’ functionalities with the device tree overlays if there is already a ‘driver’ in kernel that supports it, like uart1, uart2, i2c2, etc… But, if I try to use the pins as simple output or input then I fail.
Following the advised new approach https://forum.beagleboard.org/t/debian-12-bookworm-dbto-files/36170, I downloaded the compatible DeviceTree ‘builder’ from https://git.beagleboard.org/beagleboard/BeagleBoard-DeviceTrees, and coded my test.dtso in src/arm/overlays, and then copied the test.dtbo file, generated with ‘make’, to /lib/firmware.
In /boot/uEnv.txt, I then enabled ‘enable_uboot_overlays=1’ and referenced my DTO in uboot_overlay_addr4=/lib/firmware/test.dtbo.
I have tried multiple approaches to get it work with no luck. I will post some of them just so that some kind soul can give me light:

#1 - test01.dtso

/dts-v1/;
/plugin/;

#include <dt-bindings/pinctrl/am33xx.h>

&am33xx_pinmux {
    pinmux_p9_41_input_pu: pinmux_p9_41_input_pu {
        pinctrl-single,pins = <
            AM33XX_IOPAD(0x09B4, PIN_INPUT_PULLUP | MUX_MODE7)  // GPIO0_20
        >;
    };
};

&ocp {
    p9_41_setup {
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&pinmux_p9_41_input_pu>;
    };
};

#2 - test02.dtso

/dts-v1/;
/plugin/;

#include <dt-bindings/pinctrl/am33xx.h>

&{/chosen} {
    overlays {
        test02.kernel = __TIMESTAMP__;
    };
};

/ {
    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            P9_41_input_pu_pin: pinmux_P9_41_input_pu_pin {
                pinctrl-single,pins = <
                    AM33XX_IOPAD(0x09b4, PIN_INPUT_PULLUP | MUX_MODE7)
                >;
            };
        };
    };

    fragment@1 {
        target = <&ocp>;
        __overlay__ {
            my_gpio_user {
                status = "okay";
                pinctrl-names = "default";
                pinctrl-0 = <&P9_41_input_pu_pin>;
            };
        };
    };
};

With the above 2, when I do gpioget gpiochip3 20 I get the same result ‘0’ regardless if i am grounding the pin or not.

#3 test03.dtso

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/am33xx.h>

/ {
    compatible = "ti,am33xx";

    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            pinmux_gpio_keys: pinmux-gpio-keys {
                pinctrl-single,pins = <
                    AM33XX_IOPAD(0x09B4, PIN_INPUT_PULLUP | INPUT_EN | MUX_MODE7)
                >;
            };
        };
    };

    fragment@1 {
        target = <&gpio0>;
        __overlay__ {
            pinctrl-names = "default";
            pinctrl-0 = <&pinmux_gpio_keys>;
            status = "okay";
        };
    };

    fragment@2 {
        target-path = "/";
        __overlay__ {
            gpio_keys: gpio-keys {
                compatible = "gpio-keys";
                pinctrl-names = "default";
                pinctrl-0 = <&pinmux_gpio_keys>;

                status = "okay";

                button_p9_41 {
                    label = "P9_41_BTN";
                    gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
                };
            };
        };
    };
};

With test03 it hangs on boot:

[    6.495911] pinctrl-single 44e10800.pinmux: Invalid number of rows: 0
[    6.502518] pinctrl-single 44e10800.pinmux: no pins entries for pinmux-gpio-keys
[    6.511993] clk: Disabling unused clocks
[    6.516187] PM: genpd: Disabling unused power domains
[    6.521897] Waiting for root device /dev/mmcblk0p3...
[   16.612515] platform 48060000.mmc: deferred probe pending: platform: supplier 44e07000.gpio not ready

I even tried to use the gpio-leds framework, but then I cannot access the pins in userspace, I always get Resource Busy when trying gpioset gpiochip3 20 for example.

I also tried the BBORG_RELAY-00A2.dtbo which already comes with the DeviceTree defaults. And when I try to set any of the defined relays I also get Resource Busy…

I have not tried my own .dtbo in quite some time…

uboot_overlay_addr4=/lib/firmware/test.dtbo

uboot_overlay_addr4=test.dtbo and/or the .dtbo file may be listed in /boot/dtbs/YOUR_KERNEL/overlays/

Seth

@luke_16
so following the newer (?? format)
P9_41 works as an input, or should i say, when i “cat /dev/input/event1”
and then touch P9_41 to gnd via a 1K, the event1 outputs garbage to the console.
uEnv.txt
uboot_overlay_addr4=overlays/BBORG_p9_41_key-00A2.dtbo

also i tend to let make compile the dtbs file, install with “make install”
/opt/source/dtb-6.15
make location

/opt/source/dtb-6.15/src/arm/overlays
dtbs source location

uname
Linux BeagleBone 6.15.4-bone18

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>

/*
 * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
 */
&{/chosen} {
	overlays {
		BBORG_p9_41_key-00A2.kernel = __TIMESTAMP__;
	};
};

/*
 * Free up the pins used by the cape from the pinmux helpers.
 */
&ocp {
	P9_41_pinmux { status = "disabled"; };
};

&am33xx_pinmux {
    pinmux_p9_41_input_pu: pinmux_p9_41_input_pu {
        pinctrl-single,pins = <
            //AM33XX_IOPAD(0x09B4, PIN_INPUT_PULLUP | INPUT_EN | MUX_MODE7)  // GPIO0_20
            //AM33XX_IOPAD(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP | INPUT_EN | MUX_MODE7)  // GPIO0_20
            AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP | INPUT_EN, MUX_MODE7)  // GPIO0_20

            
        >;
    };
};


&ocp {
    gpio_keys: gpio-keys {
        compatible = "gpio-keys";
        autorepeat;
        pinctrl-names = "default";
        pinctrl-0 = <&pinmux_p9_41_input_pu>;

        status = "okay";
        button_p9_41 {
            label = "P9_41_BTN_UP";
            linux,code = <103>;            
            gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
        };
    };
};

and if your looking for a snip it of code to see what event1 outputs, this link has one

1 Like

@amf99 ,

Is it safe to say that /dev/input/event1 is a input and that another way of using inputs is frowned upon or not as safe?

So, one GPIO can be whatever gpioinfo outputs as an Output while /dev/input/eventN is always an input?

Seth

P.S. I see how old that doc from stackoverflow is currently and am to this day signaling inputs differently or used to do it differently. Hmm. Now that I think of it all, Inputs were done because of what beagleboard.org offered in the form of the source code for config-pin and the boards offered through them. Outstood

this example was about gpio-keys which are inputs and has a driver for them.

1 Like

Thank you all for the replies. I guess my problem was a mix of many problems. First of them is the lack of an actual manual reference for beginners. My understanding is that one thing is to understand all the bits that goes into a device tree overlay, and another is to know what a BeagleBone board needs. I have seen other much more complex examples, and those are really not for developers that occasionally need to setup some IO to work.
I could really not find any reliable manual for it, and as the changes took place (exclusive adoption of libgpiod), it is always in discussion forums that part of it gets clarified.

So, I will point out what worked for me for the BeagleBone Black running the official Debian 12 image with kernel 6.12.x:

  1. Make sure the overlay file, to be pointed as an overlay in
    /boot/uEnv.txt
    at
    uboot_overlay_addr#=/lib/firmware/my_overlay.dtbo
    is created in the folder (with matching kernel version, in this case 6.12)
    /opt/source/dtb-6.12/src/arm/overlays
    with extension .dtso. Then from folder /opt/source/dtb-6.12/ run make command.
    I could not get UBOOT to see my overlay file in any other folder other than /lib/firmware, so I copied it there and referenced it in the uEnv.txt file.

  2. Since gpioset only works while the command is running, when there is a need to get a pin to be set and left as set, the easiest way is to use the gpio-leds framework. When using it, the pin (my_output_pin) can be set high with: echo 1 > /sys/class/leds/my_output_pin/brightness or low with: echo 0 > /sys/class/leds/my_output_pin/brightness. gpioget works as expected.

  3. I was declaring the pins in ocp but for what I could understand, ocp does nothing. The pins must be declared in the appropriate gpio reference.

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>

//just to have the overlay listed in /proc/device-tree/overlays when it is correctly loaded
&{/chosen} {
    overlays {
        my_overaly.kernel = __TIMESTAMP__;
    };
};

&{/} {
    compatible = "ti,am335x-bone-green-gateway", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";

    //gpio-leds framework
    leds {
        compatible = "gpio-leds";

        my_output_pin {
            label = "my_output_pin";
            gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
            default-state = "off";
            pinctrl-names = "default";
            pinctrl-0 = <&p8_8_gpio_pin>;
        };
    };
};

&am33xx_pinmux {
    p8_8_gpio_pin: pinmux_p8_8_gpio_pin {
        pinctrl-single,pins = <
            AM33XX_IOPAD(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT | INPUT_EN | MUX_MODE7)
        >;
    };

    p9_23_gpio_pin: pinmux_p9_23_gpio_pin {
        pinctrl-single,pins = <
            AM33XX_IOPAD(AM335X_PIN_GPMC_A1, PIN_INPUT | MUX_MODE7)
        >;
    };
};

&gpio1 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&p9_23_gpio_pin>;
};

3 Likes