123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- From e19de30d20809af3221ef8a2648b8a8a52e02d90 Mon Sep 17 00:00:00 2001
- From: Daniel Golle <[email protected]>
- 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 <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- 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
- @@ -2736,9 +2736,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;
- @@ -2814,13 +2811,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;
- @@ -2957,6 +2947,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.
- @@ -3022,6 +3015,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));
- @@ -3052,16 +3046,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,
- @@ -3102,6 +3124,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)
|