|
|
@@ -0,0 +1,123 @@
|
|
|
+From 8e18c5fef75debfae3531fbd6901f3bf317d91ed Mon Sep 17 00:00:00 2001
|
|
|
+From: Daniel Golle <[email protected]>
|
|
|
+Date: Fri, 9 Sep 2022 04:28:43 +0100
|
|
|
+Subject: [PATCH] net: dsa: mt7530: add support for in-band link status
|
|
|
+To: [email protected],
|
|
|
+ [email protected]
|
|
|
+Cc: Russell King <[email protected]>,
|
|
|
+ Sean Wang <[email protected]>,
|
|
|
+ Landen Chao <[email protected]>,
|
|
|
+ DENG Qingfang <[email protected]>,
|
|
|
+ Andrew Lunn <[email protected]>,
|
|
|
+ Vivien Didelot <[email protected]>,
|
|
|
+ Florian Fainelli <[email protected]>,
|
|
|
+ Vladimir Oltean <[email protected]>,
|
|
|
+ David S. Miller <[email protected]>,
|
|
|
+ Eric Dumazet <[email protected]>,
|
|
|
+ Jakub Kicinski <[email protected]>,
|
|
|
+ Paolo Abeni <[email protected]>,
|
|
|
+ Matthias Brugger <[email protected]>,
|
|
|
+ Philipp Zabel <[email protected]>
|
|
|
+
|
|
|
+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 <[email protected]>
|
|
|
+---
|
|
|
+ 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);
|