realtek: 6.6: refactor mac config and link up for RTL83xx
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Tue, 27 Aug 2024 12:01:57 +0000 (08:01 -0400)
committerSander Vanheule <sander@svanheule.net>
Sat, 14 Sep 2024 18:08:57 +0000 (20:08 +0200)
Since kernel commit c5714f68a76bcad3d ("net: phylink: explicitly invalidate
link_state members in mac_config") it should be clear that link data can
only be used in mac_link_up(). Refactor that for the RTL83xx targets.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c
target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h

index e32933ee916eff7adffdb25ff34c1758adc50612..7ec3f4af1b811b8c68bfa572537d440f183db5b6 100644 (file)
@@ -671,104 +671,31 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port,
                                        unsigned int mode,
                                        const struct phylink_link_state *state)
 {
+       struct dsa_port *dp = dsa_to_port(ds, port);
        struct rtl838x_switch_priv *priv = ds->priv;
-       u32 reg;
-       int speed_bit = priv->family_id == RTL8380_FAMILY_ID ? 4 : 3;
+       u32 mcr;
 
        pr_debug("%s port %d, mode %x\n", __func__, port, mode);
 
-       if (port == priv->cpu_port) {
-               /* Set Speed, duplex, flow control
-                * FORCE_EN | LINK_EN | NWAY_EN | DUP_SEL
-                * | SPD_SEL = 0b10 | FORCE_FC_EN | PHY_MASTER_SLV_MANUAL_EN
-                * | MEDIA_SEL
-                */
-               if (priv->family_id == RTL8380_FAMILY_ID) {
-                       sw_w32(0x6192F, priv->r->mac_force_mode_ctrl(priv->cpu_port));
-                       /* allow CRC errors on CPU-port */
-                       sw_w32_mask(0, 0x8, RTL838X_MAC_PORT_CTRL(priv->cpu_port));
-               } else {
-                       sw_w32_mask(0, 3, priv->r->mac_force_mode_ctrl(priv->cpu_port));
-               }
+       /* currently only needed for RTL8380 */
+       if (priv->family_id != RTL8380_FAMILY_ID)
                return;
-       }
-
-       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 || phylink_autoneg_inband(mode)) {
-                       pr_debug("PHY autonegotiates\n");
-                       reg |= RTL838X_NWAY_EN;
-                       sw_w32(reg, priv->r->mac_force_mode_ctrl(port));
-                       rtl83xx_config_interface(port, state->interface);
-                       return;
-               }
-       }
 
-       if (mode != MLO_AN_FIXED)
-               pr_debug("Fixed state.\n");
-
-       /* Clear id_mode_dis bit, and the existing port mode, let
-                * RGMII_MODE_EN bet set by mac_link_{up,down}  */
-       if (priv->family_id == RTL8380_FAMILY_ID) {
-               reg &= ~(RTL838X_RX_PAUSE_EN | RTL838X_TX_PAUSE_EN);
-               if (state->pause & MLO_PAUSE_TXRX_MASK) {
-                       if (state->pause & MLO_PAUSE_TX)
-                               reg |= RTL838X_TX_PAUSE_EN;
-                       reg |= RTL838X_RX_PAUSE_EN;
-               }
-       } else if (priv->family_id == RTL8390_FAMILY_ID) {
-               reg &= ~(RTL839X_RX_PAUSE_EN | RTL839X_TX_PAUSE_EN);
-               if (state->pause & MLO_PAUSE_TXRX_MASK) {
-                       if (state->pause & MLO_PAUSE_TX)
-                               reg |= RTL839X_TX_PAUSE_EN;
-                       reg |= RTL839X_RX_PAUSE_EN;
-               }
-       }
-
-
-       reg &= ~(3 << speed_bit);
-       switch (state->speed) {
-       case SPEED_1000:
-               reg |= 2 << speed_bit;
-               break;
-       case SPEED_100:
-               reg |= 1 << speed_bit;
-               break;
-       default:
-               break; /* Ignore, including 10MBit which has a speed value of 0 */
+       if (dsa_port_is_cpu(dp)) {
+               /* allow CRC errors on CPU-port */
+               sw_w32_mask(0, 0x8, priv->r->mac_port_ctrl(port));
+               return;
        }
 
-       if (priv->family_id == RTL8380_FAMILY_ID) {
-               reg &= ~(RTL838X_DUPLEX_MODE | RTL838X_FORCE_LINK_EN);
-               if (state->link)
-                       reg |= RTL838X_FORCE_LINK_EN;
-               if (state->duplex == RTL838X_DUPLEX_MODE)
-                       reg |= RTL838X_DUPLEX_MODE;
-       } else if (priv->family_id == RTL8390_FAMILY_ID) {
-               reg &= ~(RTL839X_DUPLEX_MODE | RTL839X_FORCE_LINK_EN);
-               if (state->link)
-                       reg |= RTL839X_FORCE_LINK_EN;
-               if (state->duplex == RTL839X_DUPLEX_MODE)
-                       reg |= RTL839X_DUPLEX_MODE;
-       }
-
-       /* LAG members must use DUPLEX and we need to enable the link */
-       if (priv->lagmembers & BIT_ULL(port)) {
-               switch(priv->family_id) {
-               case RTL8380_FAMILY_ID:
-                       reg |= (RTL838X_DUPLEX_MODE | RTL838X_FORCE_LINK_EN);
-               break;
-               case RTL8390_FAMILY_ID:
-                       reg |= (RTL839X_DUPLEX_MODE | RTL839X_FORCE_LINK_EN);
-               break;
-               }
+       mcr = sw_r32(priv->r->mac_force_mode_ctrl(port));
+       if (mode == MLO_AN_PHY || phylink_autoneg_inband(mode)) {
+               pr_debug("port %d PHY autonegotiates\n", port);
+               rtl83xx_config_interface(port, state->interface);
+               mcr |= RTL838X_NWAY_EN;
+       } else {
+               mcr &= ~RTL838X_NWAY_EN;
        }
-
-       /* Disable AN */
-       if (priv->family_id == RTL8380_FAMILY_ID)
-               reg &= ~RTL838X_NWAY_EN;
-       sw_w32(reg, priv->r->mac_force_mode_ctrl(port));
+       sw_w32(mcr, priv->r->mac_force_mode_ctrl(port));
 }
 
 static void rtl931x_phylink_mac_config(struct dsa_switch *ds, int port,
@@ -916,12 +843,14 @@ static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
                                     phy_interface_t interface)
 {
        struct rtl838x_switch_priv *priv = ds->priv;
+       int mask = 0;
 
        /* Stop TX/RX to port */
        sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
 
        /* No longer force link */
-       sw_w32_mask(0x3, 0, priv->r->mac_force_mode_ctrl(port));
+       mask = RTL83XX_FORCE_EN | RTL83XX_FORCE_LINK_EN;
+       sw_w32_mask(mask, 0, priv->r->mac_force_mode_ctrl(port));
 }
 
 static void rtl93xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
@@ -949,10 +878,60 @@ static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port,
                                   int speed, int duplex,
                                   bool tx_pause, bool rx_pause)
 {
+       struct dsa_port *dp = dsa_to_port(ds, port);
        struct rtl838x_switch_priv *priv = ds->priv;
+       u32 mcr, spdsel;
+
+       if (speed == SPEED_1000)
+               spdsel = RTL_SPEED_1000;
+       else if (speed == SPEED_100)
+               spdsel = RTL_SPEED_100;
+       else
+               spdsel = RTL_SPEED_10;
+
+       mcr = sw_r32(priv->r->mac_force_mode_ctrl(port));
+
+       if (priv->family_id == RTL8380_FAMILY_ID) {
+               mcr &= ~RTL838X_RX_PAUSE_EN;
+               mcr &= ~RTL838X_TX_PAUSE_EN;
+               mcr &= ~RTL838X_DUPLEX_MODE;
+               mcr &= ~RTL838X_SPEED_MASK;
+               mcr |= RTL83XX_FORCE_LINK_EN;
+               mcr |= spdsel << RTL838X_SPEED_SHIFT;
+
+               if (tx_pause)
+                       mcr |= RTL838X_TX_PAUSE_EN;
+               if (rx_pause)
+                       mcr |= RTL838X_RX_PAUSE_EN;
+               if (duplex == DUPLEX_FULL || priv->lagmembers & BIT_ULL(port))
+                       mcr |= RTL838X_DUPLEX_MODE;
+               if (dsa_port_is_cpu(dp))
+                       mcr |= RTL83XX_FORCE_EN;
+
+       } else if (priv->family_id == RTL8390_FAMILY_ID) {
+               mcr &= ~RTL839X_RX_PAUSE_EN;
+               mcr &= ~RTL839X_TX_PAUSE_EN;
+               mcr &= ~RTL839X_DUPLEX_MODE;
+               mcr &= ~RTL839X_SPEED_MASK;
+               mcr |= RTL83XX_FORCE_LINK_EN;
+               mcr |= spdsel << RTL839X_SPEED_SHIFT;
+
+               if (tx_pause)
+                       mcr |= RTL839X_TX_PAUSE_EN;
+               if (rx_pause)
+                       mcr |= RTL839X_RX_PAUSE_EN;
+               if (duplex == DUPLEX_FULL || priv->lagmembers & BIT_ULL(port))
+                       mcr |= RTL839X_DUPLEX_MODE;
+               if (dsa_port_is_cpu(dp))
+                       mcr |= RTL83XX_FORCE_EN;
+       }
+
+       pr_debug("%s port %d, mode %x, speed %d, duplex %d, txpause %d, rxpause %d: set mcr=%08x\n",
+               __func__, port, mode, speed, duplex, tx_pause, rx_pause, mcr);
+       sw_w32(mcr, priv->r->mac_force_mode_ctrl(port));
+
        /* Restart TX/RX to port */
        sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port));
-       /* TODO: Set speed/duplex/pauses */
 }
 
 static void rtl93xx_phylink_mac_link_up(struct dsa_switch *ds, int port,
index 176fd07fe4328d1e0e73a76a3cbcb2b2397baf1f..13a0bb5ffa394f8ce336e692bb5f4bd8ecd7b7f1 100644 (file)
 #define RTL931X_MAC_LINK_MEDIA_STS             (0x0EC8)
 
 /* MAC link state bits */
-#define RTL838X_FORCE_EN                       (1 << 0)
-#define RTL838X_FORCE_LINK_EN                  (1 << 1)
+#define RTL_SPEED_10                           0
+#define RTL_SPEED_100                          1
+#define RTL_SPEED_1000                         2
+
+#define RTL83XX_FORCE_EN                       (1 << 0)
+#define RTL83XX_FORCE_LINK_EN                  (1 << 1)
+
 #define RTL838X_NWAY_EN                                (1 << 2)
 #define RTL838X_DUPLEX_MODE                    (1 << 3)
+#define RTL838X_SPEED_SHIFT                    (4)
+#define RTL838X_SPEED_MASK                     (3 << RTL838X_SPEED_SHIFT)
 #define RTL838X_TX_PAUSE_EN                    (1 << 6)
 #define RTL838X_RX_PAUSE_EN                    (1 << 7)
 #define RTL838X_MAC_FORCE_FC_EN                        (1 << 8)
 
-#define RTL839X_FORCE_EN                       (1 << 0)
-#define RTL839X_FORCE_LINK_EN                  (1 << 1)
 #define RTL839X_DUPLEX_MODE                    (1 << 2)
+#define RTL839X_SPEED_SHIFT                    (3)
+#define RTL839X_SPEED_MASK                     (3 << RTL839X_SPEED_SHIFT)
 #define RTL839X_TX_PAUSE_EN                    (1 << 5)
 #define RTL839X_RX_PAUSE_EN                    (1 << 6)
 #define RTL839X_MAC_FORCE_FC_EN                        (1 << 7)