realtek: enable SerDes NWAY and SGMII negotiation
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>
This commit is contained in:
		| @@ -368,8 +368,8 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) | |||||||
|  |  | ||||||
| 	/* Enable PHY control via SoC */ | 	/* Enable PHY control via SoC */ | ||||||
| 	if (priv->family_id == RTL8380_FAMILY_ID) { | 	if (priv->family_id == RTL8380_FAMILY_ID) { | ||||||
| 		/* Enable PHY control via SoC */ | 		/* Enable SerDes NWAY and PHY control via SoC */ | ||||||
| 		sw_w32_mask(0, BIT(15), RTL838X_SMI_GLB_CTRL); | 		sw_w32_mask(BIT(7), BIT(15), RTL838X_SMI_GLB_CTRL); | ||||||
| 	} else { | 	} else { | ||||||
| 		/* Disable PHY polling via SoC */ | 		/* Disable PHY polling via SoC */ | ||||||
| 		sw_w32_mask(BIT(7), 0, RTL839X_SMI_GLB_CTRL); | 		sw_w32_mask(BIT(7), 0, RTL839X_SMI_GLB_CTRL); | ||||||
|   | |||||||
| @@ -344,6 +344,44 @@ static int rtl83xx_phylink_mac_link_state(struct dsa_switch *ds, int port, | |||||||
| 	return 1; | 	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, | 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) | ||||||
| @@ -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)); | 	reg = sw_r32(priv->r->mac_force_mode_ctrl(port)); | ||||||
| 	/* Auto-Negotiation does not work for MAC in RTL8390 */ | 	/* Auto-Negotiation does not work for MAC in RTL8390 */ | ||||||
| 	if (priv->family_id == RTL8380_FAMILY_ID) { | 	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"); | 			pr_debug("PHY autonegotiates\n"); | ||||||
| 			reg |= BIT(2); | 			reg |= BIT(2); | ||||||
| 			sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); | 			sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); | ||||||
|  | 			rtl83xx_config_interface(port, state->interface); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Bjørn Mork
					Bjørn Mork