kernel: mt7530: add support for in-band managed link
Add support for in-band managed link status to support SFP cage connected to port 5 of the MT7531 switch on the Bananapi BPi-R3. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
		| @@ -0,0 +1,123 @@ | |||||||
|  | From 8e18c5fef75debfae3531fbd6901f3bf317d91ed Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Daniel Golle <daniel@makrotopia.org> | ||||||
|  | Date: Fri, 9 Sep 2022 04:28:43 +0100 | ||||||
|  | Subject: [PATCH] net: dsa: mt7530: add support for in-band link status | ||||||
|  | To: linux-mediatek@lists.infradead.org, | ||||||
|  |     netdev@vger.kernel.org | ||||||
|  | Cc: Russell King <linux@armlinux.org.uk>, | ||||||
|  |     Sean Wang <sean.wang@mediatek.com>, | ||||||
|  |     Landen Chao <Landen.Chao@mediatek.com>, | ||||||
|  |     DENG Qingfang <dqfext@gmail.com>, | ||||||
|  |     Andrew Lunn <andrew@lunn.ch>, | ||||||
|  |     Vivien Didelot <vivien.didelot@gmail.com>, | ||||||
|  |     Florian Fainelli <f.fainelli@gmail.com>, | ||||||
|  |     Vladimir Oltean <olteanv@gmail.com>, | ||||||
|  |     David S. Miller <davem@davemloft.net>, | ||||||
|  |     Eric Dumazet <edumazet@google.com>, | ||||||
|  |     Jakub Kicinski <kuba@kernel.org>, | ||||||
|  |     Paolo Abeni <pabeni@redhat.com>, | ||||||
|  |     Matthias Brugger <matthias.bgg@gmail.com>, | ||||||
|  |     Philipp Zabel <p.zabel@pengutronix.de> | ||||||
|  |  | ||||||
|  | Read link status from SGMII PCS for in-band managed 2500Base-X and | ||||||
|  | 1000Base-X connection on a MAC port of the MT7531. This is needed to | ||||||
|  | get the SFP cage working which is connected to SGMII interface of | ||||||
|  | port 5 of the MT7531 switch IC on the Bananapi BPi-R3 board. | ||||||
|  |  | ||||||
|  | Signed-off-by: Daniel Golle <daniel@makrotopia.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/dsa/mt7530.c | 48 +++++++++++++++++++++++++++++----------- | ||||||
|  |  1 file changed, 35 insertions(+), 13 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/dsa/mt7530.c | ||||||
|  | +++ b/drivers/net/dsa/mt7530.c | ||||||
|  | @@ -2703,9 +2703,6 @@ mt7531_mac_config(struct dsa_switch *ds, | ||||||
|  |  	case PHY_INTERFACE_MODE_NA: | ||||||
|  |  	case PHY_INTERFACE_MODE_1000BASEX: | ||||||
|  |  	case PHY_INTERFACE_MODE_2500BASEX: | ||||||
|  | -		if (phylink_autoneg_inband(mode)) | ||||||
|  | -			return -EINVAL; | ||||||
|  | - | ||||||
|  |  		return mt7531_sgmii_setup_mode_force(priv, port, interface); | ||||||
|  |  	default: | ||||||
|  |  		return -EINVAL; | ||||||
|  | @@ -2781,13 +2778,6 @@ unsupported: | ||||||
|  |  		return; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (phylink_autoneg_inband(mode) && | ||||||
|  | -	    state->interface != PHY_INTERFACE_MODE_SGMII) { | ||||||
|  | -		dev_err(ds->dev, "%s: in-band negotiation unsupported\n", | ||||||
|  | -			__func__); | ||||||
|  | -		return; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  |  	mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); | ||||||
|  |  	mcr_new = mcr_cur; | ||||||
|  |  	mcr_new &= ~PMCR_LINK_SETTINGS_MASK; | ||||||
|  | @@ -2924,6 +2914,9 @@ static void mt753x_phylink_get_caps(stru | ||||||
|  |  	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | | ||||||
|  |  				   MAC_10 | MAC_100 | MAC_1000FD; | ||||||
|  |   | ||||||
|  | +	if ((priv->id == ID_MT7531) && mt753x_is_mac_port(port)) | ||||||
|  | +		config->mac_capabilities |= MAC_2500FD; | ||||||
|  | + | ||||||
|  |  	/* This driver does not make use of the speed, duplex, pause or the | ||||||
|  |  	 * advertisement in its mac_config, so it is safe to mark this driver | ||||||
|  |  	 * as non-legacy. | ||||||
|  | @@ -3019,16 +3012,43 @@ mt7531_sgmii_pcs_get_state_an(struct mt7 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void | ||||||
|  | +mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port, | ||||||
|  | +				  struct phylink_link_state *state) | ||||||
|  | +{ | ||||||
|  | +	unsigned int val; | ||||||
|  | + | ||||||
|  | +	val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); | ||||||
|  | +	state->link = !!(val & MT7531_SGMII_LINK_STATUS); | ||||||
|  | +	if (!state->link) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (state->interface == PHY_INTERFACE_MODE_2500BASEX) | ||||||
|  | +		state->speed = SPEED_2500; | ||||||
|  | +	else | ||||||
|  | +		state->speed = SPEED_1000; | ||||||
|  | + | ||||||
|  | +	state->duplex = DUPLEX_FULL; | ||||||
|  | +	state->pause = 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static void mt7531_pcs_get_state(struct phylink_pcs *pcs, | ||||||
|  |  				 struct phylink_link_state *state) | ||||||
|  |  { | ||||||
|  |  	struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; | ||||||
|  |  	int port = pcs_to_mt753x_pcs(pcs)->port; | ||||||
|  | +	unsigned int val; | ||||||
|  |   | ||||||
|  | -	if (state->interface == PHY_INTERFACE_MODE_SGMII) | ||||||
|  | +	if (state->interface == PHY_INTERFACE_MODE_SGMII) { | ||||||
|  |  		mt7531_sgmii_pcs_get_state_an(priv, port, state); | ||||||
|  | -	else | ||||||
|  | -		state->link = false; | ||||||
|  | +		return; | ||||||
|  | +	} else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) || | ||||||
|  | +		   (state->interface == PHY_INTERFACE_MODE_2500BASEX)) { | ||||||
|  | +		mt7531_sgmii_pcs_get_state_inband(priv, port, state); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	state->link = false; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, | ||||||
|  | @@ -3069,6 +3089,8 @@ mt753x_setup(struct dsa_switch *ds) | ||||||
|  |  		priv->pcs[i].pcs.ops = priv->info->pcs_ops; | ||||||
|  |  		priv->pcs[i].priv = priv; | ||||||
|  |  		priv->pcs[i].port = i; | ||||||
|  | +		if (mt753x_is_mac_port(i)) | ||||||
|  | +			priv->pcs[i].pcs.poll = 1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ret = priv->info->sw_setup(ds); | ||||||
		Reference in New Issue
	
	Block a user
	 Daniel Golle
					Daniel Golle