--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -18197,6 +18197,13 @@ F: drivers/pinctrl/
+@@ -18198,6 +18198,13 @@ F: drivers/pinctrl/
F: include/dt-bindings/pinctrl/
F: include/linux/pinctrl/
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21556,6 +21556,14 @@ T: git git://linuxtv.org/media.git
+@@ -21557,6 +21557,14 @@ T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
F: drivers/media/i2c/imx415.c
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21564,6 +21564,14 @@ T: git git://linuxtv.org/media_tree.git
+@@ -21565,6 +21565,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
F: drivers/media/i2c/imx477.c
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21561,6 +21561,7 @@ M: Raspberry Pi Kernel Maintenance <kern
+@@ -21562,6 +21562,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21605,6 +21605,14 @@ T: git git://linuxtv.org/media_tree.git
+@@ -21606,6 +21606,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx519.yaml
F: drivers/media/i2c/imx519.c
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21610,7 +21610,7 @@ M: Raspberry Pi Kernel Maintenance <kern
+@@ -21611,7 +21611,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -20068,6 +20068,13 @@ S: Supported
+@@ -20069,6 +20069,13 @@ S: Supported
F: drivers/iio/light/rohm-bu27008.c
F: drivers/iio/light/rohm-bu27034.c
+
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19361,6 +19361,11 @@ L: linux-edac@vger.kernel.org
+@@ -19362,6 +19362,11 @@ L: linux-edac@vger.kernel.org
S: Maintained
F: drivers/ras/amd/fmpm.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19365,6 +19365,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER
+@@ -19366,6 +19366,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER
M: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
S: Maintained
F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
+
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21610,6 +21610,13 @@ F: Documentation/devicetree/bindings/med
+@@ -21611,6 +21611,13 @@ F: Documentation/devicetree/bindings/med
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
F: drivers/media/i2c/imx477.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -21616,6 +21616,7 @@ L: linux-media@vger.kernel.org
+@@ -21617,6 +21617,7 @@ L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx500.yaml
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19367,6 +19367,16 @@ S: Maintained
+@@ -19368,6 +19368,16 @@ S: Maintained
F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
F: drivers/spi/spi-rp2040-gpio-bridge.c
--- /dev/null
+From c4277d21ab694c7964a48759a5452e5bbbe12965 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Sat, 10 Jan 2026 16:14:05 +0100
+Subject: [PATCH] net: phy: realtek: add dummy PHY driver for RTL8127ATF
+
+RTL8127ATF supports a SFP+ port for fiber modules (10GBASE-SR/LR/ER/ZR and
+DAC). The list of supported modes was provided by Realtek. According to the
+r8127 vendor driver also 1G modules are supported, but this needs some more
+complexity in the driver, and only 10G mode has been tested so far.
+Therefore mainline support will be limited to 10G for now.
+The SFP port signals are hidden in the chip IP and driven by firmware.
+Therefore mainline SFP support can't be used here.
+This PHY driver is used by the RTL8127ATF support in r8169.
+RTL8127ATF reports the same PHY ID as the TP version. Therefore use a dummy
+PHY ID. This PHY driver is used by the RTL8127ATF support in r8169.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://patch.msgid.link/e3d55162-210a-4fab-9abf-99c6954eee10@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ MAINTAINERS | 1 +
+ drivers/net/phy/realtek/realtek_main.c | 54 ++++++++++++++++++++++++++
+ include/net/phy/realtek_phy.h | 7 ++++
+ 3 files changed, 62 insertions(+)
+ create mode 100644 include/net/phy/realtek_phy.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -8459,6 +8459,7 @@ F: include/linux/phy_link_topology.h
+ F: include/linux/phylib_stubs.h
+ F: include/linux/platform_data/mdio-bcm-unimac.h
+ F: include/linux/platform_data/mdio-gpio.h
++F: include/net/phy/
+ F: include/trace/events/mdio.h
+ F: include/uapi/linux/mdio.h
+ F: include/uapi/linux/mii.h
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -17,6 +17,7 @@
+ #include <linux/delay.h>
+ #include <linux/clk.h>
+ #include <linux/string_choices.h>
++#include <net/phy/realtek_phy.h>
+
+ #include "realtek.h"
+
+@@ -2099,6 +2100,45 @@ static irqreturn_t rtl8221b_handle_inter
+ return IRQ_HANDLED;
+ }
+
++static int rtlgen_sfp_get_features(struct phy_device *phydev)
++{
++ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
++ phydev->supported);
++
++ /* set default mode */
++ phydev->speed = SPEED_10000;
++ phydev->duplex = DUPLEX_FULL;
++
++ phydev->port = PORT_FIBRE;
++
++ return 0;
++}
++
++static int rtlgen_sfp_read_status(struct phy_device *phydev)
++{
++ int val, err;
++
++ err = genphy_update_link(phydev);
++ if (err)
++ return err;
++
++ if (!phydev->link)
++ return 0;
++
++ val = rtlgen_read_vend2(phydev, RTL_VND2_PHYSR);
++ if (val < 0)
++ return val;
++
++ rtlgen_decode_physr(phydev, val);
++
++ return 0;
++}
++
++static int rtlgen_sfp_config_aneg(struct phy_device *phydev)
++{
++ return 0;
++}
++
+ static struct phy_driver realtek_drvs[] = {
+ {
+ PHY_ID_MATCH_EXACT(0x00008201),
+@@ -2357,6 +2397,20 @@ static struct phy_driver realtek_drvs[]
+ .suspend = genphy_suspend,
+ .resume = rtlgen_resume,
+ .read_page = rtl821x_read_page,
++ .write_page = rtl821x_write_page,
++ .read_mmd = rtl822x_read_mmd,
++ .write_mmd = rtl822x_write_mmd,
++ }, {
++ PHY_ID_MATCH_EXACT(PHY_ID_RTL_DUMMY_SFP),
++ .name = "Realtek SFP PHY Mode",
++ .flags = PHY_IS_INTERNAL,
++ .probe = rtl822x_probe,
++ .get_features = rtlgen_sfp_get_features,
++ .config_aneg = rtlgen_sfp_config_aneg,
++ .read_status = rtlgen_sfp_read_status,
++ .suspend = genphy_suspend,
++ .resume = rtlgen_resume,
++ .read_page = rtl821x_read_page,
+ .write_page = rtl821x_write_page,
+ .read_mmd = rtl822x_read_mmd,
+ .write_mmd = rtl822x_write_mmd,
+--- /dev/null
++++ b/include/net/phy/realtek_phy.h
+@@ -0,0 +1,7 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _REALTEK_PHY_H
++#define _REALTEK_PHY_H
++
++#define PHY_ID_RTL_DUMMY_SFP 0x001ccbff
++
++#endif /* _REALTEK_PHY_H */
--- /dev/null
+From 8744b63e8a9ac4a3c30b557ca6bc115851a980e9 Mon Sep 17 00:00:00 2001
+From: Jan Hoffmann <jan@3e8.eu>
+Date: Tue, 13 Jan 2026 21:55:44 +0100
+Subject: [PATCH] net: phy: realtek: fix in-band capabilities for 2.5G PHYs
+
+It looks like the configuration of in-band AN only affects SGMII, and it
+is always disabled for 2500Base-X. Adjust the reported capabilities
+accordingly.
+
+This is based on testing using OpenWrt on Zyxel XGS1010-12 rev A1 with
+RTL8226-CG, and Zyxel XGS1210-12 rev B1 with RTL8221B-VB-CG. On these
+devices, 2500Base-X in-band AN is known to work with some SFP modules
+(containing an unknown PHY). However, with the built-in Realtek PHYs,
+no auto-negotiation takes place, irrespective of the configuration of
+the PHY.
+
+Fixes: 10fbd71fc5f9b ("net: phy: realtek: implement configuring in-band an")
+Signed-off-by: Jan Hoffmann <jan@3e8.eu>
+Reviewed-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/20260113205557.503409-1-jan@3e8.eu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/realtek_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -1428,6 +1428,7 @@ static unsigned int rtl822x_inband_caps(
+ {
+ switch (interface) {
+ case PHY_INTERFACE_MODE_2500BASEX:
++ return LINK_INBAND_DISABLE;
+ case PHY_INTERFACE_MODE_SGMII:
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
+ default:
-From 97f093d9c491f066e5c6bb5bd2e3758f61a9fb30 Mon Sep 17 00:00:00 2001
+From 84fb8b93fae2a4c53323b2bf6d81e7ddcc8e7cf4 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
-Date: Mon, 5 Jan 2026 16:59:06 +0000
-Subject: [PATCH 1/3] net: phy: realtek: support interrupt also for C22
+Date: Tue, 13 Jan 2026 03:44:00 +0000
+Subject: [PATCH 1/5] net: phy: realtek: support interrupt also for C22
variants
Now that access to MDIO_MMD_VEND2 works transparently also in Clause-22
driver instances now having all the same features implemented.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/7620084b1de01580edc2d0e1b9548507fb4643a8.1768275364.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/realtek/realtek_main.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -2347,6 +2347,8 @@ static struct phy_driver realtek_drvs[]
+@@ -2315,6 +2315,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
- .soft_reset = genphy_soft_reset,
.probe = rtl822x_probe,
.get_features = rtl822x_get_features,
-@@ -2381,6 +2383,8 @@ static struct phy_driver realtek_drvs[]
+ .config_aneg = rtl822x_config_aneg,
+@@ -2347,6 +2349,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vm_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
- .soft_reset = genphy_soft_reset,
.probe = rtl822x_probe,
.get_features = rtl822x_get_features,
+ .config_aneg = rtl822x_config_aneg,
--- /dev/null
+From 2809a1c4340437f2ff6b73c0094d7ca51b575e1b Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Tue, 13 Jan 2026 03:44:17 +0000
+Subject: [PATCH 2/5] net: phy: realtek: simplify C22 reg access via
+ MDIO_MMD_VEND2
+
+RealTek 2.5GE PHYs have all standard Clause-22 registers mapped also
+inside MDIO_MMD_VEND2 at offset 0xa400. This is used mainly in case the
+PHY is connected to a Clause-45-only bus. The RTL8221B is frequently
+used in copper SFP module which uses the RollBall MDIO-over-I2C
+method which *only* supports Clause-45, for example.
+
+In order to support using the PHY on Clause-45-only busses, the PHY
+driver has previously been split into a C22-only and C45-only instances,
+creating quite a bit of redundancy and confusion.
+
+In preparation of reunifying the two driver instances, add support for
+translating MDIO_MMD_VEND2 registers 0xa400 to 0xa43c back to Clause-22
+registers 0 to 30 in case the PHY is accessed on a Clause-22 bus.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/fd49d86bd0445b76269fd3ea456c709c2066683f.1768275364.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/realtek_main.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -143,6 +143,7 @@
+
+ #define RTL822X_VND2_TO_PAGE(reg) ((reg) >> 4)
+ #define RTL822X_VND2_TO_PAGE_REG(reg) (16 + (((reg) & GENMASK(3, 0)) >> 1))
++#define RTL822X_VND2_TO_C22_REG(reg) (((reg) - 0xa400) / 2)
+ #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg))
+
+ #define RTL8221B_VND2_INER 0xa4d2
+@@ -1264,6 +1265,11 @@ static int rtl822xb_read_mmd(struct phy_
+ return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr,
+ phydev->is_c45, devnum, reg);
+
++ /* Simplify access to C22-registers addressed inside MDIO_MMD_VEND2 */
++ if (reg >= RTL822X_VND2_C22_REG(0) &&
++ reg <= RTL822X_VND2_C22_REG(30))
++ return __phy_read(phydev, RTL822X_VND2_TO_C22_REG(reg));
++
+ /* Use paged access for MDIO_MMD_VEND2 over Clause-22 */
+ page = RTL822X_VND2_TO_PAGE(reg);
+ oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT);
+@@ -1299,6 +1305,11 @@ static int rtl822xb_write_mmd(struct phy
+ return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr,
+ phydev->is_c45, devnum, reg, val);
+
++ /* Simplify access to C22-registers addressed inside MDIO_MMD_VEND2 */
++ if (reg >= RTL822X_VND2_C22_REG(0) &&
++ reg <= RTL822X_VND2_C22_REG(30))
++ return __phy_write(phydev, RTL822X_VND2_TO_C22_REG(reg), val);
++
+ /* Use paged access for MDIO_MMD_VEND2 over Clause-22 */
+ page = RTL822X_VND2_TO_PAGE(reg);
+ oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT);
--- /dev/null
+From 85f75da86a0adc4798d3675aab3365e721a1dbf5 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Tue, 13 Jan 2026 03:44:25 +0000
+Subject: [PATCH 3/5] net: phy: realtek: reunify C22 and C45 drivers
+
+Reunify the split C22/C45 drivers for the RTL8221B-VB-CG 2.5Gbps and
+RTL8221B-VM-CG 2.5Gbps PHYs back into a single driver.
+
+This is possible now by using all the driver operations previously used
+by the C45 driver, as transparent access to all MMDs including
+MDIO_MMD_VEND2 is now possible also over Clause-22 MDIO.
+
+The unified driver will still only use Clause-45 access on any Clause-45
+capable busses while still working fine on Clause-22 busses.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/bffcb85fdc20e07056976962d3caaa1be5d0ddb0.1768275364.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/realtek_main.c | 72 ++++++--------------------
+ 1 file changed, 16 insertions(+), 56 deletions(-)
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -1880,28 +1880,18 @@ static int rtl8221b_match_phy_device(str
+ return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev);
+ }
+
+-static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev,
+- const struct phy_driver *phydrv)
++static int rtl8221b_vb_cg_match_phy_device(struct phy_device *phydev,
++ const struct phy_driver *phydrv)
+ {
+- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
++ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true) ||
++ rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
+ }
+
+-static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev,
+- const struct phy_driver *phydrv)
++static int rtl8221b_vm_cg_match_phy_device(struct phy_device *phydev,
++ const struct phy_driver *phydrv)
+ {
+- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
+-}
+-
+-static int rtl8221b_vm_cg_c22_match_phy_device(struct phy_device *phydev,
+- const struct phy_driver *phydrv)
+-{
+- return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false);
+-}
+-
+-static int rtl8221b_vm_cg_c45_match_phy_device(struct phy_device *phydev,
+- const struct phy_driver *phydrv)
+-{
+- return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true);
++ return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true) ||
++ rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false);
+ }
+
+ static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev,
+@@ -2324,27 +2314,8 @@ static struct phy_driver realtek_drvs[]
+ .read_mmd = rtl822xb_read_mmd,
+ .write_mmd = rtl822xb_write_mmd,
+ }, {
+- .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
+- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
+- .config_intr = rtl8221b_config_intr,
+- .handle_interrupt = rtl8221b_handle_interrupt,
+- .probe = rtl822x_probe,
+- .get_features = rtl822x_get_features,
+- .config_aneg = rtl822x_config_aneg,
+- .config_init = rtl822xb_config_init,
+- .inband_caps = rtl822x_inband_caps,
+- .config_inband = rtl822x_config_inband,
+- .get_rate_matching = rtl822xb_get_rate_matching,
+- .read_status = rtl822xb_read_status,
+- .suspend = genphy_suspend,
+- .resume = rtlgen_resume,
+- .read_page = rtl821x_read_page,
+- .write_page = rtl821x_write_page,
+- .read_mmd = rtl822xb_read_mmd,
+- .write_mmd = rtl822xb_write_mmd,
+- }, {
+- .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
+- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
++ .match_phy_device = rtl8221b_vb_cg_match_phy_device,
++ .name = "RTL8221B-VB-CG 2.5Gbps PHY",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
+ .probe = rtl822x_probe,
+@@ -2357,28 +2328,13 @@ static struct phy_driver realtek_drvs[]
+ .read_status = rtl822xb_c45_read_status,
+ .suspend = genphy_c45_pma_suspend,
+ .resume = rtlgen_c45_resume,
+- }, {
+- .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device,
+- .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
+- .config_intr = rtl8221b_config_intr,
+- .handle_interrupt = rtl8221b_handle_interrupt,
+- .probe = rtl822x_probe,
+- .get_features = rtl822x_get_features,
+- .config_aneg = rtl822x_config_aneg,
+- .config_init = rtl822xb_config_init,
+- .inband_caps = rtl822x_inband_caps,
+- .config_inband = rtl822x_config_inband,
+- .get_rate_matching = rtl822xb_get_rate_matching,
+- .read_status = rtl822xb_read_status,
+- .suspend = genphy_suspend,
+- .resume = rtlgen_resume,
+ .read_page = rtl821x_read_page,
+ .write_page = rtl821x_write_page,
+ .read_mmd = rtl822xb_read_mmd,
+ .write_mmd = rtl822xb_write_mmd,
+ }, {
+- .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device,
+- .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)",
++ .match_phy_device = rtl8221b_vm_cg_match_phy_device,
++ .name = "RTL8221B-VM-CG 2.5Gbps PHY",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
+ .probe = rtl822x_probe,
+@@ -2391,6 +2347,10 @@ static struct phy_driver realtek_drvs[]
+ .read_status = rtl822xb_c45_read_status,
+ .suspend = genphy_c45_pma_suspend,
+ .resume = rtlgen_c45_resume,
++ .read_page = rtl821x_read_page,
++ .write_page = rtl821x_write_page,
++ .read_mmd = rtl822xb_read_mmd,
++ .write_mmd = rtl822xb_write_mmd,
+ }, {
+ .match_phy_device = rtl8251b_c45_match_phy_device,
+ .name = "RTL8251B 5Gbps PHY",
--- /dev/null
+From 46ff862d376cfadf0f9e36a6edce41a003175708 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Tue, 13 Jan 2026 03:44:33 +0000
+Subject: [PATCH 4/5] net: phy: realtek: demystify PHYSR register location
+
+Turns out that register address RTL_VND2_PHYSR (0xa434) maps to
+Clause-22 register MII_RESV2. Use that to get rid of yet another magic
+number, and rename access macros accordingly.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/6ed246e0aa3ca8038d2fa432d51518959fb89b6b.1768275364.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/realtek_main.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -178,12 +178,12 @@
+ #define RTL9000A_GINMR 0x14
+ #define RTL9000A_GINMR_LINK_STATUS BIT(4)
+
+-#define RTL_VND2_PHYSR 0xa434
+-#define RTL_VND2_PHYSR_DUPLEX BIT(3)
+-#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4)
+-#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9)
+-#define RTL_VND2_PHYSR_MASTER BIT(11)
+-#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH)
++#define RTL_PHYSR MII_RESV2
++#define RTL_PHYSR_DUPLEX BIT(3)
++#define RTL_PHYSR_SPEEDL GENMASK(5, 4)
++#define RTL_PHYSR_SPEEDH GENMASK(10, 9)
++#define RTL_PHYSR_MASTER BIT(11)
++#define RTL_PHYSR_SPEED_MASK (RTL_PHYSR_SPEEDL | RTL_PHYSR_SPEEDH)
+
+ #define RTL_MDIO_PCS_EEE_ABLE 0xa5c4
+ #define RTL_MDIO_AN_EEE_ADV 0xa5d0
+@@ -1102,12 +1102,12 @@ static void rtlgen_decode_physr(struct p
+ * 0: Half Duplex
+ * 1: Full Duplex
+ */
+- if (val & RTL_VND2_PHYSR_DUPLEX)
++ if (val & RTL_PHYSR_DUPLEX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
+- switch (val & RTL_VND2_PHYSR_SPEED_MASK) {
++ switch (val & RTL_PHYSR_SPEED_MASK) {
+ case 0x0000:
+ phydev->speed = SPEED_10;
+ break;
+@@ -1135,7 +1135,7 @@ static void rtlgen_decode_physr(struct p
+ * 1: Master Mode
+ */
+ if (phydev->speed >= 1000) {
+- if (val & RTL_VND2_PHYSR_MASTER)
++ if (val & RTL_PHYSR_MASTER)
+ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
+ else
+ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
+@@ -1155,8 +1155,7 @@ static int rtlgen_read_status(struct phy
+ if (!phydev->link)
+ return 0;
+
+- val = phy_read_paged(phydev, RTL822X_VND2_TO_PAGE(RTL_VND2_PHYSR),
+- RTL822X_VND2_TO_PAGE_REG(RTL_VND2_PHYSR));
++ val = phy_read(phydev, RTL_PHYSR);
+ if (val < 0)
+ return val;
+
+@@ -1623,7 +1622,8 @@ static int rtl822x_c45_read_status(struc
+ }
+
+ /* Read actual speed from vendor register. */
+- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR);
++ val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
++ RTL822X_VND2_C22_REG(RTL_PHYSR));
+ if (val < 0)
+ return val;
+
+@@ -2127,7 +2127,7 @@ static int rtlgen_sfp_read_status(struct
+ if (!phydev->link)
+ return 0;
+
+- val = rtlgen_read_vend2(phydev, RTL_VND2_PHYSR);
++ val = phy_read(phydev, RTL_PHYSR);
+ if (val < 0)
+ return val;
+
--- /dev/null
+From 650e55f224a575cdb18c984b95036109519502d1 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Tue, 13 Jan 2026 03:44:42 +0000
+Subject: [PATCH 5/5] net: phy: realtek: simplify bogus paged operations
+
+Only registers 0x10~0x17 are affected by the value in the page
+selection register 0x1f. Hence there is no point in using paged
+operations when accessing any other registers.
+Simplify the driver by using the normal phy_read and phy_write
+operations for registers which are anyway not affected by paging.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/0c5cbb66ce3e72a011d76f8c3d61ebcac44483bb.1768275364.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/realtek_main.c | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -67,7 +67,6 @@
+ #define RTL8211E_DELAY_MASK GENMASK(13, 11)
+
+ /* RTL8211F PHY configuration */
+-#define RTL8211F_PHYCR_PAGE 0xa43
+ #define RTL8211F_PHYCR1 0x18
+ #define RTL8211F_ALDPS_PLL_OFF BIT(1)
+ #define RTL8211F_ALDPS_ENABLE BIT(2)
+@@ -77,7 +76,6 @@
+ #define RTL8211F_CLKOUT_EN BIT(0)
+ #define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5)
+
+-#define RTL8211F_INSR_PAGE 0xa43
+ #define RTL8211F_INSR 0x1d
+
+ /* RTL8211F LED configuration */
+@@ -332,7 +330,7 @@ static int rtl8211f_ack_interrupt(struct
+ {
+ int err;
+
+- err = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR);
++ err = phy_read(phydev, RTL8211F_INSR);
+
+ return (err < 0) ? err : 0;
+ }
+@@ -478,7 +476,7 @@ static irqreturn_t rtl8211f_handle_inter
+ {
+ int irq_status;
+
+- irq_status = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR);
++ irq_status = phy_read(phydev, RTL8211F_INSR);
+ if (irq_status < 0) {
+ phy_error(phydev);
+ return IRQ_NONE;
+@@ -669,8 +667,8 @@ static int rtl8211f_config_clk_out(struc
+ RTL8211FVD_CLKOUT_REG,
+ RTL8211FVD_CLKOUT_EN, 0);
+ else
+- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE,
+- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0);
++ ret = phy_modify(phydev, RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN,
++ 0);
+ if (ret)
+ return ret;
+
+@@ -695,15 +693,14 @@ static int rtl8211f_config_aldps(struct
+ if (!priv->enable_aldps)
+ return 0;
+
+- return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1,
+- mask, mask);
++ return phy_modify(phydev, RTL8211F_PHYCR1, mask, mask);
+ }
+
+ static int rtl8211f_config_phy_eee(struct phy_device *phydev)
+ {
+ /* Disable PHY-mode EEE so LPI is passed to the MAC */
+- return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2,
+- RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);
++ return phy_modify(phydev, RTL8211F_PHYCR2,
++ RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);
+ }
+
+ static int rtl8211f_config_init(struct phy_device *phydev)
+@@ -769,7 +766,7 @@ static int rtl8211f_suspend(struct phy_d
+ goto err;
+
+ /* Read the INSR to clear any pending interrupt */
+- phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR);
++ phy_read(phydev, RTL8211F_INSR);
+
+ /* Reset the WoL to ensure that an event is picked up.
+ * Unless we do this, even if we receive another packet,
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -23669,6 +23669,12 @@ F: Documentation/filesystems/ubifs-authe
+@@ -23670,6 +23670,12 @@ F: Documentation/filesystems/ubifs-authe
F: Documentation/filesystems/ubifs.rst
F: fs/ubifs/
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -2216,6 +2216,7 @@ static struct phy_driver realtek_drvs[]
+@@ -2255,6 +2255,7 @@ static struct phy_driver realtek_drvs[]
}, {
.name = "RTL8226 2.5Gbps PHY",
.match_phy_device = rtl8226_match_phy_device,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
-@@ -2228,6 +2229,7 @@ static struct phy_driver realtek_drvs[]
+@@ -2267,6 +2268,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_match_phy_device,
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
-@@ -2258,6 +2260,7 @@ static struct phy_driver realtek_drvs[]
+@@ -2297,6 +2299,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc848),
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
-@@ -2274,6 +2277,7 @@ static struct phy_driver realtek_drvs[]
- }, {
- .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
-+ .soft_reset = genphy_soft_reset,
- .probe = rtl822x_probe,
- .get_features = rtl822x_get_features,
- .config_aneg = rtl822x_config_aneg,
-@@ -2293,6 +2297,7 @@ static struct phy_driver realtek_drvs[]
- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
+@@ -2315,6 +2318,7 @@ static struct phy_driver realtek_drvs[]
+ .name = "RTL8221B-VB-CG 2.5Gbps PHY",
.config_intr = rtl8221b_config_intr,
.handle_interrupt = rtl8221b_handle_interrupt,
+ .soft_reset = rtl822x_c45_soft_reset,
.probe = rtl822x_probe,
.config_init = rtl822xb_config_init,
.inband_caps = rtl822x_inband_caps,
-@@ -2306,6 +2311,7 @@ static struct phy_driver realtek_drvs[]
- }, {
- .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device,
- .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
-+ .soft_reset = genphy_soft_reset,
- .probe = rtl822x_probe,
- .get_features = rtl822x_get_features,
- .config_aneg = rtl822x_config_aneg,
-@@ -2325,6 +2331,7 @@ static struct phy_driver realtek_drvs[]
- .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)",
+@@ -2334,6 +2338,7 @@ static struct phy_driver realtek_drvs[]
+ .name = "RTL8221B-VM-CG 2.5Gbps PHY",
.config_intr = rtl8221b_config_intr,
.handle_interrupt = rtl8221b_handle_interrupt,
+ .soft_reset = rtl822x_c45_soft_reset,
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -1813,9 +1813,11 @@ static bool rtlgen_supports_2_5gbps(stru
+@@ -1823,9 +1823,11 @@ static bool rtlgen_supports_2_5gbps(stru
{
int val;
static int rtl821x_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, RTL821x_PAGE_SELECT);
-@@ -1240,6 +1248,18 @@ static int rtl822x_write_mmd(struct phy_
+@@ -1238,6 +1246,18 @@ static int rtl822x_write_mmd(struct phy_
static int rtl822x_probe(struct phy_device *phydev)
{
if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) &&
phydev->phy_id != RTL_GENERIC_PHYID)
return rtl822x_hwmon_init(phydev);
-@@ -1320,6 +1340,19 @@ static int rtl822xb_write_mmd(struct phy
+@@ -1328,6 +1348,19 @@ static int rtl822xb_write_mmd(struct phy
return write_ret;
}
static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1)
{
bool has_2500, has_sgmii;
-@@ -1377,7 +1410,15 @@ static int rtl822x_set_serdes_option_mod
+@@ -1385,7 +1418,15 @@ static int rtl822x_set_serdes_option_mod
if (ret < 0)
return ret;
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -1898,10 +1898,32 @@ static int rtl8226_match_phy_device(stru
+@@ -1908,10 +1908,32 @@ static int rtl8226_match_phy_device(stru
static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
bool is_c45)
{
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -1595,6 +1595,9 @@ static int rtl822x_c45_get_features(stru
+@@ -1604,6 +1604,9 @@ static int rtl822x_c45_get_features(stru
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
phydev->supported);
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
-@@ -1350,7 +1351,8 @@ static int rtl822x_init_phycr1(struct ph
+@@ -1358,7 +1359,8 @@ static int rtl822x_init_phycr1(struct ph
return phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL8221B_PHYCR1,
RTL8221B_PHYCR1_ALDPS_EN |
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -1379,7 +1379,7 @@ static int rtl822x_set_serdes_option_mod
+@@ -1387,7 +1387,7 @@ static int rtl822x_set_serdes_option_mod
return 0;
/* determine SerDes option mode */
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -14425,7 +14425,9 @@ M: Daniel Golle <daniel@makrotopia.org>
+@@ -14426,7 +14426,9 @@ M: Daniel Golle <daniel@makrotopia.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/pcs/pcs-mtk-lynxi.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19031,6 +19031,13 @@ L: netdev@vger.kernel.org
+@@ -19032,6 +19032,13 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/qualcomm/emac/
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19037,6 +19037,7 @@ L: netdev@vger.kernel.org
+@@ -19038,6 +19038,7 @@ L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml
F: drivers/net/ethernet/qualcomm/ipqess/
+};
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -9113,6 +9113,14 @@ F: drivers/ptp/ptp_qoriq.c
+@@ -9114,6 +9114,14 @@ F: drivers/ptp/ptp_qoriq.c
F: drivers/ptp/ptp_qoriq_debugfs.c
F: include/linux/fsl/ptp_qoriq.h
+ };
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -14432,9 +14432,10 @@ F: include/linux/pcs/pcs-mtk-usxgmii.h
+@@ -14433,9 +14433,10 @@ F: include/linux/pcs/pcs-mtk-usxgmii.h
MEDIATEK ETHERNET PHY DRIVERS
M: Daniel Golle <daniel@makrotopia.org>
M: Qingfang Deng <dqfext@gmail.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -14436,6 +14436,7 @@ M: Sky Huang <SkyLake.Huang@mediatek.com
+@@ -14437,6 +14437,7 @@ M: Sky Huang <SkyLake.Huang@mediatek.com
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/mediatek,2p5gphy-fw.yaml
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -15153,6 +15153,13 @@ S: Maintained
+@@ -15154,6 +15154,13 @@ S: Maintained
F: Documentation/devicetree/bindings/interrupt-controller/microchip,lan966x-oic.yaml
F: drivers/irqchip/irq-lan966x-oic.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -15158,7 +15158,7 @@ M: Daniel Machon <daniel.machon@microchi
+@@ -15159,7 +15159,7 @@ M: Daniel Machon <daniel.machon@microchi
M: UNGLinuxDriver@microchip.com
L: netdev@vger.kernel.org
S: Maintained
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -10971,6 +10971,22 @@ L: virtualization@lists.linux.dev
+@@ -10972,6 +10972,22 @@ L: virtualization@lists.linux.dev
S: Supported
F: drivers/vdpa/ifcvf/
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19122,6 +19122,15 @@ S: Maintained
+@@ -19123,6 +19123,15 @@ S: Maintained
F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
F: drivers/regulator/vqmmc-ipq4019-regulator.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19139,6 +19139,14 @@ S: Maintained
+@@ -19140,6 +19140,14 @@ S: Maintained
F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
F: drivers/mtd/nand/raw/qcom_nandc.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -19500,6 +19500,12 @@ S: Maintained
+@@ -19501,6 +19501,12 @@ S: Maintained
F: Documentation/devicetree/bindings/net/dsa/realtek.yaml
F: drivers/net/dsa/realtek/*
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -20157,6 +20157,13 @@ S: Maintained
+@@ -20158,6 +20158,13 @@ S: Maintained
T: git https://github.com/pkshih/rtw.git
F: drivers/net/wireless/realtek/rtl8xxxu/
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -22071,7 +22071,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
+@@ -22072,7 +22072,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
M: Emil Renner Berthing <kernel@esmil.dk>
M: Hal Feng <hal.feng@starfivetech.com>
S: Maintained