This allows copper SFPs to negotiate speeds lower than 1gig.

Acked-by: Birger Koblitz <[email protected]>
Signed-off-by: Bjørn Mork <[email protected]>
---
 .../drivers/net/dsa/rtl83xx/common.c          |  4 +-
 .../files-5.4/drivers/net/dsa/rtl83xx/dsa.c   | 41 ++++++++++++++++++-
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/common.c 
b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/common.c
index 197a96f8ad13..6940afa7f2a1 100644
--- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/common.c
+++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/common.c
@@ -368,8 +368,8 @@ static int __init rtl83xx_mdio_probe(struct 
rtl838x_switch_priv *priv)
 
        /* Enable PHY control via SoC */
        if (priv->family_id == RTL8380_FAMILY_ID) {
-               /* Enable PHY control via SoC */
-               sw_w32_mask(0, BIT(15), RTL838X_SMI_GLB_CTRL);
+               /* Enable SerDes NWAY and PHY control via SoC */
+               sw_w32_mask(BIT(7), BIT(15), RTL838X_SMI_GLB_CTRL);
        } else {
                /* Disable PHY polling via SoC */
                sw_w32_mask(BIT(7), 0, RTL839X_SMI_GLB_CTRL);
diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/dsa.c 
b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/dsa.c
index 2c49ea27a167..987b47dc8fc6 100644
--- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/dsa.c
+++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/dsa.c
@@ -344,6 +344,44 @@ static int rtl83xx_phylink_mac_link_state(struct 
dsa_switch *ds, int port,
        return 1;
 }
 
+
+static void rtl83xx_config_interface(int port, phy_interface_t interface)
+{
+       u32 old, int_shift, sds_shift;
+
+       switch (port) {
+       case 24:
+               int_shift = 0;
+               sds_shift = 5;
+               break;
+       case 26:
+               int_shift = 3;
+               sds_shift = 0;
+               break;
+       default:
+               return;
+       }
+
+       old = sw_r32(RTL838X_SDS_MODE_SEL);
+       switch (interface) {
+       case PHY_INTERFACE_MODE_1000BASEX:
+               if ((old >> sds_shift & 0x1f) == 4)
+                       return;
+               sw_w32_mask(0x7 << int_shift, 1 << int_shift, 
RTL838X_INT_MODE_CTRL);
+               sw_w32_mask(0x1f << sds_shift, 4 << sds_shift, 
RTL838X_SDS_MODE_SEL);
+               break;
+       case PHY_INTERFACE_MODE_SGMII:
+               if ((old >> sds_shift & 0x1f) == 2)
+                       return;
+               sw_w32_mask(0x7 << int_shift, 2 << int_shift, 
RTL838X_INT_MODE_CTRL);
+               sw_w32_mask(0x1f << sds_shift, 2 << sds_shift, 
RTL838X_SDS_MODE_SEL);
+               break;
+       default:
+               return;
+       }
+       pr_debug("configured port %d for interface %s\n", port, 
phy_modes(interface));
+}
+
 static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port,
                                        unsigned int mode,
                                        const struct phylink_link_state *state)
@@ -377,10 +415,11 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch 
*ds, int port,
        reg = sw_r32(priv->r->mac_force_mode_ctrl(port));
        /* Auto-Negotiation does not work for MAC in RTL8390 */
        if (priv->family_id == RTL8380_FAMILY_ID) {
-               if (mode == MLO_AN_PHY) {
+               if (mode == MLO_AN_PHY || phylink_autoneg_inband(mode)) {
                        pr_debug("PHY autonegotiates\n");
                        reg |= BIT(2);
                        sw_w32(reg, priv->r->mac_force_mode_ctrl(port));
+                       rtl83xx_config_interface(port, state->interface);
                        return;
                }
        }
-- 
2.20.1


_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to