Compiling Custom Linux Kernel for Beaglebone Black Industrial 6.18.16-bone23

[    7.703206] systemd[1]: systemd-hibernate-clear.service - Clear Stale Hibernate Storage Info was skipped because of an unmet condition check (ConditionPathExists=/sys/firmware/efi/efivars/HibernateLocation-8cf2644b-4b0b-428f-9387-6d876050dc67).
[   22.295577] remoteproc remoteproc0: Booting fw image am335x-pm-firmware.elf, size 217148
[   22.304280] wkup_m3_ipc 44e11324.wkup_m3_ipc: CM3 Firmware Version = 0x192
[   22.318289] wkup_m3_ipc 44e11324.wkup_m3_ipc: Direct firmware load for am335x-bone-scale-data.bin failed with error -2
[   32.802679] faux_driver regulatory: Direct firmware load for regulatory.db failed with error -2
[   53.361625] rtw88_8821cu 1-1:1.0: Firmware version 24.11.0, H2C version 12
[   53.564547] usbcore: registered new interface driver rtw88_8821cu

I put the elf file in /lib/firmware

Thanks Robert, I have all the errors cleaned up by copying the regulatory.db, regulatory.db.p7s, am335x-bone-scale-data.bin and am335x-pm-firmware.elf to /lib/firmware.

Still have the strange issue with the serial terminal locking up. Basically can’t use it. Only for read only.

You’re basically encountering this:

… and it doesn’t have anything to do with your kernel.

I cleaned up init/main.c and added a function bgpioWriteMem

#define P8_11_PINMUX_ADDR 0x44e10834
#define P8_12_PINMUX_ADDR 0x44e10830
#define P8_15_PINMUX_ADDR 0x44e1083c
#define P8_18_PINMUX_ADDR 0x44e1088c

void bgpioSetPinMux(void);
int bgpioWriteMem(phys_addr_t phys_addr, uint32_t val);


int bgpioWriteMem(phys_addr_t phys_addr, uint32_t val) {
    void __iomem *addr;

  /* Map the physical 4 byte address */
    addr = ioremap(phys_addr, 4);
    if (!addr) {
        pr_err("bgpioWriteMem Failed to map address:%pa\n", &phys_addr);
        return -1;
    }

    /* Write value */
    writel(val, addr);

    /* Ensure write completes */
    wmb();

    /* Unmap */
    iounmap(addr);

    pr_info("bgpioWriteMem Set address:%pa value:0x%x\n", &phys_addr, val);

   return 0;
}

void bgpioSetPinMux(void) {

    if(bgpioWriteMem(P8_11_PINMUX_ADDR, 0x0037)) {
	 pr_err("Failed to configure P8_11\n");
	}

    if(bgpioWriteMem(P8_12_PINMUX_ADDR, 0x0037)) {
	 pr_err("Failed to configure P8_12\n");
	}

    if(bgpioWriteMem(P8_15_PINMUX_ADDR, 0x0037)) {
	 pr_err("Failed to configure P8_15\n");
	}

    if(bgpioWriteMem(P8_18_PINMUX_ADDR, 0x0037)) {
	 pr_err("Failed to configure P8_18\n");
	}


}

#endif

and of course the function call in init/main.c

// add function here to set pin mux registers before user space programs
#ifdef CONFIG_SOC_AM33XX
        bgpioSetPinMux();
#endif
        /* Do the rest non-__init'ed, we're now alive */
        rest_init();

and the output during boot

[    0.003721] bgpioWriteMem Set address:0x44e10834 value:0x37
[    0.003746] bgpioWriteMem Set address:0x44e10830 value:0x37
[    0.003753] bgpioWriteMem Set address:0x44e1083c value:0x37
[    0.003760] bgpioWriteMem Set address:0x44e1088c value:0x37

output of pinmux

pinmux|grep -E "P8.11|P8.12|P8.15|P8.18"
gpio0:12 | GPMC_AD12 P8.12         | 0x44e10830 | 0x0830 | 0x37  |    7  | FRXPULLUP
gpio0:13 | GPMC_AD13 P8.11         | 0x44e10834 | 0x0834 | 0x37  |    7  | FRXPULLUP
gpio0:15 | GPMC_AD15 P8.15         | 0x44e1083c | 0x083c | 0x37  |    7  | FRXPULLUP
gpio1:1  | GPMC_CLK P8.18          | 0x44e1088c | 0x088c | 0x37  |    7  | FRXPULLUP

If anyone knows of a way to set the pin mux via device tree overlays and then free the pins for user space libgpiod please let me know. I would rather not be compiling the kernel just to get some pins to pull up.

Yes, as I have been pointing out to you earlier,
I really does feel like you’re crossing 3 bridges and 2 pubs to get water from a creak beyond.

I think your time would be better spent if you figured out why the pinctrl driver
fails to set that bit 4 instead. That way everybody wins.

You’ve probably posted it before, but to be honest, I’ve lost track of your threads,
so if it’s not too much to ask, could you please post the overlay you have right now
and I’ll take that and apply it myself to see if I can reproduce.

gpioinfo|grep P8_45
"gpiochip1 - 32 lines:"	line   6:	"P8_45 [hdmi]"  	input

nothing has this pin

gpio1:6  | LCD_DATA0               | 0x44e108a0 | 0x08a0 | 0x2f  |    7  | FRX
/dts-v1/;
/plugin/;

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

/*
 * Record overlay in /sys/firmware/devicetree/base/chosen/overlays
 */
&{/chosen} {
    overlays {
        BB-P8_45-0x37-00A0.kernel = __TIMESTAMP__;
    };
};

/*
 * Free up the pin previously used by another cape
 */
&ocp {
    P8_45_pinmux { status = "disabled"; };
};

/*
 * Configure pinmux for P8_45 as GPIO
 */
&am33xx_pinmux {
    bb_lplcP8_45_pins: pinmux_bb_lplcP8_45_pins {
        pinctrl-single,pins = <
            AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_INPUT_PULLUP, MUX_MODE7)
        >;
    };
};

/*
 * GPIO1_6 defined for userspace control
 */
&gpio1 {
    lplc_pin: lplc_pin {
        gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; /* Logical HIGH is voltage HIGH */
        status = "okay";              /* Enable the GPIO controller line */
    };
};

add BB-P8_45-0x37-00A0.dtso to other dtso files in linux-stable-rcn-ee/arch/arm/boot/dts/ti/omap
edit Makefile, insert BB-P8_45-0x37-00A0.dtbo in random spot inside makefile between other dtbo.

BB-UART1-00A0.dtbo \
BB-P8_45-0x37-00A0.dtbo \
BB-SPIDEV1-00A0.dtbo \

make
copy BB-P8_45-0x37-00A0.dtbo to /boot/dtbs/ā€œkernel nameā€
reboot

uboot_overlays: loading /boot/dtbs/6.19.11-00008-g8d6ded334af0-dirty/BB-ADC-00A0.dtbo 
645 bytes read in 8 ms (78.1 KiB/s)
uboot_overlays: loading /boot/dtbs/6.19.11-00008-g8d6ded334af0-dirty/BB-UART2-00A0.dtbo
1025 bytes read in 9 ms (110.4 KiB/s)
uboot_overlays: loading /boot/dtbs/6.19.11-00008-g8d6ded334af0-dirty/BB-P8_45-0x37-00A0
.dtbo 
1001 bytes read in 10 ms (97.7 KiB/s)
uboot_overlays: loading /boot/dtbs/6.19.11-00008-g8d6ded334af0-dirty/BB-BONE-eMMC1-01-0
0A0.dtbo
ls sys/firmware/devicetree/base/chosen/overlays
BB-ADC-00A0.kernel            BB-P8_45-0x37-00A0.kernel  name
BB-BONE-eMMC1-01-00A0.kernel  BB-UART2-00A0.kernel

sudo gpioget -b pull-up -c /dev/gpiochip1 6
"6"=inactive

sudo beagle-version|grep P8
UBOOT: Loaded Overlay:[BB-P8_45-0x37-00A0.kernel]
uboot_overlay_options:[uboot_overlay_addr5=BB-P8_45-0x37-00A0.dtbo]

pinmux|grep 1:6
gpio1:6  | LCD_DATA0               | 0x44e108a0 | 0x08a0 | 0x2f  |    7  | FRX

Wasn’t pinctrl removed sometime in the past? Seems Robert mentioned this due to people breaking things. Maybe I’m wrong here.

after adding

    if(bgpioWriteMem(P8_41_PINMUX_ADDR, 0x0037)) {
         pr_err("Failed to configure P8_18\n");
        }
    if(bgpioWriteMem(P8_42_PINMUX_ADDR, 0x0037)) {
         pr_err("Failed to configure P8_18\n");
        }
    if(bgpioWriteMem(P8_43_PINMUX_ADDR, 0x0037)) {
         pr_err("Failed to configure P8_18\n");
        }
    if(bgpioWriteMem(P8_44_PINMUX_ADDR, 0x0037)) {
         pr_err("Failed to configure P8_18\n");
        }
    if(bgpioWriteMem(P8_45_PINMUX_ADDR, 0x0037)) {
         pr_err("Failed to configure P8_18\n");
        }
    if(bgpioWriteMem(P8_46_PINMUX_ADDR, 0x0037)) {
         pr_err("Failed to configure P8_18\n");
        }

and recompiling the kernel
BAMMM!

gpio1:6  | LCD_DATA0               | 0x44e108a0 | 0x08a0 | 0x37  |    7  | FRXPULLUP
gpio1:7  | LCD_DATA1 P8.46         | 0x44e108a4 | 0x08a4 | 0x37  |    7  | FRXPULLUP
gpio1:8  | LCD_DATA2 P8.43         | 0x44e108a8 | 0x08a8 | 0x37  |    7  | FRXPULLUP
gpio1:9  | LCD_DATA3 P8.44         | 0x44e108ac | 0x08ac | 0x37  |    7  | FRXPULLUP
gpio1:10 | LCD_DATA4 P8.41         | 0x44e108b0 | 0x08b0 | 0x37  |    7  | FRXPULLUP
gpio1:11 | LCD_DATA5 P8.42         | 0x44e108b4 | 0x08b4 | 0x37  |    7  | FRXPULLUP

No, that’s wrong!

config-pin was removed, not pinctrl.

Oh, I’m sure that what you made works, I’m just saying, it’s the wrong way to go about it.

Now, I haven’t checked this personally yet, but one thing that you seem to be missing
is a reference to that stuff you put into &am33xx_pinmux.

It doesn’t get applied ā€œon it’s ownā€; it needs another node, one that’s active,
to reference it with a pinctrl-<n> = &bb_lplcP8_45_pins statement. (n normally 0).

Just as an example, I put the following into ChatGPT:

can you make a device-tree overlay for me that turns the input on p8.13 on a beaglebone black into an input with a pullup and creates a gpio-key node as well

and out came:

/dts-v1/;
/plugin/;

/ {
    compatible = "ti,am335x-bone-black";

    part-number = "BB-P8_13-GPIOKEY";
    version = "00A0";

    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            bb_gpio_p8_13_pins: pinmux_bb_gpio_p8_13_pins {
                pinctrl-single,pins = <
                    0x034 0x37  /* gpmc_ad9 (P8.13) as GPIO0_23, MODE7 | INPUT | PULLUP */
                >;
            };
        };
    };

    fragment@1 {
        target = <&ocp>;
        __overlay__ {
            bb_gpio_p8_13 {
                compatible = "gpio-of-helper";
                pinctrl-names = "default";
                pinctrl-0 = <&bb_gpio_p8_13_pins>;

                status = "okay";
            };
        };
    };

    fragment@2 {
        target-path = "/";
        __overlay__ {
            gpio_keys {
                compatible = "gpio-keys";

                p8_13_key {
                    label = "P8_13_Button";
                    linux,code = <28>; /* KEY_ENTER */
                    gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
                    debounce-interval = <50>;
                };
            };
        };
    };
};

Granted, I don’t particularly care for the ā€œfragment-styleā€, but it looks pretty correct to me.

I did get a little suspicious about fragment@1, so I poked it again:

are you sure the "gpio-of-helper" still exists in kernel 6.18?

out came the usual apology and:

fragment@0 {
    target = <&am33xx_pinmux>;
    __overlay__ {
        p8_13_pins: pinmux_p8_13_pins {
            pinctrl-single,pins = <
                0x034 0x37  /* GPIO0_23 | input | pull-up */
            >;
        };
    };
};

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

            button {
                label = "P8_13_Button";
                linux,code = <28>;
                gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
                debounce-interval = <50>;
            };
        };
    };
};

… now that’s more like it!

I don’t see you using libgpiod.

That’s because right now we’re just looking to see if we can get the kernel
to set the right value in the PINMUX register.
There’s no need to complicate the matter by adding the libgpiod layer on
top when the device-tree is in question.

Make sense?

I got tired of compiling kernels so I decided to read the pinmux settings on boot from a file /etc/am335xpinmux.conf. The format of the file is pretty basic

cat /etc/am335xpinmux.conf
# am335x pin mux address and value to set
# this file is read by the am335xsetpinmux.c Linux kernel driver
# located in drivers/gpio
# address=value
0x44e10834=0x37
0x44e10830=0x37
0x44e1083c=0x37
0x44e1088c=0x37
0x44e108b0=0x37
0x44e108b4=0x37
0x44e108a8=0x37
0x44e108ac=0x37
0x44e108a0=0x37
0x44e108a4=0x37

The driver just reads the file and sets the control registers to the value, very simple. The kernel delays the file read by 10 seconds so that the file system is up and running. Seems to work. Here is the output during boot.

[   10.722151] am335xsetpinmux: Starting file read...
[   10.747079] am335xsetpinmux: address=0x44e10834, value=0x37
[   10.752878] bgpioWriteMem Set address:0x44e10834 value:0x37
[   10.758496] am335xsetpinmux: address=0x44e10830, value=0x37
[   10.764159] bgpioWriteMem Set address:0x44e10830 value:0x37
[   10.769765] am335xsetpinmux: address=0x44e1083c, value=0x37
[   10.775408] bgpioWriteMem Set address:0x44e1083c value:0x37
[   10.781011] am335xsetpinmux: address=0x44e1088c, value=0x37
[   10.786636] bgpioWriteMem Set address:0x44e1088c value:0x37
[   10.792260] am335xsetpinmux: address=0x44e108b0, value=0x37
[   10.797862] bgpioWriteMem Set address:0x44e108b0 value:0x37
[   10.803524] am335xsetpinmux: address=0x44e108b4, value=0x37
[   10.809128] bgpioWriteMem Set address:0x44e108b4 value:0x37
[   10.814758] am335xsetpinmux: address=0x44e108a8, value=0x37
[   10.820360] bgpioWriteMem Set address:0x44e108a8 value:0x37
[   10.825989] am335xsetpinmux: address=0x44e108ac, value=0x37
[   10.831591] bgpioWriteMem Set address:0x44e108ac value:0x37
[   10.837215] am335xsetpinmux: address=0x44e108a0, value=0x37
[   10.842836] bgpioWriteMem Set address:0x44e108a0 value:0x37
[   10.848438] am335xsetpinmux: address=0x44e108a4, value=0x37
[   10.854061] bgpioWriteMem Set address:0x44e108a4 value:0x37

and here are the pinmux settings after boot

pinmux|grep -E "0x44e10834|0x44e10830|0x44e1083c|0x44e1088c|0x44e108b0|0x44e108b4|0x44e108a8|0x44e108ac|0x44e108a0|0x44e108a4"
gpio0:12 | GPMC_AD12 P8.12         | 0x44e10830 | 0x0830 | 0x37  |    7  | FRXPULLUP
gpio0:13 | GPMC_AD13 P8.11         | 0x44e10834 | 0x0834 | 0x37  |    7  | FRXPULLUP
gpio0:15 | GPMC_AD15 P8.15         | 0x44e1083c | 0x083c | 0x37  |    7  | FRXPULLUP
gpio1:1  | GPMC_CLK P8.18          | 0x44e1088c | 0x088c | 0x37  |    7  | FRXPULLUP
gpio1:6  | LCD_DATA0               | 0x44e108a0 | 0x08a0 | 0x37  |    7  | FRXPULLUP
gpio1:7  | LCD_DATA1 P8.46         | 0x44e108a4 | 0x08a4 | 0x37  |    7  | FRXPULLUP
gpio1:8  | LCD_DATA2 P8.43         | 0x44e108a8 | 0x08a8 | 0x37  |    7  | FRXPULLUP
gpio1:9  | LCD_DATA3 P8.44         | 0x44e108ac | 0x08ac | 0x37  |    7  | FRXPULLUP
gpio1:10 | LCD_DATA4 P8.41         | 0x44e108b0 | 0x08b0 | 0x37  |    7  | FRXPULLUP
gpio1:11 | LCD_DATA5 P8.42         | 0x44e108b4 | 0x08b4 | 0x37  |    7  | FRXPULLUP

If anyone is interested in this kernel mod let me know. At this point, I’m happy with the static settings of the pinmux and I’m moving on to other things. This kernel business is time consuming. I’ll post the kernel driver for documentation when I get a few minutes.

To me it looks like you replicated what’s already available, but that’s just my point of view.

I would absolutely love to see you submit that patch to the kernel team,
just to hear what they had to say about it .. :wink:

Good luck with your endeavors!

Already available? Show me. Have you tried to used libgpiod to set pinmux from userspace? please show me the device tree overlay that sets the pins mux and then releases the pins for general user space libgpiod use. I would like to use that one.

It’s this ā€˜feature’ that’s currently broken and most users use the old 5.10.x hacks.. i’d love there to be a simple tool, kinda like what you did with GitHub - beagleboard/pinmux Ā· GitHub that we can share on am335x and k3 that allows user to bypass ā€˜libgpiod’ never ending not working.. :wink:

In most cases gpio-led works great for ā€œoutputā€ā€¦ input with gpio-key kinda works, but old sys dev was eaasier for input.. if you want to change pinmux dev mem …

Regards,

1 Like

I have to admit, I’m a little surprised that a 13 year old board still has Beta code for simple IO. I don’t really understand the history or why things changed, maybe there was a good reason. libgpiod is a beast and is difficult to use. Just compared to Raspberry PI WiringPI library.

hehe.. for 3.8 thru 5.10, we got away with abusing kernel structures.. don’t look too close in that code, you’ll see us just ā€˜over-writing’ things..

Then when we grew a few arm64 targets and riscv64 targets… (Which lead to the question, do you port the am335x pin things to other non arm335x)

Look closely at PI’s WiringPI library they just use dev mem.. We were trying to work with the kernel libgpiod.. but after 6.0.x → now they’ve been activly removing the gpio structures in the kernel we abused in 3.8 → 5.10.

So… we chose wrong.. should have just gone the pi route and used dev mem from the start..

Regards,

Except /dev/mem doesn’t work on am335x. You cannot write to the pinmux registers via /dev/mem on the BBB’s. The am335x has hardware blocks that only allow writing to those locations from within the protected kernel. I’ve been trying to work around that for a long time and have not found a way. You HAVE to have some sort of kernel driver to do the actual write. I though about some sort of driver that created a simple /dev/bb-pin-mux character device that you would just write a pin and mux value to (like: ā€œP9-46 gpioā€ or something, just never got around to doing it.

2 Likes