377ee76171c0556c44dff0e2dc59272bdd84ff59
[openwrt/staging/linusw.git] /
1 From e19de30d20809af3221ef8a2648b8a8a52e02d90 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Wed, 21 Sep 2022 01:23:14 +0100
4 Subject: [PATCH 1/1] net: dsa: mt7530: add support for in-band link status
5
6 Read link status from SGMII PCS for in-band managed 2500Base-X and
7 1000Base-X connection on a MAC port of the MT7531. This is needed to
8 get the SFP cage working which is connected to SGMII interface of
9 port 5 of the MT7531 switch IC on the Bananapi BPi-R3 board.
10 While at it also handle an_complete for both the autoneg and the
11 non-autoneg codepath.
12
13 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
15 ---
16 drivers/net/dsa/mt7530.c | 50 +++++++++++++++++++++++++++++-----------
17 drivers/net/dsa/mt7530.h | 1 +
18 2 files changed, 38 insertions(+), 13 deletions(-)
19
20 --- a/drivers/net/dsa/mt7530.c
21 +++ b/drivers/net/dsa/mt7530.c
22 @@ -2736,9 +2736,6 @@ mt7531_mac_config(struct dsa_switch *ds,
23 case PHY_INTERFACE_MODE_NA:
24 case PHY_INTERFACE_MODE_1000BASEX:
25 case PHY_INTERFACE_MODE_2500BASEX:
26 - if (phylink_autoneg_inband(mode))
27 - return -EINVAL;
28 -
29 return mt7531_sgmii_setup_mode_force(priv, port, interface);
30 default:
31 return -EINVAL;
32 @@ -2814,13 +2811,6 @@ unsupported:
33 return;
34 }
35
36 - if (phylink_autoneg_inband(mode) &&
37 - state->interface != PHY_INTERFACE_MODE_SGMII) {
38 - dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
39 - __func__);
40 - return;
41 - }
42 -
43 mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
44 mcr_new = mcr_cur;
45 mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
46 @@ -2957,6 +2947,9 @@ static void mt753x_phylink_get_caps(stru
47 config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
48 MAC_10 | MAC_100 | MAC_1000FD;
49
50 + if ((priv->id == ID_MT7531) && mt753x_is_mac_port(port))
51 + config->mac_capabilities |= MAC_2500FD;
52 +
53 /* This driver does not make use of the speed, duplex, pause or the
54 * advertisement in its mac_config, so it is safe to mark this driver
55 * as non-legacy.
56 @@ -3022,6 +3015,7 @@ mt7531_sgmii_pcs_get_state_an(struct mt7
57
58 status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
59 state->link = !!(status & MT7531_SGMII_LINK_STATUS);
60 + state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE);
61 if (state->interface == PHY_INTERFACE_MODE_SGMII &&
62 (status & MT7531_SGMII_AN_ENABLE)) {
63 val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port));
64 @@ -3052,16 +3046,44 @@ mt7531_sgmii_pcs_get_state_an(struct mt7
65 return 0;
66 }
67
68 +static void
69 +mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port,
70 + struct phylink_link_state *state)
71 +{
72 + unsigned int val;
73 +
74 + val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
75 + state->link = !!(val & MT7531_SGMII_LINK_STATUS);
76 + if (!state->link)
77 + return;
78 +
79 + state->an_complete = state->link;
80 +
81 + if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
82 + state->speed = SPEED_2500;
83 + else
84 + state->speed = SPEED_1000;
85 +
86 + state->duplex = DUPLEX_FULL;
87 + state->pause = MLO_PAUSE_NONE;
88 +}
89 +
90 static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
91 struct phylink_link_state *state)
92 {
93 struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
94 int port = pcs_to_mt753x_pcs(pcs)->port;
95
96 - if (state->interface == PHY_INTERFACE_MODE_SGMII)
97 + if (state->interface == PHY_INTERFACE_MODE_SGMII) {
98 mt7531_sgmii_pcs_get_state_an(priv, port, state);
99 - else
100 - state->link = false;
101 + return;
102 + } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) ||
103 + (state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
104 + mt7531_sgmii_pcs_get_state_inband(priv, port, state);
105 + return;
106 + }
107 +
108 + state->link = false;
109 }
110
111 static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
112 @@ -3102,6 +3124,8 @@ mt753x_setup(struct dsa_switch *ds)
113 priv->pcs[i].pcs.ops = priv->info->pcs_ops;
114 priv->pcs[i].priv = priv;
115 priv->pcs[i].port = i;
116 + if (mt753x_is_mac_port(i))
117 + priv->pcs[i].pcs.poll = 1;
118 }
119
120 ret = priv->info->sw_setup(ds);
121 --- a/drivers/net/dsa/mt7530.h
122 +++ b/drivers/net/dsa/mt7530.h
123 @@ -373,6 +373,7 @@ enum mt7530_vlan_port_acc_frm {
124 #define MT7531_SGMII_LINK_STATUS BIT(18)
125 #define MT7531_SGMII_AN_ENABLE BIT(12)
126 #define MT7531_SGMII_AN_RESTART BIT(9)
127 +#define MT7531_SGMII_AN_COMPLETE BIT(21)
128
129 /* Register for SGMII PCS_SPPED_ABILITY */
130 #define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08)