net: phy: motorcomm: YT8531 clock output (0xA012) lost after PHY reset, TX dead until reboot

flat view

From: Keith Harvey <hidden>
Date: 2026-10-26 15:18:43

(Resending as plain text: netdev rejected my first copy for an HTML part.
Apologies to those who received it twice.)

Hi,

On a board with a YT8531 PHY and a reset-gpios line, closing and re-opening the
interface leaves the PHY's clock output at its reset default instead
of the value
from "motorcomm,clk-out-frequency-hz". On this board, transmit then
stops working
until a reboot.

Hardware/software
-----------------
- Xunlong Orange Pi R1 Plus LTS (RK3328, rk_gmac-dwmac, YT8531 at stmmac-0:00)
- OpenWrt 25.12.5, kernel 6.12.94
- PHY node has: reset-gpios, motorcomm,clk-out-frequency-hz = <125000000>,
motorcomm,auto-sleep-disabled, motorcomm,keep-pll-enabled,
motorcomm,rx-clk-drv-microamp, motorcomm,rx-data-drv-microamp

Reproducer
----------
ip link set eth0 down; sleep 3; ip link set eth0 up

Ext reg 0xA012 (YTPHY_SYNCE_CFG_REG), read via 0x1e/0x1f:
before: 0x00d0 (SyncE on, 125M select, source PLL_125M)
after: 0x00c8 (SyncE on, 25M, source REF_25M)

After the down/up the link comes back at 1Gbps/Full and RX keeps working, but
nothing transmitted gets an answer: DHCP discovers are seen leaving the
interface in tcpdump, but no offer ever comes back. The driver reports no TX
errors and the TX descriptor ring is empty. Writing 0x00d0 back to 0xA012 by
hand restores TX within seconds, without a reboot. A reboot also fixes it.

The same state also happened without a manual trigger: after about 5 days of
uptime the stmmac TX watchdog fired ("NETDEV WATCHDOG: CPU: 2: transmit queue 0
timed out 5420 ms", "Reset adapter"). The interface stayed dead after the
adapter reset, and 0xA012 read 0x00c8 in that state as well.

Cause (from the source)
-----------------------
In drivers/net/phy/motorcomm.c (v6.12, and unchanged in mainline as of
fc697291ad0a) the clock output from motorcomm,clk-out-frequency-hz is written to
YTPHY_SYNCE_CFG_REG only in yt8531_probe(). phy_detach() asserts the reset
(phy_device_reset(phydev, 1)) and phy_init_hw() deasserts it again on the next
attach, then calls yt8531_config_init(). config_init re-applies the
RGMII delays,
auto-sleep, keep-pll and drive strength, but not the clock output, so 0xA012
keeps its reset value until the next probe.

On this board the GMAC appears to take its clock from the PHY's clock output,
which would explain RX working while TX does not. That part is my reading of the
setup, not something I have confirmed on the schematic.

Workaround tested
-----------------
A small out-of-tree module that registers a PHY fixup for 0x4f51e91b and sets
0xA012 the same way as the YTPHY_DTS_OUTPUT_CLK_125M case in yt8531_probe().
Fixups run in phy_init_hw() after the reset is deasserted. With it loaded, the
same down/up logs "0xa012 0x00c8 -> 0x00d0", and the WAN gets its DHCP
lease back
in about 4 seconds.

The fix in the driver is probably to apply the clock output setting from
yt8531_config_init() as well as (or instead of) yt8531_probe(). I am happy to
test a patch on this board.

Thanks,
Keith Harvey
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help