[RFC PATCH net-next v3 5/5] net: phy: qca83xx: disable SmartSpeed before resetting CPU PHYs
From: Yongzhao Chen
Date: Wed Sep 23 2026 - 18:03:06 EST
For flagged QCA8337 CPU PHYs, clear the SmartSpeed enable and
bypass-timer bits before invoking genphy_soft_reset(). The register
update preserves all other bits, and an MDIO read or write error
prevents the reset. Reapply the clear prior to soft reset on system
resume. Unflagged QCA8337 PHYs and QCA8327 retain their standard reset
sequence.
The quirk flag is set on phydev before phy_init_hw() calls soft_reset();
config_init() executes after the reset completes, and generic
config_aneg() remains in use. In the RA74 diagnostic trace, generic
config_aneg() preserved CTRL1000 at 0x0600 and returned success, yet a
later read returned 0x0400. The trace verified that no intervening
writes occurred via the instrumented Clause 22 BMCR and CTRL1000 path,
though it did not isolate the precise timing or cause of the change. A
read value of 0x0400 reflects the advertised capability rather than an
active negotiated link speed.
Disabling SmartSpeed before the initial reset maintained a 1 Gb/s
internal link during the tested RA74 boot sequence. The experiment did
not establish a broken pair condition or a functional fallback to 100
Mb/s. Board support for the RA74 is not included in this series.
Link: https://github.com/openwrt/openwrt/issues/24696
Signed-off-by: Yongzhao Chen <yongzhao.derek@xxxxxxxxx>
Assisted-by: LLM
---
drivers/net/phy/qcom/qca83xx.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/qcom/qca83xx.c b/drivers/net/phy/qcom/qca83xx.c
index 0f484cdfe..21ab015f6 100644
--- a/drivers/net/phy/qcom/qca83xx.c
+++ b/drivers/net/phy/qcom/qca83xx.c
@@ -91,6 +91,28 @@ static int qca83xx_probe(struct phy_device *phydev)
return 0;
}
+static int qca8337_disable_smartspeed(struct phy_device *phydev)
+{
+ if (!(phydev->dev_flags & QCA8K_DEVFLAGS_NO_SMARTSPEED))
+ return 0;
+
+ /* SmartSpeed settings take effect at software reset. */
+ return phy_clear_bits(phydev, AT803X_SMART_SPEED,
+ AT803X_SMART_SPEED_ENABLE |
+ AT803X_SMART_SPEED_BYPASS_TIMER);
+}
+
+static int qca8337_soft_reset(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = qca8337_disable_smartspeed(phydev);
+ if (ret)
+ return ret;
+
+ return genphy_soft_reset(phydev);
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -160,6 +182,11 @@ static int qca83xx_resume(struct phy_device *phydev)
/* Reinit the port, reset values set by suspend */
qca83xx_config_init(phydev);
+ /* Reapply the CPU PHY quirk before the resume reset. */
+ ret = qca8337_disable_smartspeed(phydev);
+ if (ret)
+ return ret;
+
/* Reset the port on port resume */
phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
@@ -218,7 +245,7 @@ static struct phy_driver qca83xx_driver[] = {
.probe = qca83xx_probe,
.flags = PHY_IS_INTERNAL,
.config_init = qca83xx_config_init,
- .soft_reset = genphy_soft_reset,
+ .soft_reset = qca8337_soft_reset,
.get_sset_count = qca83xx_get_sset_count,
.get_strings = qca83xx_get_strings,
.get_stats = qca83xx_get_stats,
--
2.43.0