How to Set GPIO in a Custom Device Tree Overlay?

I have configured the following custom overlay:

/dts-v1/;
 /plugin/;
 
 / {
        compatible = "ti,beaglebone", "ti,beaglebone-black";

        /* identification */
        part-number = "BB-TOT-ACP";
        version = "00A0";

        /* state the resources this cape uses */
        exclusive-use = 
            /* Tri-Color LED */
            "P9.12",    /* Green Lamp */
            "P8.26";    /* Red Lamp */

        fragment@0 {
            target = <&am33xx_pinmux>;
            __overlay__ {
                pinctrl_test: tot_acp_pins {
                    pinctrl-single,pins = <
                        0x078 0x07 /* P9.12 is GPIO 60 -> set to output with pulldown enabled */
                        0x07c 0x07 /* P8.26 is GPIO 61 -> set to output with pulldown enabled */
                    >;
                };
            };
        };

        fragment@1 {
            target = <&ocp>;
            __overlay__ {
                test_helper: helper {
                    compatible = "bone-pinmux-helper";
                    pinctrl-names = "default";
                    pinctrl-0 = <&pinctrl_test>;
                    status = "okay";
                };
            };
        };
    };

I have pieced that together after bouncing from the Exploring BeagleBone book to some various forums. I made two changes to uEnv.txt to enable it:

...
uboot_overlay_addr4=/lib/firmware/BB-TOT-ACP-00A0.dtbo
...
enable_uboot_cape_universal=

Before trying to make my changes permanent, I had used config-pin and /sys/class/gpio/gpio60/value to test the GPIO. Now, however, when I go to /sys/class/gpio there isn’t a single pin listed there.

Is there some other way to control the GPIO? If not, what information am I missing in my overlay?

Do you have the overlays enabled?

fred@bbb2-rt:/boot$ cat uEnv.txt 
uname_r=5.15.86-bone-rt-r32
enable_uboot_overlays=1
uboot_overlay_pru=AM335X-PRU-UIO-00A0.dtbo
enable_uboot_cape_universal=1

#This turns on HDMI output
uboot_overlay_addr0=/boot/dtbs/5.15.86-bone-rt-r32/overlays/BB-HDMI-TDA998x-00A0.dtbo
#enable UARTS


uboot_overlay_addr1=/boot/dtbs/5.15.86-bone-rt-r32/overlays/BB-UART1-00A0.dtbo
uboot_overlay_addr2=/boot/dtbs/5.15.86-bone-rt-r32/overlays/BB-UART2-00A0.dtbo
uboot_overlay_addr3=/boot/dtbs/5.15.86-bone-rt-r32/overlays/BB-UART4-00A0.dtbo
#enable I2C
uboot_overlay_addr4=/boot/dtbs/5.15.86-bone-rt-r32/overlays/BB-I2C1-RTC-DS3231.dtbo

Yes, I have the overlays enabled. I have spent a number of hours tinkering with this since I posted, and here is my latest overlay file:

 /dts-v1/;
 /plugin/;
 
 / {
        compatible = "ti,beaglebone", "ti,beaglebone-black";

        /* identification */
        part-number = "ToT-ACP-GPIO";
        version = "00A0";

        /* Show with loaded overlays in /proc/device-tree/chosen/overlays */
       fragment@0 {
           target-path = "/";
           __overlay__ {
               chosen {
                   overlays {
                       ToT-ACP-GPIO-00A0 = "Mon Jan 30 08:00:00 2023";
                   };
               };
           };
       };

        /* Configure the GPIO for the cape */
        fragment@1 {
            target = <&am33xx_pinmux>;
            __overlay__ {
                /* P8.26 is GPIO 61 and used to illuminate the red LED of the indicator lamp */
                pinctrl_tot_acp_P8_26: pinmux_tot_acp_P8_26 {
                    /* Set to Fast Slew, Output, Pulldown, Resistor Enabled, GPIO Mux Mode */
                    pinctrl-single,pins = <0x07c 0x07>;
                };

                /* P9.12 is GPIO 60 and used to illuminate the green LED of indicator lamp */
                pinctrl_tot_acp_P9_12: pinmux_tot_acp_P9_12 {
                    /* Set to Fast Slew, Output, Pulldown, Resistor Enabled, GPIO Mux Mode */
                    pinctrl-single,pins = <0x078 0x07>;
                };
            };
        };

        fragment@2 {
            target = <&ocp>;
            __overlay__ {
                P8_26_pinmux {
                    compatible = "bone-pinmux-helper";
                    pinctrl-0 = <&pinctrl_tot_acp_P8_26>;
                    pinctrl-names = "default";
                    status = "okay";
                };
                
                P9_12_pinmux {
                    compatible = "bone-pinmux-helper";
                    pinctrl-0 = <&pinctrl_tot_acp_P9_12>;
                    pinctrl-names = "default";
                    status = "okay";
                };
            };
        };
    };

I decided not to disable the universal cape, so the only change I have made to /boot/uEnv.txt is now:

###Additional custom capes
uboot_overlay_addr4=/lib/firmware/ToT-ACP-GPIO-00A0.dtbo

I have found the child node names in fragment@2 must be P8_26_pinmux and P9_12_pinmux in order for config-pin to work with them. When I use these names and have the universal cape enabled, the corresponding gpio folders (gpio60 and gpio61) are present within /sys/class/gpio. If I don’t enable the universal cape, I have to export them manually.

sudo echo 60 > /sys/class/gpio/export
sudo echo 61 > /sys/class/gpio/export

I’m still left with a couple of nagging problems:

  1. During the boot sequence the pin is high, and I suspect it is operating as an input until Linux processes the overlays. Is this unavoidable, or is there some other configuration I can do to make the pin initialize as an output as the board comes online?

  2. The direction file in sysfs always reads in after reboot despite the fact the pin is correctly muxed as an output. Is this just a bug in sysfs?

debian@beaglebone:~$ /opt/scripts/device/bone/show-pins.pl | grep P9.12
P9.12                             30 U18 fast    down 7 gpio 1.28        ocp/P9_12_pinmux (pinmux_tot_acp_P9_12)
debian@beaglebone:~$ cat /sys/class/gpio/gpio60/direction
in

I still haven’t resolved either of the 2 known issues. I did publish my article, regardless, so if anyone is inclined to purse a solution to the boot sequence pinmux or the sysfs direction mismatch my steps are fully documented as below.

1 Like

@brad-tot ,

Neat. I see how you got the source for the .dts file to work. I am not well versed in dts but I see how it can be a bit labor inducive.

Anyway, thank you for posting and all the posting you have done. I am learning still on how to achieve dts supremacy!

Seth

P.S. I am going to follow along the Tri-Color LED Control and see how far I get.

1 Like

Sadly, the reset state of the AM335x GPIO is in affect at power-on… You could also set the pin in u-boot to ensure it’s default state longer during boot… But sadly during linux initialization it’ll also return to reset. There is a devie-tree option to bypass this on boot, “gpio-hog” but sadly it’s not designed to be used as a toggle pin, it’s more of I ‘forgot’ a resistor pull-up, on a special pin.

For your example, i usually recommend user to use ‘gpio-led’ it supports startup states, and a single command to output high or low…

Regards,

1 Like

I definitely get more answers from this forum than I provide, so I’m happy to share what I can! Thanks for checking out the blog post, and please do let me know if you spot anything that can be improved.

1 Like

Thank you for the information, Robert. I’ll be sure to research ‘gpio-led’.