Skip to main content
Version: BSP 7.x.y

Ethernet PHY Bring-up Troubleshooting (Linux)

Introduction​

This article covers Ethernet bring-up problems on a custom carrier board. It focuses on the Ethernet Media Access Control (MAC), Management Data Input/Output (MDIO) bus, physical layer transceiver (PHY), and Reduced Gigabit Media Independent Interface (RGMII) between the MAC and PHY.

If the interface negotiates a link but the device cannot reach the network, refer to Network Connectivity Troubleshooting (Linux).

The examples in this article come from bringing up the second Ethernet interface (end1) on a Verdin iMX8M Plus module, backed by the i.MX 8M Plus SoC's internal Fast Ethernet Controller (FEC). The first Ethernet interface (end0), driven by a separate MAC (imx-dwmac), is already working throughout these examples and is used as a healthy reference for comparison.

For the device tree configuration needed to enable a second Ethernet port on a custom carrier board, see Add a Second Ethernet Port.

The three cases are independent faults, each investigated with a separate board configuration. Each case starts from its own configuration rather than from the preceding case's fix.

This article complies with the Typographic Conventions for Toradex Documentation.

info

Register addresses, pinmux values, and MDIO bus device names are specific to the i.MX 8M Plus and the board used in these examples. You can apply the diagnostic techniques to other SoCs and boards, but you must verify the addresses and configuration for your hardware.

Case 1: No PHY Attached to the MDIO Bus​

In this case, the PHY is not detected, therefore, the interface fails to come up:

# ip link set end1 up
RTNETLINK answers: No such device

The ethtool and dmesg output indicates a PHY problem:

# ethtool end1
netlink error: failed to retrieve link settings
netlink error: No such device
Settings for end1:
Supports Wake-on: g
Wake-on: d
Link detected: no
# dmesg | grep -i phy
[ 10.073304] fec 30be0000.ethernet end1: Unable to connect to phy
[ 10.224160] imx-dwmac 30bf0000.ethernet end0: PHY [stmmac-0:07] driver [Microchip KSZ9131 Gigabit PHY] (irq=40)

A PHY driver binds to end0, but no PHY driver binds to end1. Confirm that no PHY device links to end1:

# readlink /sys/class/net/end1/phydev

An empty result means no PHY is bound. Check whether the MAC's MDIO bus has any device on it:

# ls /sys/class/mdio_bus/
30be0000.ethernet-1 fixed-0 stmmac-0

# ls /sys/bus/mdio_bus/devices/
stmmac-0:07

The MDIO bus for end1 (30be0000.ethernet-1) exists, meaning the MAC's MDIO controller is present, but no PHY device is attached to it, while only end0's PHY (stmmac-0:07) shows up.

Checking the Device Tree​

Confirm the MAC's device tree node has an mdio child node, and that it in turn has a child node for the PHY:

# find /sys/firmware/devicetree/ | grep "ethernet@30be0000" | grep mdio | head -1
/sys/firmware/devicetree/base/soc@0/bus@30800000/ethernet@30be0000/mdio

# ls -l /sys/firmware/devicetree/base/soc@0/bus@30800000/ethernet@30be0000/mdio/
total 0
-r--r--r-- 1 root root 4 Aug 13 19:11 '#address-cells'
-r--r--r-- 1 root root 4 Aug 13 19:11 '#size-cells'
drwxr-xr-x 2 root root 0 Aug 13 19:11 ethernet-phy@7
-r--r--r-- 1 root root 4 Aug 13 19:11 name
-r--r--r-- 1 root root 4 Aug 13 19:11 phandle

The PHY is described by the ethernet-phy@7 child node. Its reg property specifies the MDIO address that the kernel probes:

# od -An -tx1 /sys/firmware/devicetree/base/soc@0/bus@30800000/ethernet@30be0000/mdio/ethernet-phy@7/reg
00 00 00 03

The node name specifies ethernet-phy@7, but the reg property specifies address 3. The kernel uses the reg property and probes the PHY at address 3. This mismatch indicates that the device tree does not reflect the PHY's actual hardware strap address on the board.

Finding the PHY's Real Address​

If the device tree specifies an incorrect address, read the PHY's identification registers directly through the MAC's Media Independent Interface (MII) management registers. This check operates independently of the kernel's PHY framework.

In the IEEE 802.3 Clause 22 register set, register 2 (PHYIDR1) holds the upper bits of the PHY identifier. Scan all 32 MDIO addresses (0 through 31) to identify which address responds to this register read.

The register names and access procedure depend on the MAC. The scan output here comes from a purpose-written program that accesses the FEC's MII management registers. This program is not included in the Board Support Package (BSP) reference image.

On this board, the scan finds a response at address 7:

raw MDIO scan (register 2 = PHYIDR1), via fec controller registers:
addr 7: 0x0022 <-- responds

addr 7 PHY ID: 0x00221642

The board straps the PHY to address 7. Update the existing PHY node so its reg property match the hardware:

 ethernet-phy@7 {
- reg = <3>;
+ reg = <7>;
};

Rebuild and deploy only the device tree, then reboot the board. The expected results are a reg value of 7 and a PHY device on the FEC's MDIO bus:

# od -An -tx1 /sys/firmware/devicetree/base/soc@0/bus@30800000/ethernet@30be0000/mdio/ethernet-phy@7/reg
00 00 00 07

# ls /sys/bus/mdio_bus/devices/
30be0000.ethernet-1:07 stmmac-0:07

Case 2: The PHY Answers With All Zeros​

In this case, the device tree specifies the PHY's actual address, and the bus detects the device. However, the interface still shows an inconsistency:

# ip link show end1
2: end1: <NO-CARRIER,BROADCAST,MULTICAST,DYNAMIC,UP> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000

# ip link set end1 up

# ip link show end1
2: end1: <NO-CARRIER,BROADCAST,MULTICAST,DYNAMIC,UP> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000

ip link set completes without an error, but the link still doesn't come up:

# ethtool end1
Settings for end1:
Supported ports: [ ]
Supported link modes: Not reported
Supports auto-negotiation: No
Speed: Unknown!
Duplex: Unknown! (255)
Auto-negotiation: off
Port: MII
PHYAD: 7
Transceiver: external
Link detected: no

Compare the preceding result with the healthy end0 link, which reports Gigabit Ethernet, full-duplex operation, and enabled autonegotiation.

# ethtool end0
Settings for end0:
Supported ports: [ TP MII ]
Supported link modes: 10baseT/Full
100baseT/Full
1000baseT/Full
Supported pause frame use: Symmetric Receive-only
Supports auto-negotiation: Yes
[...]
Link detected: yes

In contrast, end1 reports no valid link information, which indicates an issue with the PHY rather than with the cable or link negotiation:

# ls /sys/class/mdio_bus/
30be0000.ethernet-1 fixed-0 stmmac-0

# ls /sys/bus/mdio_bus/devices/
30be0000.ethernet-1:07 stmmac-0:07

# cat /sys/bus/mdio_bus/devices/30be0000.ethernet-1\:07/phy_id
0x00000000

# readlink -f /sys/bus/mdio_bus/devices/30be0000.ethernet-1:07/driver
/sys/bus/mdio_bus/drivers/Generic Clause 45 PHY

A device appears at address 7, but its phy_id value is 0x00000000. A valid PHY does not return an all-zero identifier.

The kernel therefore binds a generic PHY driver instead of the expected PHY-specific driver. A direct MDIO bus scan confirms that every address returns zero:

raw MDIO scan (register 2 = PHYIDR1), via fec controller registers:
ALL 32 addresses read 0x0000.

Use the following rule of thumb when all addresses in an MDIO bus scan return the same value:

Value returnedLikely cause
0xffffThe MDIO line remains high, and no PHY responds due to an unpowered PHY, a PHY held in reset, a missing PHY, or a missing PHY clock.
0x0000The MDIO line remains low, or communication with the PHY fails due to incorrect pin multiplexing, a signal held low, or a broken MDIO signal path.

On the i.MX 8M Plus, the Input/Output Multiplexer Controller (IOMUXC) configures pad multiplexing through the SW_MUX_CTL_PAD registers at base address 0x30330000.

On this board, the pads carrying the Management Data Clock (MDC) and MDIO signals have mux register offsets of +0x158 and +0x15c. Read these registers to check their selected functions:

# busybox devmem 0x30330158 32      # MDC
Read at address 0x30330158 (...): 0x00000005

# busybox devmem 0x3033015c 32 # MDIO
Read at address 0x3033015C (...): 0x00000005

On these pads, mux value 5 selects ALT5, the General-Purpose Input/Output (GPIO) function. Value 4 selects ALT4, the Ethernet (ENET) function. Both pads are configured as GPIO, disconnecting the MAC's management signals from the PHY.

In the existing device tree pin configuration, replace the GPIO function macros with the ENET function macros. Preserve the board's pad control values and the other entries in fsl,pins:

-MX8MP_IOMUXC_SAI1_RXD2__GPIO4_IO04
-MX8MP_IOMUXC_SAI1_RXD3__GPIO4_IO05
+MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC
+MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO

These function macros are defined in the Toradex downstream Linux kernel's pin definitions or in the upstream Linux kernel's pin definitions, according to the Linux kernel that is being used.

Rebuild and deploy only the device tree, then reboot the board. After rebooting, check that the mux mode bits (bits 2:0) in both registers select ALT4. Verify that the PHY identifier matches the expected value:

# cat /sys/bus/mdio_bus/devices/30be0000.ethernet-1:07/phy_id
0x00221642

The driver path should identify the PHY-specific driver instead of the generic driver:

# readlink -f /sys/bus/mdio_bus/devices/30be0000.ethernet-1:07/driver
/sys/bus/mdio_bus/drivers/Microchip KSZ9131 Gigabit PHY
info

The SoC defines the IOMUXC register offsets and ALT values described in this case, while the board design determines which pads carry the MDC and MDIO signals.

Before applying these settings to different hardware, verify the pad assignments for the target design and the corresponding mux options in the applicable SoC documentation.

In this case the MDIO path is healthy from the start, and the PHY negotiates a link normally:

# ip link show end1
2: end1: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000

# ethtool end1
Settings for end1:
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes

The Dynamic Host Configuration Protocol (DHCP) client does not obtain a lease. Assign a static IP address and test connectivity with the ping command:

# ip addr add 192.168.50.21/24 dev end1

# ping 192.168.50.1
PING 192.168.50.1 (192.168.50.1): 56 data bytes
--- 192.168.50.1 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

The negotiated link confirms that PHY link negotiation succeeds. It does not establish that the MAC-to-PHY data path works in both directions.

Ping requires both receive (RX) and transmit (TX) traffic, so packet loss alone cannot identify the failing direction. Compare the interface counters before and after a ping:

# ip -s link show end1
2: end1: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
RX: bytes packets errors dropped missed mcast
10398 39 0 0 0 0
TX: bytes packets errors dropped carrier collsns
35632 128 0 0 0 0

# ping 192.168.50.1
PING 192.168.50.1 (192.168.50.1): 56 data bytes
--- 192.168.50.1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss

# ip -s link show end1
2: end1: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
RX: bytes packets errors dropped missed mcast
10398 39 0 0 0 0
TX: bytes packets errors dropped carrier collsns
35758 131 0 0 0 0

The TX packet count increases with every ping attempt, while the RX packet count remains unchanged and no errors are reported. To verify RX independently, generate traffic from a peer and monitor the RX counter:

# cat /sys/class/net/end1/statistics/rx_packets
43

On a test computer on the same network segment, nmap -sn sends ARP requests to addresses in the specified range. On a local Ethernet network, Nmap uses ARP rather than ICMP for host discovery because ARP operates at Layer 2 and does not depend on the target responding to ping.

Because ARP requests are broadcast, every station on the segment receives them, regardless of the target IP address.

$ nmap -sn 192.168.50.100-130
Starting Nmap 7.99 ( https://nmap.org ) at 2026-08-14 18:13 -0300
Nmap done: 31 IP addresses (0 hosts up) scanned in 4.31 seconds
# cat /sys/class/net/end1/statistics/rx_packets
152

The counter increased, confirming that RX is working and the MAC is receiving frames from the peer. The failure is therefore isolated to the transmit path, after the frame leaves the MAC:

# ip -s link show end1
2: end1: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
RX: bytes packets errors dropped missed mcast
18136 152 0 0 0 0
TX: bytes packets errors dropped carrier collsns
80374 295 0 0 0 0

The PHY negotiates a link, RX frames arrive without errors, and Internet Protocol (IP) configuration is in place. Investigate the transmit path for hardware faults or configuration errors.

RGMII and Internal Delay​

RGMII is a source-synchronous interface: the transmitter drives both the clock and data signals. For reliable sampling, the receiver's clock edge must occur within the data-valid window, with sufficient setup and hold margin.

RGMII implementations add a delay (clock skew) between the clock and data signals. This delay moves the sampling edge away from the data transition and toward the middle of the data-valid window.

RGMII originated as a vendor specification. It operates alongside the IEEE 802.3 Gigabit Media Independent Interface (GMII) and MII standards, but IEEE 802.3 does not define RGMII timing.

In modern designs, either the PHY or the MAC (or both) can be configured to add this delay internally, instead of relying on an intentionally longer Printed Circuit Board (PCB) clock trace. The delay has to exist once in each direction because RX and TX are independent. The Linux kernel's device tree binding for RGMII interfaces (phy-mode) expresses which side is expected to add it:

phy-mode valueMeaning
rgmiiNo internal delay added. RX and TX delays are expected from the PCB.
rgmii-idInternal delay added on both RX and TX.
rgmii-rxidInternal delay added on RX only. TX delay is still expected from the PCB.
rgmii-txidInternal delay added on TX only. RX delay is still expected from the PCB.

Few PCB designs add enough trace length to provide the delay required by rgmii, rgmii-rxid, or rgmii-txid in the direction where no internal delay is applied. Therefore, most designs use rgmii-id.

Check the module's device tree to identify the mismatch:

# cat /proc/device-tree/soc@0/bus@30800000/ethernet@30be0000/phy-mode
rgmii-rxid

rgmii-rxid adds internal delay only to the RX path, leaving the TX path without the required delay. This matches the observed behavior: RX works, while TX fails. Set phy-mode to rgmii-id to enable internal delay for both directions:

-phy-mode = "rgmii-rxid";
+phy-mode = "rgmii-id";

Rebuild and deploy only the device tree, then reboot. With a static address configured, the expected result is successful communication:

# cat /proc/device-tree/soc@0/bus@30800000/ethernet@30be0000/phy-mode
rgmii-id

# ip addr show end1
2: end1: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
inet 192.168.50.47/24 brd 192.168.50.255 scope global end1
valid_lft forever preferred_lft forever

# ping 192.168.50.1
PING 192.168.50.1 (192.168.50.1): 56 data bytes
64 bytes from 192.168.50.1: seq=0 ttl=64 time=1.144 ms
64 bytes from 192.168.50.1: seq=1 ttl=64 time=1.128 ms
--- 192.168.50.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.128/1.136/1.144 ms
tip
  • Each RGMII direction requires the appropriate delay. A phy-mode that covers only one direction is likely incorrect unless the PCB provides the required delay for the other direction through trace routing.
  • The MAC or PHY can add the delay, depending on the design. Some PHYs also use strapping pins or registers to configure it independently. If communication still fails after correcting phy-mode, verify the delay configuration on both sides.
  • An RX-only or TX-only failure can also indicate a hardware issue, such as swapped or inverted RGMII clock or data lines. Treat a phy-mode mismatch as one possible cause, not the only one.

Hardware-Focused ethtool Checks​

Driver Information​

The ethtool -i command identifies the driver bound to a network interface. Different MAC drivers support different features:

# ethtool -i end1
driver: fec
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: yes
# ethtool -i end0
driver: st_gmac
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: yes

The end0 driver does not support the self-test, while end1 does. Make sure to check supports-test and supports-eeprom-access values before using these features.

For end0, ethtool -i reports the driver as st_gmac, while the kernel log identifies the platform driver as imx-dwmac. Both refer to the same Synopsys DesignWare MAC. The imx-dwmac driver provides the i.MX-specific integration, while the shared stmmac core reports st_gmac to ethtool.

Self-Test​

ethtool -t runs the driver's self-test when the driver supports this feature. Depending on the implementation, the test can include internal loopback checks across the local MAC, RGMII, and PHY path. After the PHY negotiates a link, this test can help isolate issues in the local Ethernet path.

The self-test requires a carrier. With a faulty or disconnected cable, it fails because the link cannot be established:

# ethtool -t end1
The test result is FAIL
The test extra info:
1. Carrier -67
2. PHY dev is present 0
3. PHY internal loopback, enab 0
4. PHY internal loopback, UDP -101
5. PHY internal loopback, MTU -101
6. PHY internal loopback, TCP -101
7. PHY internal loopback, disa 0

With a working cable and an established link, the test passes. During the test, the driver temporarily brings the link down and then restores it:

# ethtool -t end1
The test result is PASS
[ 3377.964196] fec 30be0000.ethernet end1: Link is Down
The test extra info:
1. Carrier 0
2. PHY dev is present 0
3. PHY internal loopback, enab 0
4. PHY internal loopback, UDP 0
5. PHY internal loopback, MTU 0
6. PHY internal loopback, TCP 0
7. PHY internal loopback, disa 0
[ 3381.498830] fec 30be0000.ethernet end1: Link is Up - 1Gbps/Full - flow control rx/tx

Additional Resources​

Send Feedback!