realtek: dsa: allow to drop phy-handle on switch ports
authorJonas Jelonek <[email protected]>
Sat, 11 Oct 2025 21:36:25 +0000 (21:36 +0000)
committerRobert Marko <[email protected]>
Sun, 2 Nov 2025 15:32:09 +0000 (16:32 +0100)
When Realtek SerDes is completely handled by PCS, it is not treated as
a regular PHY anymore. Thus, we should be able to drop the currently
used pseudo-PHYs and phy-handles for ports which just use the SerDes as
PCS but have no PHY attached.

Allow to drop the phy-handle from switch port definitions if there is a
pcs-handle defined by relaxing several checks in the DSA driver.

Signed-off-by: Jonas Jelonek <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20577
Signed-off-by: Robert Marko <[email protected]>
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c

index 190e495287c59879e914bd610825d482b9778338..583ece3208a9f3d43309be3ad6a1365eb983f6e3 100644 (file)
@@ -336,9 +336,8 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
 
                pcs_node = of_parse_phandle(dn, "pcs-handle", 0);
                phy_node = of_parse_phandle(dn, "phy-handle", 0);
-               if (!phy_node) {
-                       if (pn != priv->cpu_port)
-                               dev_err(priv->dev, "Port node %d misses phy-handle\n", pn);
+               if (pn != priv->cpu_port && !phy_node && !pcs_node) {
+                       dev_err(priv->dev, "Port node %d has neither pcs-handle nor phy-handle\n", pn);
                        continue;
                }
 
@@ -385,6 +384,13 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
                        }
                }
 
+               if (!phy_node) {
+                       if (priv->pcs[pn])
+                               priv->ports[pn].phy_is_integrated = true;
+
+                       continue;
+               }
+
                /* Check for the integrated SerDes of the RTL8380M first */
                if (of_property_read_bool(phy_node, "phy-is-integrated")
                    && priv->id == 0x8380 && pn >= 24) {
index 0e5e79c45d00d89d1b14e964fbaeb59978e88461..06909d205f7342f0bfe2be9a7cf5ea180e8110cf 100644 (file)
@@ -51,7 +51,7 @@ static void rtl83xx_enable_phy_polling(struct rtl838x_switch_priv *priv)
        msleep(1000);
        /* Enable all ports with a PHY, including the SFP-ports */
        for (int i = 0; i < priv->cpu_port; i++) {
-               if (priv->ports[i].phy)
+               if (priv->ports[i].phy || priv->pcs[i])
                        v |= BIT_ULL(i);
        }
 
@@ -436,7 +436,7 @@ static int rtl83xx_setup(struct dsa_switch *ds)
         * they will work in isolated mode (only traffic between port and CPU).
         */
        for (int i = 0; i < priv->cpu_port; i++) {
-               if (priv->ports[i].phy) {
+               if (priv->ports[i].phy || priv->pcs[i]) {
                        priv->ports[i].pm = BIT_ULL(priv->cpu_port);
                        priv->r->traffic_set(i, BIT_ULL(i));
                }
@@ -512,7 +512,7 @@ static int rtl93xx_setup(struct dsa_switch *ds)
         * they will work in isolated mode (only traffic between port and CPU).
         */
        for (int i = 0; i < priv->cpu_port; i++) {
-               if (priv->ports[i].phy) {
+               if (priv->ports[i].phy || priv->pcs[i]) {
                        priv->ports[i].pm = BIT_ULL(priv->cpu_port);
                        priv->r->traffic_set(i, BIT_ULL(i));
                }
@@ -1045,7 +1045,7 @@ static void rtldsa_poll_counters(struct work_struct *work)
        struct rtldsa_counter_state *counters;
 
        for (int i = 0; i < priv->cpu_port; i++) {
-               if (!priv->ports[i].phy)
+               if (!priv->ports[i].phy && !priv->pcs[i])
                        continue;
 
                counters = &priv->ports[i].counters;
@@ -1064,7 +1064,7 @@ static void rtldsa_init_counters(struct rtl838x_switch_priv *priv)
        struct rtldsa_counter_state *counters;
 
        for (int i = 0; i < priv->cpu_port; i++) {
-               if (!priv->ports[i].phy)
+               if (!priv->ports[i].phy && !priv->pcs[i])
                        continue;
 
                counters = &priv->ports[i].counters;
index 0f29e2f9cd7f5e99320d1fc499c2c80469c27a28..d8eee64354f2824a8b3ceffd334da0a7b35adbcd 100644 (file)
@@ -2419,7 +2419,7 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
                sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i));
                sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i));
 
-               if (!priv->ports[i].phy && !(forced_leds_per_port[i]))
+               if (!priv->ports[i].phy && !priv->pcs[i] && !(forced_leds_per_port[i]))
                        continue;
 
                if (forced_leds_per_port[i] > 0)
index 444c843db9c85e731dca8b70d18348098d3d2b0d..104fc55d2e67efcfed86c7c09fa297d8e2e928af 100644 (file)
@@ -1547,7 +1547,7 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv)
                sw_w32_mask(0x3 << pos, 0, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i));
 
                /* Skip port if not present (auto-detect) or not in forced mask */
-               if (!priv->ports[i].phy && !(forced_leds_per_port[i]))
+               if (!priv->ports[i].phy && !priv->pcs[i] && !(forced_leds_per_port[i]))
                        continue;
 
                if (forced_leds_per_port[i] > 0)