AM67A: Implementing U-Boot multi-dtb-fit – execution stuck at dm_uninit

Part Number: AM67A
Other Parts Discussed in Thread: TMDS64EVM, SK-AM64B

Hello,

We are working on adding Linux support for multiple custom boards based on the AM67A SoC, each having minor hardware variances. I noticed that several TI evaluation boards for different SoCs (like the AM64x) utilize the U-Boot multi-dtb-fit feature to handle board variants.

To avoid building and maintaining separate binaries for multiple boards, I want to implement this approach. We have an I2C EEPROM with a common data structure available on all boards, so the board detection logic was fairly straightforward to implement.

For the rest of the implementation—specifically packaging multiple DTBs and making adjustments inside the board initialization code—I have been using SoCs like the AM642 and J721S2 as a reference.

While the I2C read and board detection work perfectly, I hit a roadblock when trying to replace tiboot3.bin. The boot process always gets stuck during or immediately after dm_uninit.

Before I spend too much time debugging, I wanted to ask if there are any obvious mistakes in this approach, or if there is something platform-specific I need to consider for the AM67A regarding multi-dtb-fit in the initial boot phases.

Relevant changes made:

Inside j722s_init.c:

#ifdef CONFIG_SPL_OF_LIST
void do_dt_magic(void)
{
    int ret, rescan, mmc_dev = -1;
    static struct mmc *mmc;

    /* Perform board detection */
    do_board_detect();

    /*
     * Board detection has been done.
     * Let us see if another dtb wouldn't be a better match
     * for our board
     */
    if (IS_ENABLED(CONFIG_CPU_V7R)) {
        ret = fdtdec_resetup(&rescan);
        printf("fdtdec_resetup returned %d, rescan = %d\n", ret, rescan);
        if (!ret && rescan) {
            printf("Rescanning devices after board detection...\n");
            dm_uninit(); // HERE IT GET STUCK
            dm_init_and_scan(true);
        }
    }
}
#endif


void board_init_f(ulong dummy)
{
    int ret;
    struct udevice *dev;

    k3_spl_init();

#ifdef CONFIG_SPL_OF_LIST
    do_dt_magic();
#endif

    k3_mem_init();
    setup_qos();
    //...
}


On board level I implemented the do_board_detect and board_fit_config_name_match function:

void do_board_detect(void)
{
    board_eeprom_detect();

    switch (EEPROM_DATA->board) {
    case BOARD_A:
        printf("Board: Board A (HW rev %u.%u)\n",
               EEPROM_DATA->hw_rev_major,
               EEPROM_DATA->hw_rev_minor);
        break;
    case BOARD_B:
        printf("Board: Board B (HW rev %u.%u)\n",
               EEPROM_DATA->hw_rev_major,
               EEPROM_DATA->hw_rev_minor);
        break;
    default:
        printf("do_board_detect: unknown board variant\n");
        break;
    }
}

#if defined(CONFIG_SPL_LOAD_FIT)
int board_fit_config_name_match(const char *name)
{
    printf("board_fit_config_name_match() called with name = %s\n", name);

    if (!eeprom_was_detected()) {
        printf("EEPROM not yet detected, deferring to FIT default config\n");
        return -1;
    }

    printf("EEPROM detected, board type = %u\n", EEPROM_DATA->board);

    switch (EEPROM_DATA->board) {
    case BOARD_A:
        if (!strcmp(name, "k3-am67a-r5-board-a") || !strcmp(name, "k3-am67a-board-a")) {
            return 0;
        }
        break;
    case BOARD_B:
        if (!strcmp(name, "k3-am67a-r5-board-b") || !strcmp(name, "k3-am67a-board-b")) {
            return 0;
        }
        break;
    default:
        printf("Unknown board variant, no matching DTB found\n");
        break;
    }
    return -1;
}
#endif


Below also the boot logs.

When tiboot3.bin is replaced:
U-Boot SPL 2026.01-00054-gd872d2b6be9b-dirty (Jun 23 2026 - 06:15:00 +0000)
SYSFW ABI: 4.0 (firmware rev 0x000b '11.2.8--v11.02.08 (Fancy Rat)')
Probing I2C bus 1 for EEPROM at address 0x53
Reading EEPROM from I2C bus 1 addr 0x53
EEPROM CRC: stored=0x44b9a992 computed=0x44b9a992
EEPROM manufacturerInfo: BOARD_B
Board: Board B (HW rev 0.2)
board_fit_config_name_match() called with name = k3-am67a-r5-board-a
EEPROM detected, board type = 2
board_fit_config_name_match() called with name = k3-am67a-r5-board-b
EEPROM detected, board type = 2
Selecting config 'k3-am67a-r5-board-b'
fdtdec_resetup returned 0, rescan = 1
Rescanning devices after board detection...
dm_uninit() called
// HERE IT GETS STUCK
When fdtdec_resetup / dm_uninit .... call is commented out:
U-Boot SPL 2026.01-00054-gd872d2b6be9b-dirty (Jun 23 2026 - 09:23:48 +0000)
SYSFW ABI: 4.0 (firmware rev 0x000b '11.2.8--v11.02.08 (Fancy Rat)')
Probing I2C bus 1 for EEPROM at address 0x53
Reading EEPROM from I2C bus 1 addr 0x53
EEPROM CRC: stored=0xf0fbb19f computed=0xf0fbb19f
EEPROM manufacturerInfo: BOARD_B
Board: Board B (HW rev 0.2)
SPL initial stack usage: 17176 bytes
Trying to boot from MMC1
board_fit_config_name_match() called with name = k3-am67a-r5-board-a
EEPROM detected, board type = 2
board_fit_config_name_match() called with name = k3-am67a-r5-board-b
EEPROM detected, board type = 2
Selecting config 'k3-am67a-r5-board-b'
Authentication passed
Authentication passed
Authentication passed
init_env from device 9 not supported!
Authentication passed
Authentication passed
Starting ATF on ARM64 core...

NOTICE:  BL31: v2.14.1(release):lts-v2.14.1
NOTICE:  BL31: Built : 14:00:55, Jun 16 2026
I/TC: 
I/TC: OP-TEE version: 4.9.0 (gcc version 14.2.0 (Debian 14.2.0-19)) #1 Tue Jun 16 13:59:35 UTC 2026 aarch64
I/TC: WARNING: This OP-TEE configuration might be insecure!
I/TC: WARNING: Please check optee.readthedocs.io/.../porting_guidelines.html
I/TC: Primary CPU initializing
I/TC: GIC redistributor base address not provided
I/TC: Assuming default GIC group status and modifier
I/TC: SYSFW ABI: 4.0 (firmware rev 0x000b '11.2.8--v11.02.08 (Fancy Rat)')
I/TC: Activated SA2UL device
I/TC: Enabled firewalls for SA2UL TRNG device
I/TC: EIP76D TRNG initialized
I/TC: SA2UL Drivers initialized
I/TC: HUK Initialized
I/TC: Disabling output console

U-Boot SPL 2026.01-00054-gd872d2b6be9b-dirty (Jun 23 2026 - 06:01:11 +0000)
SYSFW ABI: 4.0 (firmware rev 0x000b '11.2.8--v11.02.08 (Fancy Rat)')
DM ABI: 3.0 (firmware ver 0x000b 'MSDK.11.01.00.05--v11.01.09' patch_ver: 9)
Probing I2C bus 1 for EEPROM at address 0x53
Reading EEPROM from I2C bus 1 addr 0x53
EEPROM CRC: stored=0x44b9a992 computed=0x44b9a992
EEPROM manufacturerInfo: BOARD_B
Board: Board B (HW rev 0.2)
Trying to boot from MMC1
board_fit_config_name_match() called with name = k3-am67a-r5-board-a
EEPROM detected, board type = 2
board_fit_config_name_match() called with name = k3-am67a-r5-board-b
EEPROM detected, board type = 2
Selecting config 'k3-am67a-r5-board-b'
Authentication passed
Authentication passed


U-Boot 2026.01-00054-gd872d2b6be9b-dirty (Jun 23 2026 - 06:01:11 +0000)

SoC:   J722S SR1.0 HS-FS
Model: Board B
DRAM:  2 GiB (total 4 GiB)
Core:  80 devices, 28 uclasses, devicetree: separate
MMC:   mmc@fa10000: 0, mmc@fa00000: 1
Loading Environment from MMC... Reading from MMC(0)... OK
In:    serial@2800000
Out:   serial@2800000
Err:   serial@2800000
Probing I2C bus 1 for EEPROM at address 0x53
Reading EEPROM from I2C bus 1 addr 0x53
EEPROM CRC: stored=0x44b9a992 computed=0x44b9a992
EEPROM manufacturerInfo: BOARD_B
Board: Board B (HW rev 0.2)
Net:   No ethernet found.
Press SPACE to abort autoboot in 2 seconds

Thank you!
Martin

  • Hi Martin,

    Sorry I didn't get a chance to look into this today. I will get back to you by this Friday if not earlier.

  • Hi Bin,

    Sorry for my impatience, but have you had a chance to look at it yet?

    The most important question for me is whether it should be possible at all on that platform.

    If that's the case, it would be worth to invest more of my time in it.

    Of course, I'd be grateful for any hints about mistakes I've made.

    Thanks!

    Martin

  • Hi Martin,

    From you description, my understanding is that with your board detect implementation, dm_uninit() hangs, but the custom board boots into U-Boot properly if dm_uninit() is removed. Correct?

    Maybe you can debug drivers/core/device-remove.c to see which device removal causes the issue?

  • The most important question for me is whether it should be possible at all on that platform.

    The board detect logic implemented for AM64x platform can be used on any other platform too. The only thing to pay attention to ensure the tiboot3.bin binary with multi device dtb included does not exceed the SRAM size.

  • Exactly

    I spent some time debugging the relevant section, and the execution appears to hang when trying to remove main_uart0. Specifically, device_remove is called for serial@2800000, and I am able to trace it as far as the call to device_free.

    I suspect the removal is actually successful, but because this tears down my serial console, I lose all output from that point forward. It might be that it actually fails during the subsequent dm_init_and_scan, but I am blind to it because of dm_uninit. Does this behavior sound familiar to you?

    Unfortunately, my debugging capabilities are currently limited by my board design and available hardware, so setting up a proper JTAG/hardware debug environment will take me some time.

    Regarding your second point regarding the SRAM size: My assumption was that CONFIG_SPL_SIZE_LIMIT and CONFIG_SPL_MAX_SIZE would protect against overflowing it. Is that incorrect?

  • Hi Martin,

    Does this behavior sound familiar to you?

    Actually our development team implemented this logic for AM64x U-Boot and it always works, so I never had a chance to debug into this section of the code.

    It might be that it actually fails during the subsequent dm_init_and_scan, but I am blind to it because of dm_uninit.

    Okay this sounds reasonable. On your u-boot devicetree, can you please try to disable all other modules except main_uart0 to see if dm_init_and_scan() can bring back the console output?

    Regarding your second point regarding the SRAM size: My assumption was that CONFIG_SPL_SIZE_LIMIT and CONFIG_SPL_MAX_SIZE would protect against overflowing it. Is that incorrect?

    I believe it is correct. My comment was about to ensure the total tiboot3.bin size doesn't grow over the limit once multiple board dtbs are included in the binary. Otherwise, the binary cannot not be loaded and run.

  • Hi Bin, unfortunately, disabling devices via DT didn't provide any insight. The UART is still silent after uninit.

    I have also tried to set up a proper JTAG debug with OpenOCD and my TUMPA, but I haven't got it working with my custom board yet.
    This may just be due to an incorrect OpenOCD configuration, so I'm still working on that.

    Do you know if the multi-board-fit feature is planned for the J722S/AM67A at any point?

  • Hi, I am out of office for the holidays and will be back mid of next week. 

  • Hi Martin,

    U-Boot has mutl-board-fit implemented for AM64x because to support both SK-AM64B and TMDS64EVM. But as far as I am aware J722S/AM67A has only one EVM, so it doesn't makes sense to implement the same multi-board-fit support for J722S/AM67A.