[PATCH net-next v2 5/5] net: phy: motorcomm: yt8821: Disable MDIO broadcast
From: Jakub Vaněk
Date: Sat Feb 28 2026 - 18:24:11 EST
By default, the YT8821 responds at two MDIO addresses: the address
selected by its strapping pins and the broadcast address 0.
This causes problems if another PHY is legitimately configured
at address 0.
Disable the broadcast address using two mechanisms. The PHY fixup
prevents collisions during initial MDIO bus scanning.
yt8821_config_init() then re-disables the broadcast address if the
PHY goes through a hardware reset (this happens if the PHY has a
reset GPIO on its device tree node, and the interface is brought
down and up).
Link: https://github.com/openwrt/openwrt/pull/21584
Fixes: b671105b88c3 ("net: phy: Add driver for Motorcomm yt8821 2.5G ethernet phy")
Signed-off-by: Jakub Vaněk <linuxtardis@xxxxxxxxx>
---
drivers/net/phy/motorcomm.c | 29 +++++++++++++++++++++++++
drivers/net/phy/phy_common_fixups.c | 33 +++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 4d62f7b36212..e1503fab568a 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -227,6 +227,9 @@
#define YT8521_LED_100_ON_EN BIT(5)
#define YT8521_LED_10_ON_EN BIT(4)
+#define YTPHY_MDIO_ADDRESS_CONTROL_REG 0xA005
+#define YTPHY_MACR_EN_PHY_ADDR_0 BIT(6)
+
#define YTPHY_MISC_CONFIG_REG 0xA006
#define YTPHY_MCR_FIBER_SPEED_MASK BIT(0)
#define YTPHY_MCR_FIBER_1000BX (0x1 << 0)
@@ -2764,6 +2767,28 @@ static int yt8821_soft_reset(struct phy_device *phydev)
YT8521_CCR_SW_RST, 0);
}
+/**
+ * yt8821_disable_mdio_address_zero() - disable MDIO broadcast address 0
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * The YT8821 responds on two MDIO addresses by default:
+ * - the address selected by its strapping pins
+ * - the broadcast address 0
+ *
+ * Some other PHYs (e.g. the MT7981B internal Gigabit PHY) are hardwired to
+ * respond only at MDIO address 0. If the YT8821 also listens on address 0,
+ * it may incorrectly react to transactions intended for those PHYs.
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8821_disable_mdio_address_zero(struct phy_device *phydev)
+{
+ return ytphy_modify_ext_with_lock(phydev,
+ YTPHY_MDIO_ADDRESS_CONTROL_REG,
+ YTPHY_MACR_EN_PHY_ADDR_0,
+ 0);
+}
+
/**
* yt8821_config_init() - phy initializatioin
* @phydev: a pointer to a &struct phy_device
@@ -2799,6 +2824,10 @@ static int yt8821_config_init(struct phy_device *phydev)
phydev->rate_matching = RATE_MATCH_PAUSE;
}
+ ret = yt8821_disable_mdio_address_zero(phydev);
+ if (ret < 0)
+ return ret;
+
ret = yt8821_serdes_init(phydev);
if (ret < 0)
return ret;
diff --git a/drivers/net/phy/phy_common_fixups.c b/drivers/net/phy/phy_common_fixups.c
index fa51c6d7b25f..5a60721b56d6 100644
--- a/drivers/net/phy/phy_common_fixups.c
+++ b/drivers/net/phy/phy_common_fixups.c
@@ -4,6 +4,32 @@
#include "phylib-internal.h"
+#define PHY_ID_YT8821 0x4f51ea19
+#define YTPHY_PAGE_SELECT 0x1E
+#define YTPHY_PAGE_DATA 0x1F
+#define YTPHY_MDIO_ADDRESS_CONTROL_REG 0xA005
+#define YTPHY_MACR_EN_PHY_ADDR_0 BIT(6)
+
+/**
+ * yt8821_disable_broadcast - Disable MDIO broadcast on address 0
+ */
+static int yt8821_disable_broadcast(struct phy_device *phydev)
+{
+ int rc = 0;
+
+ phy_lock_mdio_bus(phydev);
+
+ rc = __phy_write(phydev, YTPHY_PAGE_SELECT, YTPHY_MDIO_ADDRESS_CONTROL_REG);
+ if (rc < 0)
+ goto unlock;
+
+ rc = __phy_modify(phydev, YTPHY_PAGE_DATA, YTPHY_MACR_EN_PHY_ADDR_0, 0);
+
+unlock:
+ phy_unlock_mdio_bus(phydev);
+ return rc;
+}
+
/**
* phy_register_address_0_fixups - Register fixups for disabling MDIO
* broadcast address 0
@@ -22,5 +48,12 @@
*/
int phy_register_address_0_fixups(void)
{
+ int rc;
+
+ rc = phy_register_fixup_for_uid(PHY_ID_YT8821, 0xFFFFFFFF,
+ yt8821_disable_broadcast);
+ if (rc < 0)
+ return rc;
+
return 0;
}
--
2.43.0