--- /dev/null
+From 63161fb6353493c648a260244f6ac7eca65fd48e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jakub=20Van=C4=9Bk?= <linuxtardis@gmail.com>
+Date: Mon, 2 Mar 2026 20:31:37 +0100
+Subject: [PATCH] net: phy: Work around MDIO collisions in the YT8821 driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The Cudy M3000 router suffers from a MDIO bus collision:
+- The MT7981B internal gigabit PHY listens on address 0.
+- The Motorcomm YT8821 is strapped to listen on address 1,
+ but it initially also listens on address 0 (Motorcomm
+ incorrectly considers that address a broadcast address).
+
+Without this patch, the YT8821 reacts to MDIO commands intended
+for the internal gigabit PHY and that makes it work unreliably.
+The YT8821 state somehow gets corrupted by the commands for the MT7981
+(e.g. we get 100Mbps speeds on gigabit links).
+
+This dirty workaround resets the PHY to cancel out any earlier
+YT8821 register corruption and then it disables the address 0
+as soon as possible. This should make the YT8821 work reliably.
+
+BEWARE though: the PHY will be reset only if the device tree
+node that defines the PHY carries the reset-gpios attribute.
+The PHY will not be reset if the reset GPIO is either on the MDIO
+bus node or is not defined at all. This might not always be a problem --
+some routers do not require the PHY to be reset (e.g. Cudy WR3000H,
+where there likely is less communication with the MT7981B PHY,
+and so the YT8821 PHY works reasonably well there even without this patch).
+
+This patch also does not address the possible MDIO bus collisions
+when the MT7981B PHY driver initially configures that PHY and invokes
+some read transactions on the bus. I am hoping that the MT7981B MDIO
+bus controller gives priority to the internal PHY and so it would
+not be affected by these collisions. However, I don't have anything
+to base this on apart from it "seeming to be working okay".
+
+This patch is unlikely to be mergeable into the mainline kernel.
+Upstream has strongly indicated that they would prefer this problem
+to be resolved by the platform bootloader (e.g. U-Boot), see
+- https://lore.kernel.org/all/d3bb9c36-5a0e-4339-901d-2dd21bdba395@gmail.com/
+- https://lore.kernel.org/all/20260228232241.1274236-1-linuxtardis@gmail.com/
+
+Signed-off-by: Jakub Vaněk <linuxtardis@gmail.com>
+---
+ drivers/net/phy/motorcomm.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/net/phy/motorcomm.c
++++ b/drivers/net/phy/motorcomm.c
+@@ -214,6 +214,9 @@
+ #define YT8521_RC1R_RGMII_2_100_NS 14
+ #define YT8521_RC1R_RGMII_2_250_NS 15
+
++#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)
+@@ -2659,6 +2662,23 @@ static int yt8821_config_init(struct phy
+ int ret;
+ u16 set;
+
++ /* Hard-reset the PHY to clear out any register corruption
++ * from preceding MDIO bus conflicts.
++ */
++ phy_device_reset(phydev, 1);
++
++ /* Deassert the reset GPIO under the MDIO bus lock to make
++ * sure that nothing will communicate on the bus until we
++ * disable the broadcast address in the YT8821.
++ */
++ phy_lock_mdio_bus(phydev);
++ phy_device_reset(phydev, 0);
++ ret = ytphy_modify_ext(phydev,
++ YTPHY_MDIO_ADDRESS_CONTROL_REG,
++ YTPHY_MACR_EN_PHY_ADDR_0,
++ 0);
++ phy_unlock_mdio_bus(phydev);
++
+ if (phydev->interface == PHY_INTERFACE_MODE_2500BASEX)
+ mode = YT8821_CHIP_MODE_FORCE_BX2500;
+