1
0
mirror of https://git.openwrt.org/openwrt/openwrt.git synced 2024-10-18 21:48:23 +02:00

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 <markus.stockhausen@gmx.de>
This commit is contained in:
Markus Stockhausen 2024-08-27 08:01:57 -04:00 committed by Sander Vanheule
parent dc9fca1fd1
commit cd958d945b
2 changed files with 82 additions and 96 deletions

@ -671,104 +671,31 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port,
unsigned int mode, unsigned int mode,
const struct phylink_link_state *state) const struct phylink_link_state *state)
{ {
struct dsa_port *dp = dsa_to_port(ds, port);
struct rtl838x_switch_priv *priv = ds->priv; struct rtl838x_switch_priv *priv = ds->priv;
u32 reg; u32 mcr;
int speed_bit = priv->family_id == RTL8380_FAMILY_ID ? 4 : 3;
pr_debug("%s port %d, mode %x\n", __func__, port, mode); pr_debug("%s port %d, mode %x\n", __func__, port, mode);
if (port == priv->cpu_port) { /* currently only needed for RTL8380 */
/* Set Speed, duplex, flow control if (priv->family_id != RTL8380_FAMILY_ID)
* FORCE_EN | LINK_EN | NWAY_EN | DUP_SEL return;
* | SPD_SEL = 0b10 | FORCE_FC_EN | PHY_MASTER_SLV_MANUAL_EN
* | MEDIA_SEL if (dsa_port_is_cpu(dp)) {
*/ /* allow CRC errors on CPU-port */
if (priv->family_id == RTL8380_FAMILY_ID) { sw_w32_mask(0, 0x8, priv->r->mac_port_ctrl(port));
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));
}
return; return;
} }
reg = sw_r32(priv->r->mac_force_mode_ctrl(port)); mcr = sw_r32(priv->r->mac_force_mode_ctrl(port));
/* Auto-Negotiation does not work for MAC in RTL8390 */ if (mode == MLO_AN_PHY || phylink_autoneg_inband(mode)) {
if (priv->family_id == RTL8380_FAMILY_ID) { pr_debug("port %d PHY autonegotiates\n", port);
if (mode == MLO_AN_PHY || phylink_autoneg_inband(mode)) { rtl83xx_config_interface(port, state->interface);
pr_debug("PHY autonegotiates\n"); mcr |= RTL838X_NWAY_EN;
reg |= RTL838X_NWAY_EN; } else {
sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); mcr &= ~RTL838X_NWAY_EN;
rtl83xx_config_interface(port, state->interface);
return;
}
} }
sw_w32(mcr, priv->r->mac_force_mode_ctrl(port));
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 (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;
}
}
/* Disable AN */
if (priv->family_id == RTL8380_FAMILY_ID)
reg &= ~RTL838X_NWAY_EN;
sw_w32(reg, priv->r->mac_force_mode_ctrl(port));
} }
static void rtl931x_phylink_mac_config(struct dsa_switch *ds, int 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) phy_interface_t interface)
{ {
struct rtl838x_switch_priv *priv = ds->priv; struct rtl838x_switch_priv *priv = ds->priv;
int mask = 0;
/* Stop TX/RX to port */ /* Stop TX/RX to port */
sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port)); sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
/* No longer force link */ /* 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, 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, int speed, int duplex,
bool tx_pause, bool rx_pause) bool tx_pause, bool rx_pause)
{ {
struct dsa_port *dp = dsa_to_port(ds, port);
struct rtl838x_switch_priv *priv = ds->priv; 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 */ /* Restart TX/RX to port */
sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(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, static void rtl93xx_phylink_mac_link_up(struct dsa_switch *ds, int port,

@ -144,17 +144,24 @@
#define RTL931X_MAC_LINK_MEDIA_STS (0x0EC8) #define RTL931X_MAC_LINK_MEDIA_STS (0x0EC8)
/* MAC link state bits */ /* MAC link state bits */
#define RTL838X_FORCE_EN (1 << 0) #define RTL_SPEED_10 0
#define RTL838X_FORCE_LINK_EN (1 << 1) #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_NWAY_EN (1 << 2)
#define RTL838X_DUPLEX_MODE (1 << 3) #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_TX_PAUSE_EN (1 << 6)
#define RTL838X_RX_PAUSE_EN (1 << 7) #define RTL838X_RX_PAUSE_EN (1 << 7)
#define RTL838X_MAC_FORCE_FC_EN (1 << 8) #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_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_TX_PAUSE_EN (1 << 5)
#define RTL839X_RX_PAUSE_EN (1 << 6) #define RTL839X_RX_PAUSE_EN (1 << 6)
#define RTL839X_MAC_FORCE_FC_EN (1 << 7) #define RTL839X_MAC_FORCE_FC_EN (1 << 7)