ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 701-net-0281-net-mscc-ocelot-convert-to-PHYLINK.patch
1 From 0a2b7489bf60d24a54e16147b416f339ebe4f511 Mon Sep 17 00:00:00 2001
2 From: Vladimir Oltean <vladimir.oltean@nxp.com>
3 Date: Mon, 18 Nov 2019 18:05:01 +0200
4 Subject: [PATCH] net: mscc: ocelot: convert to PHYLINK
5
6 This patch reworks ocelot_board.c (aka the MIPS on the VSC7514) to
7 register a PHYLINK instance for each port. The registration code is
8 local to the VSC7514, but the PHYLINK callback implementation is common
9 so that the Felix DSA front-end can use it as well (but DSA does its own
10 registration).
11
12 Now Felix can use native PHYLINK callbacks instead of the PHYLIB
13 adaptation layer in DSA, which had issues supporting fixed-link slave
14 ports (no struct phy_device to pass to the adjust_link callback), as
15 well as fixed-link CPU port at 2.5Gbps.
16
17 The old code from ocelot_port_enable and ocelot_port_disable has been
18 moved into ocelot_phylink_mac_link_up and ocelot_phylink_mac_link_down.
19
20 The PHY connect operation has been moved from ocelot_port_open to
21 mscc_ocelot_probe in ocelot_board.c.
22
23 The phy_set_mode_ext() call for the SerDes PHY has also been moved into
24 mscc_ocelot_probe from ocelot_port_open, and since that was the only
25 reason why a reference to it was kept in ocelot_port_private, that
26 reference was removed.
27
28 Again, the usage of phy_interface_t phy_mode is now local to
29 mscc_ocelot_probe only, after moving the PHY connect operation.
30 So it was also removed from ocelot_port_private.
31 *Maybe* in the future, it can be added back to the common struct
32 ocelot_port, with the purpose of validating mismatches between
33 state->phy_interface and ocelot_port->phy_mode in PHYLINK callbacks.
34 But at the moment that is not critical, since other DSA drivers are not
35 doing that either. No SFP+ modules are in use with Felix/Ocelot yet, to
36 my knowledge.
37
38 In-band AN is not yet supported, due to the fact that this is a mostly
39 mechanical patch for the moment. The mac_an_restart PHYLINK operation
40 needs to be implemented, as well as mac_link_state. Both are SerDes
41 specific, and Felix does not have its PCS configured yet (it works just
42 by virtue of U-Boot initialization at the moment).
43
44 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
45 ---
46  drivers/net/dsa/ocelot/felix.c           |  65 +++++++++----
47  drivers/net/ethernet/mscc/Kconfig        |   2 +-
48  drivers/net/ethernet/mscc/ocelot.c       | 150 ++++++++++++++++--------------
49  drivers/net/ethernet/mscc/ocelot.h       |  13 +--
50  drivers/net/ethernet/mscc/ocelot_board.c | 154 +++++++++++++++++++++++++++----
51  include/soc/mscc/ocelot.h                |  22 ++++-
52  6 files changed, 289 insertions(+), 117 deletions(-)
53
54 --- a/drivers/net/dsa/ocelot/felix.c
55 +++ b/drivers/net/dsa/ocelot/felix.c
56 @@ -58,14 +58,6 @@ static int felix_set_ageing_time(struct
57         return 0;
58  }
59  
60 -static void felix_adjust_link(struct dsa_switch *ds, int port,
61 -                             struct phy_device *phydev)
62 -{
63 -       struct ocelot *ocelot = ds->priv;
64 -
65 -       ocelot_adjust_link(ocelot, port, phydev);
66 -}
67 -
68  static int felix_fdb_dump(struct dsa_switch *ds, int port,
69                           dsa_fdb_dump_cb_t *cb, void *data)
70  {
71 @@ -185,21 +177,59 @@ static int felix_tsn_enable(struct dsa_p
72  }
73  #endif
74  
75 -static int felix_port_enable(struct dsa_switch *ds, int port,
76 -                            struct phy_device *phy)
77 +static void felix_phylink_validate(struct dsa_switch *ds, int port,
78 +                                  unsigned long *supported,
79 +                                  struct phylink_link_state *state)
80  {
81         struct ocelot *ocelot = ds->priv;
82  
83 -       ocelot_port_enable(ocelot, port, phy);
84 +       ocelot_phylink_validate(ocelot, port, supported, state);
85 +}
86 +
87 +static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port,
88 +                                          struct phylink_link_state *state)
89 +{
90 +       struct ocelot *ocelot = ds->priv;
91 +
92 +       ocelot_phylink_mac_pcs_get_state(ocelot, port, state);
93  
94         return 0;
95  }
96  
97 -static void felix_port_disable(struct dsa_switch *ds, int port)
98 +static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
99 +                                    unsigned int link_an_mode,
100 +                                    const struct phylink_link_state *state)
101 +{
102 +       struct ocelot *ocelot = ds->priv;
103 +
104 +       ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
105 +}
106 +
107 +static void felix_phylink_mac_an_restart(struct dsa_switch *ds, int port)
108 +{
109 +       struct ocelot *ocelot = ds->priv;
110 +
111 +       ocelot_phylink_mac_an_restart(ocelot, port);
112 +}
113 +
114 +static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
115 +                                       unsigned int link_an_mode,
116 +                                       phy_interface_t interface)
117 +{
118 +       struct ocelot *ocelot = ds->priv;
119 +
120 +       ocelot_phylink_mac_link_down(ocelot, port, link_an_mode, interface);
121 +}
122 +
123 +static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
124 +                                     unsigned int link_an_mode,
125 +                                     phy_interface_t interface,
126 +                                     struct phy_device *phydev)
127  {
128         struct ocelot *ocelot = ds->priv;
129  
130 -       return ocelot_port_disable(ocelot, port);
131 +       ocelot_phylink_mac_link_up(ocelot, port, link_an_mode, interface,
132 +                                  phydev);
133  }
134  
135  static void felix_get_strings(struct dsa_switch *ds, int port,
136 @@ -417,9 +447,12 @@ static const struct dsa_switch_ops felix
137         .get_ethtool_stats      = felix_get_ethtool_stats,
138         .get_sset_count         = felix_get_sset_count,
139         .get_ts_info            = felix_get_ts_info,
140 -       .adjust_link            = felix_adjust_link,
141 -       .port_enable            = felix_port_enable,
142 -       .port_disable           = felix_port_disable,
143 +       .phylink_validate       = felix_phylink_validate,
144 +       .phylink_mac_link_state = felix_phylink_mac_pcs_get_state,
145 +       .phylink_mac_config     = felix_phylink_mac_config,
146 +       .phylink_mac_an_restart = felix_phylink_mac_an_restart,
147 +       .phylink_mac_link_down  = felix_phylink_mac_link_down,
148 +       .phylink_mac_link_up    = felix_phylink_mac_link_up,
149         .port_fdb_dump          = felix_fdb_dump,
150         .port_fdb_add           = felix_fdb_add,
151         .port_fdb_del           = felix_fdb_del,
152 --- a/drivers/net/ethernet/mscc/Kconfig
153 +++ b/drivers/net/ethernet/mscc/Kconfig
154 @@ -15,7 +15,7 @@ config MSCC_OCELOT_SWITCH
155         tristate "Ocelot switch driver"
156         depends on NET_SWITCHDEV
157         depends on HAS_IOMEM
158 -       select PHYLIB
159 +       select PHYLINK
160         select REGMAP_MMIO
161         help
162           This driver supports the Ocelot network switch device.
163 --- a/drivers/net/ethernet/mscc/ocelot.c
164 +++ b/drivers/net/ethernet/mscc/ocelot.c
165 @@ -13,7 +13,7 @@
166  #include <linux/kernel.h>
167  #include <linux/module.h>
168  #include <linux/netdevice.h>
169 -#include <linux/phy.h>
170 +#include <linux/phylink.h>
171  #include <linux/ptp_clock_kernel.h>
172  #include <linux/skbuff.h>
173  #include <linux/iopoll.h>
174 @@ -406,18 +406,66 @@ static u16 ocelot_wm_enc(u16 value)
175         return value;
176  }
177  
178 -void ocelot_adjust_link(struct ocelot *ocelot, int port,
179 -                       struct phy_device *phydev)
180 +void ocelot_phylink_validate(struct ocelot *ocelot, int port,
181 +                            unsigned long *supported,
182 +                            struct phylink_link_state *state)
183 +{
184 +       __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
185 +
186 +       if (state->interface != PHY_INTERFACE_MODE_NA &&
187 +           state->interface != PHY_INTERFACE_MODE_GMII &&
188 +           state->interface != PHY_INTERFACE_MODE_SGMII &&
189 +           state->interface != PHY_INTERFACE_MODE_QSGMII) {
190 +               bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
191 +               return;
192 +       }
193 +
194 +       /* No half-duplex. */
195 +       phylink_set_port_modes(mask);
196 +       phylink_set(mask, Autoneg);
197 +       phylink_set(mask, Pause);
198 +       phylink_set(mask, Asym_Pause);
199 +       phylink_set(mask, 10baseT_Full);
200 +       phylink_set(mask, 100baseT_Full);
201 +       phylink_set(mask, 1000baseT_Full);
202 +       phylink_set(mask, 2500baseT_Full);
203 +
204 +       bitmap_and(supported, supported, mask,
205 +                  __ETHTOOL_LINK_MODE_MASK_NBITS);
206 +       bitmap_and(state->advertising, state->advertising, mask,
207 +                  __ETHTOOL_LINK_MODE_MASK_NBITS);
208 +}
209 +EXPORT_SYMBOL(ocelot_phylink_validate);
210 +
211 +void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
212 +                                     struct phylink_link_state *state)
213 +{
214 +       state->link = 1;
215 +}
216 +EXPORT_SYMBOL(ocelot_phylink_mac_pcs_get_state);
217 +
218 +void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port)
219 +{
220 +       /* Not supported */
221 +}
222 +EXPORT_SYMBOL(ocelot_phylink_mac_an_restart);
223 +
224 +void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
225 +                              unsigned int link_an_mode,
226 +                              const struct phylink_link_state *state)
227  {
228         int speed, mac_speed, mac_mode = DEV_MAC_MODE_CFG_FDX_ENA;
229         struct ocelot_port *ocelot_port = ocelot->ports[port];
230 +       u32 mac_fc_cfg;
231  
232         if (ocelot->quirks & OCELOT_PCS_PERFORMS_RATE_ADAPTATION)
233                 speed = SPEED_1000;
234         else
235 -               speed = phydev->speed;
236 +               speed = state->speed;
237  
238         switch (speed) {
239 +       case SPEED_UNKNOWN:
240 +               return;
241         case SPEED_10:
242                 mac_speed = OCELOT_SPEED_10;
243                 break;
244 @@ -433,16 +481,11 @@ void ocelot_adjust_link(struct ocelot *o
245                 mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
246                 break;
247         default:
248 -               dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
249 +               dev_err(ocelot->dev, "Unsupported speed on port %d: %d\n",
250                         port, speed);
251                 return;
252         }
253  
254 -       phy_print_status(phydev);
255 -
256 -       if (!phydev->link)
257 -               return;
258 -
259         /* Only full duplex supported for now */
260         ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
261  
262 @@ -469,27 +512,36 @@ void ocelot_adjust_link(struct ocelot *o
263                          QSYS_SWITCH_PORT_MODE, port);
264  
265         /* Flow control */
266 -       ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
267 -                        SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
268 -                        SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
269 -                        SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
270 -                        SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed),
271 -                        SYS_MAC_FC_CFG, port);
272 +       mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed);
273 +       if (state->pause & MLO_PAUSE_RX)
274 +               mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA;
275 +       if (state->pause & MLO_PAUSE_TX)
276 +               mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA |
277 +                             SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
278 +                             SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
279 +                             SYS_MAC_FC_CFG_ZERO_PAUSE_ENA;
280 +       ocelot_write_rix(ocelot, mac_fc_cfg, SYS_MAC_FC_CFG, port);
281 +
282         ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
283  }
284 -EXPORT_SYMBOL(ocelot_adjust_link);
285 +EXPORT_SYMBOL(ocelot_phylink_mac_config);
286  
287 -static void ocelot_port_adjust_link(struct net_device *dev)
288 +void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
289 +                                 unsigned int link_an_mode,
290 +                                 phy_interface_t interface)
291  {
292 -       struct ocelot_port_private *priv = netdev_priv(dev);
293 -       struct ocelot *ocelot = priv->port.ocelot;
294 -       int port = priv->chip_port;
295 +       struct ocelot_port *ocelot_port = ocelot->ports[port];
296  
297 -       ocelot_adjust_link(ocelot, port, dev->phydev);
298 +       ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
299 +       ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
300 +                      QSYS_SWITCH_PORT_MODE, port);
301  }
302 +EXPORT_SYMBOL(ocelot_phylink_mac_link_down);
303  
304 -void ocelot_port_enable(struct ocelot *ocelot, int port,
305 -                       struct phy_device *phy)
306 +void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
307 +                               unsigned int link_an_mode,
308 +                               phy_interface_t interface,
309 +                               struct phy_device *phy)
310  {
311         /* Enable receiving frames on the port, and activate auto-learning of
312          * MAC addresses.
313 @@ -499,62 +551,22 @@ void ocelot_port_enable(struct ocelot *o
314                          ANA_PORT_PORT_CFG_PORTID_VAL(port),
315                          ANA_PORT_PORT_CFG, port);
316  }
317 -EXPORT_SYMBOL(ocelot_port_enable);
318 +EXPORT_SYMBOL(ocelot_phylink_mac_link_up);
319  
320  static int ocelot_port_open(struct net_device *dev)
321  {
322         struct ocelot_port_private *priv = netdev_priv(dev);
323 -       struct ocelot *ocelot = priv->port.ocelot;
324 -       int port = priv->chip_port;
325 -       int err;
326 -
327 -       if (priv->serdes) {
328 -               err = phy_set_mode_ext(priv->serdes, PHY_MODE_ETHERNET,
329 -                                      priv->phy_mode);
330 -               if (err) {
331 -                       netdev_err(dev, "Could not set mode of SerDes\n");
332 -                       return err;
333 -               }
334 -       }
335 -
336 -       err = phy_connect_direct(dev, priv->phy, &ocelot_port_adjust_link,
337 -                                priv->phy_mode);
338 -       if (err) {
339 -               netdev_err(dev, "Could not attach to PHY\n");
340 -               return err;
341 -       }
342  
343 -       dev->phydev = priv->phy;
344 -
345 -       phy_attached_info(priv->phy);
346 -       phy_start(priv->phy);
347 -
348 -       ocelot_port_enable(ocelot, port, priv->phy);
349 +       phylink_start(priv->phylink);
350  
351         return 0;
352  }
353  
354 -void ocelot_port_disable(struct ocelot *ocelot, int port)
355 -{
356 -       struct ocelot_port *ocelot_port = ocelot->ports[port];
357 -
358 -       ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
359 -       ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
360 -                      QSYS_SWITCH_PORT_MODE, port);
361 -}
362 -EXPORT_SYMBOL(ocelot_port_disable);
363 -
364  static int ocelot_port_stop(struct net_device *dev)
365  {
366         struct ocelot_port_private *priv = netdev_priv(dev);
367 -       struct ocelot *ocelot = priv->port.ocelot;
368 -       int port = priv->chip_port;
369 -
370 -       phy_disconnect(priv->phy);
371 -
372 -       dev->phydev = NULL;
373  
374 -       ocelot_port_disable(ocelot, port);
375 +       phylink_stop(priv->phylink);
376  
377         return 0;
378  }
379 @@ -2251,8 +2263,7 @@ void ocelot_init_port(struct ocelot *oce
380  EXPORT_SYMBOL(ocelot_init_port);
381  
382  int ocelot_probe_port(struct ocelot *ocelot, u8 port,
383 -                     void __iomem *regs,
384 -                     struct phy_device *phy)
385 +                     void __iomem *regs)
386  {
387         struct ocelot_port_private *priv;
388         struct ocelot_port *ocelot_port;
389 @@ -2265,7 +2276,6 @@ int ocelot_probe_port(struct ocelot *oce
390         SET_NETDEV_DEV(dev, ocelot->dev);
391         priv = netdev_priv(dev);
392         priv->dev = dev;
393 -       priv->phy = phy;
394         priv->chip_port = port;
395         ocelot_port = &priv->port;
396         ocelot_port->ocelot = ocelot;
397 --- a/drivers/net/ethernet/mscc/ocelot.h
398 +++ b/drivers/net/ethernet/mscc/ocelot.h
399 @@ -12,8 +12,7 @@
400  #include <linux/etherdevice.h>
401  #include <linux/if_vlan.h>
402  #include <linux/net_tstamp.h>
403 -#include <linux/phy.h>
404 -#include <linux/phy/phy.h>
405 +#include <linux/phylink.h>
406  #include <linux/platform_device.h>
407  #include <linux/ptp_clock_kernel.h>
408  #include <linux/regmap.h>
409 @@ -65,14 +64,12 @@ struct ocelot_multicast {
410  struct ocelot_port_private {
411         struct ocelot_port port;
412         struct net_device *dev;
413 -       struct phy_device *phy;
414 +       struct phylink *phylink;
415 +       struct phylink_config phylink_config;
416         u8 chip_port;
417  
418         u8 vlan_aware;
419  
420 -       phy_interface_t phy_mode;
421 -       struct phy *serdes;
422 -
423         struct ocelot_port_tc tc;
424  };
425  
426 @@ -83,9 +80,7 @@ void ocelot_port_writel(struct ocelot_po
427  #define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
428  
429  int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops);
430 -int ocelot_probe_port(struct ocelot *ocelot, u8 port,
431 -                     void __iomem *regs,
432 -                     struct phy_device *phy);
433 +int ocelot_probe_port(struct ocelot *ocelot, u8 port, void __iomem *regs);
434  
435  void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
436                          enum ocelot_tag_prefix injection,
437 --- a/drivers/net/ethernet/mscc/ocelot_board.c
438 +++ b/drivers/net/ethernet/mscc/ocelot_board.c
439 @@ -13,6 +13,7 @@
440  #include <linux/mfd/syscon.h>
441  #include <linux/skbuff.h>
442  #include <net/switchdev.h>
443 +#include <linux/phy/phy.h>
444  
445  #include "ocelot.h"
446  
447 @@ -262,6 +263,91 @@ static const struct ocelot_ops ocelot_op
448         .reset                  = ocelot_reset,
449  };
450  
451 +static void ocelot_port_phylink_validate(struct phylink_config *config,
452 +                                        unsigned long *supported,
453 +                                        struct phylink_link_state *state)
454 +{
455 +       struct net_device *ndev = to_net_dev(config->dev);
456 +       struct ocelot_port_private *priv = netdev_priv(ndev);
457 +       struct ocelot *ocelot = priv->port.ocelot;
458 +       int port = priv->chip_port;
459 +
460 +       ocelot_phylink_validate(ocelot, port, supported, state);
461 +}
462 +
463 +static int
464 +ocelot_port_phylink_mac_pcs_get_state(struct phylink_config *config,
465 +                                     struct phylink_link_state *state)
466 +{
467 +       struct net_device *ndev = to_net_dev(config->dev);
468 +       struct ocelot_port_private *priv = netdev_priv(ndev);
469 +       struct ocelot *ocelot = priv->port.ocelot;
470 +       int port = priv->chip_port;
471 +
472 +       ocelot_phylink_mac_pcs_get_state(ocelot, port, state);
473 +
474 +       return 0;
475 +}
476 +
477 +static void ocelot_port_phylink_mac_an_restart(struct phylink_config *config)
478 +{
479 +       struct net_device *ndev = to_net_dev(config->dev);
480 +       struct ocelot_port_private *priv = netdev_priv(ndev);
481 +       struct ocelot *ocelot = priv->port.ocelot;
482 +       int port = priv->chip_port;
483 +
484 +       ocelot_phylink_mac_an_restart(ocelot, port);
485 +}
486 +
487 +static void
488 +ocelot_port_phylink_mac_config(struct phylink_config *config,
489 +                              unsigned int link_an_mode,
490 +                              const struct phylink_link_state *state)
491 +{
492 +       struct net_device *ndev = to_net_dev(config->dev);
493 +       struct ocelot_port_private *priv = netdev_priv(ndev);
494 +       struct ocelot *ocelot = priv->port.ocelot;
495 +       int port = priv->chip_port;
496 +
497 +       ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
498 +}
499 +
500 +static void ocelot_port_phylink_mac_link_down(struct phylink_config *config,
501 +                                             unsigned int link_an_mode,
502 +                                             phy_interface_t interface)
503 +{
504 +       struct net_device *ndev = to_net_dev(config->dev);
505 +       struct ocelot_port_private *priv = netdev_priv(ndev);
506 +       struct ocelot *ocelot = priv->port.ocelot;
507 +       int port = priv->chip_port;
508 +
509 +       return ocelot_phylink_mac_link_down(ocelot, port, link_an_mode,
510 +                                           interface);
511 +}
512 +
513 +static void ocelot_port_phylink_mac_link_up(struct phylink_config *config,
514 +                                           unsigned int link_an_mode,
515 +                                           phy_interface_t interface,
516 +                                           struct phy_device *phy)
517 +{
518 +       struct net_device *ndev = to_net_dev(config->dev);
519 +       struct ocelot_port_private *priv = netdev_priv(ndev);
520 +       struct ocelot *ocelot = priv->port.ocelot;
521 +       int port = priv->chip_port;
522 +
523 +       return ocelot_phylink_mac_link_up(ocelot, port, link_an_mode,
524 +                                         interface, phy);
525 +}
526 +
527 +static const struct phylink_mac_ops ocelot_phylink_ops = {
528 +       .validate               = ocelot_port_phylink_validate,
529 +       .mac_link_state         = ocelot_port_phylink_mac_pcs_get_state,
530 +       .mac_an_restart         = ocelot_port_phylink_mac_an_restart,
531 +       .mac_config             = ocelot_port_phylink_mac_config,
532 +       .mac_link_down          = ocelot_port_phylink_mac_link_down,
533 +       .mac_link_up            = ocelot_port_phylink_mac_link_up,
534 +};
535 +
536  static int mscc_ocelot_probe(struct platform_device *pdev)
537  {
538         struct device_node *np = pdev->dev.of_node;
539 @@ -369,8 +455,6 @@ static int mscc_ocelot_probe(struct plat
540         for_each_available_child_of_node(ports, portnp) {
541                 struct ocelot_port_private *priv;
542                 struct ocelot_port *ocelot_port;
543 -               struct device_node *phy_node;
544 -               struct phy_device *phy;
545                 struct resource *res;
546                 struct phy *serdes;
547                 void __iomem *regs;
548 @@ -389,16 +473,7 @@ static int mscc_ocelot_probe(struct plat
549                 if (IS_ERR(regs))
550                         continue;
551  
552 -               phy_node = of_parse_phandle(portnp, "phy-handle", 0);
553 -               if (!phy_node)
554 -                       continue;
555 -
556 -               phy = of_phy_find_device(phy_node);
557 -               of_node_put(phy_node);
558 -               if (!phy)
559 -                       continue;
560 -
561 -               err = ocelot_probe_port(ocelot, port, regs, phy);
562 +               err = ocelot_probe_port(ocelot, port, regs);
563                 if (err) {
564                         of_node_put(portnp);
565                         goto out_put_ports;
566 @@ -412,9 +487,7 @@ static int mscc_ocelot_probe(struct plat
567                 if (phy_mode < 0)
568                         phy_mode = PHY_INTERFACE_MODE_NA;
569  
570 -               priv->phy_mode = phy_mode;
571 -
572 -               switch (priv->phy_mode) {
573 +               switch (phy_mode) {
574                 case PHY_INTERFACE_MODE_NA:
575                         continue;
576                 case PHY_INTERFACE_MODE_SGMII:
577 @@ -451,7 +524,41 @@ static int mscc_ocelot_probe(struct plat
578                         goto out_put_ports;
579                 }
580  
581 -               priv->serdes = serdes;
582 +               if (serdes) {
583 +                       err = phy_set_mode_ext(serdes, PHY_MODE_ETHERNET,
584 +                                              phy_mode);
585 +                       if (err) {
586 +                               dev_err(ocelot->dev,
587 +                                       "Could not set mode of SerDes\n");
588 +                               of_node_put(portnp);
589 +                               goto out_put_ports;
590 +                       }
591 +               }
592 +
593 +               priv->phylink_config.dev = &priv->dev->dev;
594 +               priv->phylink_config.type = PHYLINK_NETDEV;
595 +
596 +               priv->phylink = phylink_create(&priv->phylink_config,
597 +                                              of_fwnode_handle(portnp),
598 +                                              phy_mode, &ocelot_phylink_ops);
599 +               if (IS_ERR(priv->phylink)) {
600 +                       dev_err(ocelot->dev,
601 +                               "Could not create a phylink instance (%ld)\n",
602 +                               PTR_ERR(priv->phylink));
603 +                       err = PTR_ERR(priv->phylink);
604 +                       priv->phylink = NULL;
605 +                       of_node_put(portnp);
606 +                       goto out_put_ports;
607 +               }
608 +
609 +               err = phylink_of_phy_connect(priv->phylink, portnp, 0);
610 +               if (err) {
611 +                       dev_err(ocelot->dev, "Could not connect to PHY: %d\n",
612 +                               err);
613 +                       phylink_destroy(priv->phylink);
614 +                       of_node_put(portnp);
615 +                       goto out_put_ports;
616 +               }
617         }
618  
619         register_netdevice_notifier(&ocelot_netdevice_nb);
620 @@ -468,12 +575,27 @@ out_put_ports:
621  static int mscc_ocelot_remove(struct platform_device *pdev)
622  {
623         struct ocelot *ocelot = platform_get_drvdata(pdev);
624 +       int port;
625  
626         ocelot_deinit(ocelot);
627         unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
628         unregister_switchdev_notifier(&ocelot_switchdev_nb);
629         unregister_netdevice_notifier(&ocelot_netdevice_nb);
630  
631 +       for (port = 0; port < ocelot->num_phys_ports; port++) {
632 +               struct ocelot_port_private *priv;
633 +
634 +               priv = container_of(ocelot->ports[port],
635 +                                   struct ocelot_port_private,
636 +                                   port);
637 +
638 +               if (priv->phylink) {
639 +                       rtnl_lock();
640 +                       phylink_destroy(priv->phylink);
641 +                       rtnl_unlock();
642 +               }
643 +       }
644 +
645         return 0;
646  }
647  
648 --- a/include/soc/mscc/ocelot.h
649 +++ b/include/soc/mscc/ocelot.h
650 @@ -518,17 +518,12 @@ void ocelot_deinit(struct ocelot *ocelot
651  void ocelot_init_port(struct ocelot *ocelot, int port);
652  
653  /* DSA callbacks */
654 -void ocelot_port_enable(struct ocelot *ocelot, int port,
655 -                       struct phy_device *phy);
656 -void ocelot_port_disable(struct ocelot *ocelot, int port);
657  void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data);
658  void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data);
659  int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset);
660  int ocelot_get_ts_info(struct ocelot *ocelot, int port,
661                        struct ethtool_ts_info *info);
662  void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs);
663 -void ocelot_adjust_link(struct ocelot *ocelot, int port,
664 -                       struct phy_device *phydev);
665  void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
666                                 bool vlan_aware);
667  void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state);
668 @@ -597,4 +592,21 @@ int ocelot_rtag_parse_enable(struct ocel
669  int ocelot_dscp_set(struct ocelot *ocelot, int port,
670                     bool enable, const u8 dscp_ix,
671                     struct tsn_qos_switch_dscp_conf *c);
672 +void ocelot_phylink_validate(struct ocelot *ocelot, int port,
673 +                            unsigned long *supported,
674 +                            struct phylink_link_state *state);
675 +void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
676 +                                     struct phylink_link_state *state);
677 +void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port);
678 +void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
679 +                              unsigned int link_an_mode,
680 +                              const struct phylink_link_state *state);
681 +void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
682 +                                 unsigned int link_an_mode,
683 +                                 phy_interface_t interface);
684 +void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
685 +                               unsigned int link_an_mode,
686 +                               phy_interface_t interface,
687 +                               struct phy_device *phy);
688 +
689  #endif