diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c
index e6c06c44522..7ad9b5f0291 100644
--- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c
@@ -1622,7 +1622,7 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
 }
 
 /*
- * On all RealTek switch platforms the hardware periodically reads the link status of all
+ * On all Realtek switch platforms the hardware periodically reads the link status of all
  * PHYs. This is to some degree programmable, so that one can tell the hardware to read
  * specific C22 registers from specific pages, or C45 registers, to determine the current
  * link speed, duplex, flow-control, ...
@@ -1639,7 +1639,7 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  * abstractions.
  *
  * Additionally at least the RTL838x and RTL839x devices are known to have a so called
- * raw mode. Using the special MAX_PAGE-1 with the MDIO controller found in RealTek
+ * raw mode. Using the special MAX_PAGE-1 with the MDIO controller found in Realtek
  * SoCs allows to access the PHY in raw mode, ie. bypassing the cache and paging engine
  * of the MDIO controller. E.g. for RTL838x this is 0xfff.
  *
@@ -1648,9 +1648,9 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  * when they are not attached to an Realtek SoC. The paradigm should be to keep the PHY
  * implementation bus independent.
  *
- * As if this is not enough the PHYs consist of 8 ports that all can be programmed
- * individually. Writing to port 0 can configure the whole why while other operations
- * need to be replicated per port.
+ * As if this is not enough the PHY packages consist of 4 or 8 ports that all can be
+ * programmed individually. Some registers are only available on port 0 and configure
+ * the whole package.
  *
  * To bring all this together we need a tricky bus design that intercepts select page
  * calls but lets raw page accesses through. And especially knows how to handle raw
@@ -1661,7 +1661,7 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  * the accesses and the state of the bus with the attributes page[], raw[] and portaddr
  * of the bus_priv structure. The page selection works as follows:
  *
- * phy_write(phydev, RTL821X_PAGE_SELECT, 12)	: store internal page 12 in driver
+ * phy_write(phydev, RTMDIO_PAGE_SELECT, 12)	: store internal page 12 in driver
  * phy_write(phydev, 7, 33)			: write page=12, reg=7, val=33
  *
  * or simply
@@ -1670,8 +1670,8 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  *
  * The port selection works as follows and must be called under a held mdio bus lock
  *
- * __mdiobus_write(bus, RTL821X_PORT_SELECT, 4)	: switch to port paddr
- * __phy_write(phydev, RTL821X_PAGE_SELECT, 11)	: store internal page 11 in driver
+ * __mdiobus_write(bus, RTMDIO_PORT_SELECT, 4)	: switch to port 4
+ * __phy_write(phydev, RTMDIO_PAGE_SELECT, 11)	: store internal page 11 in driver
  * __phy_write(phydev, 8, 19)			: write page=11, reg=8, val=19, port=4
  *
  * Any Realtek PHY that will be connected to this bus must simply provide the standard
@@ -1689,75 +1689,57 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  *   return __phy_write(phydev, RTL821X_PAGE_SELECT, page);
  * }
  *
- * In case there are non Realtek PHYs attached to the logic might need to be
+ * In case there are non Realtek PHYs attached to the bus the logic might need to be
  * reimplemented. For now it should be sufficient.
  */
 
-#define RTL821X_PAGE_SELECT	0x1f
-#define RTL821X_PORT_SELECT	0x2000
-#define RTL838X_PAGE_RAW	0xfff
-#define RTL839X_PAGE_RAW	0x1fff
-#define RTL930X_PAGE_RAW	0xfff
-#define RTL931X_PAGE_RAW	0x1fff
-#define RTMDIO_READ		0x0
-#define RTMDIO_WRITE		0x1
+#define RTMDIO_PAGE_SELECT	0x1f
+#define RTMDIO_PORT_SELECT	0x2000
+#define RTMDIO_READ		0x1
+#define RTMDIO_WRITE		0x2
+#define RTMDIO_ABS		0x4
+#define RTMDIO_PKG		0x8
 
 /*
- * Provide a generic read/write function so we can access multiple ports on a shared PHY
- * package of the bus with separate addresses individually. This basically resembles the
+ * Provide a generic read/write function so we can access arbitrary ports on the bus.
+ * E.g. other ports of a PHY package on the bus. This basically resembles the kernel
  * phy_read_paged() and phy_write_paged() functions. To inform the bus that we are
- * workin on a not default port (8, 16, 24, ...) we send a RTL821X_PORT_SELECT command
- * at the beginning and the end to switch the port handling logic.
+ * working on a not default port send a RTMDIO_PORT_SELECT command at the beginning
+ * and the end to switch the port handling logic.
  */
 
-static int rtmdio_read_page(struct phy_device *phydev)
-{
-	if (WARN_ONCE(!phydev->drv->read_page,
-		      "read_page callback not available, PHY driver not loaded?\n"))
-		return -EOPNOTSUPP;
-
-	return phydev->drv->read_page(phydev);
-}
-
-static int rtmdio_write_page(struct phy_device *phydev, int page)
-{
-	if (WARN_ONCE(!phydev->drv->write_page,
-		      "write_page callback not available, PHY driver not loaded?\n"))
-		return -EOPNOTSUPP;
-
-	return phydev->drv->write_page(phydev, page);
-}
-
-static int rtmdio_package_rw(struct phy_device *phydev, int op, int port,
-			     int page, u32 regnum, u16 val)
+static int rtmdio_access(struct phy_device *phydev, int op, int port,
+			 int page, u32 regnum, u16 val)
 {
 	int r, ret = 0, oldpage;
-	struct phy_package_shared *shared = phydev->shared;
 
-	if (!shared)
-		return -EIO;
+	if (op & RTMDIO_PKG) {
+		if (!phydev->shared)
+			return -EIO;
+		port = phydev->shared->addr + port;
+	}
 
 	/* lock and inform bus about non default addressing */
 	phy_lock_mdio_bus(phydev);
 	__mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
-			RTL821X_PORT_SELECT, shared->addr + port);
+			RTMDIO_PORT_SELECT, port);
 
-	oldpage = ret = rtmdio_read_page(phydev);
+	oldpage = ret = __phy_read(phydev, RTMDIO_PAGE_SELECT);
 	if (oldpage >= 0 && oldpage != page) {
-		ret = rtmdio_write_page(phydev, page);
+		ret = __phy_write(phydev, RTMDIO_PAGE_SELECT, page);
 		if (ret < 0)
 			oldpage = ret;
 	}
 
 	if (oldpage >= 0) {
-		if (op == RTMDIO_WRITE)
+		if (op & RTMDIO_WRITE)
 			ret = __phy_write(phydev, regnum, val);
 		else
 			ret = __phy_read(phydev, regnum);
 	}
 
 	if (oldpage >= 0) {
-		r = rtmdio_write_page(phydev, oldpage);
+		r = __phy_write(phydev, RTMDIO_PAGE_SELECT, oldpage);
 		if (ret >= 0 && r < 0)
 			ret = r;
 	} else
@@ -1765,7 +1747,7 @@ static int rtmdio_package_rw(struct phy_device *phydev, int op, int port,
 
 	/* reset bus to default adressing and unlock it */
 	__mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
-			RTL821X_PORT_SELECT, 0);
+			RTMDIO_PORT_SELECT, -1);
 	phy_unlock_mdio_bus(phydev);
 
 	return ret;
@@ -1775,40 +1757,53 @@ static int rtmdio_package_rw(struct phy_device *phydev, int op, int port,
  * To make use of the shared package functions provide wrappers that align with kernel
  * naming conventions. The package() functions are useful to change settings on the
  * package as a whole. The package_port() functions will allow to target the PHYs
- * individually.
+ * of a package individually. The port() only functions allow to access arbitrary ports
+ * on the bus through a PHY.
  */
 
 int phy_package_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_WRITE, port, page, regnum, val);
+	return rtmdio_access(phydev, RTMDIO_WRITE | RTMDIO_PKG, port, page, regnum, val);
 }
 
 int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_WRITE, 0, page, regnum, val);
+	return rtmdio_access(phydev, RTMDIO_WRITE | RTMDIO_PKG, 0, page, regnum, val);
+}
+
+int phy_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val)
+{
+	return rtmdio_access(phydev, RTMDIO_WRITE | RTMDIO_ABS, port, page, regnum, val);
 }
 
 int phy_package_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_READ, port, page, regnum, 0);
+	return rtmdio_access(phydev, RTMDIO_READ | RTMDIO_PKG, port, page, regnum, 0);
 }
 
 int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnum)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_READ, 0, page, regnum, 0);
+	return rtmdio_access(phydev, RTMDIO_READ | RTMDIO_PKG, 0, page, regnum, 0);
 }
 
-/* These are the core functions of our fancy Realtek SoC MDIO bus. */
+int phy_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum)
+{
+	return rtmdio_access(phydev, RTMDIO_READ | RTMDIO_ABS, port, page, regnum, 0);
+}
+
+/* These are the core functions of our new Realtek SoC MDIO bus. */
 
 static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
 {
 	int err, val;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	err = (*bus_priv->read_mmd_phy)(portaddr, devnum, regnum, &val);
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+
+	err = (*bus_priv->read_mmd_phy)(addr, devnum, regnum, &val);
 	pr_debug("rd_MMD(adr=%d, dev=%d, reg=%d) = %d, err = %d\n",
-		 portaddr, devnum, regnum, val, err);
+		 addr, devnum, regnum, val, err);
 	return err ? err : val;
 }
 
@@ -1817,21 +1812,23 @@ static int rtmdio_83xx_read(struct mii_bus *bus, int addr, int regnum)
 	int err, val;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	if (portaddr >= 24 && portaddr <= 27 && eth_priv->id == 0x8380)
-		return rtl838x_read_sds_phy(portaddr, regnum);
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
 
-	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[portaddr])
-		return rtl839x_read_sds_phy(portaddr, regnum);
+	if (addr >= 24 && addr <= 27 && eth_priv->id == 0x8380)
+		return rtl838x_read_sds_phy(addr, regnum);
 
-	if (regnum == RTL821X_PAGE_SELECT && bus_priv->page[portaddr] != RTL838X_PAGE_RAW)
-		return bus_priv->page[portaddr];
+	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[addr])
+		return rtl839x_read_sds_phy(addr, regnum);
 
-	bus_priv->raw[portaddr] = (bus_priv->page[portaddr] == RTL838X_PAGE_RAW);
-	err = (*bus_priv->read_phy)(portaddr, bus_priv->page[portaddr], regnum, &val);
+	if (regnum == RTMDIO_PAGE_SELECT && bus_priv->page[addr] != bus_priv->rawpage)
+		return bus_priv->page[addr];
+
+	bus_priv->raw[addr] = (bus_priv->page[addr] == bus_priv->rawpage);
+	err = (*bus_priv->read_phy)(addr, bus_priv->page[addr], regnum, &val);
 	pr_debug("rd_PHY(adr=%d, pag=%d, reg=%d) = %d, err = %d\n",
-		 portaddr, bus_priv->page[portaddr], regnum, val, err);
+		 addr, bus_priv->page[addr], regnum, val, err);
 	return err ? err : val;
 }
 
@@ -1840,24 +1837,26 @@ static int rtmdio_93xx_read(struct mii_bus *bus, int addr, int regnum)
 	int err, val;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	if (regnum == RTL821X_PAGE_SELECT && bus_priv->page[portaddr] != RTL930X_PAGE_RAW)
-		return bus_priv->page[portaddr];
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
 
-	bus_priv->raw[portaddr] = (bus_priv->page[portaddr] == RTL930X_PAGE_RAW);
-	if (eth_priv->phy_is_internal[portaddr]) {
+	if (regnum == RTMDIO_PAGE_SELECT && bus_priv->page[addr] != bus_priv->rawpage)
+		return bus_priv->page[addr];
+
+	bus_priv->raw[addr] = (bus_priv->page[addr] == bus_priv->rawpage);
+	if (eth_priv->phy_is_internal[addr]) {
 		if (eth_priv->family_id == RTL9300_FAMILY_ID)
-			return rtl930x_read_sds_phy(eth_priv->sds_id[portaddr],
-						    bus_priv->page[portaddr], regnum);
+			return rtl930x_read_sds_phy(eth_priv->sds_id[addr],
+						    bus_priv->page[addr], regnum);
 		else
-			return rtl931x_read_sds_phy(eth_priv->sds_id[portaddr],
-						    bus_priv->page[portaddr], regnum);
+			return rtl931x_read_sds_phy(eth_priv->sds_id[addr],
+						    bus_priv->page[addr], regnum);
 	}
 
-	err = (*bus_priv->read_phy)(portaddr, bus_priv->page[portaddr], regnum, &val);
+	err = (*bus_priv->read_phy)(addr, bus_priv->page[addr], regnum, &val);
 	pr_debug("rd_PHY(adr=%d, pag=%d, reg=%d) = %d, err = %d\n",
-		 portaddr, bus_priv->page[portaddr], regnum, val, err);
+		 addr, bus_priv->page[addr], regnum, val, err);
 	return err ? err : val;
 }
 
@@ -1865,83 +1864,91 @@ static int rtmdio_write_c45(struct mii_bus *bus, int addr, int devnum, int regnu
 {
 	int err;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	err = (*bus_priv->write_mmd_phy)(portaddr, devnum, regnum, val);
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+
+	err = (*bus_priv->write_mmd_phy)(addr, devnum, regnum, val);
 	pr_debug("wr_MMD(adr=%d, dev=%d, reg=%d, val=%d) err = %d\n",
-		 portaddr, devnum, regnum, val, err);
+		 addr, devnum, regnum, val, err);
 	return err;
 }
 
 static int rtmdio_83xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
+	int err, page, offset = 0;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
-	int err, page = bus_priv->page[portaddr], offset = 0;
 
-	if (regnum == RTL821X_PORT_SELECT) {
-		bus_priv->portaddr = val;
+	if (regnum == RTMDIO_PORT_SELECT) {
+		bus_priv->extaddr = (s16)val;
 		return 0;
 	}
 
-	if (portaddr >= 24 && portaddr <= 27 && eth_priv->id == 0x8380) {
-		if (portaddr == 26)
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+	page = bus_priv->page[addr];
+
+	if (addr >= 24 && addr <= 27 && eth_priv->id == 0x8380) {
+		if (addr == 26)
 			offset = 0x100;
 		sw_w32(val, RTL838X_SDS4_FIB_REG0 + offset + (regnum << 2));
 		return 0;
 	}
 
-	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[portaddr])
-		return rtl839x_write_sds_phy(portaddr, regnum, val);
+	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[addr])
+		return rtl839x_write_sds_phy(addr, regnum, val);
 
-	if (regnum == RTL821X_PAGE_SELECT)
-		bus_priv->page[portaddr] = val;
+	if (regnum == RTMDIO_PAGE_SELECT)
+		bus_priv->page[addr] = val;
 
-	if (!bus_priv->raw[portaddr] && (regnum != RTL821X_PAGE_SELECT || page == RTL838X_PAGE_RAW)) {
-		bus_priv->raw[portaddr] = (page == RTL838X_PAGE_RAW);
-		err = (*bus_priv->write_phy)(portaddr, page, regnum, val);
+	if (!bus_priv->raw[addr] && (regnum != RTMDIO_PAGE_SELECT || page == bus_priv->rawpage)) {
+		bus_priv->raw[addr] = (page == bus_priv->rawpage);
+		err = (*bus_priv->write_phy)(addr, page, regnum, val);
 		pr_debug("wr_PHY(adr=%d, pag=%d, reg=%d, val=%d) err = %d\n",
-			 portaddr, page, regnum, val, err);
+			 addr, page, regnum, val, err);
 		return err;
 	}
 
-	bus_priv->raw[portaddr] = false;
+	bus_priv->raw[addr] = false;
 	return 0;
 }
 
 static int rtmdio_93xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
+	int err, page;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
-	int err, page = bus_priv->page[portaddr];
 
-	if (regnum == RTL821X_PORT_SELECT) {
-		bus_priv->portaddr = val;
+	if (regnum == RTMDIO_PORT_SELECT) {
+		bus_priv->extaddr = (s16)val;
 		return 0;
 	}
 
-	if (regnum == RTL821X_PAGE_SELECT)
-		bus_priv->page[portaddr] = val;
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+	page = bus_priv->page[addr];
 
-	if (!bus_priv->raw[portaddr] && (regnum != RTL821X_PAGE_SELECT || page == RTL930X_PAGE_RAW)) {
-		bus_priv->raw[portaddr] = (page == RTL930X_PAGE_RAW);
-		if (eth_priv->phy_is_internal[portaddr]) {
+	if (regnum == RTMDIO_PAGE_SELECT)
+		bus_priv->page[addr] = val;
+
+	if (!bus_priv->raw[addr] && (regnum != RTMDIO_PAGE_SELECT || page == bus_priv->rawpage)) {
+		bus_priv->raw[addr] = (page == bus_priv->rawpage);
+		if (eth_priv->phy_is_internal[addr]) {
 			if (eth_priv->family_id == RTL9300_FAMILY_ID)
-				return rtl930x_write_sds_phy(eth_priv->sds_id[portaddr],
+				return rtl930x_write_sds_phy(eth_priv->sds_id[addr],
 							     page, regnum, val);
 			else
-				return rtl931x_write_sds_phy(eth_priv->sds_id[portaddr],
+				return rtl931x_write_sds_phy(eth_priv->sds_id[addr],
 							     page, regnum, val);
 		}
 
-		err = (*bus_priv->write_phy)(portaddr, page, regnum, val);
+		err = (*bus_priv->write_phy)(addr, page, regnum, val);
 		pr_debug("wr_PHY(adr=%d, pag=%d, reg=%d, val=%d) err = %d\n",
-			 portaddr, page, regnum, val, err);
+			 addr, page, regnum, val, err);
 	}
 
-	bus_priv->raw[portaddr] = false;
+	bus_priv->raw[addr] = false;
 	return 0;
 }
 
@@ -2244,11 +2251,11 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 
 	bus_priv = priv->mii_bus->priv;
 	bus_priv->eth_priv = priv;
-	for (i = 0; i < 64; i++) {
+	for (i=0; i < 64; i++) {
 		bus_priv->page[i] = 0;
 		bus_priv->raw[i] = false;
 	}
-	bus_priv->portaddr = 0;
+	bus_priv->extaddr = -1;
 
 	switch(priv->family_id) {
 	case RTL8380_FAMILY_ID:
@@ -2260,6 +2267,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl838x_write_mmd_phy;
 		bus_priv->read_phy = rtl838x_read_phy;
 		bus_priv->write_phy = rtl838x_write_phy;
+		bus_priv->rawpage = 0xfff;
 		break;
 	case RTL8390_FAMILY_ID:
 		priv->mii_bus->name = "rtl839x-eth-mdio";
@@ -2270,6 +2278,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl839x_write_mmd_phy;
 		bus_priv->read_phy = rtl839x_read_phy;
 		bus_priv->write_phy = rtl839x_write_phy;
+		bus_priv->rawpage = 0x1fff;
 		break;
 	case RTL9300_FAMILY_ID:
 		priv->mii_bus->name = "rtl930x-eth-mdio";
@@ -2280,6 +2289,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl930x_write_mmd_phy;
 		bus_priv->read_phy = rtl930x_read_phy;
 		bus_priv->write_phy = rtl930x_write_phy;
+		bus_priv->rawpage = 0xfff;
 		priv->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
 		break;
 	case RTL9310_FAMILY_ID:
@@ -2291,6 +2301,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl931x_write_mmd_phy;
 		bus_priv->read_phy = rtl931x_read_phy;
 		bus_priv->write_phy = rtl931x_write_phy;
+		bus_priv->rawpage = 0x1fff;
 		priv->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
 		break;
 	}
diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h
index 0f49eae23da..d6d88fc2ed0 100644
--- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h
+++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h
@@ -410,7 +410,8 @@ struct dsa_tag;
 
 struct rtl838x_bus_priv {
 	struct rtl838x_eth_priv *eth_priv;
-	int portaddr;
+	int extaddr;
+	int rawpage;
 	int page[64];
 	bool raw[64];
 	int (*read_mmd_phy)(u32 port, u32 addr, u32 reg, u32 *val);
diff --git a/target/linux/realtek/files-5.15/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-5.15/drivers/net/phy/rtl83xx-phy.c
index 0c8b1dfd4dc..df5e2e44406 100644
--- a/target/linux/realtek/files-5.15/drivers/net/phy/rtl83xx-phy.c
+++ b/target/linux/realtek/files-5.15/drivers/net/phy/rtl83xx-phy.c
@@ -22,8 +22,10 @@ extern struct rtl83xx_soc_info soc_info;
 extern struct mutex smi_lock;
 extern int phy_package_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val);
 extern int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val);
+extern int phy_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val);
 extern int phy_package_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum);
 extern int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnum);
+extern int phy_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum);
 
 #define PHY_PAGE_2	2
 #define PHY_PAGE_4	4
diff --git a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c
index 44390593451..07664f9f382 100644
--- a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c
@@ -1629,7 +1629,7 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
 }
 
 /*
- * On all RealTek switch platforms the hardware periodically reads the link status of all
+ * On all Realtek switch platforms the hardware periodically reads the link status of all
  * PHYs. This is to some degree programmable, so that one can tell the hardware to read
  * specific C22 registers from specific pages, or C45 registers, to determine the current
  * link speed, duplex, flow-control, ...
@@ -1646,7 +1646,7 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  * abstractions.
  *
  * Additionally at least the RTL838x and RTL839x devices are known to have a so called
- * raw mode. Using the special MAX_PAGE-1 with the MDIO controller found in RealTek
+ * raw mode. Using the special MAX_PAGE-1 with the MDIO controller found in Realtek
  * SoCs allows to access the PHY in raw mode, ie. bypassing the cache and paging engine
  * of the MDIO controller. E.g. for RTL838x this is 0xfff.
  *
@@ -1655,9 +1655,9 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  * when they are not attached to an Realtek SoC. The paradigm should be to keep the PHY
  * implementation bus independent.
  *
- * As if this is not enough the PHYs consist of 8 ports that all can be programmed
- * individually. Writing to port 0 can configure the whole why while other operations
- * need to be replicated per port.
+ * As if this is not enough the PHY packages consist of 4 or 8 ports that all can be
+ * programmed individually. Some registers are only available on port 0 and configure
+ * the whole package.
  *
  * To bring all this together we need a tricky bus design that intercepts select page
  * calls but lets raw page accesses through. And especially knows how to handle raw
@@ -1668,7 +1668,7 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  * the accesses and the state of the bus with the attributes page[], raw[] and portaddr
  * of the bus_priv structure. The page selection works as follows:
  *
- * phy_write(phydev, RTL821X_PAGE_SELECT, 12)	: store internal page 12 in driver
+ * phy_write(phydev, RTMDIO_PAGE_SELECT, 12)	: store internal page 12 in driver
  * phy_write(phydev, 7, 33)			: write page=12, reg=7, val=33
  *
  * or simply
@@ -1677,8 +1677,8 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  *
  * The port selection works as follows and must be called under a held mdio bus lock
  *
- * __mdiobus_write(bus, RTL821X_PORT_SELECT, 4)	: switch to port paddr
- * __phy_write(phydev, RTL821X_PAGE_SELECT, 11)	: store internal page 11 in driver
+ * __mdiobus_write(bus, RTMDIO_PORT_SELECT, 4)	: switch to port 4
+ * __phy_write(phydev, RTMDIO_PAGE_SELECT, 11)	: store internal page 11 in driver
  * __phy_write(phydev, 8, 19)			: write page=11, reg=8, val=19, port=4
  *
  * Any Realtek PHY that will be connected to this bus must simply provide the standard
@@ -1696,75 +1696,57 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev,
  *   return __phy_write(phydev, RTL821X_PAGE_SELECT, page);
  * }
  *
- * In case there are non Realtek PHYs attached to the logic might need to be
+ * In case there are non Realtek PHYs attached to the bus the logic might need to be
  * reimplemented. For now it should be sufficient.
  */
 
-#define RTL821X_PAGE_SELECT	0x1f
-#define RTL821X_PORT_SELECT	0x2000
-#define RTL838X_PAGE_RAW	0xfff
-#define RTL839X_PAGE_RAW	0x1fff
-#define RTL930X_PAGE_RAW	0xfff
-#define RTL931X_PAGE_RAW	0x1fff
-#define RTMDIO_READ		0x0
-#define RTMDIO_WRITE		0x1
+#define RTMDIO_PAGE_SELECT	0x1f
+#define RTMDIO_PORT_SELECT	0x2000
+#define RTMDIO_READ		0x1
+#define RTMDIO_WRITE		0x2
+#define RTMDIO_ABS		0x4
+#define RTMDIO_PKG		0x8
 
 /*
- * Provide a generic read/write function so we can access multiple ports on a shared PHY
- * package of the bus with separate addresses individually. This basically resembles the
+ * Provide a generic read/write function so we can access arbitrary ports on the bus.
+ * E.g. other ports of a PHY package on the bus. This basically resembles the kernel
  * phy_read_paged() and phy_write_paged() functions. To inform the bus that we are
- * workin on a not default port (8, 16, 24, ...) we send a RTL821X_PORT_SELECT command
- * at the beginning and the end to switch the port handling logic.
+ * working on a not default port send a RTMDIO_PORT_SELECT command at the beginning
+ * and the end to switch the port handling logic.
  */
 
-static int rtmdio_read_page(struct phy_device *phydev)
-{
-	if (WARN_ONCE(!phydev->drv->read_page,
-		      "read_page callback not available, PHY driver not loaded?\n"))
-		return -EOPNOTSUPP;
-
-	return phydev->drv->read_page(phydev);
-}
-
-static int rtmdio_write_page(struct phy_device *phydev, int page)
-{
-	if (WARN_ONCE(!phydev->drv->write_page,
-		      "write_page callback not available, PHY driver not loaded?\n"))
-		return -EOPNOTSUPP;
-
-	return phydev->drv->write_page(phydev, page);
-}
-
-static int rtmdio_package_rw(struct phy_device *phydev, int op, int port,
-			     int page, u32 regnum, u16 val)
+static int rtmdio_access(struct phy_device *phydev, int op, int port,
+			 int page, u32 regnum, u16 val)
 {
 	int r, ret = 0, oldpage;
-	struct phy_package_shared *shared = phydev->shared;
 
-	if (!shared)
-		return -EIO;
+	if (op & RTMDIO_PKG) {
+		if (!phydev->shared)
+			return -EIO;
+		port = phydev->shared->base_addr + port;
+	}
 
 	/* lock and inform bus about non default addressing */
 	phy_lock_mdio_bus(phydev);
 	__mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
-			RTL821X_PORT_SELECT, shared->base_addr + port);
+			RTMDIO_PORT_SELECT, port);
 
-	oldpage = ret = rtmdio_read_page(phydev);
+	oldpage = ret = __phy_read(phydev, RTMDIO_PAGE_SELECT);
 	if (oldpage >= 0 && oldpage != page) {
-		ret = rtmdio_write_page(phydev, page);
+		ret = __phy_write(phydev, RTMDIO_PAGE_SELECT, page);
 		if (ret < 0)
 			oldpage = ret;
 	}
 
 	if (oldpage >= 0) {
-		if (op == RTMDIO_WRITE)
+		if (op & RTMDIO_WRITE)
 			ret = __phy_write(phydev, regnum, val);
 		else
 			ret = __phy_read(phydev, regnum);
 	}
 
 	if (oldpage >= 0) {
-		r = rtmdio_write_page(phydev, oldpage);
+		r = __phy_write(phydev, RTMDIO_PAGE_SELECT, oldpage);
 		if (ret >= 0 && r < 0)
 			ret = r;
 	} else
@@ -1772,7 +1754,7 @@ static int rtmdio_package_rw(struct phy_device *phydev, int op, int port,
 
 	/* reset bus to default adressing and unlock it */
 	__mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
-			RTL821X_PORT_SELECT, 0);
+			RTMDIO_PORT_SELECT, -1);
 	phy_unlock_mdio_bus(phydev);
 
 	return ret;
@@ -1782,40 +1764,53 @@ static int rtmdio_package_rw(struct phy_device *phydev, int op, int port,
  * To make use of the shared package functions provide wrappers that align with kernel
  * naming conventions. The package() functions are useful to change settings on the
  * package as a whole. The package_port() functions will allow to target the PHYs
- * individually.
+ * of a package individually. The port() only functions allow to access arbitrary ports
+ * on the bus through a PHY.
  */
 
 int phy_package_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_WRITE, port, page, regnum, val);
+	return rtmdio_access(phydev, RTMDIO_WRITE | RTMDIO_PKG, port, page, regnum, val);
 }
 
 int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_WRITE, 0, page, regnum, val);
+	return rtmdio_access(phydev, RTMDIO_WRITE | RTMDIO_PKG, 0, page, regnum, val);
+}
+
+int phy_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val)
+{
+	return rtmdio_access(phydev, RTMDIO_WRITE | RTMDIO_ABS, port, page, regnum, val);
 }
 
 int phy_package_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_READ, port, page, regnum, 0);
+	return rtmdio_access(phydev, RTMDIO_READ | RTMDIO_PKG, port, page, regnum, 0);
 }
 
 int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnum)
 {
-	return rtmdio_package_rw(phydev, RTMDIO_READ, 0, page, regnum, 0);
+	return rtmdio_access(phydev, RTMDIO_READ | RTMDIO_PKG, 0, page, regnum, 0);
 }
 
-/* These are the core functions of our fancy Realtek SoC MDIO bus. */
+int phy_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum)
+{
+	return rtmdio_access(phydev, RTMDIO_READ | RTMDIO_ABS, port, page, regnum, 0);
+}
+
+/* These are the core functions of our new Realtek SoC MDIO bus. */
 
 static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
 {
 	int err, val;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	err = (*bus_priv->read_mmd_phy)(portaddr, devnum, regnum, &val);
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+
+	err = (*bus_priv->read_mmd_phy)(addr, devnum, regnum, &val);
 	pr_debug("rd_MMD(adr=%d, dev=%d, reg=%d) = %d, err = %d\n",
-		 portaddr, devnum, regnum, val, err);
+		 addr, devnum, regnum, val, err);
 	return err ? err : val;
 }
 
@@ -1824,21 +1819,23 @@ static int rtmdio_83xx_read(struct mii_bus *bus, int addr, int regnum)
 	int err, val;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	if (portaddr >= 24 && portaddr <= 27 && eth_priv->id == 0x8380)
-		return rtl838x_read_sds_phy(portaddr, regnum);
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
 
-	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[portaddr])
-		return rtl839x_read_sds_phy(portaddr, regnum);
+	if (addr >= 24 && addr <= 27 && eth_priv->id == 0x8380)
+		return rtl838x_read_sds_phy(addr, regnum);
 
-	if (regnum == RTL821X_PAGE_SELECT && bus_priv->page[portaddr] != RTL838X_PAGE_RAW)
-		return bus_priv->page[portaddr];
+	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[addr])
+		return rtl839x_read_sds_phy(addr, regnum);
 
-	bus_priv->raw[portaddr] = (bus_priv->page[portaddr] == RTL838X_PAGE_RAW);
-	err = (*bus_priv->read_phy)(portaddr, bus_priv->page[portaddr], regnum, &val);
+	if (regnum == RTMDIO_PAGE_SELECT && bus_priv->page[addr] != bus_priv->rawpage)
+		return bus_priv->page[addr];
+
+	bus_priv->raw[addr] = (bus_priv->page[addr] == bus_priv->rawpage);
+	err = (*bus_priv->read_phy)(addr, bus_priv->page[addr], regnum, &val);
 	pr_debug("rd_PHY(adr=%d, pag=%d, reg=%d) = %d, err = %d\n",
-		 portaddr, bus_priv->page[portaddr], regnum, val, err);
+		 addr, bus_priv->page[addr], regnum, val, err);
 	return err ? err : val;
 }
 
@@ -1847,24 +1844,26 @@ static int rtmdio_93xx_read(struct mii_bus *bus, int addr, int regnum)
 	int err, val;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	if (regnum == RTL821X_PAGE_SELECT && bus_priv->page[portaddr] != RTL930X_PAGE_RAW)
-		return bus_priv->page[portaddr];
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
 
-	bus_priv->raw[portaddr] = (bus_priv->page[portaddr] == RTL930X_PAGE_RAW);
-	if (eth_priv->phy_is_internal[portaddr]) {
+	if (regnum == RTMDIO_PAGE_SELECT && bus_priv->page[addr] != bus_priv->rawpage)
+		return bus_priv->page[addr];
+
+	bus_priv->raw[addr] = (bus_priv->page[addr] == bus_priv->rawpage);
+	if (eth_priv->phy_is_internal[addr]) {
 		if (eth_priv->family_id == RTL9300_FAMILY_ID)
-			return rtl930x_read_sds_phy(eth_priv->sds_id[portaddr],
-						    bus_priv->page[portaddr], regnum);
+			return rtl930x_read_sds_phy(eth_priv->sds_id[addr],
+						    bus_priv->page[addr], regnum);
 		else
-			return rtl931x_read_sds_phy(eth_priv->sds_id[portaddr],
-						    bus_priv->page[portaddr], regnum);
+			return rtl931x_read_sds_phy(eth_priv->sds_id[addr],
+						    bus_priv->page[addr], regnum);
 	}
 
-	err = (*bus_priv->read_phy)(portaddr, bus_priv->page[portaddr], regnum, &val);
+	err = (*bus_priv->read_phy)(addr, bus_priv->page[addr], regnum, &val);
 	pr_debug("rd_PHY(adr=%d, pag=%d, reg=%d) = %d, err = %d\n",
-		 portaddr, bus_priv->page[portaddr], regnum, val, err);
+		 addr, bus_priv->page[addr], regnum, val, err);
 	return err ? err : val;
 }
 
@@ -1872,83 +1871,91 @@ static int rtmdio_write_c45(struct mii_bus *bus, int addr, int devnum, int regnu
 {
 	int err;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
 
-	err = (*bus_priv->write_mmd_phy)(portaddr, devnum, regnum, val);
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+
+	err = (*bus_priv->write_mmd_phy)(addr, devnum, regnum, val);
 	pr_debug("wr_MMD(adr=%d, dev=%d, reg=%d, val=%d) err = %d\n",
-		 portaddr, devnum, regnum, val, err);
+		 addr, devnum, regnum, val, err);
 	return err;
 }
 
 static int rtmdio_83xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
+	int err, page, offset = 0;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
-	int err, page = bus_priv->page[portaddr], offset = 0;
 
-	if (regnum == RTL821X_PORT_SELECT) {
-		bus_priv->portaddr = val;
+	if (regnum == RTMDIO_PORT_SELECT) {
+		bus_priv->extaddr = (s16)val;
 		return 0;
 	}
 
-	if (portaddr >= 24 && portaddr <= 27 && eth_priv->id == 0x8380) {
-		if (portaddr == 26)
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+	page = bus_priv->page[addr];
+
+	if (addr >= 24 && addr <= 27 && eth_priv->id == 0x8380) {
+		if (addr == 26)
 			offset = 0x100;
 		sw_w32(val, RTL838X_SDS4_FIB_REG0 + offset + (regnum << 2));
 		return 0;
 	}
 
-	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[portaddr])
-		return rtl839x_write_sds_phy(portaddr, regnum, val);
+	if (eth_priv->family_id == RTL8390_FAMILY_ID && eth_priv->phy_is_internal[addr])
+		return rtl839x_write_sds_phy(addr, regnum, val);
 
-	if (regnum == RTL821X_PAGE_SELECT)
-		bus_priv->page[portaddr] = val;
+	if (regnum == RTMDIO_PAGE_SELECT)
+		bus_priv->page[addr] = val;
 
-	if (!bus_priv->raw[portaddr] && (regnum != RTL821X_PAGE_SELECT || page == RTL838X_PAGE_RAW)) {
-		bus_priv->raw[portaddr] = (page == RTL838X_PAGE_RAW);
-		err = (*bus_priv->write_phy)(portaddr, page, regnum, val);
+	if (!bus_priv->raw[addr] && (regnum != RTMDIO_PAGE_SELECT || page == bus_priv->rawpage)) {
+		bus_priv->raw[addr] = (page == bus_priv->rawpage);
+		err = (*bus_priv->write_phy)(addr, page, regnum, val);
 		pr_debug("wr_PHY(adr=%d, pag=%d, reg=%d, val=%d) err = %d\n",
-			 portaddr, page, regnum, val, err);
+			 addr, page, regnum, val, err);
 		return err;
 	}
 
-	bus_priv->raw[portaddr] = false;
+	bus_priv->raw[addr] = false;
 	return 0;
 }
 
 static int rtmdio_93xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
+	int err, page;
 	struct rtl838x_bus_priv *bus_priv = bus->priv;
 	struct rtl838x_eth_priv *eth_priv = bus_priv->eth_priv;
-	int portaddr = bus_priv->portaddr ? bus_priv->portaddr : addr;
-	int err, page = bus_priv->page[portaddr];
 
-	if (regnum == RTL821X_PORT_SELECT) {
-		bus_priv->portaddr = val;
+	if (regnum == RTMDIO_PORT_SELECT) {
+		bus_priv->extaddr = (s16)val;
 		return 0;
 	}
 
-	if (regnum == RTL821X_PAGE_SELECT)
-		bus_priv->page[portaddr] = val;
+	if (bus_priv->extaddr >= 0)
+		addr = bus_priv->extaddr;
+	page = bus_priv->page[addr];
 
-	if (!bus_priv->raw[portaddr] && (regnum != RTL821X_PAGE_SELECT || page == RTL930X_PAGE_RAW)) {
-		bus_priv->raw[portaddr] = (page == RTL930X_PAGE_RAW);
-		if (eth_priv->phy_is_internal[portaddr]) {
+	if (regnum == RTMDIO_PAGE_SELECT)
+		bus_priv->page[addr] = val;
+
+	if (!bus_priv->raw[addr] && (regnum != RTMDIO_PAGE_SELECT || page == bus_priv->rawpage)) {
+		bus_priv->raw[addr] = (page == bus_priv->rawpage);
+		if (eth_priv->phy_is_internal[addr]) {
 			if (eth_priv->family_id == RTL9300_FAMILY_ID)
-				return rtl930x_write_sds_phy(eth_priv->sds_id[portaddr],
+				return rtl930x_write_sds_phy(eth_priv->sds_id[addr],
 							     page, regnum, val);
 			else
-				return rtl931x_write_sds_phy(eth_priv->sds_id[portaddr],
+				return rtl931x_write_sds_phy(eth_priv->sds_id[addr],
 							     page, regnum, val);
 		}
 
-		err = (*bus_priv->write_phy)(portaddr, page, regnum, val);
+		err = (*bus_priv->write_phy)(addr, page, regnum, val);
 		pr_debug("wr_PHY(adr=%d, pag=%d, reg=%d, val=%d) err = %d\n",
-			 portaddr, page, regnum, val, err);
+			 addr, page, regnum, val, err);
 	}
 
-	bus_priv->raw[portaddr] = false;
+	bus_priv->raw[addr] = false;
 	return 0;
 }
 
@@ -2217,7 +2224,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->page[i] = 0;
 		bus_priv->raw[i] = false;
 	}
-	bus_priv->portaddr = 0;
+	bus_priv->extaddr = -1;
 
 	switch(priv->family_id) {
 	case RTL8380_FAMILY_ID:
@@ -2229,6 +2236,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl838x_write_mmd_phy;
 		bus_priv->read_phy = rtl838x_read_phy;
 		bus_priv->write_phy = rtl838x_write_phy;
+		bus_priv->rawpage = 0xfff;
 		break;
 	case RTL8390_FAMILY_ID:
 		priv->mii_bus->name = "rtl839x-eth-mdio";
@@ -2239,6 +2247,7 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl839x_write_mmd_phy;
 		bus_priv->read_phy = rtl839x_read_phy;
 		bus_priv->write_phy = rtl839x_write_phy;
+		bus_priv->rawpage = 0x1fff;
 		break;
 	case RTL9300_FAMILY_ID:
 		priv->mii_bus->name = "rtl930x-eth-mdio";
@@ -2249,16 +2258,18 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		bus_priv->write_mmd_phy = rtl930x_write_mmd_phy;
 		bus_priv->read_phy = rtl930x_read_phy;
 		bus_priv->write_phy = rtl930x_write_phy;
+		bus_priv->rawpage = 0xfff;
 		break;
 	case RTL9310_FAMILY_ID:
 		priv->mii_bus->name = "rtl931x-eth-mdio";
 		priv->mii_bus->read = rtmdio_93xx_read;
 		priv->mii_bus->write = rtmdio_93xx_write;
- 		priv->mii_bus->reset = rtmdio_931x_reset;
+		priv->mii_bus->reset = rtmdio_931x_reset;
 		bus_priv->read_mmd_phy = rtl931x_read_mmd_phy;
 		bus_priv->write_mmd_phy = rtl931x_write_mmd_phy;
 		bus_priv->read_phy = rtl931x_read_phy;
 		bus_priv->write_phy = rtl931x_write_phy;
+		bus_priv->rawpage = 0x1fff;
 		break;
 	}
 	priv->mii_bus->read_c45 = rtmdio_read_c45;
diff --git a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.h
index 0f49eae23da..d6d88fc2ed0 100644
--- a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.h
+++ b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.h
@@ -410,7 +410,8 @@ struct dsa_tag;
 
 struct rtl838x_bus_priv {
 	struct rtl838x_eth_priv *eth_priv;
-	int portaddr;
+	int extaddr;
+	int rawpage;
 	int page[64];
 	bool raw[64];
 	int (*read_mmd_phy)(u32 port, u32 addr, u32 reg, u32 *val);
diff --git a/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c
index 0c8b1dfd4dc..df5e2e44406 100644
--- a/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c
+++ b/target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c
@@ -22,8 +22,10 @@ extern struct rtl83xx_soc_info soc_info;
 extern struct mutex smi_lock;
 extern int phy_package_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val);
 extern int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val);
+extern int phy_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val);
 extern int phy_package_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum);
 extern int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnum);
+extern int phy_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum);
 
 #define PHY_PAGE_2	2
 #define PHY_PAGE_4	4