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.

Hi @erikr !

Regarding the Ethernet not coming up when Cortex-M7 is running, it is likely that the M7 is indeed using some resource (like a pin) that is somewhat shared/related with something used by the Ethernet.

This is a nice recommendation from ToradexAI. Adding pins to your firmware one by one is a nice and effective way to find the culprit(s) - there might be more than one.

From the code you shared, these are the pins you are using, correct? I got their names from the code you shared and searched for them in imx8mp-verdin.dtsi « freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules.

IOMUXC_GPIO1_IO01_GPIO1_IO01    pinctrl_gpio2       SODIMM 208
IOMUXC_GPIO1_IO05_GPIO1_IO05    pinctrl_gpio3       SODIMM 210
IOMUXC_GPIO1_IO06_GPIO1_IO06    pinctrl_gpio4       SODIMM 212
IOMUXC_SAI5_MCLK_GPIO3_IO25     pinctrl_sai1        SODIMM 30
IOMUXC_SAI1_RXD0_GPIO4_IO02     pinctrl_sai1        SODIMM 36
IOMUXC_SAI1_MCLK_GPIO4_IO20     pinctrl_sai1        SODIMM 38
IOMUXC_UART1_RXD_UART1_RX       pinctrl_uart1       SODIMM 133
IOMUXC_UART1_TXD_UART1_TX       pinctrl_uart1       SODIMM 129
IOMUXC_I2C3_SCL_I2C3_SCL        pinctrl_i2c3(_gpio) SODIMM 95
IOMUXC_I2C3_SDA_I2C3_SDA        pinctrl_i2c3(_gpio) SODIMM 93
IOMUXC_I2C4_SCL_I2C4_SCL        pinctrl_i2c4(_gpio) SODIMM 14
IOMUXC_I2C4_SDA_I2C4_SDA        pinctrl_i2c4(_gpio) SODIMM 12
IOMUXC_UART4_RXD_UART4_RX       pinctrl_uart4       SODIMM 151
IOMUXC_UART4_TXD_UART4_TX       pinctrl_uart4       SODIMM 153
IOMUXC_SPDIF_EXT_CLK_PWM1_OUT   pinctrl_pwm_1       SODIMM 15
IOMUXC_SAI5_RXD1_GPIO3_IO22     pinctrl_sai1        SODIMM 32
IOMUXC_SAI5_RXFS_GPIO3_IO19     pinctrl_sai1        SODIMM 34
IOMUXC_SPDIF_TX_GPIO5_IO03      pinctrl_flexcan1    SODIMM 20

At first glance, there is nothing that directly relates to Ethernet. But if any of these pins are in the same GPIO bank as, e.g. a pin used for Ethernet, this might cause issues. It happens because from Linux point of view, a GPIO bank (gpiochip) is one single device, therefore the GPIO driver takes ownership.

Another thing to check: on Cortex-M7 firmware, are you manipulating (e.g. disabling) any clock or power domain? This might impact other resources/interfaces.

Could you check in your boot log when the Ethernet driver is probed? Looking at the tests we have, it is only 3 seconds between the probe of the driver and the link coming up:

kern  :info  : [    7.231055] imx-dwmac 30bf0000.ethernet eth0: PHY [stmmac-0:07] driver [Microchip KSZ9131 Gigabit PHY] (irq=86)
kern  :info  : [    7.236766] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-0
kern  :info  : [    7.237228] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-1
kern  :info  : [    7.237737] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-2
kern  :info  : [    7.238197] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-3
kern  :info  : [    7.238569] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-4
kern  :info  : [    7.249462] imx-dwmac 30bf0000.ethernet eth0: No Safety Features support found
kern  :info  : [    7.249495] imx-dwmac 30bf0000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
kern  :info  : [    7.249792] imx-dwmac 30bf0000.ethernet eth0: registered PTP clock
kern  :info  : [    7.250335] imx-dwmac 30bf0000.ethernet eth0: FPE workqueue start
kern  :info  : [    7.250353] imx-dwmac 30bf0000.ethernet eth0: configuring for phy/rgmii-id link mode
kern  :info  : [    7.253355] 8021q: adding VLAN 0 to HW filter on device eth0
kern  :notice: [    7.484498] audit: type=1334 audit(1750530862.532:12): prog-id=15 op=LOAD
kern  :notice: [    7.484586] audit: type=1334 audit(1750530862.532:13): prog-id=16 op=LOAD
kern  :info  : [    7.677655] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
kern  :info  : [   10.612102] imx-dwmac 30bf0000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
kern  :info  : [   10.612128] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

If you need the Ethernet to be available earlier, you will need to customize the boot of your image.

Could you please share more details on why 11s for the “Link Up” is not good enough for your use case?

This means that you are probably using Verdin Development Board’s device tree on your image. If you want to use a different device tree, you can change it directly on your image:

For production, you should customize it on Yocto (this might be helpful: Device Tree Technical Overview | Toradex Developer Center).

Best regards,

1 Like

Hi @henrique.tx !

Thank you for this answer, and sorry for the long response time.

We will look some more into this, and I will answer your questions when I have time.

Hi @henrique.tx,

Sorry for the long response time.

The pins we are using are matching the ones you shared in the previous reply. Last time i check, there are pins that we use that are in the same GPIO bank as the Ethernet, which was my initial suspicion.

Blockquote
Another thing to check: on Cortex-M7 firmware, are you manipulating (e.g. disabling) any clock or power domain? This might impact other resources/interfaces.

I am pretty sure we are not manipulating any clock or power domain. We are using a timer interrupt on the M7, but no other changes to power domain via RTOS or otherwise.

Blockquote
Could you please share more details on why 11s for the “Link Up” is not good enough for your use case?

For the Link up time, the goal is just to get the IPv6 link established as soon as possible to optimize the start up time of the M7 firmware.

We found a nice solution using a override wait conf on eth0, which will work for us for now, and we can probably tinker a bit with static IPs and the DHCP configuration we have to lower the Link up time further if we want to.

When checking the boot log, i can see that the Ethernet driver is probed, and around 12 seconds later, the IPv6 link is established:

[    7.946277] imx-dwmac 30bf0000.ethernet eth0: PHY [stmmac-0:07] driver [Microchip KSZ9131 Gigabit PHY] (irq=84)
[    7.965711] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-0
[    7.977251] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-1
[    7.988899] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-2
[    8.000443] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-3
[    8.012039] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-4
[    8.032872] imx-dwmac 30bf0000.ethernet eth0: No Safety Features support found
[    8.044014] imx-dwmac 30bf0000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[    8.056847] imx-dwmac 30bf0000.ethernet eth0: registered PTP clock
[    8.067247] imx-dwmac 30bf0000.ethernet eth0: FPE workqueue start
[    8.077266] imx-dwmac 30bf0000.ethernet eth0: configuring for phy/rgmii-id link mode
[    8.091890] 8021q: adding VLAN 0 to HW filter on device eth0
[   20.831761] imx-dwmac 30bf0000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx

Best regards,
erikr