--- /dev/null
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -103,10 +103,30 @@ static u32 _mtk_mdio_write(struct mtk_et
+
+ write_data &= 0xffff;
+
+- mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_WRITE |
+- (phy_register << PHY_IAC_REG_SHIFT) |
+- (phy_addr << PHY_IAC_ADDR_SHIFT) | write_data,
+- MTK_PHY_IAC);
++ if (phy_register & MII_ADDR_C45) {
++ u8 dev_num = (phy_register >> 16) & 0x1f;
++ u16 reg = (u16)(phy_register & 0xffff);
++
++ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_SET_ADDR |
++ (phy_addr << PHY_IAC_ADDR_SHIFT) |
++ (dev_num << PHY_IAC_REG_SHIFT) |
++ reg,
++ MTK_PHY_IAC);
++
++ if (mtk_mdio_busy_wait(eth))
++ return 0xffff;
++
++ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_WRITE |
++ (phy_addr << PHY_IAC_ADDR_SHIFT) |
++ (dev_num << PHY_IAC_REG_SHIFT) |
++ write_data,
++ MTK_PHY_IAC);
++ } else {
++ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_WRITE |
++ (phy_register << PHY_IAC_REG_SHIFT) |
++ (phy_addr << PHY_IAC_ADDR_SHIFT) | write_data,
++ MTK_PHY_IAC);
++ }
+
+ if (mtk_mdio_busy_wait(eth))
+ return -1;
+@@ -121,10 +141,29 @@ static u32 _mtk_mdio_read(struct mtk_eth
+ if (mtk_mdio_busy_wait(eth))
+ return 0xffff;
+
+- mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_READ |
+- (phy_reg << PHY_IAC_REG_SHIFT) |
+- (phy_addr << PHY_IAC_ADDR_SHIFT),
+- MTK_PHY_IAC);
++ if (phy_reg & MII_ADDR_C45) {
++ u8 dev_num = (phy_reg >> 16) & 0x1f;
++ u16 reg = (u16)(phy_reg & 0xffff);
++
++ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_SET_ADDR |
++ (phy_addr << PHY_IAC_ADDR_SHIFT) |
++ (dev_num << PHY_IAC_REG_SHIFT) |
++ reg,
++ MTK_PHY_IAC);
++
++ if (mtk_mdio_busy_wait(eth))
++ return 0xffff;
++
++ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_READ_C45 |
++ (phy_addr << PHY_IAC_ADDR_SHIFT) |
++ (dev_num << PHY_IAC_REG_SHIFT),
++ MTK_PHY_IAC);
++ } else {
++ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_READ |
++ (phy_reg << PHY_IAC_REG_SHIFT) |
++ (phy_addr << PHY_IAC_ADDR_SHIFT),
++ MTK_PHY_IAC);
++ }
+
+ if (mtk_mdio_busy_wait(eth))
+ return 0xffff;
+@@ -584,6 +623,7 @@ static int mtk_mdio_init(struct mtk_eth
+ eth->mii_bus->name = "mdio";
+ eth->mii_bus->read = mtk_mdio_read;
+ eth->mii_bus->write = mtk_mdio_write;
++ eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
+ eth->mii_bus->priv = eth;
+ eth->mii_bus->parent = eth->dev;
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -340,9 +340,12 @@
+ /* PHY Indirect Access Control registers */
+ #define MTK_PHY_IAC 0x10004
+ #define PHY_IAC_ACCESS BIT(31)
++#define PHY_IAC_SET_ADDR 0
+ #define PHY_IAC_READ BIT(19)
++#define PHY_IAC_READ_C45 (BIT(18) | BIT(19))
+ #define PHY_IAC_WRITE BIT(18)
+ #define PHY_IAC_START BIT(16)
++#define PHY_IAC_START_C45 0
+ #define PHY_IAC_ADDR_SHIFT 20
+ #define PHY_IAC_REG_SHIFT 25
+ #define PHY_IAC_TIMEOUT HZ