aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.15/782-v6.1-net-dsa-mt7530-add-support-for-in-band-link-status.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.15/782-v6.1-net-dsa-mt7530-add-support-for-in-band-link-status.patch')
-rw-r--r--target/linux/generic/backport-5.15/782-v6.1-net-dsa-mt7530-add-support-for-in-band-link-status.patch130
1 files changed, 130 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.15/782-v6.1-net-dsa-mt7530-add-support-for-in-band-link-status.patch b/target/linux/generic/backport-5.15/782-v6.1-net-dsa-mt7530-add-support-for-in-band-link-status.patch
new file mode 100644
index 0000000000..7bb6530266
--- /dev/null
+++ b/target/linux/generic/backport-5.15/782-v6.1-net-dsa-mt7530-add-support-for-in-band-link-status.patch
@@ -0,0 +1,130 @@
+From e19de30d20809af3221ef8a2648b8a8a52e02d90 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Wed, 21 Sep 2022 01:23:14 +0100
+Subject: [PATCH 1/1] net: dsa: mt7530: add support for in-band link status
+
+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.
+While at it also handle an_complete for both the autoneg and the
+non-autoneg codepath.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/mt7530.c | 50 +++++++++++++++++++++++++++++-----------
+ drivers/net/dsa/mt7530.h | 1 +
+ 2 files changed, 38 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2699,9 +2699,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;
+@@ -2777,13 +2774,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;
+@@ -2920,6 +2910,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.
+@@ -2985,6 +2978,7 @@ mt7531_sgmii_pcs_get_state_an(struct mt7
+
+ status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
+ state->link = !!(status & MT7531_SGMII_LINK_STATUS);
++ state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE);
+ if (state->interface == PHY_INTERFACE_MODE_SGMII &&
+ (status & MT7531_SGMII_AN_ENABLE)) {
+ val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port));
+@@ -3015,16 +3009,44 @@ 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;
++
++ state->an_complete = state->link;
++
++ 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;
+
+- 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,
+@@ -3065,6 +3087,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);
+--- 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)