--- /dev/null
+From c1887257a81bf62f48178d3b9d31e23520d67b2c Mon Sep 17 00:00:00 2001
+From: Damien Dejean <dam.dejean@gmail.com>
+Date: Wed, 18 Mar 2026 22:54:58 +0100
+Subject: [PATCH 1/4] dt-bindings: net: ethernet-phy: add property
+ enet-phy-pair-order
+
+Add property enet-phy-pair-order to the device tree bindings to define
+the pair order of the PHY. To simplify PCB design some manufacturers
+allow to wire the pairs in a reverse order, and change the order in
+software.
+
+The property can be set to 0 to force the normal pair order (ABCD), or 1
+to force the reverse pair order (DCBA).
+
+Signed-off-by: Damien Dejean <dam.dejean@gmail.com>
+Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
+Link: https://patch.msgid.link/20260318215502.106528-2-dam.dejean@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ Documentation/devicetree/bindings/net/ethernet-phy.yaml | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml
++++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+@@ -122,6 +122,12 @@ properties:
+ e.g. wrong bootstrap configuration caused by issues in PCB
+ layout design.
+
++ enet-phy-pair-order:
++ $ref: /schemas/types.yaml#/definitions/uint32
++ enum: [0, 1]
++ description:
++ For normal (0) or reverse (1) order of the pairs (ABCD -> DCBA).
++
+ eee-broken-100tx:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
--- /dev/null
+From 330296ea9e158758aa65631f5ec64aa74806b7e2 Mon Sep 17 00:00:00 2001
+From: Damien Dejean <dam.dejean@gmail.com>
+Date: Wed, 18 Mar 2026 22:54:59 +0100
+Subject: [PATCH 2/4] net: phy: realtek: add RTL8224 pair order support
+
+The RTL8224 has a register to configure a pair swap (from ABCD order to
+DCBA) providing PCB designers more flexbility when wiring the chip. The
+swap parameter has to be set correctly for each of the 4 ports before
+the chip can detect a link.
+
+After a reset, this register is (unfortunately) left in a random state,
+thus it has to be initialized. On most of the devices the bootloader
+does it once for all and we can rely on the value set, on some other it
+is not and the kernel has to do it.
+
+The MDI pair swap can be set in the device tree using the property
+enet-phy-pair-order. The property is set to 0 to keep the default order
+(ABCD), or 1 to reverse the pairs (DCBA).
+
+Signed-off-by: Damien Dejean <dam.dejean@gmail.com>
+Link: https://patch.msgid.link/20260318215502.106528-3-dam.dejean@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/Kconfig | 1 +
+ drivers/net/phy/realtek/realtek_main.c | 64 ++++++++++++++++++++++++++
+ 2 files changed, 65 insertions(+)
+
+--- a/drivers/net/phy/realtek/Kconfig
++++ b/drivers/net/phy/realtek/Kconfig
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ config REALTEK_PHY
+ tristate "Realtek PHYs"
++ select PHY_PACKAGE
+ help
+ Currently supports RTL821x/RTL822x and fast ethernet PHYs
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -175,6 +175,8 @@
+ #define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12)
+ #define RTL8221B_PHYCR1_PHYAD_0_EN BIT(13)
+
++#define RTL8224_VND1_MDI_PAIR_SWAP 0xa90
++
+ #define RTL8366RB_POWER_SAVE 0x15
+ #define RTL8366RB_POWER_SAVE_ON BIT(12)
+
+@@ -1865,6 +1867,66 @@ static int rtl8224_cable_test_get_status
+ return rtl8224_cable_test_report(phydev, finished);
+ }
+
++static int rtl8224_package_modify_mmd(struct phy_device *phydev, int devad,
++ u32 regnum, u16 mask, u16 set)
++{
++ int val, ret;
++
++ phy_lock_mdio_bus(phydev);
++
++ val = __phy_package_read_mmd(phydev, 0, devad, regnum);
++ if (val < 0) {
++ ret = val;
++ goto exit;
++ }
++
++ val &= ~mask;
++ val |= set;
++
++ ret = __phy_package_write_mmd(phydev, 0, devad, regnum, val);
++
++exit:
++ phy_unlock_mdio_bus(phydev);
++ return ret;
++}
++
++static int rtl8224_mdi_config_order(struct phy_device *phydev)
++{
++ struct device_node *np = phydev->mdio.dev.of_node;
++ u8 port_offset = phydev->mdio.addr & 3;
++ u32 order = 0;
++ int ret;
++
++ ret = of_property_read_u32(np, "enet-phy-pair-order", &order);
++
++ /* Do nothing in case the property is not present */
++ if (ret == -EINVAL || ret == -ENOSYS)
++ return 0;
++
++ if (ret)
++ return ret;
++
++ if (order & ~1)
++ return -EINVAL;
++
++ return rtl8224_package_modify_mmd(phydev, MDIO_MMD_VEND1,
++ RTL8224_VND1_MDI_PAIR_SWAP,
++ BIT(port_offset),
++ order ? BIT(port_offset) : 0);
++}
++
++static int rtl8224_config_init(struct phy_device *phydev)
++{
++ return rtl8224_mdi_config_order(phydev);
++}
++
++static int rtl8224_probe(struct phy_device *phydev)
++{
++ /* Chip exposes 4 ports, join all of them in the same package */
++ return devm_phy_package_join(&phydev->mdio.dev, phydev,
++ phydev->mdio.addr & ~3, 0);
++}
++
+ static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
+ {
+ int val;
+@@ -2466,6 +2528,8 @@ static struct phy_driver realtek_drvs[]
+ PHY_ID_MATCH_EXACT(0x001ccad0),
+ .name = "RTL8224 2.5Gbps PHY",
+ .flags = PHY_POLL_CABLE_TEST,
++ .probe = rtl8224_probe,
++ .config_init = rtl8224_config_init,
+ .get_features = rtl822x_c45_get_features,
+ .config_aneg = rtl822x_c45_config_aneg,
+ .read_status = rtl822x_c45_read_status,
--- /dev/null
+From 58ffb5910f32e5b387d4af31ee21851c40eb31b5 Mon Sep 17 00:00:00 2001
+From: Damien Dejean <dam.dejean@gmail.com>
+Date: Wed, 18 Mar 2026 22:55:00 +0100
+Subject: [PATCH 3/4] dt-bindings: net: ethernet-phy: add property
+ enet-phy-pair-polarity
+
+Add the property enet-phy-pair-polarity to describe the polarity of the
+PHY pairs. To ease PCB designs some manufacturers allow to wire the
+pairs with a reverse polarity and provide a way to configure it.
+
+The property 'enet-phy-pair-polarity' sets the polarity of each pair.
+Bit 0 to 3 configure the polarity or pairs A to D, if set to 1 the
+polarity is reversed for this pair.
+
+Signed-off-by: Damien Dejean <dam.dejean@gmail.com>
+Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
+Link: https://patch.msgid.link/20260318215502.106528-4-dam.dejean@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ Documentation/devicetree/bindings/net/ethernet-phy.yaml | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml
++++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+@@ -128,6 +128,14 @@ properties:
+ description:
+ For normal (0) or reverse (1) order of the pairs (ABCD -> DCBA).
+
++ enet-phy-pair-polarity:
++ $ref: /schemas/types.yaml#/definitions/uint32
++ maximum: 0xf
++ description:
++ A bitmap to describe pair polarity swap. Bit 0 to swap polarity of pair A,
++ bit 1 to swap polarity of pair B, bit 2 to swap polarity of pair C and bit
++ 3 to swap polarity of pair D.
++
+ eee-broken-100tx:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
--- /dev/null
+From beed9c0e9b53c98bc66d28d46fbe38c347e9aa74 Mon Sep 17 00:00:00 2001
+From: Damien Dejean <dam.dejean@gmail.com>
+Date: Wed, 18 Mar 2026 22:55:01 +0100
+Subject: [PATCH 4/4] net: phy: realtek: add RTL8224 polarity support
+
+The RTL8224 has a register to configure the polarity of every pair of
+each port. It provides device designers more flexbility when wiring the
+chip.
+
+Unfortunately, the register is left in an unknown state after a reset.
+Thus on devices where the bootloader don't initialize it, the driver has
+to do it to detect and use a link.
+
+The MDI polarity swap can be set in the device tree using the property
+enet-phy-pair-polarity. The u32 value is a bitfield where bit[0..3]
+control the polarity of pairs A..D.
+
+Signed-off-by: Damien Dejean <dam.dejean@gmail.com>
+Link: https://patch.msgid.link/20260318215502.106528-5-dam.dejean@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek/realtek_main.c | 34 +++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/realtek/realtek_main.c
++++ b/drivers/net/phy/realtek/realtek_main.c
+@@ -176,6 +176,7 @@
+ #define RTL8221B_PHYCR1_PHYAD_0_EN BIT(13)
+
+ #define RTL8224_VND1_MDI_PAIR_SWAP 0xa90
++#define RTL8224_VND1_MDI_POLARITY_SWAP 0xa94
+
+ #define RTL8366RB_POWER_SAVE 0x15
+ #define RTL8366RB_POWER_SAVE_ON BIT(12)
+@@ -1915,9 +1916,40 @@ static int rtl8224_mdi_config_order(stru
+ order ? BIT(port_offset) : 0);
+ }
+
++static int rtl8224_mdi_config_polarity(struct phy_device *phydev)
++{
++ struct device_node *np = phydev->mdio.dev.of_node;
++ u8 offset = (phydev->mdio.addr & 3) * 4;
++ u32 polarity = 0;
++ int ret;
++
++ ret = of_property_read_u32(np, "enet-phy-pair-polarity", &polarity);
++
++ /* Do nothing if the property is not present */
++ if (ret == -EINVAL || ret == -ENOSYS)
++ return 0;
++
++ if (ret)
++ return ret;
++
++ if (polarity & ~0xf)
++ return -EINVAL;
++
++ return rtl8224_package_modify_mmd(phydev, MDIO_MMD_VEND1,
++ RTL8224_VND1_MDI_POLARITY_SWAP,
++ 0xf << offset,
++ polarity << offset);
++}
++
+ static int rtl8224_config_init(struct phy_device *phydev)
+ {
+- return rtl8224_mdi_config_order(phydev);
++ int ret;
++
++ ret = rtl8224_mdi_config_order(phydev);
++ if (ret)
++ return ret;
++
++ return rtl8224_mdi_config_polarity(phydev);
+ }
+
+ static int rtl8224_probe(struct phy_device *phydev)
+obj-$(CONFIG_REALTEK_PHY_MULTIPORT) += realtek_multiport.o
--- a/drivers/net/phy/realtek/Kconfig
+++ b/drivers/net/phy/realtek/Kconfig
-@@ -4,6 +4,11 @@ config REALTEK_PHY
+@@ -5,6 +5,11 @@ config REALTEK_PHY
help
Currently supports RTL821x/RTL822x and fast ethernet PHYs
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
-@@ -1486,6 +1486,148 @@ static unsigned int rtl822x_inband_caps(
+@@ -1489,6 +1489,148 @@ static unsigned int rtl822x_inband_caps(
}
}
static int rtl822xb_get_rate_matching(struct phy_device *phydev,
phy_interface_t iface)
{
-@@ -2358,7 +2500,7 @@ static struct phy_driver realtek_drvs[]
+@@ -2452,7 +2594,7 @@ static struct phy_driver realtek_drvs[]
.soft_reset = rtl822x_c45_soft_reset,
.get_features = rtl822x_c45_get_features,
.config_aneg = rtl822x_c45_config_aneg,