realtek: Add SDS configuration routines for the RTL93XX platforms

Adds configuration routines for the internal SerDes of the
RTL930X and RTL931X.

Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
This commit is contained in:
Birger Koblitz 2022-01-17 13:21:09 +01:00 committed by Daniel Golle
parent 51c8f76612
commit 7026084066
4 changed files with 2144 additions and 44 deletions

View File

@ -224,6 +224,7 @@
#define RTL838X_MODEL_NAME_INFO (0x00D4)
#define RTL839X_MODEL_NAME_INFO (0x0FF0)
#define RTL93XX_MODEL_NAME_INFO (0x0004)
#define RTL931X_CHIP_INFO_ADDR (0x0008)
#define RTL838X_LED_GLB_CTRL (0xA000)
#define RTL839X_LED_GLB_CTRL (0x00E4)

View File

@ -345,6 +345,7 @@ static void rtl93xx_phylink_validate(struct dsa_switch *ds, int port,
state->interface != PHY_INTERFACE_MODE_QSGMII &&
state->interface != PHY_INTERFACE_MODE_XGMII &&
state->interface != PHY_INTERFACE_MODE_HSGMII &&
state->interface != PHY_INTERFACE_MODE_10GBASER &&
state->interface != PHY_INTERFACE_MODE_10GKR &&
state->interface != PHY_INTERFACE_MODE_USXGMII &&
state->interface != PHY_INTERFACE_MODE_INTERNAL &&
@ -390,6 +391,9 @@ static void rtl93xx_phylink_validate(struct dsa_switch *ds, int port,
phylink_set(mask, 10000baseCR_Full);
}
if (state->interface == PHY_INTERFACE_MODE_USXGMII)
phylink_set(mask, 10000baseT_Full);
phylink_set(mask, 10baseT_Half);
phylink_set(mask, 10baseT_Full);
phylink_set(mask, 100baseT_Half);
@ -736,9 +740,6 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
if (priv->family_id == RTL9310_FAMILY_ID)
return rtl931x_phylink_mac_config(ds, port, mode, state);
reg = sw_r32(priv->r->mac_force_mode_ctrl(port));
reg &= ~(0xf << 3);
sds_num = priv->ports[port].sds_num;
pr_info("%s SDS is %d\n", __func__, sds_num);
if (sds_num >= 0) {
@ -747,15 +748,14 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
sds_mode = 0x12;
break;
case PHY_INTERFACE_MODE_1000BASEX:
sds_mode = 0x1b; // 10G 1000X Auto
sds_mode = 0x04;
break;
case PHY_INTERFACE_MODE_XGMII:
sds_mode = 0x10;
break;
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_10GKR:
sds_mode = 0x1a;
// We need to use media sel for fibre media:
reg |= BIT(16);
sds_mode = 0x1b; // 10G 1000X Auto
break;
case PHY_INTERFACE_MODE_USXGMII:
sds_mode = 0x0d;
@ -768,6 +768,9 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
rtl9300_sds_rst(sds_num, sds_mode);
}
reg = sw_r32(priv->r->mac_force_mode_ctrl(port));
reg &= ~(0xf << 3);
switch (state->speed) {
case SPEED_10000:
reg |= 4 << 3;
@ -805,8 +808,17 @@ static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
phy_interface_t interface)
{
struct rtl838x_switch_priv *priv = ds->priv;
u32 v;
/* Stop TX/RX to port */
sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
// No longer force link
if (priv->family_id == RTL9300_FAMILY_ID)
v = RTL930X_FORCE_EN | RTL930X_FORCE_LINK_EN;
else if (priv->family_id == RTL9310_FAMILY_ID)
v = RTL931X_FORCE_EN | RTL931X_FORCE_LINK_EN;
sw_w32_mask(v, 0, priv->r->mac_port_ctrl(port));
}
static void rtl93xx_phylink_mac_link_down(struct dsa_switch *ds, int port,

File diff suppressed because it is too large Load Diff

View File

@ -58,9 +58,11 @@ struct __attribute__ ((__packed__)) fw_header {
/* Registers of the internal Serdes of the 9300 */
#define RTL930X_SDS_INDACS_CMD (0x03B0)
#define RTL930X_SDS_INDACS_DATA (0x03B4)
#define RTL930X_MAC_FORCE_MODE_CTRL (0xCA1C)
/*Registers of the internal SerDes of the 9310 */
#define RTL931X_SERDES_INDRT_ACCESS_CTRL (0x5638)
#define RTL931X_SERDES_INDRT_DATA_CTRL (0x563C)
#define RTL931X_SERDES_MODE_CTRL (0x13cc)
#define RTL931X_PS_SERDES_OFF_MODE_CTRL (0x13f4)
#define RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR (0x13F4)
#define RTL931X_MAC_SERDES_MODE_CTRL(sds) (0x136C + (((sds) << 2)))