realtek: enable SerDes NWAY and SGMII negotiation
authorBjørn Mork <bjorn@mork.no>
Sat, 13 Mar 2021 16:45:54 +0000 (17:45 +0100)
committerHauke Mehrtens <hauke@hauke-m.de>
Sun, 18 Apr 2021 10:06:45 +0000 (12:06 +0200)
This allows copper SFPs to negotiate speeds lower than 1gig.

Acked-by: Birger Koblitz <mail@birger-koblitz.de>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
(cherry picked from commit 963b2ae702510c11e912c9438fdb9222763a22d5)

target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/common.c
target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/dsa.c

index 197a96f8ad13b54e14cfc7e85a13c6153b86c026..6940afa7f2a16c81a9fdbc3f5df874b4b8b8b393 100644 (file)
@@ -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);
index 2c49ea27a1672019602afcfb19b88ded2cbda8cf..987b47dc8fc6d525167f4b662bd8194bc124361c 100644 (file)
@@ -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;
                }
        }