* [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support
@ 2026-01-16 17:39 Damien Dejean
2026-01-16 17:39 ` [PATCH 2/2] net: phy: realtek: add RTL8224 polarity " Damien Dejean
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Damien Dejean @ 2026-01-16 17:39 UTC (permalink / raw)
To: netdev; +Cc: Damien Dejean
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
realtek,mdi-pair-swap. The property is set to "off" to disable the pair
swap, "on" to enable it, or "keep"/unset to keep the current
configuration.
Signed-off-by: Damien Dejean <dam.dejean@gmail.com>
---
.../bindings/net/realtek,rtl82xx.yaml | 13 ++++
drivers/net/phy/realtek/Kconfig | 1 +
drivers/net/phy/realtek/realtek_main.c | 74 +++++++++++++++++++
3 files changed, 88 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
index 2b5697bd7c5d..2d04d90f8b97 100644
--- a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
+++ b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
@@ -55,6 +55,18 @@ properties:
description:
Enable Wake-on-LAN support for the RTL8211F PHY.
+ realtek,mdi-pair-swap:
+ description:
+ Enable or disable the swap of the ethernet pairs (from ABCD to DCBA).
+ The "keep" setting will keep the pair configuration at whatever its
+ current state is.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - keep
+ - on
+ - off
+ default: keep
+
unevaluatedProperties: false
allOf:
@@ -79,5 +91,6 @@ examples:
reg = <1>;
realtek,clkout-disable;
realtek,aldps-enable;
+ realtek,mdi-pair-swap = "on";
};
};
diff --git a/drivers/net/phy/realtek/Kconfig b/drivers/net/phy/realtek/Kconfig
index b05c2a1e9024..a741b34d193e 100644
--- 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
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index 6ff0385201a5..e01bfad37cf5 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -18,6 +18,7 @@
#include <linux/clk.h>
#include <linux/string_choices.h>
+#include "../phylib.h"
#include "realtek.h"
#define RTL8201F_IER 0x13
@@ -162,6 +163,8 @@
#define RTL8224_SRAM_RTCT_LEN(pair) (0x8028 + (pair) * 4)
+#define RTL8224_VND1_MDI_PAIR_SWAP 0xa90
+
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -208,6 +211,16 @@ struct rtl821x_priv {
u16 iner;
};
+enum pair_swap_state {
+ PAIR_SWAP_KEEP = 0,
+ PAIR_SWAP_OFF = 1,
+ PAIR_SWAP_ON = 2,
+};
+
+struct rtl8224_priv {
+ enum pair_swap_state pair_swap;
+};
+
static int rtl821x_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, RTL821x_PAGE_SELECT);
@@ -1683,6 +1696,65 @@ static int rtl8224_cable_test_get_status(struct phy_device *phydev, bool *finish
return rtl8224_cable_test_report(phydev, finished);
}
+static void rtl8224_mdi_pair_swap(struct phy_device *phydev, bool swap)
+{
+ u32 val;
+ u8 port_offset;
+
+ port_offset = phydev->mdio.addr & 3;
+ val = __phy_package_read_mmd(phydev, 0, MDIO_MMD_VEND1,
+ RTL8224_VND1_MDI_PAIR_SWAP);
+ if (swap)
+ val |= (1 << port_offset);
+ else
+ val &= ~(1 << port_offset);
+
+ __phy_package_write_mmd(phydev, 0, MDIO_MMD_VEND1,
+ RTL8224_VND1_MDI_PAIR_SWAP, val);
+}
+
+static int rtl8224_config_init(struct phy_device *phydev)
+{
+ struct rtl8224_priv *priv = phydev->priv;
+
+ if (priv->pair_swap != PAIR_SWAP_KEEP)
+ rtl8224_mdi_pair_swap(phydev, priv->pair_swap == PAIR_SWAP_ON);
+
+ return 0;
+}
+
+static enum pair_swap_state rtlgen_pair_swap_state_get(const struct device_node *np)
+{
+ const char *state = NULL;
+
+ if (!of_property_read_string(np, "realtek,mdi-pair-swap", &state)) {
+ if (!strcmp(state, "off"))
+ return PAIR_SWAP_OFF;
+ if (!strcmp(state, "on"))
+ return PAIR_SWAP_ON;
+ }
+
+ return PAIR_SWAP_KEEP;
+}
+
+static int rtl8224_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct rtl8224_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ phydev->priv = priv;
+
+ priv->pair_swap = rtlgen_pair_swap_state_get(dev->of_node);
+
+ /* Device has 4 ports */
+ devm_phy_package_join(dev, phydev, phydev->mdio.addr & (~3), 0);
+
+ return 0;
+}
+
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
{
int val;
@@ -2212,6 +2284,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,
base-commit: 983d014aafb14ee5e4915465bf8948e8f3a723b5
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] net: phy: realtek: add RTL8224 polarity swap support
2026-01-16 17:39 [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support Damien Dejean
@ 2026-01-16 17:39 ` Damien Dejean
2026-01-17 10:47 ` Krzysztof Kozlowski
2026-01-16 18:10 ` [PATCH 1/2] net: phy: realtek: add RTL8224 pair " Andrew Lunn
2026-01-17 10:47 ` Krzysztof Kozlowski
2 siblings, 1 reply; 6+ messages in thread
From: Damien Dejean @ 2026-01-16 17:39 UTC (permalink / raw)
To: netdev; +Cc: Damien Dejean
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
realtek,mdi-polarity-swap. 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>
---
.../bindings/net/realtek,rtl82xx.yaml | 7 +++++
drivers/net/phy/realtek/realtek_main.c | 29 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
index 2d04d90f8b97..4abcc5cfaf5f 100644
--- a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
+++ b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
@@ -67,6 +67,13 @@ properties:
- off
default: keep
+ realtek,mdi-polarity-swap:
+ 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.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
unevaluatedProperties: false
allOf:
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index e01bfad37cf5..3bcee2f40a44 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -164,6 +164,7 @@
#define RTL8224_SRAM_RTCT_LEN(pair) (0x8028 + (pair) * 4)
#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)
@@ -219,6 +220,7 @@ enum pair_swap_state {
struct rtl8224_priv {
enum pair_swap_state pair_swap;
+ int polarity_swap;
};
static int rtl821x_read_page(struct phy_device *phydev)
@@ -1713,12 +1715,28 @@ static void rtl8224_mdi_pair_swap(struct phy_device *phydev, bool swap)
RTL8224_VND1_MDI_PAIR_SWAP, val);
}
+static void rtl8224_mdi_polarity_swap(struct phy_device *phydev, u32 swap)
+{
+ u32 val;
+ u8 offset;
+
+ offset = (phydev->mdio.addr & 3) * 4;
+ val = __phy_package_read_mmd(phydev, 0, MDIO_MMD_VEND1,
+ RTL8224_VND1_MDI_POLARITY_SWAP);
+ val &= ~(0xf << offset);
+ val |= (swap & 0xf) << offset;
+ __phy_package_write_mmd(phydev, 0, MDIO_MMD_VEND1,
+ RTL8224_VND1_MDI_POLARITY_SWAP, val);
+}
+
static int rtl8224_config_init(struct phy_device *phydev)
{
struct rtl8224_priv *priv = phydev->priv;
if (priv->pair_swap != PAIR_SWAP_KEEP)
rtl8224_mdi_pair_swap(phydev, priv->pair_swap == PAIR_SWAP_ON);
+ if (priv->polarity_swap >= 0)
+ rtl8224_mdi_polarity_swap(phydev, priv->polarity_swap);
return 0;
}
@@ -1737,6 +1755,16 @@ static enum pair_swap_state rtlgen_pair_swap_state_get(const struct device_node
return PAIR_SWAP_KEEP;
}
+static int rtlgen_polarity_swap_get(const struct device_node *np)
+{
+ u32 polarity;
+
+ if (!of_property_read_u32(np, "realtek,mdi-polarity-swap", &polarity))
+ return polarity;
+
+ return -1;
+}
+
static int rtl8224_probe(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
@@ -1748,6 +1776,7 @@ static int rtl8224_probe(struct phy_device *phydev)
phydev->priv = priv;
priv->pair_swap = rtlgen_pair_swap_state_get(dev->of_node);
+ priv->polarity_swap = rtlgen_polarity_swap_get(dev->of_node);
/* Device has 4 ports */
devm_phy_package_join(dev, phydev, phydev->mdio.addr & (~3), 0);
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support
2026-01-16 17:39 [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support Damien Dejean
2026-01-16 17:39 ` [PATCH 2/2] net: phy: realtek: add RTL8224 polarity " Damien Dejean
@ 2026-01-16 18:10 ` Andrew Lunn
2026-01-19 17:54 ` Damien Dejean
2026-01-17 10:47 ` Krzysztof Kozlowski
2 siblings, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2026-01-16 18:10 UTC (permalink / raw)
To: Damien Dejean; +Cc: netdev
On Fri, Jan 16, 2026 at 06:39:19PM +0100, Damien Dejean wrote:
> 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.
Does the PHY support auto MDI-X, where it figures out a working
combination at link up time? That allows you to use crossed or not
crossed cables.
Anyway, the DT property you are adding seems to be the same as
marvell,mdi-cfg-order. See commit:
1432965bf5ce ("dt-bindings: net: marvell,aquantia: add property to override MDI_CFG")
> + realtek,mdi-pair-swap:
Maybe call this realtek,mdi-cfg-order and use the same binding?
> + description:
> + Enable or disable the swap of the ethernet pairs (from ABCD to DCBA).
> + The "keep" setting will keep the pair configuration at whatever its
> + current state is.
> + $ref: /schemas/types.yaml#/definitions/string
> + enum:
> + - keep
You should not need keep. If the property is not present in DT, you by
default do nothing, which would be keep.
> diff --git a/drivers/net/phy/realtek/Kconfig b/drivers/net/phy/realtek/Kconfig
> index b05c2a1e9024..a741b34d193e 100644
> --- 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
Changes to DT bindings should be in a patch of its own.
Andrew
---
pw-bot: cr
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support
2026-01-16 17:39 [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support Damien Dejean
2026-01-16 17:39 ` [PATCH 2/2] net: phy: realtek: add RTL8224 polarity " Damien Dejean
2026-01-16 18:10 ` [PATCH 1/2] net: phy: realtek: add RTL8224 pair " Andrew Lunn
@ 2026-01-17 10:47 ` Krzysztof Kozlowski
2 siblings, 0 replies; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-01-17 10:47 UTC (permalink / raw)
To: Damien Dejean, netdev
On 16/01/2026 18:39, Damien Dejean wrote:
> 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
> realtek,mdi-pair-swap. The property is set to "off" to disable the pair
> swap, "on" to enable it, or "keep"/unset to keep the current
> configuration.
>
> Signed-off-by: Damien Dejean <dam.dejean@gmail.com>
> ---
> .../bindings/net/realtek,rtl82xx.yaml | 13 ++++
Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.
Please use scripts/get_maintainers.pl to get a list of necessary people
and lists to CC (and consider --no-git-fallback argument, so you will
not CC people just because they made one commit years ago). It might
happen, that command when run on an older kernel, gives you outdated
entries. Therefore please be sure you base your patches on recent Linux
kernel.
Tools like b4 or scripts/get_maintainer.pl provide you proper list of
people, so fix your workflow. Tools might also fail if you work on some
ancient tree (don't, instead use mainline) or work on fork of kernel
(don't, instead use mainline). Just use b4 and everything should be
fine, although remember about `b4 prep --auto-to-cc` if you added new
patches to the patchset.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] net: phy: realtek: add RTL8224 polarity swap support
2026-01-16 17:39 ` [PATCH 2/2] net: phy: realtek: add RTL8224 polarity " Damien Dejean
@ 2026-01-17 10:47 ` Krzysztof Kozlowski
0 siblings, 0 replies; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-01-17 10:47 UTC (permalink / raw)
To: Damien Dejean, netdev
On 16/01/2026 18:39, Damien Dejean wrote:
> 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
> realtek,mdi-polarity-swap. 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>
> ---
> .../bindings/net/realtek,rtl82xx.yaml | 7 +++++
> drivers/net/phy/realtek/realtek_main.c | 29 +++++++++++++++++++
> 2 files changed, 36 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
> index 2d04d90f8b97..4abcc5cfaf5f 100644
> --- a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
> +++ b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
> @@ -67,6 +67,13 @@ properties:
> - off
> default: keep
>
> + realtek,mdi-polarity-swap:
> + 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.
> + $ref: /schemas/types.yaml#/definitions/uint32
Same problem.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support
2026-01-16 18:10 ` [PATCH 1/2] net: phy: realtek: add RTL8224 pair " Andrew Lunn
@ 2026-01-19 17:54 ` Damien Dejean
0 siblings, 0 replies; 6+ messages in thread
From: Damien Dejean @ 2026-01-19 17:54 UTC (permalink / raw)
To: Andrew Lunn, krzk; +Cc: netdev
Hi Andrew, Krzysztof,
Thanks for your feedbacks.
On 16 Jan 2026, at 19:10, Andrew Lunn <andrew@lunn.ch> wrote:
>
> Does the PHY support auto MDI-X, where it figures out a working
> combination at link up time? That allows you to use crossed or not
> crossed cables.
It does support auto MDI-X, it’s possible to read the status of it after a cable is connected. However this is different from the swap mechanism I’m introducing here.
>
> Anyway, the DT property you are adding seems to be the same as
> marvell,mdi-cfg-order. See commit:
>
> 1432965bf5ce ("dt-bindings: net: marvell,aquantia: add property to override MDI_CFG")
>
>> + realtek,mdi-pair-swap:
>
> Maybe call this realtek,mdi-cfg-order and use the same binding?
It looks like the same mechanism, thanks for the reference. The aquantia implementation looks more straightforward, let me rework the patchs to have a similar implementation.
> Changes to DT bindings should be in a patch of its own.
Thanks for the notice, I missed that when I ran checkpatch.
Damien
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-01-19 17:55 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-16 17:39 [PATCH 1/2] net: phy: realtek: add RTL8224 pair swap support Damien Dejean
2026-01-16 17:39 ` [PATCH 2/2] net: phy: realtek: add RTL8224 polarity " Damien Dejean
2026-01-17 10:47 ` Krzysztof Kozlowski
2026-01-16 18:10 ` [PATCH 1/2] net: phy: realtek: add RTL8224 pair " Andrew Lunn
2026-01-19 17:54 ` Damien Dejean
2026-01-17 10:47 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox