Problems with the IPv6 driver when using remoteproc on Verdin imx8mp

Hello,

I’m having some issues with the IPv6 driver on the Verdin-imx8mp 4 GB Quad Core. When starting the M7 core firmware as early as possible (or, on network.target), it looks like its blocking the IPv6 driver of bringing the eth0 interface up.

When not starting M7 core at boot using remoteproc, I get this dmesg output, which is expected, eth0 is up after ~11 seconds:
[ 11.056835] imx-dwmac XXXXXX.ethernet eth0: Link is Up - 1Gbps/Full - flow control off
[ 11.064983] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

However, when i start M7 using remoteproc between 0 boot time and the time it takes IPv6 to bring the eth0 interface up, no eth0 interface is brought up, and i cannot see any “Link is up” or “Link becomes ready” by any imx or IPv6 driver, and the device is not reachable using the known hostname + I can see in my router that no DHCP lease is given to the toradex.

I’m not using any custom device tree overlays for this test, only the dual core overlay hmp is applied after flashing. On the M7 side I’m doing some pinmuxing, but I’ve checked the device tree overlays iomuxing, and it does not look like there are any overlap with eqos or fec (ethernet0 and ethernet1) pin groups.

This is the current pin configuration I’m using in the M7 firmware:

void BOARD_InitPins(void)
{ /*!< Function assigned for the core: Cortex-M7F[m7] */
    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO00_GPIO1_IO00, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO00_GPIO1_IO00,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO05_GPIO1_IO05, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO05_GPIO1_IO05,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO06_GPIO1_IO06, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO06_GPIO1_IO06,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    // Enable button pinmux
    IOMUXC_SetPinMux(IOMUXC_SAI5_MCLK_GPIO3_IO25, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SAI5_MCLK_GPIO3_IO25,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_SAI1_RXD0_GPIO4_IO02, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SAI1_RXD0_GPIO4_IO02,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_SAI1_MCLK_GPIO4_IO20, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SAI1_MCLK_GPIO4_IO20,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_UART1_RXD_UART1_RX, 0U);
    IOMUXC_SetPinConfig(IOMUXC_UART1_RXD_UART1_RX,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
    IOMUXC_SetPinMux(IOMUXC_UART1_TXD_UART1_TX, 0U);
    IOMUXC_SetPinConfig(IOMUXC_UART1_TXD_UART1_TX,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PE_MASK);

    // I2C3
    IOMUXC_SetPinMux(IOMUXC_I2C3_SCL_I2C3_SCL, 1U);
    IOMUXC_SetPinConfig(IOMUXC_I2C3_SCL_I2C3_SCL,
                        IOMUXC_SW_PAD_CTL_PAD_DSE(3U) | IOMUXC_SW_PAD_CTL_PAD_FSEL_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK);

    IOMUXC_SetPinMux(IOMUXC_I2C3_SDA_I2C3_SDA, 1U);
    IOMUXC_SetPinConfig(IOMUXC_I2C3_SDA_I2C3_SDA,
                        IOMUXC_SW_PAD_CTL_PAD_DSE(3U) | IOMUXC_SW_PAD_CTL_PAD_FSEL_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK);

    // I2C4 (this is mapped to I2C_1)
    IOMUXC_SetPinMux(IOMUXC_I2C4_SCL_I2C4_SCL, 1U);
    IOMUXC_SetPinConfig(IOMUXC_I2C4_SCL_I2C4_SCL,
                        IOMUXC_SW_PAD_CTL_PAD_DSE(3U) | IOMUXC_SW_PAD_CTL_PAD_FSEL_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK);

    IOMUXC_SetPinMux(IOMUXC_I2C4_SDA_I2C4_SDA, 1U);
    IOMUXC_SetPinConfig(IOMUXC_I2C4_SDA_I2C4_SDA,
                        IOMUXC_SW_PAD_CTL_PAD_DSE(3U) | IOMUXC_SW_PAD_CTL_PAD_FSEL_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK);

    IOMUXC_SetPinMux(IOMUXC_UART4_RXD_UART4_RX, 0U);
    IOMUXC_SetPinConfig(IOMUXC_UART4_RXD_UART4_RX,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
    IOMUXC_SetPinMux(IOMUXC_UART4_TXD_UART4_TX, 0U);
    IOMUXC_SetPinConfig(IOMUXC_UART4_TXD_UART4_TX,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PE_MASK);

    // Configure SPDIF_EXT_CLK as PWM1
    IOMUXC_SetPinMux(IOMUXC_SPDIF_EXT_CLK_PWM1_OUT, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SPDIF_EXT_CLK_PWM1_OUT,
                        IOMUXC_SW_PAD_CTL_PAD_DSE(3U) |      // Drive Strength = 3 (medium)
                            IOMUXC_SW_PAD_CTL_PAD_FSEL(2U) | // Fast Slew Rate
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK |  // Pull Enable
                            IOMUXC_SW_PAD_CTL_PAD_PUE_MASK); // Pull Up

    // Configure SAI5_RXD1 as GPIO output
    IOMUXC_SetPinMux(IOMUXC_SAI5_RXD1_GPIO3_IO22, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SAI5_RXD1_GPIO3_IO22,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_SAI5_RXFS_GPIO3_IO19, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SAI5_RXFS_GPIO3_IO19,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)

    IOMUXC_SetPinMux(IOMUXC_SPDIF_TX_GPIO5_IO03, 0U);
    IOMUXC_SetPinConfig(IOMUXC_SPDIF_TX_GPIO5_IO03,
                        IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |    // Enable pull
                            IOMUXC_SW_PAD_CTL_PAD_PE_MASK); // Pull enable (pull-up)
}

There is probably something I’m not understanding correctly here. Could it be that the muxing on the M7 side causing the ethernet iomuxing to fail even if the pins are different, but the IO banks are the same? Also, is there any reason why the eth0 interface takes so long to link, and is there something that can be done to speed it up?

tdx-info:

Software summary

Bootloader: U-Boot
Kernel version: 5.15.148-6.8.0-devel+git.8c5c2dcbf6ba #1 SMP PREEMPT Tue Aug 6 10:01:59 UTC 2024
Kernel command line: root=PARTUUID=ad0b759c-02 ro rootwait console=tty1 console=ttymxc2,115200 consoleblank=0 earlycon clk-imx8mp.mcore_booted=1
Distro name: NAME=“TDX Wayland with XWayland”
Distro version: VERSION_ID=6.8.0-devel-20250314090650-build.0
Distro variant: -
Hostname: verdin-imx8mp-1550xxxx

Hardware info

HW model: Toradex Verdin iMX8M Plus WB on Verdin Development Board
Toradex version: 0063 V1.1B
Serial number: 1550xxxx
Processor arch: aarch64

tdx-info is showing “Verdin Development Board”, but we are using a normal Verdin imx8mp 4 GB quad core with a Mallow carrier board, any reason why its showing as a development board?

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello! Thanks for your detailed description and for sharing your observations and pin configuration. Let me help clarify your main concerns regarding the IPv6/ethernet interface behavior and interaction with the Cortex-M7 (M7) core on the Verdin iMX8M Plus.

1. Eth0 Interface Fails When M7 Core Starts Early

Your observation that eth0 fails to come up when the M7 core is started early—especially during the network bring-up—can be explained by shared hardware resources and potential contention or misconfiguration caused by the M7 side’s pinmux routines.

Pinmux & Resource Conflicts:

  • On i.MX8MP, IOMUXC (the pin mux and pad configuration controller) is used by both A53 (Linux) and M7 (RTOS/Baremetal) cores.
  • If the M7 firmware configures any pins or pads that overlap with or are in the same IOMUXC register bank as used for eth0 (EQOS or FEC controller pins for ethernet), it may inadvertently alter the settings applied by Linux.
  • Even if the specific pins differ, if any pad config or IOMUXC settings affect shared resources, you may see such conflicts.

Recommendations:

  • Double-check the pin list for the Ethernet MAC you’re using (eth0 = EQOS on Verdin iMX8MP). See the Verdin iMX8M Plus datasheet and the Mallow carrier board pinout for details.
  • Confirm nothing in BOARD_InitPins in your M7 firmware is touching any pad or mux involved with EQOS (reference the Verdin Family Spec Table 5–3). For EQOS (eth0) on Verdin iMX8MP, this typically involves ENET_MDC, ENET_MDIO, EQOS_RX*, EQOS_TX*, EQOS_CRS_DV, EQOS_REF_CLK, etc.
  • Try running the M7 core without any pin configuration (comment out BOARD_InitPins calls unless needed for your specific needs) and see if eth0 works as expected. Gradually reintroduce your required configs, verifying that each does not overlap with EQOS.

IO Bank Interactions:

  • IOMUXC pad setting “banks” (internal register layout) rarely cause conflicts unless different cores write to the same register or to adjacent pads with some shared bits—but always best to verify that unrelated pin settings do not affect Ethernet pads.

2. Why Does eth0 Take ~11 Seconds to Link Up?

The ~11 seconds delay is typical in some embedded systems and is often due to:

  • Autonegotiation: The PHY and MAC negotiate speed/duplex with the switch/router—this can add several seconds.
  • DHCP client timeout: Linux waits while requesting a lease; if the network or switch is not instantly ready, this adds seconds.

Speeding Up:

  • If fast link is critical, set the link to static or fixed parameters in the kernel device tree or your network manager configuration, and/or use a static IP (no DHCP).
  • You may also want to examine your switch/router settings.

3. Why Does tdx-info Report “Verdin Development Board” and Not “Mallow”?

  • This is just a detection artifact. The tdx-info tool checks for specific board EEPROM signatures or I2C bus markers.
  • On new carrier boards (like Mallow), if EEPROM is not programmed with an identifier, or if the board-id overlay is not updated, it may default to “Verdin Development Board.” This does not affect function, but accurate carrier autodetect may require updated software support.
  • The Mallow Carrier Board is fully compatible with Verdin iMX8M Plus, and software support is being updated in ongoing releases.

Summary/Checklist

  1. Pinmux: Carefully audit your M7 firmware’s use of IOMUXC—do not touch any pads used by EQOS or FEC interfaces.
  2. Test: Temporarily remove all pinmux from M7 firmware and confirm if eth0 works as expected.
  3. Link delay: Typical; may improve with static network config.
  4. tdx-info: Harmless cosmetic issue, not functional. Software updates may address this.

Resources:

If you have a specific pin in question or further log output, feel free to share! Let me know if this helps or if you need a deeper look at your specific firmware’s pinmuxing.

Best regards,
Toradex AI Assistant.