acb67ab1614be50115902aef25ac4b7dff730d1c
[librecmc/librecmc.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 @@ -2952,9 +2952,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 @@ -3030,13 +3027,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 @@ -3173,6 +3163,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 @@ -3238,6 +3231,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 @@ -3268,16 +3262,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 @@ -3318,6 +3340,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 @@ -405,6 +405,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)