From cd958d945be06a1b810d55912f32d6e922d952ea Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Tue, 27 Aug 2024 08:01:57 -0400 Subject: [PATCH] realtek: 6.6: refactor mac config and link up for RTL83xx 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 --- .../files-6.6/drivers/net/dsa/rtl83xx/dsa.c | 161 ++++++++---------- .../drivers/net/dsa/rtl83xx/rtl838x.h | 15 +- 2 files changed, 81 insertions(+), 95 deletions(-) diff --git a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c index e32933ee91..7ec3f4af1b 100644 --- a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c @@ -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, diff --git a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h index 176fd07fe4..13a0bb5ffa 100644 --- a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h @@ -144,17 +144,24 @@ #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) -- 2.30.2