diff mbox series

[v2] net: dsa: mt7530: add support for in-band link status

Message ID Yx5I6nRPxYIiC1ZT@makrotopia.org (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [v2] net: dsa: mt7530: add support for in-band link status | expand

Checks

Context Check Description
netdev/tree_selection success Guessed tree name to be net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cover_letter success Single patches do not need cover letters
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 0 this patch: 1
netdev/cc_maintainers warning 1 maintainers not CCed: linux-arm-kernel@lists.infradead.org
netdev/build_clang fail Errors and warnings before: 0 this patch: 2
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 0 this patch: 1
netdev/checkpatch warning CHECK: Unnecessary parentheses around 'priv->id == ID_MT7531'
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Daniel Golle Sept. 11, 2022, 8:45 p.m. UTC
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>
---
v2: Use MLO_PAUSE_NONE and read an_complete from SGMII status register.

 drivers/net/dsa/mt7530.c | 50 +++++++++++++++++++++++++++++-----------
 drivers/net/dsa/mt7530.h |  1 +
 2 files changed, 38 insertions(+), 13 deletions(-)

Comments

Jakub Kicinski Sept. 20, 2022, 1:36 a.m. UTC | #1
On Sun, 11 Sep 2022 21:45:30 +0100 Daniel Golle wrote:
>  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;

drivers/net/dsa/mt7530.c:3040:15: warning: unused variable 'val' [-Wunused-variable]
        unsigned int val;
                     ^
Daniel Golle Sept. 20, 2022, 10:28 p.m. UTC | #2
On Mon, Sep 19, 2022 at 06:36:22PM -0700, Jakub Kicinski wrote:
> On Sun, 11 Sep 2022 21:45:30 +0100 Daniel Golle wrote:
> >  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;
> 
> drivers/net/dsa/mt7530.c:3040:15: warning: unused variable 'val' [-Wunused-variable]
>         unsigned int val;
>                      ^

Oops, forgot that one there. Just sent out v3 with this fixed and
an_complete handled more decently.

Thank you for the review!
diff mbox series

Patch

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 835807911be019..2e329881f461d9 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2699,9 +2699,6 @@  mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
 	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;
@@ -2777,13 +2774,6 @@  mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
 		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;
@@ -2922,6 +2912,9 @@  static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
 	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.
@@ -3017,16 +3010,45 @@  mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port,
 	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;
+
+	state->an_complete = !!(val & MT7531_SGMII_AN_COMPLETE);
+
+	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
+		state->speed = SPEED_2500;
+	else
+		state->speed = SPEED_1000;
+
+	state->duplex = DUPLEX_FULL;
+	state->pause = MLO_PAUSE_NONE;
+}
+
 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,
@@ -3067,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);
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index e509af95c35414..e8d9664353504f 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -373,6 +373,7 @@  enum mt7530_vlan_port_acc_frm {
 #define  MT7531_SGMII_LINK_STATUS	BIT(18)
 #define  MT7531_SGMII_AN_ENABLE		BIT(12)
 #define  MT7531_SGMII_AN_RESTART	BIT(9)
+#define  MT7531_SGMII_AN_COMPLETE	BIT(21)
 
 /* Register for SGMII PCS_SPPED_ABILITY */
 #define MT7531_PCS_SPEED_ABILITY(p)	MT7531_SGMII_REG(p, 0x08)