layerscape: add patches-5.4
[openwrt/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