]> Git Repo - linux.git/blame - drivers/net/dsa/mv88e6xxx/chip.c
net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset
[linux.git] / drivers / net / dsa / mv88e6xxx / chip.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
91da11f8 2/*
0d3cd4b6
VD
3 * Marvell 88e6xxx Ethernet switch single-chip support
4 *
91da11f8
LB
5 * Copyright (c) 2008 Marvell Semiconductor
6 *
14c7b3c3
AL
7 * Copyright (c) 2016 Andrew Lunn <[email protected]>
8 *
4333d619
VD
9 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
10 * Vivien Didelot <[email protected]>
91da11f8
LB
11 */
12
19fb7f69 13#include <linux/bitfield.h>
19b2f97e 14#include <linux/delay.h>
5bded825 15#include <linux/dsa/mv88e6xxx.h>
defb05b9 16#include <linux/etherdevice.h>
dea87024 17#include <linux/ethtool.h>
facd95b2 18#include <linux/if_bridge.h>
dc30c35b
AL
19#include <linux/interrupt.h>
20#include <linux/irq.h>
21#include <linux/irqdomain.h>
19b2f97e 22#include <linux/jiffies.h>
91da11f8 23#include <linux/list.h>
14c7b3c3 24#include <linux/mdio.h>
2bbba277 25#include <linux/module.h>
caac8545 26#include <linux/of_device.h>
dc30c35b 27#include <linux/of_irq.h>
b516d453 28#include <linux/of_mdio.h>
877b7cb0 29#include <linux/platform_data/mv88e6xxx.h>
91da11f8 30#include <linux/netdevice.h>
c8c1b39a 31#include <linux/gpio/consumer.h>
c9a2356f 32#include <linux/phylink.h>
c8f0b869 33#include <net/dsa.h>
ec561276 34
4d5f2ba7 35#include "chip.h"
9dd43aa2 36#include "devlink.h"
a935c052 37#include "global1.h"
ec561276 38#include "global2.h"
c6fe0ad2 39#include "hwtstamp.h"
10fa5bfc 40#include "phy.h"
18abed21 41#include "port.h"
2fa8d3af 42#include "ptp.h"
6d91782f 43#include "serdes.h"
e7ba0fad 44#include "smi.h"
91da11f8 45
fad09c73 46static void assert_reg_lock(struct mv88e6xxx_chip *chip)
3996a4ff 47{
fad09c73
VD
48 if (unlikely(!mutex_is_locked(&chip->reg_lock))) {
49 dev_err(chip->dev, "Switch registers lock not held!\n");
3996a4ff
VD
50 dump_stack();
51 }
52}
53
ec561276 54int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)
914b32f6
VD
55{
56 int err;
57
fad09c73 58 assert_reg_lock(chip);
914b32f6 59
fad09c73 60 err = mv88e6xxx_smi_read(chip, addr, reg, val);
914b32f6
VD
61 if (err)
62 return err;
63
fad09c73 64 dev_dbg(chip->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
914b32f6
VD
65 addr, reg, *val);
66
67 return 0;
68}
69
ec561276 70int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
91da11f8 71{
914b32f6
VD
72 int err;
73
fad09c73 74 assert_reg_lock(chip);
91da11f8 75
fad09c73 76 err = mv88e6xxx_smi_write(chip, addr, reg, val);
914b32f6
VD
77 if (err)
78 return err;
79
fad09c73 80 dev_dbg(chip->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
bb92ea5e
VD
81 addr, reg, val);
82
914b32f6
VD
83 return 0;
84}
85
683f2244
VD
86int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
87 u16 mask, u16 val)
88{
35da1dfd 89 const unsigned long timeout = jiffies + msecs_to_jiffies(50);
683f2244
VD
90 u16 data;
91 int err;
92 int i;
93
35da1dfd
TW
94 /* There's no bus specific operation to wait for a mask. Even
95 * if the initial poll takes longer than 50ms, always do at
96 * least one more attempt.
97 */
98 for (i = 0; time_before(jiffies, timeout) || (i < 2); i++) {
683f2244
VD
99 err = mv88e6xxx_read(chip, addr, reg, &data);
100 if (err)
101 return err;
102
103 if ((data & mask) == val)
104 return 0;
105
35da1dfd
TW
106 if (i < 2)
107 cpu_relax();
108 else
109 usleep_range(1000, 2000);
683f2244
VD
110 }
111
95ce158b
LW
112 err = mv88e6xxx_read(chip, addr, reg, &data);
113 if (err)
114 return err;
115
116 if ((data & mask) == val)
117 return 0;
118
683f2244
VD
119 dev_err(chip->dev, "Timeout while waiting for switch\n");
120 return -ETIMEDOUT;
121}
122
19fb7f69
VD
123int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
124 int bit, int val)
125{
126 return mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit),
127 val ? BIT(bit) : 0x0000);
128}
129
10fa5bfc 130struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
a3c53be5
AL
131{
132 struct mv88e6xxx_mdio_bus *mdio_bus;
133
134 mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus,
135 list);
136 if (!mdio_bus)
137 return NULL;
138
139 return mdio_bus->bus;
140}
141
dc30c35b
AL
142static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
143{
144 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
145 unsigned int n = d->hwirq;
146
147 chip->g1_irq.masked |= (1 << n);
148}
149
150static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
151{
152 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
153 unsigned int n = d->hwirq;
154
155 chip->g1_irq.masked &= ~(1 << n);
156}
157
294d711e 158static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
dc30c35b 159{
dc30c35b
AL
160 unsigned int nhandled = 0;
161 unsigned int sub_irq;
162 unsigned int n;
163 u16 reg;
7c0db24c 164 u16 ctl1;
dc30c35b
AL
165 int err;
166
c9acece0 167 mv88e6xxx_reg_lock(chip);
82466921 168 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
c9acece0 169 mv88e6xxx_reg_unlock(chip);
dc30c35b
AL
170
171 if (err)
172 goto out;
173
7c0db24c
JDA
174 do {
175 for (n = 0; n < chip->g1_irq.nirqs; ++n) {
176 if (reg & (1 << n)) {
177 sub_irq = irq_find_mapping(chip->g1_irq.domain,
178 n);
179 handle_nested_irq(sub_irq);
180 ++nhandled;
181 }
dc30c35b 182 }
7c0db24c 183
c9acece0 184 mv88e6xxx_reg_lock(chip);
7c0db24c
JDA
185 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
186 if (err)
187 goto unlock;
188 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
189unlock:
c9acece0 190 mv88e6xxx_reg_unlock(chip);
7c0db24c
JDA
191 if (err)
192 goto out;
193 ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
194 } while (reg & ctl1);
195
dc30c35b
AL
196out:
197 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
198}
199
294d711e
AL
200static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
201{
202 struct mv88e6xxx_chip *chip = dev_id;
203
204 return mv88e6xxx_g1_irq_thread_work(chip);
205}
206
dc30c35b
AL
207static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
208{
209 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
210
c9acece0 211 mv88e6xxx_reg_lock(chip);
dc30c35b
AL
212}
213
214static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
215{
216 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
217 u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
218 u16 reg;
219 int err;
220
d77f4321 221 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &reg);
dc30c35b
AL
222 if (err)
223 goto out;
224
225 reg &= ~mask;
226 reg |= (~chip->g1_irq.masked & mask);
227
d77f4321 228 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);
dc30c35b
AL
229 if (err)
230 goto out;
231
232out:
c9acece0 233 mv88e6xxx_reg_unlock(chip);
dc30c35b
AL
234}
235
6eb15e21 236static const struct irq_chip mv88e6xxx_g1_irq_chip = {
dc30c35b
AL
237 .name = "mv88e6xxx-g1",
238 .irq_mask = mv88e6xxx_g1_irq_mask,
239 .irq_unmask = mv88e6xxx_g1_irq_unmask,
240 .irq_bus_lock = mv88e6xxx_g1_irq_bus_lock,
241 .irq_bus_sync_unlock = mv88e6xxx_g1_irq_bus_sync_unlock,
242};
243
244static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
245 unsigned int irq,
246 irq_hw_number_t hwirq)
247{
248 struct mv88e6xxx_chip *chip = d->host_data;
249
250 irq_set_chip_data(irq, d->host_data);
251 irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
252 irq_set_noprobe(irq);
253
254 return 0;
255}
256
257static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
258 .map = mv88e6xxx_g1_irq_domain_map,
259 .xlate = irq_domain_xlate_twocell,
260};
261
3d82475a 262/* To be called with reg_lock held */
294d711e 263static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)
dc30c35b
AL
264{
265 int irq, virq;
3460a577
AL
266 u16 mask;
267
d77f4321 268 mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
3d5fdba1 269 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
d77f4321 270 mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
3460a577 271
5edef2f2 272 for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
a3db3d3a 273 virq = irq_find_mapping(chip->g1_irq.domain, irq);
dc30c35b
AL
274 irq_dispose_mapping(virq);
275 }
276
a3db3d3a 277 irq_domain_remove(chip->g1_irq.domain);
dc30c35b
AL
278}
279
294d711e
AL
280static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
281{
3d82475a
UKK
282 /*
283 * free_irq must be called without reg_lock taken because the irq
284 * handler takes this lock, too.
285 */
294d711e 286 free_irq(chip->irq, chip);
3d82475a 287
c9acece0 288 mv88e6xxx_reg_lock(chip);
3d82475a 289 mv88e6xxx_g1_irq_free_common(chip);
c9acece0 290 mv88e6xxx_reg_unlock(chip);
294d711e
AL
291}
292
293static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)
dc30c35b 294{
3dd0ef05
AL
295 int err, irq, virq;
296 u16 reg, mask;
dc30c35b
AL
297
298 chip->g1_irq.nirqs = chip->info->g1_irqs;
299 chip->g1_irq.domain = irq_domain_add_simple(
300 NULL, chip->g1_irq.nirqs, 0,
301 &mv88e6xxx_g1_irq_domain_ops, chip);
302 if (!chip->g1_irq.domain)
303 return -ENOMEM;
304
305 for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
306 irq_create_mapping(chip->g1_irq.domain, irq);
307
308 chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
309 chip->g1_irq.masked = ~0;
310
d77f4321 311 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
dc30c35b 312 if (err)
3dd0ef05 313 goto out_mapping;
dc30c35b 314
3dd0ef05 315 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
dc30c35b 316
d77f4321 317 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
dc30c35b 318 if (err)
3dd0ef05 319 goto out_disable;
dc30c35b
AL
320
321 /* Reading the interrupt status clears (most of) them */
82466921 322 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
dc30c35b 323 if (err)
3dd0ef05 324 goto out_disable;
dc30c35b 325
dc30c35b
AL
326 return 0;
327
3dd0ef05 328out_disable:
3d5fdba1 329 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
d77f4321 330 mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
3dd0ef05
AL
331
332out_mapping:
333 for (irq = 0; irq < 16; irq++) {
334 virq = irq_find_mapping(chip->g1_irq.domain, irq);
335 irq_dispose_mapping(virq);
336 }
337
338 irq_domain_remove(chip->g1_irq.domain);
dc30c35b
AL
339
340 return err;
341}
342
294d711e
AL
343static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
344{
f6d9758b
AL
345 static struct lock_class_key lock_key;
346 static struct lock_class_key request_key;
294d711e
AL
347 int err;
348
349 err = mv88e6xxx_g1_irq_setup_common(chip);
350 if (err)
351 return err;
352
f6d9758b
AL
353 /* These lock classes tells lockdep that global 1 irqs are in
354 * a different category than their parent GPIO, so it won't
355 * report false recursion.
356 */
357 irq_set_lockdep_class(chip->irq, &lock_key, &request_key);
358
3095383a
AL
359 snprintf(chip->irq_name, sizeof(chip->irq_name),
360 "mv88e6xxx-%s", dev_name(chip->dev));
361
c9acece0 362 mv88e6xxx_reg_unlock(chip);
294d711e
AL
363 err = request_threaded_irq(chip->irq, NULL,
364 mv88e6xxx_g1_irq_thread_fn,
0340376e 365 IRQF_ONESHOT | IRQF_SHARED,
3095383a 366 chip->irq_name, chip);
c9acece0 367 mv88e6xxx_reg_lock(chip);
294d711e
AL
368 if (err)
369 mv88e6xxx_g1_irq_free_common(chip);
370
371 return err;
372}
373
374static void mv88e6xxx_irq_poll(struct kthread_work *work)
375{
376 struct mv88e6xxx_chip *chip = container_of(work,
377 struct mv88e6xxx_chip,
378 irq_poll_work.work);
379 mv88e6xxx_g1_irq_thread_work(chip);
380
381 kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
382 msecs_to_jiffies(100));
383}
384
385static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)
386{
387 int err;
388
389 err = mv88e6xxx_g1_irq_setup_common(chip);
390 if (err)
391 return err;
392
393 kthread_init_delayed_work(&chip->irq_poll_work,
394 mv88e6xxx_irq_poll);
395
3f8b8696 396 chip->kworker = kthread_create_worker(0, "%s", dev_name(chip->dev));
294d711e
AL
397 if (IS_ERR(chip->kworker))
398 return PTR_ERR(chip->kworker);
399
400 kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
401 msecs_to_jiffies(100));
402
403 return 0;
404}
405
406static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
407{
408 kthread_cancel_delayed_work_sync(&chip->irq_poll_work);
409 kthread_destroy_worker(chip->kworker);
3d82475a 410
c9acece0 411 mv88e6xxx_reg_lock(chip);
3d82475a 412 mv88e6xxx_g1_irq_free_common(chip);
c9acece0 413 mv88e6xxx_reg_unlock(chip);
294d711e
AL
414}
415
64d47d50
RK
416static int mv88e6xxx_port_config_interface(struct mv88e6xxx_chip *chip,
417 int port, phy_interface_t interface)
418{
419 int err;
420
421 if (chip->info->ops->port_set_rgmii_delay) {
422 err = chip->info->ops->port_set_rgmii_delay(chip, port,
423 interface);
424 if (err && err != -EOPNOTSUPP)
425 return err;
426 }
427
428 if (chip->info->ops->port_set_cmode) {
429 err = chip->info->ops->port_set_cmode(chip, port,
430 interface);
431 if (err && err != -EOPNOTSUPP)
432 return err;
433 }
434
435 return 0;
436}
437
a5a6858b
RK
438static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
439 int link, int speed, int duplex, int pause,
440 phy_interface_t mode)
d78343d2
VD
441{
442 int err;
443
444 if (!chip->info->ops->port_set_link)
445 return 0;
446
447 /* Port's MAC control must not be changed unless the link is down */
43c8e0ae 448 err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
d78343d2
VD
449 if (err)
450 return err;
451
f365c6f7
RK
452 if (chip->info->ops->port_set_speed_duplex) {
453 err = chip->info->ops->port_set_speed_duplex(chip, port,
454 speed, duplex);
d78343d2
VD
455 if (err && err != -EOPNOTSUPP)
456 goto restore_link;
457 }
458
54186b91
AL
459 if (chip->info->ops->port_set_pause) {
460 err = chip->info->ops->port_set_pause(chip, port, pause);
461 if (err)
462 goto restore_link;
463 }
464
64d47d50 465 err = mv88e6xxx_port_config_interface(chip, port, mode);
d78343d2
VD
466restore_link:
467 if (chip->info->ops->port_set_link(chip, port, link))
774439e5 468 dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port);
d78343d2
VD
469
470 return err;
471}
472
ca345931 473static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)
d700ec41 474{
3ba89b28
AL
475 return port >= chip->info->internal_phys_offset &&
476 port < chip->info->num_internal_phys +
477 chip->info->internal_phys_offset;
d700ec41
MV
478}
479
5d5b231d
RK
480static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
481{
482 u16 reg;
483 int err;
484
2b29cb9e
RKO
485 /* The 88e6250 family does not have the PHY detect bit. Instead,
486 * report whether the port is internal.
487 */
488 if (chip->info->family == MV88E6XXX_FAMILY_6250)
7a2dd00b 489 return mv88e6xxx_phy_is_internal(chip, port);
2b29cb9e 490
5d5b231d
RK
491 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
492 if (err) {
493 dev_err(chip->dev,
494 "p%d: %s: failed to read port status\n",
495 port, __func__);
496 return err;
497 }
498
499 return !!(reg & MV88E6XXX_PORT_STS_PHY_DETECT);
500}
501
a5a6858b
RK
502static int mv88e6xxx_serdes_pcs_get_state(struct dsa_switch *ds, int port,
503 struct phylink_link_state *state)
504{
505 struct mv88e6xxx_chip *chip = ds->priv;
193c5b26 506 int lane;
a5a6858b
RK
507 int err;
508
509 mv88e6xxx_reg_lock(chip);
510 lane = mv88e6xxx_serdes_get_lane(chip, port);
193c5b26 511 if (lane >= 0 && chip->info->ops->serdes_pcs_get_state)
a5a6858b
RK
512 err = chip->info->ops->serdes_pcs_get_state(chip, port, lane,
513 state);
514 else
515 err = -EOPNOTSUPP;
516 mv88e6xxx_reg_unlock(chip);
517
518 return err;
519}
520
521static int mv88e6xxx_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
522 unsigned int mode,
523 phy_interface_t interface,
524 const unsigned long *advertise)
525{
526 const struct mv88e6xxx_ops *ops = chip->info->ops;
193c5b26 527 int lane;
a5a6858b
RK
528
529 if (ops->serdes_pcs_config) {
530 lane = mv88e6xxx_serdes_get_lane(chip, port);
193c5b26 531 if (lane >= 0)
a5a6858b
RK
532 return ops->serdes_pcs_config(chip, port, lane, mode,
533 interface, advertise);
534 }
535
536 return 0;
537}
538
539static void mv88e6xxx_serdes_pcs_an_restart(struct dsa_switch *ds, int port)
540{
541 struct mv88e6xxx_chip *chip = ds->priv;
542 const struct mv88e6xxx_ops *ops;
543 int err = 0;
193c5b26 544 int lane;
a5a6858b
RK
545
546 ops = chip->info->ops;
547
548 if (ops->serdes_pcs_an_restart) {
549 mv88e6xxx_reg_lock(chip);
550 lane = mv88e6xxx_serdes_get_lane(chip, port);
193c5b26 551 if (lane >= 0)
a5a6858b
RK
552 err = ops->serdes_pcs_an_restart(chip, port, lane);
553 mv88e6xxx_reg_unlock(chip);
554
555 if (err)
556 dev_err(ds->dev, "p%d: failed to restart AN\n", port);
557 }
558}
559
560static int mv88e6xxx_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
561 unsigned int mode,
562 int speed, int duplex)
563{
564 const struct mv88e6xxx_ops *ops = chip->info->ops;
193c5b26 565 int lane;
a5a6858b
RK
566
567 if (!phylink_autoneg_inband(mode) && ops->serdes_pcs_link_up) {
568 lane = mv88e6xxx_serdes_get_lane(chip, port);
193c5b26 569 if (lane >= 0)
a5a6858b
RK
570 return ops->serdes_pcs_link_up(chip, port, lane,
571 speed, duplex);
572 }
573
574 return 0;
575}
576
d4ebf12b
RKO
577static const u8 mv88e6185_phy_interface_modes[] = {
578 [MV88E6185_PORT_STS_CMODE_GMII_FD] = PHY_INTERFACE_MODE_GMII,
579 [MV88E6185_PORT_STS_CMODE_MII_100_FD_PS] = PHY_INTERFACE_MODE_MII,
580 [MV88E6185_PORT_STS_CMODE_MII_100] = PHY_INTERFACE_MODE_MII,
581 [MV88E6185_PORT_STS_CMODE_MII_10] = PHY_INTERFACE_MODE_MII,
582 [MV88E6185_PORT_STS_CMODE_SERDES] = PHY_INTERFACE_MODE_1000BASEX,
583 [MV88E6185_PORT_STS_CMODE_1000BASE_X] = PHY_INTERFACE_MODE_1000BASEX,
584 [MV88E6185_PORT_STS_CMODE_PHY] = PHY_INTERFACE_MODE_SGMII,
585};
586
d0b78ab1
TW
587static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
588 struct phylink_config *config)
589{
590 u8 cmode = chip->ports[port].cmode;
591
592 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
593
ca345931 594 if (mv88e6xxx_phy_is_internal(chip, port)) {
d0b78ab1
TW
595 __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
596 } else {
597 if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) &&
598 mv88e6185_phy_interface_modes[cmode])
599 __set_bit(mv88e6185_phy_interface_modes[cmode],
600 config->supported_interfaces);
601
602 config->mac_capabilities |= MAC_1000FD;
603 }
604}
605
d4ebf12b
RKO
606static void mv88e6185_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
607 struct phylink_config *config)
608{
609 u8 cmode = chip->ports[port].cmode;
610
dde41a69 611 if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) &&
d4ebf12b
RKO
612 mv88e6185_phy_interface_modes[cmode])
613 __set_bit(mv88e6185_phy_interface_modes[cmode],
614 config->supported_interfaces);
6c422e34 615
d4ebf12b
RKO
616 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
617 MAC_1000FD;
618}
619
620static const u8 mv88e6xxx_phy_interface_modes[] = {
18bb56ab 621 [MV88E6XXX_PORT_STS_CMODE_MII_PHY] = PHY_INTERFACE_MODE_REVMII,
d4ebf12b
RKO
622 [MV88E6XXX_PORT_STS_CMODE_MII] = PHY_INTERFACE_MODE_MII,
623 [MV88E6XXX_PORT_STS_CMODE_GMII] = PHY_INTERFACE_MODE_GMII,
18bb56ab 624 [MV88E6XXX_PORT_STS_CMODE_RMII_PHY] = PHY_INTERFACE_MODE_REVRMII,
d4ebf12b
RKO
625 [MV88E6XXX_PORT_STS_CMODE_RMII] = PHY_INTERFACE_MODE_RMII,
626 [MV88E6XXX_PORT_STS_CMODE_100BASEX] = PHY_INTERFACE_MODE_100BASEX,
627 [MV88E6XXX_PORT_STS_CMODE_1000BASEX] = PHY_INTERFACE_MODE_1000BASEX,
628 [MV88E6XXX_PORT_STS_CMODE_SGMII] = PHY_INTERFACE_MODE_SGMII,
629 /* higher interface modes are not needed here, since ports supporting
630 * them are writable, and so the supported interfaces are filled in the
631 * corresponding .phylink_set_interfaces() implementation below
6c422e34 632 */
d4ebf12b
RKO
633};
634
635static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)
636{
637 if (cmode < ARRAY_SIZE(mv88e6xxx_phy_interface_modes) &&
638 mv88e6xxx_phy_interface_modes[cmode])
639 __set_bit(mv88e6xxx_phy_interface_modes[cmode], supported);
640 else if (cmode == MV88E6XXX_PORT_STS_CMODE_RGMII)
641 phy_interface_set_rgmii(supported);
642}
643
644static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
645 struct phylink_config *config)
646{
647 unsigned long *supported = config->supported_interfaces;
648
649 /* Translate the default cmode */
650 mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
651
652 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
653}
654
655static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip)
656{
657 u16 reg, val;
658 int err;
659
660 err = mv88e6xxx_port_read(chip, 4, MV88E6XXX_PORT_STS, &reg);
661 if (err)
662 return err;
663
664 /* If PHY_DETECT is zero, then we are not in auto-media mode */
665 if (!(reg & MV88E6XXX_PORT_STS_PHY_DETECT))
666 return 0xf;
667
668 val = reg & ~MV88E6XXX_PORT_STS_PHY_DETECT;
669 err = mv88e6xxx_port_write(chip, 4, MV88E6XXX_PORT_STS, val);
670 if (err)
671 return err;
672
673 err = mv88e6xxx_port_read(chip, 4, MV88E6XXX_PORT_STS, &val);
674 if (err)
675 return err;
676
677 /* Restore PHY_DETECT value */
678 err = mv88e6xxx_port_write(chip, 4, MV88E6XXX_PORT_STS, reg);
679 if (err)
680 return err;
681
682 return val & MV88E6XXX_PORT_STS_CMODE_MASK;
683}
684
685static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
686 struct phylink_config *config)
687{
688 unsigned long *supported = config->supported_interfaces;
689 int err, cmode;
690
691 /* Translate the default cmode */
692 mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
693
694 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
695 MAC_1000FD;
696
697 /* Port 4 supports automedia if the serdes is associated with it. */
698 if (port == 4) {
d4ebf12b
RKO
699 err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
700 if (err < 0)
701 dev_err(chip->dev, "p%d: failed to read scratch\n",
702 port);
703 if (err <= 0)
a7d82367 704 return;
d4ebf12b
RKO
705
706 cmode = mv88e6352_get_port4_serdes_cmode(chip);
707 if (cmode < 0)
708 dev_err(chip->dev, "p%d: failed to read serdes cmode\n",
709 port);
710 else
711 mv88e6xxx_translate_cmode(cmode, supported);
d4ebf12b
RKO
712 }
713}
714
715static void mv88e6341_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
716 struct phylink_config *config)
717{
718 unsigned long *supported = config->supported_interfaces;
719
720 /* Translate the default cmode */
721 mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
722
723 /* No ethtool bits for 200Mbps */
724 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
725 MAC_1000FD;
726
727 /* The C_Mode field is programmable on port 5 */
728 if (port == 5) {
729 __set_bit(PHY_INTERFACE_MODE_SGMII, supported);
730 __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported);
731 __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported);
732
733 config->mac_capabilities |= MAC_2500FD;
734 }
735}
736
737static void mv88e6390_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
738 struct phylink_config *config)
739{
740 unsigned long *supported = config->supported_interfaces;
741
742 /* Translate the default cmode */
743 mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
744
745 /* No ethtool bits for 200Mbps */
746 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
747 MAC_1000FD;
748
749 /* The C_Mode field is programmable on ports 9 and 10 */
750 if (port == 9 || port == 10) {
751 __set_bit(PHY_INTERFACE_MODE_SGMII, supported);
752 __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported);
753 __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported);
754
755 config->mac_capabilities |= MAC_2500FD;
756 }
757}
758
759static void mv88e6390x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
760 struct phylink_config *config)
761{
762 unsigned long *supported = config->supported_interfaces;
763
764 mv88e6390_phylink_get_caps(chip, port, config);
765
766 /* For the 6x90X, ports 2-7 can be in automedia mode.
767 * (Note that 6x90 doesn't support RXAUI nor XAUI).
768 *
769 * Port 2 can also support 1000BASE-X in automedia mode if port 9 is
770 * configured for 1000BASE-X, SGMII or 2500BASE-X.
771 * Port 3-4 can also support 1000BASE-X in automedia mode if port 9 is
772 * configured for RXAUI, 1000BASE-X, SGMII or 2500BASE-X.
773 *
774 * Port 5 can also support 1000BASE-X in automedia mode if port 10 is
775 * configured for 1000BASE-X, SGMII or 2500BASE-X.
776 * Port 6-7 can also support 1000BASE-X in automedia mode if port 10 is
777 * configured for RXAUI, 1000BASE-X, SGMII or 2500BASE-X.
778 *
779 * For now, be permissive (as the old code was) and allow 1000BASE-X
780 * on ports 2..7.
781 */
782 if (port >= 2 && port <= 7)
783 __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported);
784
785 /* The C_Mode field can also be programmed for 10G speeds */
786 if (port == 9 || port == 10) {
787 __set_bit(PHY_INTERFACE_MODE_XAUI, supported);
788 __set_bit(PHY_INTERFACE_MODE_RXAUI, supported);
789
790 config->mac_capabilities |= MAC_10000FD;
791 }
792}
793
794static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
795 struct phylink_config *config)
796{
797 unsigned long *supported = config->supported_interfaces;
798 bool is_6191x =
799 chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X;
12899f29
AL
800 bool is_6361 =
801 chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361;
d4ebf12b
RKO
802
803 mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
804
805 config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
806 MAC_1000FD;
807
808 /* The C_Mode field can be programmed for ports 0, 9 and 10 */
809 if (port == 0 || port == 9 || port == 10) {
810 __set_bit(PHY_INTERFACE_MODE_SGMII, supported);
811 __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported);
812
813 /* 6191X supports >1G modes only on port 10 */
814 if (!is_6191x || port == 10) {
815 __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported);
12899f29
AL
816 config->mac_capabilities |= MAC_2500FD;
817
818 /* 6361 only supports up to 2500BaseX */
819 if (!is_6361) {
820 __set_bit(PHY_INTERFACE_MODE_5GBASER, supported);
821 __set_bit(PHY_INTERFACE_MODE_10GBASER, supported);
4a562127 822 __set_bit(PHY_INTERFACE_MODE_USXGMII, supported);
12899f29
AL
823 config->mac_capabilities |= MAC_5000FD |
824 MAC_10000FD;
825 }
d4ebf12b
RKO
826 }
827 }
1d2577ab
MC
828
829 if (port == 0) {
830 __set_bit(PHY_INTERFACE_MODE_RMII, supported);
831 __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
832 __set_bit(PHY_INTERFACE_MODE_RGMII_ID, supported);
833 __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, supported);
834 __set_bit(PHY_INTERFACE_MODE_RGMII_TXID, supported);
835 }
d4ebf12b
RKO
836}
837
838static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
839 struct phylink_config *config)
840{
841 struct mv88e6xxx_chip *chip = ds->priv;
842
a7d82367 843 mv88e6xxx_reg_lock(chip);
d4ebf12b 844 chip->info->ops->phylink_get_caps(chip, port, config);
a7d82367 845 mv88e6xxx_reg_unlock(chip);
d4ebf12b 846
ca345931 847 if (mv88e6xxx_phy_is_internal(chip, port)) {
87a39882
VO
848 __set_bit(PHY_INTERFACE_MODE_INTERNAL,
849 config->supported_interfaces);
850 /* Internal ports with no phy-mode need GMII for PHYLIB */
d4ebf12b
RKO
851 __set_bit(PHY_INTERFACE_MODE_GMII,
852 config->supported_interfaces);
87a39882 853 }
c9a2356f
RK
854}
855
267d7692
RKO
856static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
857 unsigned int mode, phy_interface_t interface)
858{
859 struct mv88e6xxx_chip *chip = ds->priv;
860 int err = 0;
861
862 /* In inband mode, the link may come up at any time while the link
863 * is not forced down. Force the link down while we reconfigure the
864 * interface mode.
865 */
866 if (mode == MLO_AN_INBAND &&
867 chip->ports[port].interface != interface &&
868 chip->info->ops->port_set_link) {
869 mv88e6xxx_reg_lock(chip);
870 err = chip->info->ops->port_set_link(chip, port,
871 LINK_FORCED_DOWN);
872 mv88e6xxx_reg_unlock(chip);
873 }
874
875 return err;
876}
877
c9a2356f
RK
878static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
879 unsigned int mode,
880 const struct phylink_link_state *state)
881{
882 struct mv88e6xxx_chip *chip = ds->priv;
04ec4e62 883 int err = 0;
c9a2356f 884
c9acece0 885 mv88e6xxx_reg_lock(chip);
fad58190 886
ca345931 887 if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) {
04ec4e62
RKO
888 err = mv88e6xxx_port_config_interface(chip, port,
889 state->interface);
890 if (err && err != -EOPNOTSUPP)
891 goto err_unlock;
892
893 err = mv88e6xxx_serdes_pcs_config(chip, port, mode,
894 state->interface,
895 state->advertising);
896 /* FIXME: we should restart negotiation if something changed -
897 * which is something we get if we convert to using phylinks
898 * PCS operations.
899 */
900 if (err > 0)
901 err = 0;
902 }
a5a6858b 903
267d7692
RKO
904err_unlock:
905 mv88e6xxx_reg_unlock(chip);
906
907 if (err && err != -EOPNOTSUPP)
908 dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
909}
910
911static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
912 unsigned int mode, phy_interface_t interface)
913{
914 struct mv88e6xxx_chip *chip = ds->priv;
915 int err = 0;
916
fad58190 917 /* Undo the forced down state above after completing configuration
04ec4e62
RKO
918 * irrespective of its state on entry, which allows the link to come
919 * up in the in-band case where there is no separate SERDES. Also
920 * ensure that the link can come up if the PPU is in use and we are
921 * in PHY mode (we treat the PPU as an effective in-band mechanism.)
fad58190 922 */
267d7692
RKO
923 mv88e6xxx_reg_lock(chip);
924
04ec4e62 925 if (chip->info->ops->port_set_link &&
267d7692
RKO
926 ((mode == MLO_AN_INBAND &&
927 chip->ports[port].interface != interface) ||
04ec4e62 928 (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port))))
267d7692 929 err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
fad58190 930
c9acece0 931 mv88e6xxx_reg_unlock(chip);
c9a2356f 932
267d7692
RKO
933 chip->ports[port].interface = interface;
934
935 return err;
c9a2356f
RK
936}
937
30c4a5b0
RK
938static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
939 unsigned int mode,
940 phy_interface_t interface)
c9a2356f
RK
941{
942 struct mv88e6xxx_chip *chip = ds->priv;
30c4a5b0
RK
943 const struct mv88e6xxx_ops *ops;
944 int err = 0;
c9a2356f 945
30c4a5b0 946 ops = chip->info->ops;
c9a2356f 947
5d5b231d 948 mv88e6xxx_reg_lock(chip);
2b29cb9e
RKO
949 /* Force the link down if we know the port may not be automatically
950 * updated by the switch or if we are using fixed-link mode.
4a3e0aed 951 */
2b29cb9e 952 if ((!mv88e6xxx_port_ppu_updates(chip, port) ||
4efe7662
CP
953 mode == MLO_AN_FIXED) && ops->port_sync_link)
954 err = ops->port_sync_link(chip, port, mode, false);
9d591fc0
MB
955
956 if (!err && ops->port_set_speed_duplex)
957 err = ops->port_set_speed_duplex(chip, port, SPEED_UNFORCED,
958 DUPLEX_UNFORCED);
5d5b231d 959 mv88e6xxx_reg_unlock(chip);
c9a2356f 960
5d5b231d
RK
961 if (err)
962 dev_err(chip->dev,
963 "p%d: failed to force MAC link down\n", port);
c9a2356f
RK
964}
965
966static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
967 unsigned int mode, phy_interface_t interface,
5b502a7b
RK
968 struct phy_device *phydev,
969 int speed, int duplex,
970 bool tx_pause, bool rx_pause)
c9a2356f 971{
30c4a5b0
RK
972 struct mv88e6xxx_chip *chip = ds->priv;
973 const struct mv88e6xxx_ops *ops;
974 int err = 0;
975
976 ops = chip->info->ops;
977
5d5b231d 978 mv88e6xxx_reg_lock(chip);
2b29cb9e
RKO
979 /* Configure and force the link up if we know that the port may not
980 * automatically updated by the switch or if we are using fixed-link
981 * mode.
4a3e0aed 982 */
2b29cb9e 983 if (!mv88e6xxx_port_ppu_updates(chip, port) ||
4a3e0aed 984 mode == MLO_AN_FIXED) {
30c4a5b0
RK
985 /* FIXME: for an automedia port, should we force the link
986 * down here - what if the link comes up due to "other" media
987 * while we're bringing the port up, how is the exclusivity
a5a6858b 988 * handled in the Marvell hardware? E.g. port 2 on 88E6390
30c4a5b0
RK
989 * shared between internal PHY and Serdes.
990 */
a5a6858b
RK
991 err = mv88e6xxx_serdes_pcs_link_up(chip, port, mode, speed,
992 duplex);
993 if (err)
994 goto error;
995
f365c6f7
RK
996 if (ops->port_set_speed_duplex) {
997 err = ops->port_set_speed_duplex(chip, port,
998 speed, duplex);
30c4a5b0
RK
999 if (err && err != -EOPNOTSUPP)
1000 goto error;
1001 }
1002
4efe7662
CP
1003 if (ops->port_sync_link)
1004 err = ops->port_sync_link(chip, port, mode, true);
5d5b231d 1005 }
30c4a5b0 1006error:
5d5b231d 1007 mv88e6xxx_reg_unlock(chip);
30c4a5b0 1008
5d5b231d
RK
1009 if (err && err != -EOPNOTSUPP)
1010 dev_err(ds->dev,
1011 "p%d: failed to configure MAC link up\n", port);
c9a2356f
RK
1012}
1013
a605a0fe 1014static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
91da11f8 1015{
a605a0fe
AL
1016 if (!chip->info->ops->stats_snapshot)
1017 return -EOPNOTSUPP;
91da11f8 1018
a605a0fe 1019 return chip->info->ops->stats_snapshot(chip, port);
91da11f8
LB
1020}
1021
e413e7e1 1022static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
dfafe449
AL
1023 { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
1024 { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
1025 { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
1026 { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
1027 { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
1028 { "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
1029 { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
1030 { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
1031 { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
1032 { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
1033 { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
1034 { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
1035 { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
1036 { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
1037 { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
1038 { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
1039 { "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
1040 { "excessive", 4, 0x11, STATS_TYPE_BANK0, },
1041 { "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
1042 { "deferred", 4, 0x05, STATS_TYPE_BANK0, },
1043 { "single", 4, 0x14, STATS_TYPE_BANK0, },
1044 { "multiple", 4, 0x17, STATS_TYPE_BANK0, },
1045 { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
1046 { "late", 4, 0x1f, STATS_TYPE_BANK0, },
1047 { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
1048 { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
1049 { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
1050 { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
1051 { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
1052 { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
1053 { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
1054 { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
1055 { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
1056 { "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
1057 { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
1058 { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
1059 { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
1060 { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
1061 { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
1062 { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
1063 { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
1064 { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
1065 { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
1066 { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
1067 { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
1068 { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
1069 { "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
1070 { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
1071 { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
1072 { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
1073 { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
1074 { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
1075 { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
1076 { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
1077 { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
1078 { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
1079 { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
1080 { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
1081 { "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
e413e7e1
AL
1082};
1083
fad09c73 1084static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
f5e2ed02 1085 struct mv88e6xxx_hw_stat *s,
e0d8b615
AL
1086 int port, u16 bank1_select,
1087 u16 histogram)
80c4627b 1088{
80c4627b
AL
1089 u32 low;
1090 u32 high = 0;
dfafe449 1091 u16 reg = 0;
0e7b9925 1092 int err;
80c4627b
AL
1093 u64 value;
1094
f5e2ed02 1095 switch (s->type) {
dfafe449 1096 case STATS_TYPE_PORT:
0e7b9925
AL
1097 err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
1098 if (err)
6c3442f5 1099 return U64_MAX;
80c4627b 1100
0e7b9925 1101 low = reg;
cda9f4aa 1102 if (s->size == 4) {
0e7b9925
AL
1103 err = mv88e6xxx_port_read(chip, port, s->reg + 1, &reg);
1104 if (err)
6c3442f5 1105 return U64_MAX;
84b3fd1f 1106 low |= ((u32)reg) << 16;
80c4627b 1107 }
f5e2ed02 1108 break;
dfafe449 1109 case STATS_TYPE_BANK1:
e0d8b615 1110 reg = bank1_select;
df561f66 1111 fallthrough;
dfafe449 1112 case STATS_TYPE_BANK0:
e0d8b615 1113 reg |= s->reg | histogram;
7f9ef3af 1114 mv88e6xxx_g1_stats_read(chip, reg, &low);
cda9f4aa 1115 if (s->size == 8)
7f9ef3af 1116 mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
9fc3e4dc
GS
1117 break;
1118 default:
6c3442f5 1119 return U64_MAX;
80c4627b 1120 }
6e46e2d8 1121 value = (((u64)high) << 32) | low;
80c4627b
AL
1122 return value;
1123}
1124
436fe17d
AL
1125static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
1126 uint8_t *data, int types)
91da11f8 1127{
f5e2ed02
AL
1128 struct mv88e6xxx_hw_stat *stat;
1129 int i, j;
91da11f8 1130
f5e2ed02
AL
1131 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
1132 stat = &mv88e6xxx_hw_stats[i];
dfafe449 1133 if (stat->type & types) {
f5e2ed02
AL
1134 memcpy(data + j * ETH_GSTRING_LEN, stat->string,
1135 ETH_GSTRING_LEN);
1136 j++;
1137 }
91da11f8 1138 }
436fe17d
AL
1139
1140 return j;
e413e7e1
AL
1141}
1142
436fe17d
AL
1143static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
1144 uint8_t *data)
dfafe449 1145{
436fe17d
AL
1146 return mv88e6xxx_stats_get_strings(chip, data,
1147 STATS_TYPE_BANK0 | STATS_TYPE_PORT);
dfafe449
AL
1148}
1149
1f71836f
RV
1150static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
1151 uint8_t *data)
1152{
1153 return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
1154}
1155
436fe17d
AL
1156static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
1157 uint8_t *data)
dfafe449 1158{
436fe17d
AL
1159 return mv88e6xxx_stats_get_strings(chip, data,
1160 STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
dfafe449
AL
1161}
1162
65f60e45
AL
1163static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
1164 "atu_member_violation",
1165 "atu_miss_violation",
1166 "atu_full_violation",
1167 "vtu_member_violation",
1168 "vtu_miss_violation",
1169};
1170
1171static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
1172{
1173 unsigned int i;
1174
1175 for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
fb3ceec1 1176 strscpy(data + i * ETH_GSTRING_LEN,
65f60e45
AL
1177 mv88e6xxx_atu_vtu_stats_strings[i],
1178 ETH_GSTRING_LEN);
1179}
1180
dfafe449 1181static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
89f09048 1182 u32 stringset, uint8_t *data)
e413e7e1 1183{
04bed143 1184 struct mv88e6xxx_chip *chip = ds->priv;
436fe17d 1185 int count = 0;
dfafe449 1186
89f09048
FF
1187 if (stringset != ETH_SS_STATS)
1188 return;
1189
c9acece0 1190 mv88e6xxx_reg_lock(chip);
c6c8cd5e 1191
dfafe449 1192 if (chip->info->ops->stats_get_strings)
436fe17d
AL
1193 count = chip->info->ops->stats_get_strings(chip, data);
1194
1195 if (chip->info->ops->serdes_get_strings) {
1196 data += count * ETH_GSTRING_LEN;
65f60e45 1197 count = chip->info->ops->serdes_get_strings(chip, port, data);
436fe17d 1198 }
c6c8cd5e 1199
65f60e45
AL
1200 data += count * ETH_GSTRING_LEN;
1201 mv88e6xxx_atu_vtu_get_strings(data);
1202
c9acece0 1203 mv88e6xxx_reg_unlock(chip);
dfafe449
AL
1204}
1205
1206static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
1207 int types)
1208{
f5e2ed02
AL
1209 struct mv88e6xxx_hw_stat *stat;
1210 int i, j;
1211
1212 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
1213 stat = &mv88e6xxx_hw_stats[i];
dfafe449 1214 if (stat->type & types)
f5e2ed02
AL
1215 j++;
1216 }
1217 return j;
e413e7e1
AL
1218}
1219
dfafe449
AL
1220static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
1221{
1222 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
1223 STATS_TYPE_PORT);
1224}
1225
1f71836f
RV
1226static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip)
1227{
1228 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0);
1229}
1230
dfafe449
AL
1231static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
1232{
1233 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
1234 STATS_TYPE_BANK1);
1235}
1236
89f09048 1237static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
dfafe449
AL
1238{
1239 struct mv88e6xxx_chip *chip = ds->priv;
436fe17d
AL
1240 int serdes_count = 0;
1241 int count = 0;
dfafe449 1242
89f09048
FF
1243 if (sset != ETH_SS_STATS)
1244 return 0;
1245
c9acece0 1246 mv88e6xxx_reg_lock(chip);
dfafe449 1247 if (chip->info->ops->stats_get_sset_count)
436fe17d
AL
1248 count = chip->info->ops->stats_get_sset_count(chip);
1249 if (count < 0)
1250 goto out;
1251
1252 if (chip->info->ops->serdes_get_sset_count)
1253 serdes_count = chip->info->ops->serdes_get_sset_count(chip,
1254 port);
65f60e45 1255 if (serdes_count < 0) {
436fe17d 1256 count = serdes_count;
65f60e45
AL
1257 goto out;
1258 }
1259 count += serdes_count;
1260 count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);
1261
436fe17d 1262out:
c9acece0 1263 mv88e6xxx_reg_unlock(chip);
dfafe449 1264
436fe17d 1265 return count;
dfafe449
AL
1266}
1267
436fe17d
AL
1268static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1269 uint64_t *data, int types,
1270 u16 bank1_select, u16 histogram)
052f947f
AL
1271{
1272 struct mv88e6xxx_hw_stat *stat;
1273 int i, j;
1274
1275 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
1276 stat = &mv88e6xxx_hw_stats[i];
1277 if (stat->type & types) {
c9acece0 1278 mv88e6xxx_reg_lock(chip);
e0d8b615
AL
1279 data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
1280 bank1_select,
1281 histogram);
c9acece0 1282 mv88e6xxx_reg_unlock(chip);
377cda13 1283
052f947f
AL
1284 j++;
1285 }
1286 }
436fe17d 1287 return j;
052f947f
AL
1288}
1289
436fe17d
AL
1290static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1291 uint64_t *data)
052f947f
AL
1292{
1293 return mv88e6xxx_stats_get_stats(chip, port, data,
e0d8b615 1294 STATS_TYPE_BANK0 | STATS_TYPE_PORT,
57d1ef38 1295 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
052f947f
AL
1296}
1297
1f71836f
RV
1298static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1299 uint64_t *data)
1300{
1301 return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
1302 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
1303}
1304
436fe17d
AL
1305static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1306 uint64_t *data)
052f947f
AL
1307{
1308 return mv88e6xxx_stats_get_stats(chip, port, data,
e0d8b615 1309 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
57d1ef38
VD
1310 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
1311 MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
e0d8b615
AL
1312}
1313
436fe17d
AL
1314static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1315 uint64_t *data)
e0d8b615
AL
1316{
1317 return mv88e6xxx_stats_get_stats(chip, port, data,
1318 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
57d1ef38
VD
1319 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
1320 0);
052f947f
AL
1321}
1322
65f60e45
AL
1323static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
1324 uint64_t *data)
1325{
1326 *data++ = chip->ports[port].atu_member_violation;
1327 *data++ = chip->ports[port].atu_miss_violation;
1328 *data++ = chip->ports[port].atu_full_violation;
1329 *data++ = chip->ports[port].vtu_member_violation;
1330 *data++ = chip->ports[port].vtu_miss_violation;
1331}
1332
052f947f
AL
1333static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
1334 uint64_t *data)
1335{
436fe17d
AL
1336 int count = 0;
1337
052f947f 1338 if (chip->info->ops->stats_get_stats)
436fe17d
AL
1339 count = chip->info->ops->stats_get_stats(chip, port, data);
1340
c9acece0 1341 mv88e6xxx_reg_lock(chip);
436fe17d
AL
1342 if (chip->info->ops->serdes_get_stats) {
1343 data += count;
65f60e45 1344 count = chip->info->ops->serdes_get_stats(chip, port, data);
436fe17d 1345 }
65f60e45
AL
1346 data += count;
1347 mv88e6xxx_atu_vtu_get_stats(chip, port, data);
c9acece0 1348 mv88e6xxx_reg_unlock(chip);
052f947f
AL
1349}
1350
f81ec90f
VD
1351static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
1352 uint64_t *data)
e413e7e1 1353{
04bed143 1354 struct mv88e6xxx_chip *chip = ds->priv;
f5e2ed02 1355 int ret;
f5e2ed02 1356
c9acece0 1357 mv88e6xxx_reg_lock(chip);
f5e2ed02 1358
a605a0fe 1359 ret = mv88e6xxx_stats_snapshot(chip, port);
c9acece0 1360 mv88e6xxx_reg_unlock(chip);
377cda13
AL
1361
1362 if (ret < 0)
f5e2ed02 1363 return;
052f947f
AL
1364
1365 mv88e6xxx_get_stats(chip, port, data);
f5e2ed02 1366
e413e7e1
AL
1367}
1368
f81ec90f 1369static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
a1ab91f3 1370{
0d30bbd0
AL
1371 struct mv88e6xxx_chip *chip = ds->priv;
1372 int len;
1373
1374 len = 32 * sizeof(u16);
1375 if (chip->info->ops->serdes_get_regs_len)
1376 len += chip->info->ops->serdes_get_regs_len(chip, port);
1377
1378 return len;
a1ab91f3
GR
1379}
1380
f81ec90f
VD
1381static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
1382 struct ethtool_regs *regs, void *_p)
a1ab91f3 1383{
04bed143 1384 struct mv88e6xxx_chip *chip = ds->priv;
0e7b9925
AL
1385 int err;
1386 u16 reg;
a1ab91f3
GR
1387 u16 *p = _p;
1388 int i;
1389
a5f39326 1390 regs->version = chip->info->prod_num;
a1ab91f3
GR
1391
1392 memset(p, 0xff, 32 * sizeof(u16));
1393
c9acece0 1394 mv88e6xxx_reg_lock(chip);
23062513 1395
a1ab91f3 1396 for (i = 0; i < 32; i++) {
a1ab91f3 1397
0e7b9925
AL
1398 err = mv88e6xxx_port_read(chip, port, i, &reg);
1399 if (!err)
1400 p[i] = reg;
a1ab91f3 1401 }
23062513 1402
0d30bbd0
AL
1403 if (chip->info->ops->serdes_get_regs)
1404 chip->info->ops->serdes_get_regs(chip, port, &p[i]);
1405
c9acece0 1406 mv88e6xxx_reg_unlock(chip);
a1ab91f3
GR
1407}
1408
08f50061
VD
1409static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
1410 struct ethtool_eee *e)
68b8f60c 1411{
5480db69
VD
1412 /* Nothing to do on the port's MAC */
1413 return 0;
11b3b45d
GR
1414}
1415
08f50061
VD
1416static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
1417 struct ethtool_eee *e)
11b3b45d 1418{
5480db69
VD
1419 /* Nothing to do on the port's MAC */
1420 return 0;
11b3b45d
GR
1421}
1422
9dc8b13e 1423/* Mask of the local ports allowed to receive frames from a given fabric port */
e5887a2a 1424static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
facd95b2 1425{
9dc8b13e
VD
1426 struct dsa_switch *ds = chip->ds;
1427 struct dsa_switch_tree *dst = ds->dst;
65144067 1428 struct dsa_port *dp, *other_dp;
9dc8b13e 1429 bool found = false;
e5887a2a 1430 u16 pvlan;
b7666efe 1431
ce5df689
VO
1432 /* dev is a physical switch */
1433 if (dev <= dst->last_switch) {
1434 list_for_each_entry(dp, &dst->ports, list) {
1435 if (dp->ds->index == dev && dp->index == port) {
1436 /* dp might be a DSA link or a user port, so it
65144067
VO
1437 * might or might not have a bridge.
1438 * Use the "found" variable for both cases.
ce5df689 1439 */
ce5df689
VO
1440 found = true;
1441 break;
1442 }
1443 }
1444 /* dev is a virtual bridge */
1445 } else {
1446 list_for_each_entry(dp, &dst->ports, list) {
41fb0cf1
VO
1447 unsigned int bridge_num = dsa_port_bridge_num_get(dp);
1448
1449 if (!bridge_num)
ce5df689
VO
1450 continue;
1451
41fb0cf1 1452 if (bridge_num + dst->last_switch != dev)
ce5df689
VO
1453 continue;
1454
9dc8b13e
VD
1455 found = true;
1456 break;
1457 }
1458 }
e5887a2a 1459
ce5df689 1460 /* Prevent frames from unknown switch or virtual bridge */
9dc8b13e 1461 if (!found)
e5887a2a
VD
1462 return 0;
1463
1464 /* Frames from DSA links and CPU ports can egress any local port */
9dc8b13e 1465 if (dp->type == DSA_PORT_TYPE_CPU || dp->type == DSA_PORT_TYPE_DSA)
e5887a2a
VD
1466 return mv88e6xxx_port_mask(chip);
1467
e5887a2a
VD
1468 pvlan = 0;
1469
7af4a361
TW
1470 /* Frames from standalone user ports can only egress on the
1471 * upstream port.
1472 */
1473 if (!dsa_port_bridge_dev_get(dp))
1474 return BIT(dsa_switch_upstream_port(ds));
1475
1476 /* Frames from bridged user ports can egress any local DSA
1477 * links and CPU ports, as well as any local member of their
1478 * bridge group.
e5887a2a 1479 */
65144067
VO
1480 dsa_switch_for_each_port(other_dp, ds)
1481 if (other_dp->type == DSA_PORT_TYPE_CPU ||
1482 other_dp->type == DSA_PORT_TYPE_DSA ||
41fb0cf1 1483 dsa_port_bridge_same(dp, other_dp))
65144067 1484 pvlan |= BIT(other_dp->index);
e5887a2a
VD
1485
1486 return pvlan;
1487}
1488
240ea3ef 1489static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
e5887a2a
VD
1490{
1491 u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
b7666efe
VD
1492
1493 /* prevent frames from going back out of the port they came in on */
1494 output_ports &= ~BIT(port);
facd95b2 1495
5a7921f4 1496 return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
facd95b2
GR
1497}
1498
f81ec90f
VD
1499static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
1500 u8 state)
facd95b2 1501{
04bed143 1502 struct mv88e6xxx_chip *chip = ds->priv;
553eb544 1503 int err;
facd95b2 1504
c9acece0 1505 mv88e6xxx_reg_lock(chip);
f894c29c 1506 err = mv88e6xxx_port_set_state(chip, port, state);
c9acece0 1507 mv88e6xxx_reg_unlock(chip);
553eb544
VD
1508
1509 if (err)
774439e5 1510 dev_err(ds->dev, "p%d: failed to update state\n", port);
facd95b2
GR
1511}
1512
93e18d61
VD
1513static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip)
1514{
1515 int err;
1516
1517 if (chip->info->ops->ieee_pri_map) {
1518 err = chip->info->ops->ieee_pri_map(chip);
1519 if (err)
1520 return err;
1521 }
1522
1523 if (chip->info->ops->ip_pri_map) {
1524 err = chip->info->ops->ip_pri_map(chip);
1525 if (err)
1526 return err;
1527 }
1528
1529 return 0;
1530}
1531
c7f047b6
VD
1532static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
1533{
c5f51765 1534 struct dsa_switch *ds = chip->ds;
c7f047b6
VD
1535 int target, port;
1536 int err;
1537
1538 if (!chip->info->global2_addr)
1539 return 0;
1540
1541 /* Initialize the routing port to the 32 possible target devices */
1542 for (target = 0; target < 32; target++) {
c5f51765
VD
1543 port = dsa_routing_port(ds, target);
1544 if (port == ds->num_ports)
1545 port = 0x1f;
c7f047b6
VD
1546
1547 err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
1548 if (err)
1549 return err;
1550 }
1551
02317e68
VD
1552 if (chip->info->ops->set_cascade_port) {
1553 port = MV88E6XXX_CASCADE_PORT_MULTIPLE;
1554 err = chip->info->ops->set_cascade_port(chip, port);
1555 if (err)
1556 return err;
1557 }
1558
23c98919
VD
1559 err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index);
1560 if (err)
1561 return err;
1562
c7f047b6
VD
1563 return 0;
1564}
1565
b28f872d
VD
1566static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip)
1567{
1568 /* Clear all trunk masks and mapping */
1569 if (chip->info->global2_addr)
1570 return mv88e6xxx_g2_trunk_clear(chip);
1571
1572 return 0;
1573}
1574
9e5baf9b
VD
1575static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip)
1576{
1577 if (chip->info->ops->rmu_disable)
1578 return chip->info->ops->rmu_disable(chip);
1579
1580 return 0;
1581}
1582
9e907d73
VD
1583static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
1584{
1585 if (chip->info->ops->pot_clear)
1586 return chip->info->ops->pot_clear(chip);
1587
1588 return 0;
1589}
1590
51c901a7
VD
1591static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip)
1592{
1593 if (chip->info->ops->mgmt_rsvd2cpu)
1594 return chip->info->ops->mgmt_rsvd2cpu(chip);
1595
1596 return 0;
1597}
1598
a2ac29d2
VD
1599static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
1600{
c3a7d4ad
VD
1601 int err;
1602
daefc943
VD
1603 err = mv88e6xxx_g1_atu_flush(chip, 0, true);
1604 if (err)
1605 return err;
1606
49506a9b
RV
1607 /* The chips that have a "learn2all" bit in Global1, ATU
1608 * Control are precisely those whose port registers have a
1609 * Message Port bit in Port Control 1 and hence implement
1610 * ->port_setup_message_port.
1611 */
1612 if (chip->info->ops->port_setup_message_port) {
1613 err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
1614 if (err)
1615 return err;
1616 }
c3a7d4ad 1617
a2ac29d2
VD
1618 return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
1619}
1620
cd8da8bb
VD
1621static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
1622{
1623 int port;
1624 int err;
1625
1626 if (!chip->info->ops->irl_init_all)
1627 return 0;
1628
1629 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
1630 /* Disable ingress rate limiting by resetting all per port
1631 * ingress rate limit resources to their initial state.
1632 */
1633 err = chip->info->ops->irl_init_all(chip, port);
1634 if (err)
1635 return err;
1636 }
1637
1638 return 0;
1639}
1640
04a69a17
VD
1641static int mv88e6xxx_mac_setup(struct mv88e6xxx_chip *chip)
1642{
1643 if (chip->info->ops->set_switch_mac) {
1644 u8 addr[ETH_ALEN];
1645
1646 eth_random_addr(addr);
1647
1648 return chip->info->ops->set_switch_mac(chip, addr);
1649 }
1650
1651 return 0;
1652}
1653
17a1594e
VD
1654static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
1655{
57e661aa
TW
1656 struct dsa_switch_tree *dst = chip->ds->dst;
1657 struct dsa_switch *ds;
1658 struct dsa_port *dp;
17a1594e
VD
1659 u16 pvlan = 0;
1660
1661 if (!mv88e6xxx_has_pvt(chip))
d14939be 1662 return 0;
17a1594e
VD
1663
1664 /* Skip the local source device, which uses in-chip port VLAN */
57e661aa 1665 if (dev != chip->ds->index) {
aec5ac88 1666 pvlan = mv88e6xxx_port_vlan(chip, dev, port);
17a1594e 1667
57e661aa
TW
1668 ds = dsa_switch_find(dst->index, dev);
1669 dp = ds ? dsa_to_port(ds, port) : NULL;
dedd6a00 1670 if (dp && dp->lag) {
57e661aa
TW
1671 /* As the PVT is used to limit flooding of
1672 * FORWARD frames, which use the LAG ID as the
1673 * source port, we must translate dev/port to
1674 * the special "LAG device" in the PVT, using
3d4a0a2a
VO
1675 * the LAG ID (one-based) as the port number
1676 * (zero-based).
57e661aa 1677 */
78e70dbc 1678 dev = MV88E6XXX_G2_PVT_ADDR_DEV_TRUNK;
dedd6a00 1679 port = dsa_port_lag_id_get(dp) - 1;
57e661aa
TW
1680 }
1681 }
1682
17a1594e
VD
1683 return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan);
1684}
1685
81228996
VD
1686static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
1687{
17a1594e
VD
1688 int dev, port;
1689 int err;
1690
81228996
VD
1691 if (!mv88e6xxx_has_pvt(chip))
1692 return 0;
1693
1694 /* Clear 5 Bit Port for usage with Marvell Link Street devices:
1695 * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev.
1696 */
17a1594e
VD
1697 err = mv88e6xxx_g2_misc_4_bit_port(chip);
1698 if (err)
1699 return err;
1700
1701 for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; ++dev) {
1702 for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; ++port) {
1703 err = mv88e6xxx_pvt_map(chip, dev, port);
1704 if (err)
1705 return err;
1706 }
1707 }
1708
1709 return 0;
81228996
VD
1710}
1711
acaf4d2e
TW
1712static int mv88e6xxx_port_fast_age_fid(struct mv88e6xxx_chip *chip, int port,
1713 u16 fid)
749efcb8 1714{
acaf4d2e 1715 if (dsa_to_port(chip->ds, port)->lag)
ffcec3f2
TW
1716 /* Hardware is incapable of fast-aging a LAG through a
1717 * regular ATU move operation. Until we have something
1718 * more fancy in place this is a no-op.
1719 */
acaf4d2e
TW
1720 return -EOPNOTSUPP;
1721
1722 return mv88e6xxx_g1_atu_remove(chip, fid, port, false);
1723}
1724
1725static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
1726{
1727 struct mv88e6xxx_chip *chip = ds->priv;
1728 int err;
ffcec3f2 1729
c9acece0 1730 mv88e6xxx_reg_lock(chip);
acaf4d2e 1731 err = mv88e6xxx_port_fast_age_fid(chip, port, 0);
c9acece0 1732 mv88e6xxx_reg_unlock(chip);
749efcb8
VD
1733
1734 if (err)
acaf4d2e
TW
1735 dev_err(chip->ds->dev, "p%d: failed to flush ATU: %d\n",
1736 port, err);
749efcb8
VD
1737}
1738
b486d7c9
VD
1739static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
1740{
e545f865 1741 if (!mv88e6xxx_max_vid(chip))
b486d7c9
VD
1742 return 0;
1743
1744 return mv88e6xxx_g1_vtu_flush(chip);
1745}
1746
34065c58
TW
1747static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
1748 struct mv88e6xxx_vtu_entry *entry)
f1394b78 1749{
34065c58
TW
1750 int err;
1751
f1394b78
VD
1752 if (!chip->info->ops->vtu_getnext)
1753 return -EOPNOTSUPP;
1754
34065c58
TW
1755 entry->vid = vid ? vid - 1 : mv88e6xxx_max_vid(chip);
1756 entry->valid = false;
1757
1758 err = chip->info->ops->vtu_getnext(chip, entry);
1759
1760 if (entry->vid != vid)
1761 entry->valid = false;
1762
1763 return err;
f1394b78
VD
1764}
1765
830763b9
HS
1766int mv88e6xxx_vtu_walk(struct mv88e6xxx_chip *chip,
1767 int (*cb)(struct mv88e6xxx_chip *chip,
1768 const struct mv88e6xxx_vtu_entry *entry,
1769 void *priv),
1770 void *priv)
d89ef4b8
TW
1771{
1772 struct mv88e6xxx_vtu_entry entry = {
1773 .vid = mv88e6xxx_max_vid(chip),
1774 .valid = false,
1775 };
1776 int err;
1777
1778 if (!chip->info->ops->vtu_getnext)
1779 return -EOPNOTSUPP;
1780
1781 do {
1782 err = chip->info->ops->vtu_getnext(chip, &entry);
1783 if (err)
1784 return err;
1785
1786 if (!entry.valid)
1787 break;
1788
1789 err = cb(chip, &entry, priv);
1790 if (err)
1791 return err;
1792 } while (entry.vid < mv88e6xxx_max_vid(chip));
1793
1794 return 0;
1795}
1796
0ad5daf6
VD
1797static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
1798 struct mv88e6xxx_vtu_entry *entry)
1799{
1800 if (!chip->info->ops->vtu_loadpurge)
1801 return -EOPNOTSUPP;
1802
1803 return chip->info->ops->vtu_loadpurge(chip, entry);
1804}
1805
d89ef4b8
TW
1806static int mv88e6xxx_fid_map_vlan(struct mv88e6xxx_chip *chip,
1807 const struct mv88e6xxx_vtu_entry *entry,
1808 void *_fid_bitmap)
1809{
1810 unsigned long *fid_bitmap = _fid_bitmap;
1811
1812 set_bit(entry->fid, fid_bitmap);
1813 return 0;
1814}
1815
90b6dbdf 1816int mv88e6xxx_fid_map(struct mv88e6xxx_chip *chip, unsigned long *fid_bitmap)
3285f9e8 1817{
3285f9e8
VD
1818 bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
1819
d352b20f
TW
1820 /* Every FID has an associated VID, so walking the VTU
1821 * will discover the full set of FIDs in use.
1822 */
d89ef4b8 1823 return mv88e6xxx_vtu_walk(chip, mv88e6xxx_fid_map_vlan, fid_bitmap);
90b6dbdf
AL
1824}
1825
1826static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
1827{
1828 DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
1829 int err;
1830
1831 err = mv88e6xxx_fid_map(chip, fid_bitmap);
1832 if (err)
1833 return err;
1834
d352b20f 1835 *fid = find_first_zero_bit(fid_bitmap, MV88E6XXX_N_FID);
fad09c73 1836 if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
3285f9e8
VD
1837 return -ENOSPC;
1838
1839 /* Clear the database */
daefc943 1840 return mv88e6xxx_g1_atu_flush(chip, *fid, true);
3285f9e8
VD
1841}
1842
49c98c1d
TW
1843static int mv88e6xxx_stu_loadpurge(struct mv88e6xxx_chip *chip,
1844 struct mv88e6xxx_stu_entry *entry)
1845{
1846 if (!chip->info->ops->stu_loadpurge)
1847 return -EOPNOTSUPP;
1848
1849 return chip->info->ops->stu_loadpurge(chip, entry);
1850}
1851
1852static int mv88e6xxx_stu_setup(struct mv88e6xxx_chip *chip)
1853{
1854 struct mv88e6xxx_stu_entry stu = {
1855 .valid = true,
1856 .sid = 0
1857 };
1858
1859 if (!mv88e6xxx_has_stu(chip))
1860 return 0;
1861
1862 /* Make sure that SID 0 is always valid. This is used by VTU
1863 * entries that do not make use of the STU, e.g. when creating
1864 * a VLAN upper on a port that is also part of a VLAN
1865 * filtering bridge.
1866 */
1867 return mv88e6xxx_stu_loadpurge(chip, &stu);
1868}
1869
acaf4d2e
TW
1870static int mv88e6xxx_sid_get(struct mv88e6xxx_chip *chip, u8 *sid)
1871{
1872 DECLARE_BITMAP(busy, MV88E6XXX_N_SID) = { 0 };
1873 struct mv88e6xxx_mst *mst;
1874
1875 __set_bit(0, busy);
1876
1877 list_for_each_entry(mst, &chip->msts, node)
1878 __set_bit(mst->stu.sid, busy);
1879
1880 *sid = find_first_zero_bit(busy, MV88E6XXX_N_SID);
1881
1882 return (*sid >= mv88e6xxx_max_sid(chip)) ? -ENOSPC : 0;
1883}
1884
1885static int mv88e6xxx_mst_put(struct mv88e6xxx_chip *chip, u8 sid)
1886{
1887 struct mv88e6xxx_mst *mst, *tmp;
1888 int err;
1889
1890 if (!sid)
1891 return 0;
1892
1893 list_for_each_entry_safe(mst, tmp, &chip->msts, node) {
1894 if (mst->stu.sid != sid)
1895 continue;
1896
1897 if (!refcount_dec_and_test(&mst->refcnt))
1898 return 0;
1899
1900 mst->stu.valid = false;
1901 err = mv88e6xxx_stu_loadpurge(chip, &mst->stu);
1902 if (err) {
1903 refcount_set(&mst->refcnt, 1);
1904 return err;
1905 }
1906
1907 list_del(&mst->node);
1908 kfree(mst);
1909 return 0;
1910 }
1911
1912 return -ENOENT;
1913}
1914
1915static int mv88e6xxx_mst_get(struct mv88e6xxx_chip *chip, struct net_device *br,
1916 u16 msti, u8 *sid)
1917{
1918 struct mv88e6xxx_mst *mst;
1919 int err, i;
1920
1921 if (!mv88e6xxx_has_stu(chip)) {
1922 err = -EOPNOTSUPP;
1923 goto err;
1924 }
1925
1926 if (!msti) {
1927 *sid = 0;
1928 return 0;
1929 }
1930
1931 list_for_each_entry(mst, &chip->msts, node) {
1932 if (mst->br == br && mst->msti == msti) {
1933 refcount_inc(&mst->refcnt);
1934 *sid = mst->stu.sid;
1935 return 0;
1936 }
1937 }
1938
1939 err = mv88e6xxx_sid_get(chip, sid);
1940 if (err)
1941 goto err;
1942
1943 mst = kzalloc(sizeof(*mst), GFP_KERNEL);
1944 if (!mst) {
1945 err = -ENOMEM;
1946 goto err;
1947 }
1948
1949 INIT_LIST_HEAD(&mst->node);
1950 refcount_set(&mst->refcnt, 1);
1951 mst->br = br;
1952 mst->msti = msti;
1953 mst->stu.valid = true;
1954 mst->stu.sid = *sid;
1955
1956 /* The bridge starts out all ports in the disabled state. But
1957 * a STU state of disabled means to go by the port-global
1958 * state. So we set all user port's initial state to blocking,
1959 * to match the bridge's behavior.
1960 */
1961 for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
1962 mst->stu.state[i] = dsa_is_user_port(chip->ds, i) ?
1963 MV88E6XXX_PORT_CTL0_STATE_BLOCKING :
1964 MV88E6XXX_PORT_CTL0_STATE_DISABLED;
1965
1966 err = mv88e6xxx_stu_loadpurge(chip, &mst->stu);
1967 if (err)
1968 goto err_free;
1969
1970 list_add_tail(&mst->node, &chip->msts);
1971 return 0;
1972
1973err_free:
1974 kfree(mst);
1975err:
1976 return err;
1977}
1978
1979static int mv88e6xxx_port_mst_state_set(struct dsa_switch *ds, int port,
1980 const struct switchdev_mst_state *st)
1981{
1982 struct dsa_port *dp = dsa_to_port(ds, port);
1983 struct mv88e6xxx_chip *chip = ds->priv;
1984 struct mv88e6xxx_mst *mst;
1985 u8 state;
1986 int err;
1987
1988 if (!mv88e6xxx_has_stu(chip))
1989 return -EOPNOTSUPP;
1990
1991 switch (st->state) {
1992 case BR_STATE_DISABLED:
1993 case BR_STATE_BLOCKING:
1994 case BR_STATE_LISTENING:
1995 state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
1996 break;
1997 case BR_STATE_LEARNING:
1998 state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
1999 break;
2000 case BR_STATE_FORWARDING:
2001 state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
2002 break;
2003 default:
2004 return -EINVAL;
2005 }
2006
2007 list_for_each_entry(mst, &chip->msts, node) {
2008 if (mst->br == dsa_port_bridge_dev_get(dp) &&
2009 mst->msti == st->msti) {
2010 if (mst->stu.state[port] == state)
2011 return 0;
2012
2013 mst->stu.state[port] = state;
2014 mv88e6xxx_reg_lock(chip);
2015 err = mv88e6xxx_stu_loadpurge(chip, &mst->stu);
2016 mv88e6xxx_reg_unlock(chip);
2017 return err;
2018 }
2019 }
2020
2021 return -ENOENT;
2022}
2023
da9c359e 2024static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
b7a9e0da 2025 u16 vid)
da9c359e 2026{
0493fa79 2027 struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
04bed143 2028 struct mv88e6xxx_chip *chip = ds->priv;
425d2d37 2029 struct mv88e6xxx_vtu_entry vlan;
0493fa79 2030 int err;
da9c359e 2031
db06ae41 2032 /* DSA and CPU ports have to be members of multiple vlans */
0493fa79 2033 if (dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp))
db06ae41
AL
2034 return 0;
2035
34065c58 2036 err = mv88e6xxx_vtu_get(chip, vid, &vlan);
b7a9e0da
VO
2037 if (err)
2038 return err;
da9c359e 2039
b7a9e0da
VO
2040 if (!vlan.valid)
2041 return 0;
da9c359e 2042
0493fa79 2043 dsa_switch_for_each_user_port(other_dp, ds) {
41fb0cf1
VO
2044 struct net_device *other_br;
2045
0493fa79 2046 if (vlan.member[other_dp->index] ==
b7a9e0da
VO
2047 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
2048 continue;
da9c359e 2049
41fb0cf1 2050 if (dsa_port_bridge_same(dp, other_dp))
b7a9e0da 2051 break; /* same bridge, check next VLAN */
da9c359e 2052
41fb0cf1
VO
2053 other_br = dsa_port_bridge_dev_get(other_dp);
2054 if (!other_br)
b7a9e0da 2055 continue;
66e2809d 2056
b7a9e0da 2057 dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n",
41fb0cf1 2058 port, vlan.vid, other_dp->index, netdev_name(other_br));
b7a9e0da
VO
2059 return -EOPNOTSUPP;
2060 }
da9c359e 2061
7095a4c4 2062 return 0;
da9c359e
VD
2063}
2064
8b6836d8
VO
2065static int mv88e6xxx_port_commit_pvid(struct mv88e6xxx_chip *chip, int port)
2066{
2067 struct dsa_port *dp = dsa_to_port(chip->ds, port);
41fb0cf1 2068 struct net_device *br = dsa_port_bridge_dev_get(dp);
8b6836d8 2069 struct mv88e6xxx_port *p = &chip->ports[port];
5bded825 2070 u16 pvid = MV88E6XXX_VID_STANDALONE;
8b6836d8 2071 bool drop_untagged = false;
8b6836d8
VO
2072 int err;
2073
41fb0cf1
VO
2074 if (br) {
2075 if (br_vlan_enabled(br)) {
5bded825
VO
2076 pvid = p->bridge_pvid.vid;
2077 drop_untagged = !p->bridge_pvid.valid;
2078 } else {
2079 pvid = MV88E6XXX_VID_BRIDGED;
2080 }
8b6836d8
VO
2081 }
2082
2083 err = mv88e6xxx_port_set_pvid(chip, port, pvid);
2084 if (err)
2085 return err;
2086
2087 return mv88e6xxx_port_drop_untagged(chip, port, drop_untagged);
2088}
2089
f81ec90f 2090static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
89153ed6
VO
2091 bool vlan_filtering,
2092 struct netlink_ext_ack *extack)
214cdb99 2093{
04bed143 2094 struct mv88e6xxx_chip *chip = ds->priv;
81c6edb2
VD
2095 u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
2096 MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
0e7b9925 2097 int err;
214cdb99 2098
bae33f2b
VO
2099 if (!mv88e6xxx_max_vid(chip))
2100 return -EOPNOTSUPP;
54d77b5b 2101
c9acece0 2102 mv88e6xxx_reg_lock(chip);
8b6836d8 2103
385a0995 2104 err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
8b6836d8
VO
2105 if (err)
2106 goto unlock;
2107
2108 err = mv88e6xxx_port_commit_pvid(chip, port);
2109 if (err)
2110 goto unlock;
2111
2112unlock:
c9acece0 2113 mv88e6xxx_reg_unlock(chip);
214cdb99 2114
0e7b9925 2115 return err;
214cdb99
VD
2116}
2117
57d32310
VD
2118static int
2119mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
80e02360 2120 const struct switchdev_obj_port_vlan *vlan)
76e398a6 2121{
04bed143 2122 struct mv88e6xxx_chip *chip = ds->priv;
da9c359e
VD
2123 int err;
2124
e545f865 2125 if (!mv88e6xxx_max_vid(chip))
54d77b5b
VD
2126 return -EOPNOTSUPP;
2127
da9c359e
VD
2128 /* If the requested port doesn't belong to the same bridge as the VLAN
2129 * members, do not support it (yet) and fallback to software VLAN.
2130 */
7095a4c4 2131 mv88e6xxx_reg_lock(chip);
b7a9e0da 2132 err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid);
7095a4c4 2133 mv88e6xxx_reg_unlock(chip);
da9c359e 2134
7095a4c4 2135 return err;
76e398a6
VD
2136}
2137
a4c93ae1
AL
2138static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
2139 const unsigned char *addr, u16 vid,
2140 u8 state)
2141{
a4c93ae1 2142 struct mv88e6xxx_atu_entry entry;
5ef8d249
VD
2143 struct mv88e6xxx_vtu_entry vlan;
2144 u16 fid;
a4c93ae1
AL
2145 int err;
2146
5bded825
VO
2147 /* Ports have two private address databases: one for when the port is
2148 * standalone and one for when the port is under a bridge and the
2149 * 802.1Q mode is disabled. When the port is standalone, DSA wants its
2150 * address database to remain 100% empty, so we never load an ATU entry
2151 * into a standalone port's database. Therefore, translate the null
2152 * VLAN ID into the port's database used for VLAN-unaware bridging.
2153 */
5ef8d249 2154 if (vid == 0) {
5bded825 2155 fid = MV88E6XXX_FID_BRIDGED;
5ef8d249 2156 } else {
34065c58 2157 err = mv88e6xxx_vtu_get(chip, vid, &vlan);
5ef8d249
VD
2158 if (err)
2159 return err;
2160
2161 /* switchdev expects -EOPNOTSUPP to honor software VLANs */
34065c58 2162 if (!vlan.valid)
5ef8d249
VD
2163 return -EOPNOTSUPP;
2164
2165 fid = vlan.fid;
2166 }
a4c93ae1 2167
d8291a95 2168 entry.state = 0;
a4c93ae1
AL
2169 ether_addr_copy(entry.mac, addr);
2170 eth_addr_dec(entry.mac);
2171
5ef8d249 2172 err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry);
a4c93ae1
AL
2173 if (err)
2174 return err;
2175
2176 /* Initialize a fresh ATU entry if it isn't found */
d8291a95 2177 if (!entry.state || !ether_addr_equal(entry.mac, addr)) {
a4c93ae1
AL
2178 memset(&entry, 0, sizeof(entry));
2179 ether_addr_copy(entry.mac, addr);
2180 }
2181
2182 /* Purge the ATU entry only if no port is using it anymore */
d8291a95 2183 if (!state) {
a4c93ae1
AL
2184 entry.portvec &= ~BIT(port);
2185 if (!entry.portvec)
d8291a95 2186 entry.state = 0;
a4c93ae1 2187 } else {
f72f2fb8
DQ
2188 if (state == MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC)
2189 entry.portvec = BIT(port);
2190 else
2191 entry.portvec |= BIT(port);
2192
a4c93ae1
AL
2193 entry.state = state;
2194 }
2195
5ef8d249 2196 return mv88e6xxx_g1_atu_loadpurge(chip, fid, &entry);
a4c93ae1
AL
2197}
2198
da7dc875
VD
2199static int mv88e6xxx_policy_apply(struct mv88e6xxx_chip *chip, int port,
2200 const struct mv88e6xxx_policy *policy)
2201{
2202 enum mv88e6xxx_policy_mapping mapping = policy->mapping;
2203 enum mv88e6xxx_policy_action action = policy->action;
2204 const u8 *addr = policy->addr;
2205 u16 vid = policy->vid;
2206 u8 state;
2207 int err;
2208 int id;
2209
2210 if (!chip->info->ops->port_set_policy)
2211 return -EOPNOTSUPP;
2212
2213 switch (mapping) {
2214 case MV88E6XXX_POLICY_MAPPING_DA:
2215 case MV88E6XXX_POLICY_MAPPING_SA:
2216 if (action == MV88E6XXX_POLICY_ACTION_NORMAL)
2217 state = 0; /* Dissociate the port and address */
2218 else if (action == MV88E6XXX_POLICY_ACTION_DISCARD &&
2219 is_multicast_ether_addr(addr))
2220 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC_POLICY;
2221 else if (action == MV88E6XXX_POLICY_ACTION_DISCARD &&
2222 is_unicast_ether_addr(addr))
2223 state = MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC_POLICY;
2224 else
2225 return -EOPNOTSUPP;
2226
2227 err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
2228 state);
2229 if (err)
2230 return err;
2231 break;
2232 default:
2233 return -EOPNOTSUPP;
2234 }
2235
2236 /* Skip the port's policy clearing if the mapping is still in use */
2237 if (action == MV88E6XXX_POLICY_ACTION_NORMAL)
2238 idr_for_each_entry(&chip->policies, policy, id)
2239 if (policy->port == port &&
2240 policy->mapping == mapping &&
2241 policy->action != action)
2242 return 0;
2243
2244 return chip->info->ops->port_set_policy(chip, port, mapping, action);
2245}
2246
2247static int mv88e6xxx_policy_insert(struct mv88e6xxx_chip *chip, int port,
2248 struct ethtool_rx_flow_spec *fs)
2249{
2250 struct ethhdr *mac_entry = &fs->h_u.ether_spec;
2251 struct ethhdr *mac_mask = &fs->m_u.ether_spec;
2252 enum mv88e6xxx_policy_mapping mapping;
2253 enum mv88e6xxx_policy_action action;
2254 struct mv88e6xxx_policy *policy;
2255 u16 vid = 0;
2256 u8 *addr;
2257 int err;
2258 int id;
2259
2260 if (fs->location != RX_CLS_LOC_ANY)
2261 return -EINVAL;
2262
2263 if (fs->ring_cookie == RX_CLS_FLOW_DISC)
2264 action = MV88E6XXX_POLICY_ACTION_DISCARD;
2265 else
2266 return -EOPNOTSUPP;
2267
2268 switch (fs->flow_type & ~FLOW_EXT) {
2269 case ETHER_FLOW:
2270 if (!is_zero_ether_addr(mac_mask->h_dest) &&
2271 is_zero_ether_addr(mac_mask->h_source)) {
2272 mapping = MV88E6XXX_POLICY_MAPPING_DA;
2273 addr = mac_entry->h_dest;
2274 } else if (is_zero_ether_addr(mac_mask->h_dest) &&
2275 !is_zero_ether_addr(mac_mask->h_source)) {
2276 mapping = MV88E6XXX_POLICY_MAPPING_SA;
2277 addr = mac_entry->h_source;
2278 } else {
2279 /* Cannot support DA and SA mapping in the same rule */
2280 return -EOPNOTSUPP;
2281 }
2282 break;
2283 default:
2284 return -EOPNOTSUPP;
2285 }
2286
2287 if ((fs->flow_type & FLOW_EXT) && fs->m_ext.vlan_tci) {
04844280 2288 if (fs->m_ext.vlan_tci != htons(0xffff))
da7dc875
VD
2289 return -EOPNOTSUPP;
2290 vid = be16_to_cpu(fs->h_ext.vlan_tci) & VLAN_VID_MASK;
2291 }
2292
2293 idr_for_each_entry(&chip->policies, policy, id) {
2294 if (policy->port == port && policy->mapping == mapping &&
2295 policy->action == action && policy->vid == vid &&
2296 ether_addr_equal(policy->addr, addr))
2297 return -EEXIST;
2298 }
2299
2300 policy = devm_kzalloc(chip->dev, sizeof(*policy), GFP_KERNEL);
2301 if (!policy)
2302 return -ENOMEM;
2303
2304 fs->location = 0;
2305 err = idr_alloc_u32(&chip->policies, policy, &fs->location, 0xffffffff,
2306 GFP_KERNEL);
2307 if (err) {
2308 devm_kfree(chip->dev, policy);
2309 return err;
2310 }
2311
2312 memcpy(&policy->fs, fs, sizeof(*fs));
2313 ether_addr_copy(policy->addr, addr);
2314 policy->mapping = mapping;
2315 policy->action = action;
2316 policy->port = port;
2317 policy->vid = vid;
2318
2319 err = mv88e6xxx_policy_apply(chip, port, policy);
2320 if (err) {
2321 idr_remove(&chip->policies, fs->location);
2322 devm_kfree(chip->dev, policy);
2323 return err;
2324 }
2325
2326 return 0;
2327}
2328
2329static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port,
2330 struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
2331{
2332 struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
2333 struct mv88e6xxx_chip *chip = ds->priv;
2334 struct mv88e6xxx_policy *policy;
2335 int err;
2336 int id;
2337
2338 mv88e6xxx_reg_lock(chip);
2339
2340 switch (rxnfc->cmd) {
2341 case ETHTOOL_GRXCLSRLCNT:
2342 rxnfc->data = 0;
2343 rxnfc->data |= RX_CLS_LOC_SPECIAL;
2344 rxnfc->rule_cnt = 0;
2345 idr_for_each_entry(&chip->policies, policy, id)
2346 if (policy->port == port)
2347 rxnfc->rule_cnt++;
2348 err = 0;
2349 break;
2350 case ETHTOOL_GRXCLSRULE:
2351 err = -ENOENT;
2352 policy = idr_find(&chip->policies, fs->location);
2353 if (policy) {
2354 memcpy(fs, &policy->fs, sizeof(*fs));
2355 err = 0;
2356 }
2357 break;
2358 case ETHTOOL_GRXCLSRLALL:
2359 rxnfc->data = 0;
2360 rxnfc->rule_cnt = 0;
2361 idr_for_each_entry(&chip->policies, policy, id)
2362 if (policy->port == port)
2363 rule_locs[rxnfc->rule_cnt++] = id;
2364 err = 0;
2365 break;
2366 default:
2367 err = -EOPNOTSUPP;
2368 break;
2369 }
2370
2371 mv88e6xxx_reg_unlock(chip);
2372
2373 return err;
2374}
2375
2376static int mv88e6xxx_set_rxnfc(struct dsa_switch *ds, int port,
2377 struct ethtool_rxnfc *rxnfc)
2378{
2379 struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
2380 struct mv88e6xxx_chip *chip = ds->priv;
2381 struct mv88e6xxx_policy *policy;
2382 int err;
2383
2384 mv88e6xxx_reg_lock(chip);
2385
2386 switch (rxnfc->cmd) {
2387 case ETHTOOL_SRXCLSRLINS:
2388 err = mv88e6xxx_policy_insert(chip, port, fs);
2389 break;
2390 case ETHTOOL_SRXCLSRLDEL:
2391 err = -ENOENT;
2392 policy = idr_remove(&chip->policies, fs->location);
2393 if (policy) {
2394 policy->action = MV88E6XXX_POLICY_ACTION_NORMAL;
2395 err = mv88e6xxx_policy_apply(chip, port, policy);
2396 devm_kfree(chip->dev, policy);
2397 }
2398 break;
2399 default:
2400 err = -EOPNOTSUPP;
2401 break;
2402 }
2403
2404 mv88e6xxx_reg_unlock(chip);
2405
2406 return err;
2407}
2408
87fa886e
AL
2409static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port,
2410 u16 vid)
2411{
87fa886e 2412 u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC;
0806dd46
TW
2413 u8 broadcast[ETH_ALEN];
2414
2415 eth_broadcast_addr(broadcast);
87fa886e
AL
2416
2417 return mv88e6xxx_port_db_load_purge(chip, port, broadcast, vid, state);
2418}
2419
2420static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid)
2421{
2422 int port;
2423 int err;
2424
2425 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
8d1d8298
TW
2426 struct dsa_port *dp = dsa_to_port(chip->ds, port);
2427 struct net_device *brport;
2428
2429 if (dsa_is_unused_port(chip->ds, port))
2430 continue;
2431
2432 brport = dsa_port_to_bridge_port(dp);
2433 if (brport && !br_port_flag_is_set(brport, BR_BCAST_FLOOD))
2434 /* Skip bridged user ports where broadcast
2435 * flooding is disabled.
2436 */
2437 continue;
2438
87fa886e
AL
2439 err = mv88e6xxx_port_add_broadcast(chip, port, vid);
2440 if (err)
2441 return err;
2442 }
2443
2444 return 0;
2445}
2446
8d1d8298
TW
2447struct mv88e6xxx_port_broadcast_sync_ctx {
2448 int port;
2449 bool flood;
2450};
2451
2452static int
2453mv88e6xxx_port_broadcast_sync_vlan(struct mv88e6xxx_chip *chip,
2454 const struct mv88e6xxx_vtu_entry *vlan,
2455 void *_ctx)
2456{
2457 struct mv88e6xxx_port_broadcast_sync_ctx *ctx = _ctx;
2458 u8 broadcast[ETH_ALEN];
2459 u8 state;
2460
2461 if (ctx->flood)
2462 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC;
2463 else
2464 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_UNUSED;
2465
2466 eth_broadcast_addr(broadcast);
2467
2468 return mv88e6xxx_port_db_load_purge(chip, ctx->port, broadcast,
2469 vlan->vid, state);
2470}
2471
2472static int mv88e6xxx_port_broadcast_sync(struct mv88e6xxx_chip *chip, int port,
2473 bool flood)
2474{
2475 struct mv88e6xxx_port_broadcast_sync_ctx ctx = {
2476 .port = port,
2477 .flood = flood,
2478 };
2479 struct mv88e6xxx_vtu_entry vid0 = {
2480 .vid = 0,
2481 };
2482 int err;
2483
2484 /* Update the port's private database... */
2485 err = mv88e6xxx_port_broadcast_sync_vlan(chip, &vid0, &ctx);
2486 if (err)
2487 return err;
2488
2489 /* ...and the database for all VLANs. */
2490 return mv88e6xxx_vtu_walk(chip, mv88e6xxx_port_broadcast_sync_vlan,
2491 &ctx);
2492}
2493
b1ac6fb4 2494static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
933b4425 2495 u16 vid, u8 member, bool warn)
0d3b33e6 2496{
b1ac6fb4 2497 const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
b4e47c0f 2498 struct mv88e6xxx_vtu_entry vlan;
b1ac6fb4 2499 int i, err;
0d3b33e6 2500
34065c58 2501 err = mv88e6xxx_vtu_get(chip, vid, &vlan);
87fa886e
AL
2502 if (err)
2503 return err;
2504
34065c58 2505 if (!vlan.valid) {
b1ac6fb4
VD
2506 memset(&vlan, 0, sizeof(vlan));
2507
d352b20f
TW
2508 if (vid == MV88E6XXX_VID_STANDALONE)
2509 vlan.policy = true;
2510
b1ac6fb4
VD
2511 err = mv88e6xxx_atu_new(chip, &vlan.fid);
2512 if (err)
2513 return err;
2514
2515 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
2516 if (i == port)
2517 vlan.member[i] = member;
2518 else
2519 vlan.member[i] = non_member;
2520
2521 vlan.vid = vid;
2522 vlan.valid = true;
2523
2524 err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
2525 if (err)
2526 return err;
2527
2528 err = mv88e6xxx_broadcast_setup(chip, vlan.vid);
2529 if (err)
2530 return err;
2531 } else if (vlan.member[port] != member) {
2532 vlan.member[port] = member;
2533
2534 err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
2535 if (err)
2536 return err;
933b4425 2537 } else if (warn) {
b1ac6fb4
VD
2538 dev_info(chip->dev, "p%d: already a member of VLAN %d\n",
2539 port, vid);
2540 }
2541
2542 return 0;
76e398a6
VD
2543}
2544
1958d581 2545static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
31046a5f
VO
2546 const struct switchdev_obj_port_vlan *vlan,
2547 struct netlink_ext_ack *extack)
76e398a6 2548{
04bed143 2549 struct mv88e6xxx_chip *chip = ds->priv;
76e398a6
VD
2550 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
2551 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
8b6836d8 2552 struct mv88e6xxx_port *p = &chip->ports[port];
933b4425 2553 bool warn;
c91498e1 2554 u8 member;
1958d581 2555 int err;
76e398a6 2556
b8b79c41
EG
2557 if (!vlan->vid)
2558 return 0;
2559
1958d581
VO
2560 err = mv88e6xxx_port_vlan_prepare(ds, port, vlan);
2561 if (err)
2562 return err;
54d77b5b 2563
c91498e1 2564 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
7ec60d6e 2565 member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED;
c91498e1 2566 else if (untagged)
7ec60d6e 2567 member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED;
c91498e1 2568 else
7ec60d6e 2569 member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED;
c91498e1 2570
933b4425
RK
2571 /* net/dsa/slave.c will call dsa_port_vlan_add() for the affected port
2572 * and then the CPU port. Do not warn for duplicates for the CPU port.
2573 */
2574 warn = !dsa_is_cpu_port(ds, port) && !dsa_is_dsa_port(ds, port);
2575
c9acece0 2576 mv88e6xxx_reg_lock(chip);
76e398a6 2577
1958d581
VO
2578 err = mv88e6xxx_port_vlan_join(chip, port, vlan->vid, member, warn);
2579 if (err) {
b7a9e0da
VO
2580 dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
2581 vlan->vid, untagged ? 'u' : 't');
1958d581
VO
2582 goto out;
2583 }
76e398a6 2584
1958d581 2585 if (pvid) {
8b6836d8
VO
2586 p->bridge_pvid.vid = vlan->vid;
2587 p->bridge_pvid.valid = true;
2588
2589 err = mv88e6xxx_port_commit_pvid(chip, port);
2590 if (err)
2591 goto out;
2592 } else if (vlan->vid && p->bridge_pvid.vid == vlan->vid) {
2593 /* The old pvid was reinstalled as a non-pvid VLAN */
2594 p->bridge_pvid.valid = false;
2595
2596 err = mv88e6xxx_port_commit_pvid(chip, port);
2597 if (err)
1958d581 2598 goto out;
1958d581 2599 }
8b6836d8 2600
1958d581 2601out:
c9acece0 2602 mv88e6xxx_reg_unlock(chip);
1958d581
VO
2603
2604 return err;
0d3b33e6
VD
2605}
2606
52109892
VD
2607static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip,
2608 int port, u16 vid)
7dad08d7 2609{
b4e47c0f 2610 struct mv88e6xxx_vtu_entry vlan;
7dad08d7
VD
2611 int i, err;
2612
52109892 2613 if (!vid)
c92c7413 2614 return 0;
52109892 2615
34065c58 2616 err = mv88e6xxx_vtu_get(chip, vid, &vlan);
7dad08d7 2617 if (err)
76e398a6 2618 return err;
7dad08d7 2619
52109892
VD
2620 /* If the VLAN doesn't exist in hardware or the port isn't a member,
2621 * tell switchdev that this VLAN is likely handled in software.
2622 */
34065c58 2623 if (!vlan.valid ||
52109892 2624 vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
3c06f08b 2625 return -EOPNOTSUPP;
7dad08d7 2626
7ec60d6e 2627 vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
7dad08d7
VD
2628
2629 /* keep the VLAN unless all ports are excluded */
f02bdffc 2630 vlan.valid = false;
370b4ffb 2631 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
7ec60d6e
VD
2632 if (vlan.member[i] !=
2633 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
f02bdffc 2634 vlan.valid = true;
7dad08d7
VD
2635 break;
2636 }
2637 }
2638
0ad5daf6 2639 err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
76e398a6
VD
2640 if (err)
2641 return err;
2642
acaf4d2e
TW
2643 if (!vlan.valid) {
2644 err = mv88e6xxx_mst_put(chip, vlan.sid);
2645 if (err)
2646 return err;
2647 }
2648
e606ca36 2649 return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
76e398a6
VD
2650}
2651
f81ec90f
VD
2652static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
2653 const struct switchdev_obj_port_vlan *vlan)
76e398a6 2654{
04bed143 2655 struct mv88e6xxx_chip *chip = ds->priv;
8b6836d8 2656 struct mv88e6xxx_port *p = &chip->ports[port];
76e398a6 2657 int err = 0;
b7a9e0da 2658 u16 pvid;
76e398a6 2659
e545f865 2660 if (!mv88e6xxx_max_vid(chip))
54d77b5b
VD
2661 return -EOPNOTSUPP;
2662
a2614140
VO
2663 /* The ATU removal procedure needs the FID to be mapped in the VTU,
2664 * but FDB deletion runs concurrently with VLAN deletion. Flush the DSA
2665 * switchdev workqueue to ensure that all FDB entries are deleted
2666 * before we remove the VLAN.
2667 */
2668 dsa_flush_workqueue();
2669
c9acece0 2670 mv88e6xxx_reg_lock(chip);
76e398a6 2671
77064f37 2672 err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
7dad08d7
VD
2673 if (err)
2674 goto unlock;
2675
b7a9e0da
VO
2676 err = mv88e6xxx_port_vlan_leave(chip, port, vlan->vid);
2677 if (err)
2678 goto unlock;
2679
2680 if (vlan->vid == pvid) {
8b6836d8
VO
2681 p->bridge_pvid.valid = false;
2682
2683 err = mv88e6xxx_port_commit_pvid(chip, port);
76e398a6
VD
2684 if (err)
2685 goto unlock;
76e398a6
VD
2686 }
2687
7dad08d7 2688unlock:
c9acece0 2689 mv88e6xxx_reg_unlock(chip);
7dad08d7
VD
2690
2691 return err;
2692}
2693
acaf4d2e
TW
2694static int mv88e6xxx_port_vlan_fast_age(struct dsa_switch *ds, int port, u16 vid)
2695{
2696 struct mv88e6xxx_chip *chip = ds->priv;
2697 struct mv88e6xxx_vtu_entry vlan;
2698 int err;
2699
2700 mv88e6xxx_reg_lock(chip);
2701
2702 err = mv88e6xxx_vtu_get(chip, vid, &vlan);
2703 if (err)
2704 goto unlock;
2705
2706 err = mv88e6xxx_port_fast_age_fid(chip, port, vlan.fid);
2707
2708unlock:
2709 mv88e6xxx_reg_unlock(chip);
2710
2711 return err;
2712}
2713
2714static int mv88e6xxx_vlan_msti_set(struct dsa_switch *ds,
2715 struct dsa_bridge bridge,
2716 const struct switchdev_vlan_msti *msti)
2717{
2718 struct mv88e6xxx_chip *chip = ds->priv;
2719 struct mv88e6xxx_vtu_entry vlan;
2720 u8 old_sid, new_sid;
2721 int err;
2722
bd48b911
TW
2723 if (!mv88e6xxx_has_stu(chip))
2724 return -EOPNOTSUPP;
2725
acaf4d2e
TW
2726 mv88e6xxx_reg_lock(chip);
2727
2728 err = mv88e6xxx_vtu_get(chip, msti->vid, &vlan);
2729 if (err)
2730 goto unlock;
2731
2732 if (!vlan.valid) {
2733 err = -EINVAL;
2734 goto unlock;
2735 }
2736
2737 old_sid = vlan.sid;
2738
2739 err = mv88e6xxx_mst_get(chip, bridge.dev, msti->msti, &new_sid);
2740 if (err)
2741 goto unlock;
2742
2743 if (new_sid != old_sid) {
2744 vlan.sid = new_sid;
2745
2746 err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
2747 if (err) {
2748 mv88e6xxx_mst_put(chip, new_sid);
2749 goto unlock;
2750 }
2751 }
2752
2753 err = mv88e6xxx_mst_put(chip, old_sid);
2754
2755unlock:
2756 mv88e6xxx_reg_unlock(chip);
2757 return err;
2758}
2759
1b6dd556 2760static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
c2693363
VO
2761 const unsigned char *addr, u16 vid,
2762 struct dsa_db db)
87820510 2763{
04bed143 2764 struct mv88e6xxx_chip *chip = ds->priv;
1b6dd556 2765 int err;
87820510 2766
c9acece0 2767 mv88e6xxx_reg_lock(chip);
1b6dd556
AS
2768 err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
2769 MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
c9acece0 2770 mv88e6xxx_reg_unlock(chip);
1b6dd556
AS
2771
2772 return err;
87820510
VD
2773}
2774
f81ec90f 2775static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
c2693363
VO
2776 const unsigned char *addr, u16 vid,
2777 struct dsa_db db)
87820510 2778{
04bed143 2779 struct mv88e6xxx_chip *chip = ds->priv;
83dabd1f 2780 int err;
87820510 2781
c9acece0 2782 mv88e6xxx_reg_lock(chip);
d8291a95 2783 err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 0);
c9acece0 2784 mv88e6xxx_reg_unlock(chip);
87820510 2785
83dabd1f 2786 return err;
87820510
VD
2787}
2788
83dabd1f
VD
2789static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
2790 u16 fid, u16 vid, int port,
2bedde1a 2791 dsa_fdb_dump_cb_t *cb, void *data)
74b6ba0d 2792{
dabc1a96 2793 struct mv88e6xxx_atu_entry addr;
2bedde1a 2794 bool is_static;
74b6ba0d
VD
2795 int err;
2796
d8291a95 2797 addr.state = 0;
dabc1a96 2798 eth_broadcast_addr(addr.mac);
74b6ba0d
VD
2799
2800 do {
dabc1a96 2801 err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
74b6ba0d 2802 if (err)
83dabd1f 2803 return err;
74b6ba0d 2804
d8291a95 2805 if (!addr.state)
74b6ba0d
VD
2806 break;
2807
01bd96c8 2808 if (addr.trunk || (addr.portvec & BIT(port)) == 0)
83dabd1f
VD
2809 continue;
2810
2bedde1a
AS
2811 if (!is_unicast_ether_addr(addr.mac))
2812 continue;
83dabd1f 2813
2bedde1a
AS
2814 is_static = (addr.state ==
2815 MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
2816 err = cb(addr.mac, vid, is_static, data);
83dabd1f
VD
2817 if (err)
2818 return err;
74b6ba0d
VD
2819 } while (!is_broadcast_ether_addr(addr.mac));
2820
2821 return err;
2822}
2823
d89ef4b8
TW
2824struct mv88e6xxx_port_db_dump_vlan_ctx {
2825 int port;
2826 dsa_fdb_dump_cb_t *cb;
2827 void *data;
2828};
2829
2830static int mv88e6xxx_port_db_dump_vlan(struct mv88e6xxx_chip *chip,
2831 const struct mv88e6xxx_vtu_entry *entry,
2832 void *_data)
2833{
2834 struct mv88e6xxx_port_db_dump_vlan_ctx *ctx = _data;
2835
2836 return mv88e6xxx_port_db_dump_fid(chip, entry->fid, entry->vid,
2837 ctx->port, ctx->cb, ctx->data);
2838}
2839
83dabd1f 2840static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
2bedde1a 2841 dsa_fdb_dump_cb_t *cb, void *data)
f33475bd 2842{
d89ef4b8
TW
2843 struct mv88e6xxx_port_db_dump_vlan_ctx ctx = {
2844 .port = port,
2845 .cb = cb,
2846 .data = data,
2847 };
2db9ce1f 2848 u16 fid;
f33475bd
VD
2849 int err;
2850
2db9ce1f 2851 /* Dump port's default Filtering Information Database (VLAN ID 0) */
b4e48c50 2852 err = mv88e6xxx_port_get_fid(chip, port, &fid);
2db9ce1f 2853 if (err)
83dabd1f 2854 return err;
2db9ce1f 2855
2bedde1a 2856 err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data);
2db9ce1f 2857 if (err)
83dabd1f 2858 return err;
2db9ce1f 2859
d89ef4b8 2860 return mv88e6xxx_vtu_walk(chip, mv88e6xxx_port_db_dump_vlan, &ctx);
83dabd1f
VD
2861}
2862
2863static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2bedde1a 2864 dsa_fdb_dump_cb_t *cb, void *data)
83dabd1f 2865{
04bed143 2866 struct mv88e6xxx_chip *chip = ds->priv;
fcf15367
VD
2867 int err;
2868
c9acece0 2869 mv88e6xxx_reg_lock(chip);
fcf15367 2870 err = mv88e6xxx_port_db_dump(chip, port, cb, data);
c9acece0 2871 mv88e6xxx_reg_unlock(chip);
83dabd1f 2872
fcf15367 2873 return err;
f33475bd
VD
2874}
2875
240ea3ef 2876static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
d3eed0e5 2877 struct dsa_bridge bridge)
e79a8bcb 2878{
ef2025ec
VD
2879 struct dsa_switch *ds = chip->ds;
2880 struct dsa_switch_tree *dst = ds->dst;
2881 struct dsa_port *dp;
240ea3ef 2882 int err;
466dfa07 2883
ef2025ec 2884 list_for_each_entry(dp, &dst->ports, list) {
d3eed0e5 2885 if (dsa_port_offloads_bridge(dp, &bridge)) {
ef2025ec
VD
2886 if (dp->ds == ds) {
2887 /* This is a local bridge group member,
2888 * remap its Port VLAN Map.
2889 */
2890 err = mv88e6xxx_port_vlan_map(chip, dp->index);
2891 if (err)
2892 return err;
2893 } else {
2894 /* This is an external bridge group member,
2895 * remap its cross-chip Port VLAN Table entry.
2896 */
2897 err = mv88e6xxx_pvt_map(chip, dp->ds->index,
2898 dp->index);
e96a6e02
VD
2899 if (err)
2900 return err;
2901 }
2902 }
2903 }
2904
240ea3ef
VD
2905 return 0;
2906}
2907
857fdd74
VO
2908/* Treat the software bridge as a virtual single-port switch behind the
2909 * CPU and map in the PVT. First dst->last_switch elements are taken by
2910 * physical switches, so start from beyond that range.
2911 */
2912static int mv88e6xxx_map_virtual_bridge_to_pvt(struct dsa_switch *ds,
2913 unsigned int bridge_num)
2914{
2915 u8 dev = bridge_num + ds->dst->last_switch;
2916 struct mv88e6xxx_chip *chip = ds->priv;
2917
2918 return mv88e6xxx_pvt_map(chip, dev, 0);
2919}
2920
240ea3ef 2921static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
b079922b 2922 struct dsa_bridge bridge,
06b9cce4
VO
2923 bool *tx_fwd_offload,
2924 struct netlink_ext_ack *extack)
240ea3ef
VD
2925{
2926 struct mv88e6xxx_chip *chip = ds->priv;
2927 int err;
2928
c9acece0 2929 mv88e6xxx_reg_lock(chip);
5bded825 2930
d3eed0e5 2931 err = mv88e6xxx_bridge_map(chip, bridge);
5bded825
VO
2932 if (err)
2933 goto unlock;
2934
7af4a361
TW
2935 err = mv88e6xxx_port_set_map_da(chip, port, true);
2936 if (err)
ff624338 2937 goto unlock;
7af4a361 2938
5bded825
VO
2939 err = mv88e6xxx_port_commit_pvid(chip, port);
2940 if (err)
2941 goto unlock;
2942
857fdd74
VO
2943 if (mv88e6xxx_has_pvt(chip)) {
2944 err = mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num);
2945 if (err)
2946 goto unlock;
2947
2948 *tx_fwd_offload = true;
2949 }
2950
5bded825 2951unlock:
c9acece0 2952 mv88e6xxx_reg_unlock(chip);
a6692754 2953
466dfa07 2954 return err;
e79a8bcb
VD
2955}
2956
f123f2fb 2957static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
d3eed0e5 2958 struct dsa_bridge bridge)
66d9cd0f 2959{
04bed143 2960 struct mv88e6xxx_chip *chip = ds->priv;
5bded825 2961 int err;
466dfa07 2962
c9acece0 2963 mv88e6xxx_reg_lock(chip);
5bded825 2964
857fdd74
VO
2965 if (bridge.tx_fwd_offload &&
2966 mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num))
2967 dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
2968
d3eed0e5 2969 if (mv88e6xxx_bridge_map(chip, bridge) ||
240ea3ef
VD
2970 mv88e6xxx_port_vlan_map(chip, port))
2971 dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
5bded825 2972
7af4a361
TW
2973 err = mv88e6xxx_port_set_map_da(chip, port, false);
2974 if (err)
2975 dev_err(ds->dev,
2976 "port %d failed to restore map-DA: %pe\n",
2977 port, ERR_PTR(err));
2978
5bded825
VO
2979 err = mv88e6xxx_port_commit_pvid(chip, port);
2980 if (err)
2981 dev_err(ds->dev,
2982 "port %d failed to restore standalone pvid: %pe\n",
2983 port, ERR_PTR(err));
2984
c9acece0 2985 mv88e6xxx_reg_unlock(chip);
66d9cd0f
VD
2986}
2987
f66a6a69
VO
2988static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds,
2989 int tree_index, int sw_index,
06b9cce4
VO
2990 int port, struct dsa_bridge bridge,
2991 struct netlink_ext_ack *extack)
aec5ac88
VD
2992{
2993 struct mv88e6xxx_chip *chip = ds->priv;
2994 int err;
2995
f66a6a69
VO
2996 if (tree_index != ds->dst->index)
2997 return 0;
2998
c9acece0 2999 mv88e6xxx_reg_lock(chip);
f66a6a69 3000 err = mv88e6xxx_pvt_map(chip, sw_index, port);
e0068620 3001 err = err ? : mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num);
c9acece0 3002 mv88e6xxx_reg_unlock(chip);
aec5ac88
VD
3003
3004 return err;
3005}
3006
f66a6a69
VO
3007static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds,
3008 int tree_index, int sw_index,
d3eed0e5 3009 int port, struct dsa_bridge bridge)
aec5ac88
VD
3010{
3011 struct mv88e6xxx_chip *chip = ds->priv;
3012
f66a6a69
VO
3013 if (tree_index != ds->dst->index)
3014 return;
3015
c9acece0 3016 mv88e6xxx_reg_lock(chip);
e0068620
TW
3017 if (mv88e6xxx_pvt_map(chip, sw_index, port) ||
3018 mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num))
aec5ac88 3019 dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
c9acece0 3020 mv88e6xxx_reg_unlock(chip);
aec5ac88
VD
3021}
3022
17e708ba
VD
3023static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
3024{
3025 if (chip->info->ops->reset)
3026 return chip->info->ops->reset(chip);
3027
3028 return 0;
3029}
3030
309eca6d
VD
3031static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
3032{
3033 struct gpio_desc *gpiod = chip->reset;
3034
3035 /* If there is a GPIO connected to the reset pin, toggle it */
3036 if (gpiod) {
23d775f1
AL
3037 /* If the switch has just been reset and not yet completed
3038 * loading EEPROM, the reset may interrupt the I2C transaction
3039 * mid-byte, causing the first EEPROM read after the reset
3040 * from the wrong location resulting in the switch booting
3041 * to wrong mode and inoperable.
3042 */
3043 mv88e6xxx_g1_wait_eeprom_done(chip);
3044
309eca6d
VD
3045 gpiod_set_value_cansleep(gpiod, 1);
3046 usleep_range(10000, 20000);
3047 gpiod_set_value_cansleep(gpiod, 0);
3048 usleep_range(10000, 20000);
a3dcb3e7
AL
3049
3050 mv88e6xxx_g1_wait_eeprom_done(chip);
309eca6d
VD
3051 }
3052}
3053
4ac4b5a6 3054static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
552238b5 3055{
4ac4b5a6 3056 int i, err;
552238b5 3057
4ac4b5a6 3058 /* Set all ports to the Disabled state */
370b4ffb 3059 for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
f894c29c 3060 err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED);
0e7b9925
AL
3061 if (err)
3062 return err;
552238b5
VD
3063 }
3064
4ac4b5a6
VD
3065 /* Wait for transmit queues to drain,
3066 * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
3067 */
552238b5
VD
3068 usleep_range(2000, 4000);
3069
4ac4b5a6
VD
3070 return 0;
3071}
3072
3073static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
3074{
4ac4b5a6
VD
3075 int err;
3076
3077 err = mv88e6xxx_disable_ports(chip);
3078 if (err)
3079 return err;
3080
309eca6d 3081 mv88e6xxx_hardware_reset(chip);
552238b5 3082
17e708ba 3083 return mv88e6xxx_software_reset(chip);
552238b5
VD
3084}
3085
4314557c 3086static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
31bef4e9
VD
3087 enum mv88e6xxx_frame_mode frame,
3088 enum mv88e6xxx_egress_mode egress, u16 etype)
56995cbc
AL
3089{
3090 int err;
3091
4314557c
VD
3092 if (!chip->info->ops->port_set_frame_mode)
3093 return -EOPNOTSUPP;
3094
3095 err = mv88e6xxx_port_set_egress_mode(chip, port, egress);
56995cbc
AL
3096 if (err)
3097 return err;
3098
4314557c
VD
3099 err = chip->info->ops->port_set_frame_mode(chip, port, frame);
3100 if (err)
3101 return err;
3102
3103 if (chip->info->ops->port_set_ether_type)
3104 return chip->info->ops->port_set_ether_type(chip, port, etype);
3105
3106 return 0;
56995cbc
AL
3107}
3108
4314557c 3109static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port)
56995cbc 3110{
4314557c 3111 return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
31bef4e9 3112 MV88E6XXX_EGRESS_MODE_UNMODIFIED,
b8109594 3113 MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
4314557c 3114}
56995cbc 3115
4314557c
VD
3116static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
3117{
3118 return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
31bef4e9 3119 MV88E6XXX_EGRESS_MODE_UNMODIFIED,
b8109594 3120 MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
4314557c 3121}
56995cbc 3122
4314557c
VD
3123static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
3124{
3125 return mv88e6xxx_set_port_mode(chip, port,
3126 MV88E6XXX_FRAME_MODE_ETHERTYPE,
31bef4e9
VD
3127 MV88E6XXX_EGRESS_MODE_ETHERTYPE,
3128 ETH_P_EDSA);
4314557c 3129}
56995cbc 3130
4314557c
VD
3131static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
3132{
3133 if (dsa_is_dsa_port(chip->ds, port))
3134 return mv88e6xxx_set_port_mode_dsa(chip, port);
56995cbc 3135
2b3e9891 3136 if (dsa_is_user_port(chip->ds, port))
4314557c 3137 return mv88e6xxx_set_port_mode_normal(chip, port);
56995cbc 3138
4314557c 3139 /* Setup CPU port mode depending on its supported tag format */
670bb80f 3140 if (chip->tag_protocol == DSA_TAG_PROTO_DSA)
4314557c 3141 return mv88e6xxx_set_port_mode_dsa(chip, port);
56995cbc 3142
670bb80f 3143 if (chip->tag_protocol == DSA_TAG_PROTO_EDSA)
4314557c 3144 return mv88e6xxx_set_port_mode_edsa(chip, port);
56995cbc 3145
4314557c 3146 return -EINVAL;
56995cbc
AL
3147}
3148
601aeed3 3149static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
56995cbc 3150{
601aeed3 3151 bool message = dsa_is_dsa_port(chip->ds, port);
56995cbc 3152
601aeed3 3153 return mv88e6xxx_port_set_message_port(chip, port, message);
4314557c 3154}
56995cbc 3155
601aeed3 3156static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
4314557c 3157{
a8b659e7 3158 int err;
56995cbc 3159
a8b659e7 3160 if (chip->info->ops->port_set_ucast_flood) {
7b9f16fe 3161 err = chip->info->ops->port_set_ucast_flood(chip, port, true);
a8b659e7
VO
3162 if (err)
3163 return err;
3164 }
3165 if (chip->info->ops->port_set_mcast_flood) {
7b9f16fe 3166 err = chip->info->ops->port_set_mcast_flood(chip, port, true);
a8b659e7
VO
3167 if (err)
3168 return err;
3169 }
ea698f4f 3170
407308f6 3171 return 0;
ea698f4f
VD
3172}
3173
45de77ff
VD
3174static irqreturn_t mv88e6xxx_serdes_irq_thread_fn(int irq, void *dev_id)
3175{
3176 struct mv88e6xxx_port *mvp = dev_id;
3177 struct mv88e6xxx_chip *chip = mvp->chip;
3178 irqreturn_t ret = IRQ_NONE;
3179 int port = mvp->port;
193c5b26 3180 int lane;
45de77ff
VD
3181
3182 mv88e6xxx_reg_lock(chip);
3183 lane = mv88e6xxx_serdes_get_lane(chip, port);
193c5b26 3184 if (lane >= 0)
45de77ff
VD
3185 ret = mv88e6xxx_serdes_irq_status(chip, port, lane);
3186 mv88e6xxx_reg_unlock(chip);
3187
3188 return ret;
3189}
3190
3191static int mv88e6xxx_serdes_irq_request(struct mv88e6xxx_chip *chip, int port,
193c5b26 3192 int lane)
45de77ff
VD
3193{
3194 struct mv88e6xxx_port *dev_id = &chip->ports[port];
3195 unsigned int irq;
3196 int err;
3197
3198 /* Nothing to request if this SERDES port has no IRQ */
3199 irq = mv88e6xxx_serdes_irq_mapping(chip, port);
3200 if (!irq)
3201 return 0;
3202
e6f2f6b8
AL
3203 snprintf(dev_id->serdes_irq_name, sizeof(dev_id->serdes_irq_name),
3204 "mv88e6xxx-%s-serdes-%d", dev_name(chip->dev), port);
3205
45de77ff
VD
3206 /* Requesting the IRQ will trigger IRQ callbacks, so release the lock */
3207 mv88e6xxx_reg_unlock(chip);
3208 err = request_threaded_irq(irq, NULL, mv88e6xxx_serdes_irq_thread_fn,
e6f2f6b8
AL
3209 IRQF_ONESHOT, dev_id->serdes_irq_name,
3210 dev_id);
45de77ff
VD
3211 mv88e6xxx_reg_lock(chip);
3212 if (err)
3213 return err;
3214
3215 dev_id->serdes_irq = irq;
3216
3217 return mv88e6xxx_serdes_irq_enable(chip, port, lane);
3218}
3219
3220static int mv88e6xxx_serdes_irq_free(struct mv88e6xxx_chip *chip, int port,
193c5b26 3221 int lane)
45de77ff
VD
3222{
3223 struct mv88e6xxx_port *dev_id = &chip->ports[port];
3224 unsigned int irq = dev_id->serdes_irq;
3225 int err;
3226
3227 /* Nothing to free if no IRQ has been requested */
3228 if (!irq)
3229 return 0;
3230
3231 err = mv88e6xxx_serdes_irq_disable(chip, port, lane);
3232
3233 /* Freeing the IRQ will trigger IRQ callbacks, so release the lock */
3234 mv88e6xxx_reg_unlock(chip);
3235 free_irq(irq, dev_id);
3236 mv88e6xxx_reg_lock(chip);
3237
3238 dev_id->serdes_irq = 0;
3239
3240 return err;
3241}
3242
6d91782f
AL
3243static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
3244 bool on)
3245{
193c5b26 3246 int lane;
fc0bc019 3247 int err;
04aca993 3248
dc272f60 3249 lane = mv88e6xxx_serdes_get_lane(chip, port);
193c5b26 3250 if (lane < 0)
fc0bc019
VD
3251 return 0;
3252
3253 if (on) {
dc272f60 3254 err = mv88e6xxx_serdes_power_up(chip, port, lane);
fc0bc019
VD
3255 if (err)
3256 return err;
3257
45de77ff 3258 err = mv88e6xxx_serdes_irq_request(chip, port, lane);
fc0bc019 3259 } else {
45de77ff
VD
3260 err = mv88e6xxx_serdes_irq_free(chip, port, lane);
3261 if (err)
3262 return err;
fc0bc019 3263
dc272f60 3264 err = mv88e6xxx_serdes_power_down(chip, port, lane);
fc0bc019
VD
3265 }
3266
3267 return err;
6d91782f
AL
3268}
3269
2fda45f0
MB
3270static int mv88e6xxx_set_egress_port(struct mv88e6xxx_chip *chip,
3271 enum mv88e6xxx_egress_direction direction,
3272 int port)
3273{
3274 int err;
3275
3276 if (!chip->info->ops->set_egress_port)
3277 return -EOPNOTSUPP;
3278
3279 err = chip->info->ops->set_egress_port(chip, direction, port);
3280 if (err)
3281 return err;
3282
3283 if (direction == MV88E6XXX_EGRESS_DIR_INGRESS)
3284 chip->ingress_dest_port = port;
3285 else
3286 chip->egress_dest_port = port;
3287
3288 return 0;
3289}
3290
fa371c80
VD
3291static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
3292{
3293 struct dsa_switch *ds = chip->ds;
3294 int upstream_port;
3295 int err;
3296
07073c79 3297 upstream_port = dsa_upstream_port(ds, port);
fa371c80
VD
3298 if (chip->info->ops->port_set_upstream_port) {
3299 err = chip->info->ops->port_set_upstream_port(chip, port,
3300 upstream_port);
3301 if (err)
3302 return err;
3303 }
3304
0ea54dda
VD
3305 if (port == upstream_port) {
3306 if (chip->info->ops->set_cpu_port) {
3307 err = chip->info->ops->set_cpu_port(chip,
3308 upstream_port);
3309 if (err)
3310 return err;
3311 }
3312
2fda45f0 3313 err = mv88e6xxx_set_egress_port(chip,
5c74c54c
IT
3314 MV88E6XXX_EGRESS_DIR_INGRESS,
3315 upstream_port);
2fda45f0
MB
3316 if (err && err != -EOPNOTSUPP)
3317 return err;
5c74c54c 3318
2fda45f0 3319 err = mv88e6xxx_set_egress_port(chip,
5c74c54c
IT
3320 MV88E6XXX_EGRESS_DIR_EGRESS,
3321 upstream_port);
2fda45f0
MB
3322 if (err && err != -EOPNOTSUPP)
3323 return err;
0ea54dda
VD
3324 }
3325
fa371c80
VD
3326 return 0;
3327}
3328
fad09c73 3329static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
d827e88a 3330{
926eae60 3331 struct device_node *phy_handle = NULL;
fad09c73 3332 struct dsa_switch *ds = chip->ds;
3c783b83 3333 phy_interface_t mode;
926eae60 3334 struct dsa_port *dp;
3c783b83 3335 int tx_amp, speed;
0e7b9925 3336 int err;
54d792f2 3337 u16 reg;
d827e88a 3338
7b898469
AL
3339 chip->ports[port].chip = chip;
3340 chip->ports[port].port = port;
3341
3c783b83
RK
3342 dp = dsa_to_port(ds, port);
3343
d78343d2
VD
3344 /* MAC Forcing register: don't force link, speed, duplex or flow control
3345 * state to any particular values on physical ports, but force the CPU
3346 * port and all DSA ports to their maximum bandwidth and full duplex.
3347 */
3c783b83 3348 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
cc1049cc
MW
3349 struct phylink_config pl_config = {};
3350 unsigned long caps;
3351
a7d82367 3352 chip->info->ops->phylink_get_caps(chip, port, &pl_config);
cc1049cc
MW
3353
3354 caps = pl_config.mac_capabilities;
3c783b83
RK
3355
3356 if (chip->info->ops->port_max_speed_mode)
18e1b742 3357 mode = chip->info->ops->port_max_speed_mode(chip, port);
3c783b83
RK
3358 else
3359 mode = PHY_INTERFACE_MODE_NA;
3360
3361 if (caps & MAC_10000FD)
3362 speed = SPEED_10000;
3363 else if (caps & MAC_5000FD)
3364 speed = SPEED_5000;
3365 else if (caps & MAC_2500FD)
3366 speed = SPEED_2500;
3367 else if (caps & MAC_1000)
3368 speed = SPEED_1000;
3369 else if (caps & MAC_100)
3370 speed = SPEED_100;
3371 else
3372 speed = SPEED_10;
3373
d78343d2 3374 err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
3c783b83
RK
3375 speed, DUPLEX_FULL,
3376 PAUSE_OFF, mode);
3377 } else {
d78343d2
VD
3378 err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
3379 SPEED_UNFORCED, DUPLEX_UNFORCED,
54186b91 3380 PAUSE_ON,
d78343d2 3381 PHY_INTERFACE_MODE_NA);
3c783b83 3382 }
d78343d2
VD
3383 if (err)
3384 return err;
54d792f2
AL
3385
3386 /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
3387 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
3388 * tunneling, determine priority by looking at 802.1p and IP
3389 * priority fields (IP prio has precedence), and set STP state
3390 * to Forwarding.
3391 *
3392 * If this is the CPU link, use DSA or EDSA tagging depending
3393 * on which tagging mode was configured.
3394 *
3395 * If this is a link to another switch, use DSA tagging mode.
3396 *
3397 * If this is the upstream port for this switch, enable
3398 * forwarding of unknown unicasts and multicasts.
3399 */
7bcad0f0 3400 reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
a89b433b 3401 MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
7bcad0f0
SB
3402 /* Forward any IPv4 IGMP or IPv6 MLD frames received
3403 * by a USER port to the CPU port to allow snooping.
3404 */
3405 if (dsa_is_user_port(ds, port))
3406 reg |= MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP;
3407
a89b433b 3408 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
56995cbc
AL
3409 if (err)
3410 return err;
6083ce71 3411
601aeed3 3412 err = mv88e6xxx_setup_port_mode(chip, port);
56995cbc
AL
3413 if (err)
3414 return err;
54d792f2 3415
601aeed3 3416 err = mv88e6xxx_setup_egress_floods(chip, port);
4314557c
VD
3417 if (err)
3418 return err;
3419
b92ce2f5 3420 /* Port Control 2: don't force a good FCS, set the MTU size to
7af4a361
TW
3421 * 10222 bytes, disable 802.1q tags checking, don't discard
3422 * tagged or untagged frames on this port, skip destination
3423 * address lookup on user ports, disable ARP mirroring and don't
3424 * send a copy of all transmitted/received frames on this port
3425 * to the CPU.
54d792f2 3426 */
7af4a361 3427 err = mv88e6xxx_port_set_map_da(chip, port, !dsa_is_user_port(ds, port));
a23b2961
AL
3428 if (err)
3429 return err;
8efdda4a 3430
fa371c80
VD
3431 err = mv88e6xxx_setup_upstream_port(chip, port);
3432 if (err)
3433 return err;
54d792f2 3434
d352b20f
TW
3435 /* On chips that support it, set all downstream DSA ports'
3436 * VLAN policy to TRAP. In combination with loading
3437 * MV88E6XXX_VID_STANDALONE as a policy entry in the VTU, this
3438 * provides a better isolation barrier between standalone
3439 * ports, as the ATU is bypassed on any intermediate switches
3440 * between the incoming port and the CPU.
3441 */
3442 if (dsa_is_downstream_port(ds, port) &&
3443 chip->info->ops->port_set_policy) {
3444 err = chip->info->ops->port_set_policy(chip, port,
3445 MV88E6XXX_POLICY_MAPPING_VTU,
3446 MV88E6XXX_POLICY_ACTION_TRAP);
3447 if (err)
3448 return err;
3449 }
3450
3451 /* User ports start out in standalone mode and 802.1Q is
3452 * therefore disabled. On DSA ports, all valid VIDs are always
3453 * loaded in the VTU - therefore, enable 802.1Q in order to take
3454 * advantage of VLAN policy on chips that supports it.
3455 */
a23b2961 3456 err = mv88e6xxx_port_set_8021q_mode(chip, port,
d352b20f
TW
3457 dsa_is_user_port(ds, port) ?
3458 MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED :
3459 MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE);
3460 if (err)
3461 return err;
3462
3463 /* Bind MV88E6XXX_VID_STANDALONE to MV88E6XXX_FID_STANDALONE by
3464 * virtue of the fact that mv88e6xxx_atu_new() will pick it as
3465 * the first free FID. This will be used as the private PVID for
3466 * unbridged ports. Shared (DSA and CPU) ports must also be
3467 * members of this VID, in order to trap all frames assigned to
3468 * it to the CPU.
3469 */
3470 err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_STANDALONE,
3471 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED,
3472 false);
a23b2961
AL
3473 if (err)
3474 return err;
3475
5bded825
VO
3476 /* Associate MV88E6XXX_VID_BRIDGED with MV88E6XXX_FID_BRIDGED in the
3477 * ATU by virtue of the fact that mv88e6xxx_atu_new() will pick it as
3478 * the first free FID after MV88E6XXX_FID_STANDALONE. This will be used
3479 * as the private PVID on ports under a VLAN-unaware bridge.
3480 * Shared (DSA and CPU) ports must also be members of it, to translate
3481 * the VID from the DSA tag into MV88E6XXX_FID_BRIDGED, instead of
3482 * relying on their port default FID.
3483 */
3484 err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_BRIDGED,
d352b20f 3485 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED,
5bded825
VO
3486 false);
3487 if (err)
3488 return err;
3489
cd782656 3490 if (chip->info->ops->port_set_jumbo_size) {
b92ce2f5 3491 err = chip->info->ops->port_set_jumbo_size(chip, port, 10218);
5f436666
AL
3492 if (err)
3493 return err;
3494 }
3495
041bd545
TW
3496 /* Port Association Vector: disable automatic address learning
3497 * on all user ports since they start out in standalone
3498 * mode. When joining a bridge, learning will be configured to
3499 * match the bridge port settings. Enable learning on all
3500 * DSA/CPU ports. NOTE: FROM_CPU frames always bypass the
3501 * learning process.
3502 *
3503 * Disable HoldAt1, IntOnAgeOut, LockedPort, IgnoreWrongData,
3504 * and RefreshLocked. I.e. setup standard automatic learning.
54d792f2 3505 */
041bd545 3506 if (dsa_is_user_port(ds, port))
65fa4027 3507 reg = 0;
041bd545
TW
3508 else
3509 reg = 1 << port;
4c7ea3c0 3510
2a4614e4
VD
3511 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
3512 reg);
0e7b9925
AL
3513 if (err)
3514 return err;
54d792f2
AL
3515
3516 /* Egress rate control 2: disable egress rate control. */
2cb8cb14
VD
3517 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2,
3518 0x0000);
0e7b9925
AL
3519 if (err)
3520 return err;
54d792f2 3521
0898432c
VD
3522 if (chip->info->ops->port_pause_limit) {
3523 err = chip->info->ops->port_pause_limit(chip, port, 0, 0);
0e7b9925
AL
3524 if (err)
3525 return err;
b35d322a 3526 }
54d792f2 3527
c8c94891
VD
3528 if (chip->info->ops->port_disable_learn_limit) {
3529 err = chip->info->ops->port_disable_learn_limit(chip, port);
3530 if (err)
3531 return err;
3532 }
3533
9dbfb4e1
VD
3534 if (chip->info->ops->port_disable_pri_override) {
3535 err = chip->info->ops->port_disable_pri_override(chip, port);
0e7b9925
AL
3536 if (err)
3537 return err;
ef0a7318 3538 }
2bbb33be 3539
ef0a7318
AL
3540 if (chip->info->ops->port_tag_remap) {
3541 err = chip->info->ops->port_tag_remap(chip, port);
0e7b9925
AL
3542 if (err)
3543 return err;
54d792f2
AL
3544 }
3545
ef70b111
AL
3546 if (chip->info->ops->port_egress_rate_limiting) {
3547 err = chip->info->ops->port_egress_rate_limiting(chip, port);
0e7b9925
AL
3548 if (err)
3549 return err;
54d792f2
AL
3550 }
3551
121b8fe2
HF
3552 if (chip->info->ops->port_setup_message_port) {
3553 err = chip->info->ops->port_setup_message_port(chip, port);
3554 if (err)
3555 return err;
3556 }
d827e88a 3557
926eae60 3558 if (chip->info->ops->serdes_set_tx_amplitude) {
926eae60
HB
3559 if (dp)
3560 phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
3561
3562 if (phy_handle && !of_property_read_u32(phy_handle,
3563 "tx-p2p-microvolt",
3564 &tx_amp))
3565 err = chip->info->ops->serdes_set_tx_amplitude(chip,
3566 port, tx_amp);
3567 if (phy_handle) {
3568 of_node_put(phy_handle);
3569 if (err)
3570 return err;
3571 }
3572 }
3573
207afda1 3574 /* Port based VLAN map: give each port the same default address
b7666efe
VD
3575 * database, and allow bidirectional communication between the
3576 * CPU and DSA port(s), and the other ports.
d827e88a 3577 */
5bded825 3578 err = mv88e6xxx_port_set_fid(chip, port, MV88E6XXX_FID_STANDALONE);
0e7b9925
AL
3579 if (err)
3580 return err;
2db9ce1f 3581
240ea3ef 3582 err = mv88e6xxx_port_vlan_map(chip, port);
0e7b9925
AL
3583 if (err)
3584 return err;
d827e88a
GR
3585
3586 /* Default VLAN ID and priority: don't set a default VLAN
3587 * ID, and set the default packet priority to zero.
3588 */
b7929fb3 3589 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
dbde9e66
AL
3590}
3591
2a550aec
AL
3592static int mv88e6xxx_get_max_mtu(struct dsa_switch *ds, int port)
3593{
3594 struct mv88e6xxx_chip *chip = ds->priv;
3595
3596 if (chip->info->ops->port_set_jumbo_size)
b9c587fe 3597 return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
1baf0fac 3598 else if (chip->info->ops->set_max_frame_size)
b9c587fe 3599 return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
7e951737 3600 return ETH_DATA_LEN;
2a550aec
AL
3601}
3602
3603static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
3604{
3605 struct mv88e6xxx_chip *chip = ds->priv;
3606 int ret = 0;
3607
7e951737
VO
3608 /* For families where we don't know how to alter the MTU,
3609 * just accept any value up to ETH_DATA_LEN
3610 */
3611 if (!chip->info->ops->port_set_jumbo_size &&
3612 !chip->info->ops->set_max_frame_size) {
3613 if (new_mtu > ETH_DATA_LEN)
3614 return -EINVAL;
3615
3616 return 0;
3617 }
3618
b9c587fe
AL
3619 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
3620 new_mtu += EDSA_HLEN;
3621
2a550aec
AL
3622 mv88e6xxx_reg_lock(chip);
3623 if (chip->info->ops->port_set_jumbo_size)
3624 ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu);
1baf0fac
CP
3625 else if (chip->info->ops->set_max_frame_size)
3626 ret = chip->info->ops->set_max_frame_size(chip, new_mtu);
2a550aec
AL
3627 mv88e6xxx_reg_unlock(chip);
3628
3629 return ret;
3630}
3631
04aca993
AL
3632static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
3633 struct phy_device *phydev)
3634{
3635 struct mv88e6xxx_chip *chip = ds->priv;
523a8904 3636 int err;
04aca993 3637
c9acece0 3638 mv88e6xxx_reg_lock(chip);
523a8904 3639 err = mv88e6xxx_serdes_power(chip, port, true);
c9acece0 3640 mv88e6xxx_reg_unlock(chip);
04aca993
AL
3641
3642 return err;
3643}
3644
75104db0 3645static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port)
04aca993
AL
3646{
3647 struct mv88e6xxx_chip *chip = ds->priv;
3648
c9acece0 3649 mv88e6xxx_reg_lock(chip);
523a8904
VD
3650 if (mv88e6xxx_serdes_power(chip, port, false))
3651 dev_err(chip->dev, "failed to power off SERDES\n");
c9acece0 3652 mv88e6xxx_reg_unlock(chip);
04aca993
AL
3653}
3654
2cfcd964
VD
3655static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds,
3656 unsigned int ageing_time)
3657{
04bed143 3658 struct mv88e6xxx_chip *chip = ds->priv;
2cfcd964
VD
3659 int err;
3660
c9acece0 3661 mv88e6xxx_reg_lock(chip);
720c6343 3662 err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time);
c9acece0 3663 mv88e6xxx_reg_unlock(chip);
2cfcd964
VD
3664
3665 return err;
3666}
3667
447b1bb8 3668static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
acdaffcc 3669{
552238b5 3670 int err;
54d792f2 3671
de227387 3672 /* Initialize the statistics unit */
447b1bb8
VD
3673 if (chip->info->ops->stats_set_histogram) {
3674 err = chip->info->ops->stats_set_histogram(chip);
3675 if (err)
3676 return err;
3677 }
de227387 3678
40cff8fc 3679 return mv88e6xxx_g1_stats_clear(chip);
9729934c
VD
3680}
3681
ea89098e
AL
3682/* Check if the errata has already been applied. */
3683static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
3684{
3685 int port;
3686 int err;
3687 u16 val;
3688
3689 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
60907013 3690 err = mv88e6xxx_port_hidden_read(chip, 0xf, port, 0, &val);
ea89098e
AL
3691 if (err) {
3692 dev_err(chip->dev,
3693 "Error reading hidden register: %d\n", err);
3694 return false;
3695 }
3696 if (val != 0x01c0)
3697 return false;
3698 }
3699
3700 return true;
3701}
3702
3703/* The 6390 copper ports have an errata which require poking magic
3704 * values into undocumented hidden registers and then performing a
3705 * software reset.
3706 */
3707static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
3708{
3709 int port;
3710 int err;
3711
3712 if (mv88e6390_setup_errata_applied(chip))
3713 return 0;
3714
3715 /* Set the ports into blocking mode */
3716 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
3717 err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
3718 if (err)
3719 return err;
3720 }
3721
3722 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
60907013 3723 err = mv88e6xxx_port_hidden_write(chip, 0xf, port, 0, 0x01c0);
ea89098e
AL
3724 if (err)
3725 return err;
3726 }
3727
3728 return mv88e6xxx_software_reset(chip);
3729}
3730
1fe976d3
PR
3731/* prod_id for switch families which do not have a PHY model number */
3732static const u16 family_prod_id_table[] = {
3733 [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
3734 [MV88E6XXX_FAMILY_6390] = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
c5d015b0 3735 [MV88E6XXX_FAMILY_6393] = MV88E6XXX_PORT_SWITCH_ID_PROD_6393X,
1fe976d3
PR
3736};
3737
e57e5e77 3738static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
fd3a0ee4 3739{
0dd12d54
AL
3740 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
3741 struct mv88e6xxx_chip *chip = mdio_bus->chip;
1fe976d3 3742 u16 prod_id;
e57e5e77
VD
3743 u16 val;
3744 int err;
fd3a0ee4 3745
ee26a228
AL
3746 if (!chip->info->ops->phy_read)
3747 return -EOPNOTSUPP;
3748
c9acece0 3749 mv88e6xxx_reg_lock(chip);
ee26a228 3750 err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
c9acece0 3751 mv88e6xxx_reg_unlock(chip);
e57e5e77 3752
1fe976d3
PR
3753 /* Some internal PHYs don't have a model number. */
3754 if (reg == MII_PHYSID2 && !(val & 0x3f0) &&
3755 chip->info->family < ARRAY_SIZE(family_prod_id_table)) {
3756 prod_id = family_prod_id_table[chip->info->family];
3757 if (prod_id)
3758 val |= prod_id >> 4;
da9f3301
AL
3759 }
3760
e57e5e77 3761 return err ? err : val;
fd3a0ee4
AL
3762}
3763
743a19e3
AL
3764static int mv88e6xxx_mdio_read_c45(struct mii_bus *bus, int phy, int devad,
3765 int reg)
3766{
3767 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
3768 struct mv88e6xxx_chip *chip = mdio_bus->chip;
3769 u16 val;
3770 int err;
3771
3772 if (!chip->info->ops->phy_read_c45)
3773 return -EOPNOTSUPP;
3774
3775 mv88e6xxx_reg_lock(chip);
3776 err = chip->info->ops->phy_read_c45(chip, bus, phy, devad, reg, &val);
3777 mv88e6xxx_reg_unlock(chip);
3778
3779 return err ? err : val;
3780}
3781
e57e5e77 3782static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
fd3a0ee4 3783{
0dd12d54
AL
3784 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
3785 struct mv88e6xxx_chip *chip = mdio_bus->chip;
e57e5e77 3786 int err;
fd3a0ee4 3787
ee26a228
AL
3788 if (!chip->info->ops->phy_write)
3789 return -EOPNOTSUPP;
3790
c9acece0 3791 mv88e6xxx_reg_lock(chip);
ee26a228 3792 err = chip->info->ops->phy_write(chip, bus, phy, reg, val);
c9acece0 3793 mv88e6xxx_reg_unlock(chip);
e57e5e77
VD
3794
3795 return err;
fd3a0ee4
AL
3796}
3797
743a19e3
AL
3798static int mv88e6xxx_mdio_write_c45(struct mii_bus *bus, int phy, int devad,
3799 int reg, u16 val)
3800{
3801 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
3802 struct mv88e6xxx_chip *chip = mdio_bus->chip;
3803 int err;
3804
3805 if (!chip->info->ops->phy_write_c45)
3806 return -EOPNOTSUPP;
3807
3808 mv88e6xxx_reg_lock(chip);
3809 err = chip->info->ops->phy_write_c45(chip, bus, phy, devad, reg, val);
3810 mv88e6xxx_reg_unlock(chip);
3811
3812 return err;
3813}
3814
fad09c73 3815static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
a3c53be5
AL
3816 struct device_node *np,
3817 bool external)
b516d453
AL
3818{
3819 static int index;
0dd12d54 3820 struct mv88e6xxx_mdio_bus *mdio_bus;
b516d453
AL
3821 struct mii_bus *bus;
3822 int err;
3823
2510babc 3824 if (external) {
c9acece0 3825 mv88e6xxx_reg_lock(chip);
2510babc 3826 err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true);
c9acece0 3827 mv88e6xxx_reg_unlock(chip);
2510babc
AL
3828
3829 if (err)
3830 return err;
3831 }
3832
f53a2ce8 3833 bus = mdiobus_alloc_size(sizeof(*mdio_bus));
b516d453
AL
3834 if (!bus)
3835 return -ENOMEM;
3836
0dd12d54 3837 mdio_bus = bus->priv;
a3c53be5 3838 mdio_bus->bus = bus;
0dd12d54 3839 mdio_bus->chip = chip;
a3c53be5
AL
3840 INIT_LIST_HEAD(&mdio_bus->list);
3841 mdio_bus->external = external;
0dd12d54 3842
b516d453
AL
3843 if (np) {
3844 bus->name = np->full_name;
f7ce9103 3845 snprintf(bus->id, MII_BUS_ID_SIZE, "%pOF", np);
b516d453
AL
3846 } else {
3847 bus->name = "mv88e6xxx SMI";
3848 snprintf(bus->id, MII_BUS_ID_SIZE, "mv88e6xxx-%d", index++);
3849 }
3850
3851 bus->read = mv88e6xxx_mdio_read;
3852 bus->write = mv88e6xxx_mdio_write;
743a19e3
AL
3853 bus->read_c45 = mv88e6xxx_mdio_read_c45;
3854 bus->write_c45 = mv88e6xxx_mdio_write_c45;
fad09c73 3855 bus->parent = chip->dev;
a4926c29
MB
3856 bus->phy_mask = ~GENMASK(chip->info->phy_base_addr +
3857 mv88e6xxx_num_ports(chip) - 1,
3858 chip->info->phy_base_addr);
b516d453 3859
6f88284f
AL
3860 if (!external) {
3861 err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
3862 if (err)
f53a2ce8 3863 goto out;
6f88284f
AL
3864 }
3865
00e798c7 3866 err = of_mdiobus_register(bus, np);
b516d453 3867 if (err) {
fad09c73 3868 dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
6f88284f 3869 mv88e6xxx_g2_irq_mdio_free(chip, bus);
f53a2ce8 3870 goto out;
b516d453 3871 }
a3c53be5
AL
3872
3873 if (external)
3874 list_add_tail(&mdio_bus->list, &chip->mdios);
3875 else
3876 list_add(&mdio_bus->list, &chip->mdios);
b516d453
AL
3877
3878 return 0;
f53a2ce8
VO
3879
3880out:
3881 mdiobus_free(bus);
3882 return err;
a3c53be5 3883}
b516d453 3884
3126aeec
AL
3885static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)
3886
3887{
51a04ebf 3888 struct mv88e6xxx_mdio_bus *mdio_bus, *p;
3126aeec
AL
3889 struct mii_bus *bus;
3890
51a04ebf 3891 list_for_each_entry_safe(mdio_bus, p, &chip->mdios, list) {
3126aeec
AL
3892 bus = mdio_bus->bus;
3893
6f88284f
AL
3894 if (!mdio_bus->external)
3895 mv88e6xxx_g2_irq_mdio_free(chip, bus);
3896
3126aeec 3897 mdiobus_unregister(bus);
f53a2ce8 3898 mdiobus_free(bus);
3126aeec
AL
3899 }
3900}
3901
2cb0658d 3902static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip)
a3c53be5 3903{
2cb0658d 3904 struct device_node *np = chip->dev->of_node;
a3c53be5
AL
3905 struct device_node *child;
3906 int err;
3907
3908 /* Always register one mdio bus for the internal/default mdio
3909 * bus. This maybe represented in the device tree, but is
3910 * optional.
3911 */
3912 child = of_get_child_by_name(np, "mdio");
3913 err = mv88e6xxx_mdio_register(chip, child, false);
02ded5a1 3914 of_node_put(child);
a3c53be5
AL
3915 if (err)
3916 return err;
3917
3918 /* Walk the device tree, and see if there are any other nodes
3919 * which say they are compatible with the external mdio
3920 * bus.
3921 */
3922 for_each_available_child_of_node(np, child) {
ceb96fae
AL
3923 if (of_device_is_compatible(
3924 child, "marvell,mv88e6xxx-mdio-external")) {
a3c53be5 3925 err = mv88e6xxx_mdio_register(chip, child, true);
3126aeec
AL
3926 if (err) {
3927 mv88e6xxx_mdios_unregister(chip);
78e42040 3928 of_node_put(child);
a3c53be5 3929 return err;
3126aeec 3930 }
a3c53be5
AL
3931 }
3932 }
3933
3934 return 0;
b516d453
AL
3935}
3936
f1bee740
KK
3937static void mv88e6xxx_teardown(struct dsa_switch *ds)
3938{
2cb0658d
KK
3939 struct mv88e6xxx_chip *chip = ds->priv;
3940
f1bee740
KK
3941 mv88e6xxx_teardown_devlink_params(ds);
3942 dsa_devlink_resources_unregister(ds);
3943 mv88e6xxx_teardown_devlink_regions_global(ds);
2cb0658d 3944 mv88e6xxx_mdios_unregister(chip);
f1bee740
KK
3945}
3946
3947static int mv88e6xxx_setup(struct dsa_switch *ds)
3948{
3949 struct mv88e6xxx_chip *chip = ds->priv;
3950 u8 cmode;
3951 int err;
3952 int i;
3953
2cb0658d
KK
3954 err = mv88e6xxx_mdios_register(chip);
3955 if (err)
3956 return err;
3957
f1bee740
KK
3958 chip->ds = ds;
3959 ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
3960
3961 /* Since virtual bridges are mapped in the PVT, the number we support
3962 * depends on the physical switch topology. We need to let DSA figure
3963 * that out and therefore we cannot set this at dsa_register_switch()
3964 * time.
3965 */
3966 if (mv88e6xxx_has_pvt(chip))
3967 ds->max_num_bridges = MV88E6XXX_MAX_PVT_SWITCHES -
3968 ds->dst->last_switch - 1;
3969
3970 mv88e6xxx_reg_lock(chip);
3971
3972 if (chip->info->ops->setup_errata) {
3973 err = chip->info->ops->setup_errata(chip);
3974 if (err)
3975 goto unlock;
3976 }
3977
3978 /* Cache the cmode of each port. */
3979 for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
3980 if (chip->info->ops->port_get_cmode) {
3981 err = chip->info->ops->port_get_cmode(chip, i, &cmode);
3982 if (err)
3983 goto unlock;
3984
3985 chip->ports[i].cmode = cmode;
3986 }
3987 }
3988
3989 err = mv88e6xxx_vtu_setup(chip);
3990 if (err)
3991 goto unlock;
3992
3993 /* Must be called after mv88e6xxx_vtu_setup (which flushes the
3994 * VTU, thereby also flushing the STU).
3995 */
3996 err = mv88e6xxx_stu_setup(chip);
3997 if (err)
3998 goto unlock;
3999
4000 /* Setup Switch Port Registers */
4001 for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
4002 if (dsa_is_unused_port(ds, i))
4003 continue;
4004
4005 /* Prevent the use of an invalid port. */
4006 if (mv88e6xxx_is_invalid_port(chip, i)) {
4007 dev_err(chip->dev, "port %d is invalid\n", i);
4008 err = -EINVAL;
4009 goto unlock;
4010 }
4011
4012 err = mv88e6xxx_setup_port(chip, i);
4013 if (err)
4014 goto unlock;
4015 }
4016
4017 err = mv88e6xxx_irl_setup(chip);
4018 if (err)
4019 goto unlock;
4020
4021 err = mv88e6xxx_mac_setup(chip);
4022 if (err)
4023 goto unlock;
4024
4025 err = mv88e6xxx_phy_setup(chip);
4026 if (err)
4027 goto unlock;
4028
4029 err = mv88e6xxx_pvt_setup(chip);
4030 if (err)
4031 goto unlock;
4032
4033 err = mv88e6xxx_atu_setup(chip);
4034 if (err)
4035 goto unlock;
4036
4037 err = mv88e6xxx_broadcast_setup(chip, 0);
4038 if (err)
4039 goto unlock;
4040
4041 err = mv88e6xxx_pot_setup(chip);
4042 if (err)
4043 goto unlock;
4044
4045 err = mv88e6xxx_rmu_setup(chip);
4046 if (err)
4047 goto unlock;
4048
4049 err = mv88e6xxx_rsvd2cpu_setup(chip);
4050 if (err)
4051 goto unlock;
4052
4053 err = mv88e6xxx_trunk_setup(chip);
4054 if (err)
4055 goto unlock;
4056
4057 err = mv88e6xxx_devmap_setup(chip);
4058 if (err)
4059 goto unlock;
4060
4061 err = mv88e6xxx_pri_setup(chip);
4062 if (err)
4063 goto unlock;
4064
4065 /* Setup PTP Hardware Clock and timestamping */
4066 if (chip->info->ptp_support) {
4067 err = mv88e6xxx_ptp_setup(chip);
4068 if (err)
4069 goto unlock;
4070
4071 err = mv88e6xxx_hwtstamp_setup(chip);
4072 if (err)
4073 goto unlock;
4074 }
4075
4076 err = mv88e6xxx_stats_setup(chip);
4077 if (err)
4078 goto unlock;
4079
4080unlock:
4081 mv88e6xxx_reg_unlock(chip);
4082
4083 if (err)
2cb0658d 4084 goto out_mdios;
f1bee740
KK
4085
4086 /* Have to be called without holding the register lock, since
4087 * they take the devlink lock, and we later take the locks in
4088 * the reverse order when getting/setting parameters or
4089 * resource occupancy.
4090 */
4091 err = mv88e6xxx_setup_devlink_resources(ds);
4092 if (err)
2cb0658d 4093 goto out_mdios;
f1bee740
KK
4094
4095 err = mv88e6xxx_setup_devlink_params(ds);
4096 if (err)
4097 goto out_resources;
4098
4099 err = mv88e6xxx_setup_devlink_regions_global(ds);
4100 if (err)
4101 goto out_params;
4102
4103 return 0;
4104
4105out_params:
4106 mv88e6xxx_teardown_devlink_params(ds);
4107out_resources:
4108 dsa_devlink_resources_unregister(ds);
2cb0658d
KK
4109out_mdios:
4110 mv88e6xxx_mdios_unregister(chip);
f1bee740
KK
4111
4112 return err;
4113}
4114
4115static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port)
4116{
4117 return mv88e6xxx_setup_devlink_regions_port(ds, port);
4118}
4119
4120static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port)
4121{
4122 mv88e6xxx_teardown_devlink_regions_port(ds, port);
4123}
4124
855b1932
VD
4125static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
4126{
04bed143 4127 struct mv88e6xxx_chip *chip = ds->priv;
855b1932
VD
4128
4129 return chip->eeprom_len;
4130}
4131
855b1932
VD
4132static int mv88e6xxx_get_eeprom(struct dsa_switch *ds,
4133 struct ethtool_eeprom *eeprom, u8 *data)
4134{
04bed143 4135 struct mv88e6xxx_chip *chip = ds->priv;
855b1932
VD
4136 int err;
4137
ee4dc2e7
VD
4138 if (!chip->info->ops->get_eeprom)
4139 return -EOPNOTSUPP;
855b1932 4140
c9acece0 4141 mv88e6xxx_reg_lock(chip);
ee4dc2e7 4142 err = chip->info->ops->get_eeprom(chip, eeprom, data);
c9acece0 4143 mv88e6xxx_reg_unlock(chip);
855b1932
VD
4144
4145 if (err)
4146 return err;
4147
4148 eeprom->magic = 0xc3ec4951;
4149
4150 return 0;
4151}
4152
855b1932
VD
4153static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
4154 struct ethtool_eeprom *eeprom, u8 *data)
4155{
04bed143 4156 struct mv88e6xxx_chip *chip = ds->priv;
855b1932
VD
4157 int err;
4158
ee4dc2e7
VD
4159 if (!chip->info->ops->set_eeprom)
4160 return -EOPNOTSUPP;
4161
855b1932
VD
4162 if (eeprom->magic != 0xc3ec4951)
4163 return -EINVAL;
4164
c9acece0 4165 mv88e6xxx_reg_lock(chip);
ee4dc2e7 4166 err = chip->info->ops->set_eeprom(chip, eeprom, data);
c9acece0 4167 mv88e6xxx_reg_unlock(chip);
855b1932
VD
4168
4169 return err;
4170}
4171
b3469dd8 4172static const struct mv88e6xxx_ops mv88e6085_ops = {
4b325d8c 4173 /* MV88E6XXX_FAMILY_6097 */
93e18d61
VD
4174 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4175 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4176 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 4177 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
7e20cfb5
VD
4178 .phy_read = mv88e6185_phy_ppu_read,
4179 .phy_write = mv88e6185_phy_ppu_write,
08ef7f10 4180 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4181 .port_sync_link = mv88e6xxx_port_sync_link,
f365c6f7 4182 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 4183 .port_tag_remap = mv88e6095_port_tag_remap,
45f22f2f 4184 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4185 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4186 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4187 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4188 .port_set_ether_type = mv88e6351_port_set_ether_type,
ef70b111 4189 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4190 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4191 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4192 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4193 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4194 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4195 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4196 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4197 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4198 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4199 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4200 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4201 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4202 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4203 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4204 .pot_clear = mv88e6xxx_g2_pot_clear,
a199d8b6
VD
4205 .ppu_enable = mv88e6185_g1_ppu_enable,
4206 .ppu_disable = mv88e6185_g1_ppu_disable,
17e708ba 4207 .reset = mv88e6185_g1_reset,
9e5baf9b 4208 .rmu_disable = mv88e6085_g1_rmu_disable,
f1394b78 4209 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4210 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4211 .stu_getnext = mv88e6352_g1_stu_getnext,
4212 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d4ebf12b 4213 .phylink_get_caps = mv88e6185_phylink_get_caps,
1baf0fac 4214 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
b3469dd8
VD
4215};
4216
4217static const struct mv88e6xxx_ops mv88e6095_ops = {
4b325d8c 4218 /* MV88E6XXX_FAMILY_6095 */
93e18d61
VD
4219 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4220 .ip_pri_map = mv88e6085_g1_ip_pri_map,
b073d4e2 4221 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
7e20cfb5
VD
4222 .phy_read = mv88e6185_phy_ppu_read,
4223 .phy_write = mv88e6185_phy_ppu_write,
08ef7f10 4224 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4225 .port_sync_link = mv88e6185_port_sync_link,
f365c6f7 4226 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
56995cbc 4227 .port_set_frame_mode = mv88e6085_port_set_frame_mode,
a8b659e7
VO
4228 .port_set_ucast_flood = mv88e6185_port_set_forward_unknown,
4229 .port_set_mcast_flood = mv88e6185_port_set_default_forward,
a23b2961 4230 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
2d2e1dd2 4231 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4232 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4233 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4234 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4235 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4236 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4237 .stats_get_stats = mv88e6095_stats_get_stats,
51c901a7 4238 .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
f5be107c
CP
4239 .serdes_power = mv88e6185_serdes_power,
4240 .serdes_get_lane = mv88e6185_serdes_get_lane,
4241 .serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state,
a199d8b6
VD
4242 .ppu_enable = mv88e6185_g1_ppu_enable,
4243 .ppu_disable = mv88e6185_g1_ppu_disable,
17e708ba 4244 .reset = mv88e6185_g1_reset,
f1394b78 4245 .vtu_getnext = mv88e6185_g1_vtu_getnext,
0ad5daf6 4246 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
d0b78ab1 4247 .phylink_get_caps = mv88e6095_phylink_get_caps,
1baf0fac 4248 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
b3469dd8
VD
4249};
4250
7d381a02 4251static const struct mv88e6xxx_ops mv88e6097_ops = {
15da3cc8 4252 /* MV88E6XXX_FAMILY_6097 */
93e18d61
VD
4253 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4254 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4255 .irl_init_all = mv88e6352_g2_irl_init_all,
7d381a02 4256 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4257 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4258 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4259 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4260 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
7d381a02 4261 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4262 .port_sync_link = mv88e6185_port_sync_link,
f365c6f7 4263 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 4264 .port_tag_remap = mv88e6095_port_tag_remap,
585d42bb 4265 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4266 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4267 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4268 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4269 .port_set_ether_type = mv88e6351_port_set_ether_type,
ef70b111 4270 .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
0898432c 4271 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4272 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4273 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4274 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4275 .port_setup_message_port = mv88e6xxx_setup_message_port,
7d381a02 4276 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4277 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
7d381a02
SE
4278 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4279 .stats_get_strings = mv88e6095_stats_get_strings,
4280 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4281 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4282 .set_egress_port = mv88e6095_g1_set_egress_port,
91eaa475 4283 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4284 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
f5be107c
CP
4285 .serdes_power = mv88e6185_serdes_power,
4286 .serdes_get_lane = mv88e6185_serdes_get_lane,
4287 .serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state,
5c19bc8b
CP
4288 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
4289 .serdes_irq_enable = mv88e6097_serdes_irq_enable,
4290 .serdes_irq_status = mv88e6097_serdes_irq_status,
9e907d73 4291 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4292 .reset = mv88e6352_g1_reset,
9e5baf9b 4293 .rmu_disable = mv88e6085_g1_rmu_disable,
f1394b78 4294 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4295 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
d0b78ab1 4296 .phylink_get_caps = mv88e6095_phylink_get_caps,
49c98c1d
TW
4297 .stu_getnext = mv88e6352_g1_stu_getnext,
4298 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
1baf0fac 4299 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
7d381a02
SE
4300};
4301
b3469dd8 4302static const struct mv88e6xxx_ops mv88e6123_ops = {
4b325d8c 4303 /* MV88E6XXX_FAMILY_6165 */
93e18d61
VD
4304 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4305 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4306 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 4307 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4308 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4309 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4310 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4311 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4312 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4313 .port_sync_link = mv88e6xxx_port_sync_link,
f365c6f7 4314 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
56995cbc 4315 .port_set_frame_mode = mv88e6085_port_set_frame_mode,
a8b659e7
VO
4316 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4317 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
c8c94891 4318 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4319 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4320 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4321 .port_setup_message_port = mv88e6xxx_setup_message_port,
0ac64c39 4322 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 4323 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4324 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4325 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4326 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4327 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4328 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4329 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4330 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4331 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4332 .reset = mv88e6352_g1_reset,
23e8b470
AL
4333 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4334 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4335 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4336 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4337 .stu_getnext = mv88e6352_g1_stu_getnext,
4338 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d4ebf12b 4339 .phylink_get_caps = mv88e6185_phylink_get_caps,
1baf0fac 4340 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
b3469dd8
VD
4341};
4342
4343static const struct mv88e6xxx_ops mv88e6131_ops = {
4b325d8c 4344 /* MV88E6XXX_FAMILY_6185 */
93e18d61
VD
4345 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4346 .ip_pri_map = mv88e6085_g1_ip_pri_map,
b073d4e2 4347 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
7e20cfb5
VD
4348 .phy_read = mv88e6185_phy_ppu_read,
4349 .phy_write = mv88e6185_phy_ppu_write,
08ef7f10 4350 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4351 .port_sync_link = mv88e6xxx_port_sync_link,
f365c6f7 4352 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 4353 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 4354 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4355 .port_set_ucast_flood = mv88e6185_port_set_forward_unknown,
4356 .port_set_mcast_flood = mv88e6185_port_set_default_forward,
56995cbc 4357 .port_set_ether_type = mv88e6351_port_set_ether_type,
a23b2961 4358 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
cd782656 4359 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 4360 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4361 .port_pause_limit = mv88e6097_port_pause_limit,
54186b91 4362 .port_set_pause = mv88e6185_port_set_pause,
2d2e1dd2 4363 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4364 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4365 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4366 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4367 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4368 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4369 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4370 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4371 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4372 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4373 .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
a199d8b6 4374 .ppu_enable = mv88e6185_g1_ppu_enable,
02317e68 4375 .set_cascade_port = mv88e6185_g1_set_cascade_port,
a199d8b6 4376 .ppu_disable = mv88e6185_g1_ppu_disable,
17e708ba 4377 .reset = mv88e6185_g1_reset,
f1394b78 4378 .vtu_getnext = mv88e6185_g1_vtu_getnext,
0ad5daf6 4379 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
d4ebf12b 4380 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
4381};
4382
990e27b0
VD
4383static const struct mv88e6xxx_ops mv88e6141_ops = {
4384 /* MV88E6XXX_FAMILY_6341 */
93e18d61
VD
4385 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4386 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4387 .irl_init_all = mv88e6352_g2_irl_init_all,
990e27b0
VD
4388 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
4389 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
4390 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4391 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4392 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4393 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4394 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
990e27b0 4395 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4396 .port_sync_link = mv88e6xxx_port_sync_link,
990e27b0 4397 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 4398 .port_set_speed_duplex = mv88e6341_port_set_speed_duplex,
7cbbee05 4399 .port_max_speed_mode = mv88e6341_port_max_speed_mode,
990e27b0 4400 .port_tag_remap = mv88e6095_port_tag_remap,
7da467d8 4401 .port_set_policy = mv88e6352_port_set_policy,
990e27b0 4402 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4403 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4404 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
990e27b0 4405 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 4406 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
990e27b0 4407 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4408 .port_pause_limit = mv88e6097_port_pause_limit,
990e27b0
VD
4409 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
4410 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4411 .port_get_cmode = mv88e6352_port_get_cmode,
7a3007d2 4412 .port_set_cmode = mv88e6341_port_set_cmode,
121b8fe2 4413 .port_setup_message_port = mv88e6xxx_setup_message_port,
990e27b0 4414 .stats_snapshot = mv88e6390_g1_stats_snapshot,
11527f3c 4415 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
990e27b0
VD
4416 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
4417 .stats_get_strings = mv88e6320_stats_get_strings,
4418 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
4419 .set_cpu_port = mv88e6390_g1_set_cpu_port,
4420 .set_egress_port = mv88e6390_g1_set_egress_port,
990e27b0
VD
4421 .watchdog_ops = &mv88e6390_watchdog_ops,
4422 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 4423 .pot_clear = mv88e6xxx_g2_pot_clear,
990e27b0 4424 .reset = mv88e6352_g1_reset,
37094887 4425 .rmu_disable = mv88e6390_g1_rmu_disable,
c07fff34
MB
4426 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4427 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4428 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4429 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4430 .stu_getnext = mv88e6352_g1_stu_getnext,
4431 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d3cf7d8f
MB
4432 .serdes_power = mv88e6390_serdes_power,
4433 .serdes_get_lane = mv88e6341_serdes_get_lane,
a5a6858b
RK
4434 /* Check status register pause & lpa register */
4435 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
4436 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
4437 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
4438 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 4439 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 4440 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 4441 .serdes_irq_status = mv88e6390_serdes_irq_status,
a73ccd61 4442 .gpio_ops = &mv88e6352_gpio_ops,
a03b98d6
MB
4443 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
4444 .serdes_get_strings = mv88e6390_serdes_get_strings,
4445 .serdes_get_stats = mv88e6390_serdes_get_stats,
953b0dcb
MB
4446 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
4447 .serdes_get_regs = mv88e6390_serdes_get_regs,
d4ebf12b 4448 .phylink_get_caps = mv88e6341_phylink_get_caps,
990e27b0
VD
4449};
4450
b3469dd8 4451static const struct mv88e6xxx_ops mv88e6161_ops = {
4b325d8c 4452 /* MV88E6XXX_FAMILY_6165 */
93e18d61
VD
4453 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4454 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4455 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 4456 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4457 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4458 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4459 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4460 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4461 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4462 .port_sync_link = mv88e6xxx_port_sync_link,
f365c6f7 4463 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 4464 .port_tag_remap = mv88e6095_port_tag_remap,
45f22f2f 4465 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4466 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4467 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4468 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4469 .port_set_ether_type = mv88e6351_port_set_ether_type,
ef70b111 4470 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4471 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4472 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4473 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4474 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4475 .port_setup_message_port = mv88e6xxx_setup_message_port,
a6da21bb 4476 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4477 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4478 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4479 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4480 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4481 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4482 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4483 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4484 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4485 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4486 .reset = mv88e6352_g1_reset,
23e8b470
AL
4487 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4488 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4489 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4490 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4491 .stu_getnext = mv88e6352_g1_stu_getnext,
4492 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
a469a612 4493 .avb_ops = &mv88e6165_avb_ops,
dfa54348 4494 .ptp_ops = &mv88e6165_ptp_ops,
d4ebf12b 4495 .phylink_get_caps = mv88e6185_phylink_get_caps,
fe230361 4496 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
b3469dd8
VD
4497};
4498
4499static const struct mv88e6xxx_ops mv88e6165_ops = {
4b325d8c 4500 /* MV88E6XXX_FAMILY_6165 */
93e18d61
VD
4501 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4502 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4503 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 4504 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
efb3e74d
AL
4505 .phy_read = mv88e6165_phy_read,
4506 .phy_write = mv88e6165_phy_write,
08ef7f10 4507 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4508 .port_sync_link = mv88e6xxx_port_sync_link,
f365c6f7 4509 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
c8c94891 4510 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4511 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4512 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4513 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4514 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4515 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4516 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4517 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4518 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4519 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4520 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4521 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4522 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4523 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4524 .reset = mv88e6352_g1_reset,
23e8b470
AL
4525 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4526 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4527 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4528 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4529 .stu_getnext = mv88e6352_g1_stu_getnext,
4530 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
a469a612 4531 .avb_ops = &mv88e6165_avb_ops,
dfa54348 4532 .ptp_ops = &mv88e6165_ptp_ops,
d4ebf12b 4533 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
4534};
4535
4536static const struct mv88e6xxx_ops mv88e6171_ops = {
4b325d8c 4537 /* MV88E6XXX_FAMILY_6351 */
93e18d61
VD
4538 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4539 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4540 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 4541 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4542 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4543 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4544 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4545 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4546 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4547 .port_sync_link = mv88e6xxx_port_sync_link,
94d66ae6 4548 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 4549 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 4550 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 4551 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4552 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4553 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4554 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 4555 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 4556 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4557 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4558 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4559 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4560 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 4561 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4562 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 4563 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4564 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4565 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4566 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4567 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4568 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4569 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4570 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4571 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4572 .reset = mv88e6352_g1_reset,
23e8b470
AL
4573 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4574 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4575 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4576 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4577 .stu_getnext = mv88e6352_g1_stu_getnext,
4578 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d4ebf12b 4579 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
4580};
4581
4582static const struct mv88e6xxx_ops mv88e6172_ops = {
4b325d8c 4583 /* MV88E6XXX_FAMILY_6352 */
93e18d61
VD
4584 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4585 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4586 .irl_init_all = mv88e6352_g2_irl_init_all,
ee4dc2e7
VD
4587 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
4588 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
b073d4e2 4589 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4590 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4591 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4592 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4593 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4594 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4595 .port_sync_link = mv88e6xxx_port_sync_link,
a0a0f622 4596 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 4597 .port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
ef0a7318 4598 .port_tag_remap = mv88e6095_port_tag_remap,
f3a2cd32 4599 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4600 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4601 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4602 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4603 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 4604 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 4605 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4606 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4607 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4608 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4609 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 4610 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4611 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 4612 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4613 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4614 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4615 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4616 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4617 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4618 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4619 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4620 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4621 .reset = mv88e6352_g1_reset,
9e5baf9b 4622 .rmu_disable = mv88e6352_g1_rmu_disable,
23e8b470
AL
4623 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4624 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4625 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4626 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4627 .stu_getnext = mv88e6352_g1_stu_getnext,
4628 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
9db4a725 4629 .serdes_get_lane = mv88e6352_serdes_get_lane,
a5a6858b
RK
4630 .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state,
4631 .serdes_pcs_config = mv88e6352_serdes_pcs_config,
4632 .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart,
4633 .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up,
6d91782f 4634 .serdes_power = mv88e6352_serdes_power,
d3f88a24
AL
4635 .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
4636 .serdes_get_regs = mv88e6352_serdes_get_regs,
a73ccd61 4637 .gpio_ops = &mv88e6352_gpio_ops,
d4ebf12b 4638 .phylink_get_caps = mv88e6352_phylink_get_caps,
b3469dd8
VD
4639};
4640
4641static const struct mv88e6xxx_ops mv88e6175_ops = {
4b325d8c 4642 /* MV88E6XXX_FAMILY_6351 */
93e18d61
VD
4643 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4644 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4645 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 4646 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4647 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4648 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4649 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4650 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4651 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4652 .port_sync_link = mv88e6xxx_port_sync_link,
94d66ae6 4653 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 4654 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 4655 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 4656 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4657 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4658 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4659 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 4660 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 4661 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4662 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4663 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4664 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4665 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 4666 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4667 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 4668 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4669 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4670 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4671 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4672 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4673 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4674 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4675 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4676 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4677 .reset = mv88e6352_g1_reset,
23e8b470
AL
4678 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4679 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4680 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4681 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4682 .stu_getnext = mv88e6352_g1_stu_getnext,
4683 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d4ebf12b 4684 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
4685};
4686
4687static const struct mv88e6xxx_ops mv88e6176_ops = {
4b325d8c 4688 /* MV88E6XXX_FAMILY_6352 */
93e18d61
VD
4689 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4690 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4691 .irl_init_all = mv88e6352_g2_irl_init_all,
ee4dc2e7
VD
4692 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
4693 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
b073d4e2 4694 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4695 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4696 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4697 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4698 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4699 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4700 .port_sync_link = mv88e6xxx_port_sync_link,
a0a0f622 4701 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 4702 .port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
ef0a7318 4703 .port_tag_remap = mv88e6095_port_tag_remap,
f3a2cd32 4704 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4705 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4706 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4707 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4708 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 4709 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 4710 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 4711 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 4712 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4713 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4714 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 4715 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4716 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 4717 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4718 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4719 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4720 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4721 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4722 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4723 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4724 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 4725 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4726 .reset = mv88e6352_g1_reset,
9e5baf9b 4727 .rmu_disable = mv88e6352_g1_rmu_disable,
23e8b470
AL
4728 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4729 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 4730 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 4731 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
4732 .stu_getnext = mv88e6352_g1_stu_getnext,
4733 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
9db4a725 4734 .serdes_get_lane = mv88e6352_serdes_get_lane,
a5a6858b
RK
4735 .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state,
4736 .serdes_pcs_config = mv88e6352_serdes_pcs_config,
4737 .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart,
4738 .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up,
6d91782f 4739 .serdes_power = mv88e6352_serdes_power,
4241ef52 4740 .serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
61a46b41 4741 .serdes_irq_enable = mv88e6352_serdes_irq_enable,
907b9b9f 4742 .serdes_irq_status = mv88e6352_serdes_irq_status,
d3f88a24
AL
4743 .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
4744 .serdes_get_regs = mv88e6352_serdes_get_regs,
926eae60 4745 .serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
a73ccd61 4746 .gpio_ops = &mv88e6352_gpio_ops,
d4ebf12b 4747 .phylink_get_caps = mv88e6352_phylink_get_caps,
b3469dd8
VD
4748};
4749
4750static const struct mv88e6xxx_ops mv88e6185_ops = {
4b325d8c 4751 /* MV88E6XXX_FAMILY_6185 */
93e18d61
VD
4752 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4753 .ip_pri_map = mv88e6085_g1_ip_pri_map,
b073d4e2 4754 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
7e20cfb5
VD
4755 .phy_read = mv88e6185_phy_ppu_read,
4756 .phy_write = mv88e6185_phy_ppu_write,
08ef7f10 4757 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4758 .port_sync_link = mv88e6185_port_sync_link,
f365c6f7 4759 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
56995cbc 4760 .port_set_frame_mode = mv88e6085_port_set_frame_mode,
a8b659e7
VO
4761 .port_set_ucast_flood = mv88e6185_port_set_forward_unknown,
4762 .port_set_mcast_flood = mv88e6185_port_set_default_forward,
ef70b111 4763 .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
a23b2961 4764 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
54186b91 4765 .port_set_pause = mv88e6185_port_set_pause,
2d2e1dd2 4766 .port_get_cmode = mv88e6185_port_get_cmode,
121b8fe2 4767 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 4768 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
40cff8fc 4769 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
4770 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
4771 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 4772 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
4773 .set_cpu_port = mv88e6095_g1_set_cpu_port,
4774 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 4775 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 4776 .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
f5be107c
CP
4777 .serdes_power = mv88e6185_serdes_power,
4778 .serdes_get_lane = mv88e6185_serdes_get_lane,
4779 .serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state,
02317e68 4780 .set_cascade_port = mv88e6185_g1_set_cascade_port,
a199d8b6
VD
4781 .ppu_enable = mv88e6185_g1_ppu_enable,
4782 .ppu_disable = mv88e6185_g1_ppu_disable,
17e708ba 4783 .reset = mv88e6185_g1_reset,
f1394b78 4784 .vtu_getnext = mv88e6185_g1_vtu_getnext,
0ad5daf6 4785 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
d4ebf12b 4786 .phylink_get_caps = mv88e6185_phylink_get_caps,
1baf0fac 4787 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
b3469dd8
VD
4788};
4789
1a3b39ec 4790static const struct mv88e6xxx_ops mv88e6190_ops = {
4b325d8c 4791 /* MV88E6XXX_FAMILY_6390 */
ea89098e 4792 .setup_errata = mv88e6390_setup_errata,
cd8da8bb 4793 .irl_init_all = mv88e6390_g2_irl_init_all,
98fc3c6f
VD
4794 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
4795 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
1a3b39ec 4796 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4797 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4798 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4799 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4800 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1a3b39ec 4801 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4802 .port_sync_link = mv88e6xxx_port_sync_link,
1a3b39ec 4803 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 4804 .port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
7cbbee05 4805 .port_max_speed_mode = mv88e6390_port_max_speed_mode,
ef0a7318 4806 .port_tag_remap = mv88e6390_port_tag_remap,
f3a2cd32 4807 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4808 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4809 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4810 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4811 .port_set_ether_type = mv88e6351_port_set_ether_type,
e8b34c67 4812 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
0898432c 4813 .port_pause_limit = mv88e6390_port_pause_limit,
c8c94891 4814 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4815 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4816 .port_get_cmode = mv88e6352_port_get_cmode,
fdc71eea 4817 .port_set_cmode = mv88e6390_port_set_cmode,
121b8fe2 4818 .port_setup_message_port = mv88e6xxx_setup_message_port,
79523473 4819 .stats_snapshot = mv88e6390_g1_stats_snapshot,
de227387 4820 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
dfafe449
AL
4821 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
4822 .stats_get_strings = mv88e6320_stats_get_strings,
e0d8b615 4823 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
4824 .set_cpu_port = mv88e6390_g1_set_cpu_port,
4825 .set_egress_port = mv88e6390_g1_set_egress_port,
61303736 4826 .watchdog_ops = &mv88e6390_watchdog_ops,
6e55f698 4827 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 4828 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4829 .reset = mv88e6352_g1_reset,
9e5baf9b 4830 .rmu_disable = mv88e6390_g1_rmu_disable,
23e8b470
AL
4831 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4832 .atu_set_hash = mv88e6165_g1_atu_set_hash,
931d1822
VD
4833 .vtu_getnext = mv88e6390_g1_vtu_getnext,
4834 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
c050f5e9
TW
4835 .stu_getnext = mv88e6390_g1_stu_getnext,
4836 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
6335e9f2 4837 .serdes_power = mv88e6390_serdes_power,
17deaf5c 4838 .serdes_get_lane = mv88e6390_serdes_get_lane,
a5a6858b
RK
4839 /* Check status register pause & lpa register */
4840 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
4841 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
4842 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
4843 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 4844 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 4845 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 4846 .serdes_irq_status = mv88e6390_serdes_irq_status,
4262c38d
AL
4847 .serdes_get_strings = mv88e6390_serdes_get_strings,
4848 .serdes_get_stats = mv88e6390_serdes_get_stats,
bf3504ce
AL
4849 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
4850 .serdes_get_regs = mv88e6390_serdes_get_regs,
a73ccd61 4851 .gpio_ops = &mv88e6352_gpio_ops,
d4ebf12b 4852 .phylink_get_caps = mv88e6390_phylink_get_caps,
1a3b39ec
AL
4853};
4854
4855static const struct mv88e6xxx_ops mv88e6190x_ops = {
4b325d8c 4856 /* MV88E6XXX_FAMILY_6390 */
ea89098e 4857 .setup_errata = mv88e6390_setup_errata,
cd8da8bb 4858 .irl_init_all = mv88e6390_g2_irl_init_all,
98fc3c6f
VD
4859 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
4860 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
1a3b39ec 4861 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4862 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4863 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4864 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4865 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1a3b39ec 4866 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4867 .port_sync_link = mv88e6xxx_port_sync_link,
1a3b39ec 4868 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 4869 .port_set_speed_duplex = mv88e6390x_port_set_speed_duplex,
7cbbee05 4870 .port_max_speed_mode = mv88e6390x_port_max_speed_mode,
ef0a7318 4871 .port_tag_remap = mv88e6390_port_tag_remap,
f3a2cd32 4872 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 4873 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4874 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4875 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4876 .port_set_ether_type = mv88e6351_port_set_ether_type,
e8b34c67 4877 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
0898432c 4878 .port_pause_limit = mv88e6390_port_pause_limit,
c8c94891 4879 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4880 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4881 .port_get_cmode = mv88e6352_port_get_cmode,
fdc71eea 4882 .port_set_cmode = mv88e6390x_port_set_cmode,
121b8fe2 4883 .port_setup_message_port = mv88e6xxx_setup_message_port,
79523473 4884 .stats_snapshot = mv88e6390_g1_stats_snapshot,
de227387 4885 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
dfafe449
AL
4886 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
4887 .stats_get_strings = mv88e6320_stats_get_strings,
e0d8b615 4888 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
4889 .set_cpu_port = mv88e6390_g1_set_cpu_port,
4890 .set_egress_port = mv88e6390_g1_set_egress_port,
61303736 4891 .watchdog_ops = &mv88e6390_watchdog_ops,
6e55f698 4892 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 4893 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4894 .reset = mv88e6352_g1_reset,
9e5baf9b 4895 .rmu_disable = mv88e6390_g1_rmu_disable,
23e8b470
AL
4896 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4897 .atu_set_hash = mv88e6165_g1_atu_set_hash,
931d1822
VD
4898 .vtu_getnext = mv88e6390_g1_vtu_getnext,
4899 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
c050f5e9
TW
4900 .stu_getnext = mv88e6390_g1_stu_getnext,
4901 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
d3cf7d8f 4902 .serdes_power = mv88e6390_serdes_power,
17deaf5c 4903 .serdes_get_lane = mv88e6390x_serdes_get_lane,
a5a6858b
RK
4904 /* Check status register pause & lpa register */
4905 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
4906 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
4907 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
4908 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 4909 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 4910 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 4911 .serdes_irq_status = mv88e6390_serdes_irq_status,
4262c38d
AL
4912 .serdes_get_strings = mv88e6390_serdes_get_strings,
4913 .serdes_get_stats = mv88e6390_serdes_get_stats,
bf3504ce
AL
4914 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
4915 .serdes_get_regs = mv88e6390_serdes_get_regs,
a73ccd61 4916 .gpio_ops = &mv88e6352_gpio_ops,
d4ebf12b 4917 .phylink_get_caps = mv88e6390x_phylink_get_caps,
1a3b39ec
AL
4918};
4919
4920static const struct mv88e6xxx_ops mv88e6191_ops = {
4b325d8c 4921 /* MV88E6XXX_FAMILY_6390 */
ea89098e 4922 .setup_errata = mv88e6390_setup_errata,
cd8da8bb 4923 .irl_init_all = mv88e6390_g2_irl_init_all,
98fc3c6f
VD
4924 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
4925 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
1a3b39ec 4926 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4927 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4928 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4929 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4930 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1a3b39ec 4931 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4932 .port_sync_link = mv88e6xxx_port_sync_link,
1a3b39ec 4933 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 4934 .port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
7cbbee05 4935 .port_max_speed_mode = mv88e6390_port_max_speed_mode,
ef0a7318 4936 .port_tag_remap = mv88e6390_port_tag_remap,
56995cbc 4937 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
4938 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
4939 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 4940 .port_set_ether_type = mv88e6351_port_set_ether_type,
0898432c 4941 .port_pause_limit = mv88e6390_port_pause_limit,
c8c94891 4942 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 4943 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 4944 .port_get_cmode = mv88e6352_port_get_cmode,
fdc71eea 4945 .port_set_cmode = mv88e6390_port_set_cmode,
121b8fe2 4946 .port_setup_message_port = mv88e6xxx_setup_message_port,
79523473 4947 .stats_snapshot = mv88e6390_g1_stats_snapshot,
de227387 4948 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
dfafe449
AL
4949 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
4950 .stats_get_strings = mv88e6320_stats_get_strings,
e0d8b615 4951 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
4952 .set_cpu_port = mv88e6390_g1_set_cpu_port,
4953 .set_egress_port = mv88e6390_g1_set_egress_port,
61303736 4954 .watchdog_ops = &mv88e6390_watchdog_ops,
6e55f698 4955 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 4956 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 4957 .reset = mv88e6352_g1_reset,
9e5baf9b 4958 .rmu_disable = mv88e6390_g1_rmu_disable,
23e8b470
AL
4959 .atu_get_hash = mv88e6165_g1_atu_get_hash,
4960 .atu_set_hash = mv88e6165_g1_atu_set_hash,
931d1822
VD
4961 .vtu_getnext = mv88e6390_g1_vtu_getnext,
4962 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
c050f5e9
TW
4963 .stu_getnext = mv88e6390_g1_stu_getnext,
4964 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
6335e9f2 4965 .serdes_power = mv88e6390_serdes_power,
17deaf5c 4966 .serdes_get_lane = mv88e6390_serdes_get_lane,
a5a6858b
RK
4967 /* Check status register pause & lpa register */
4968 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
4969 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
4970 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
4971 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 4972 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 4973 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 4974 .serdes_irq_status = mv88e6390_serdes_irq_status,
4262c38d
AL
4975 .serdes_get_strings = mv88e6390_serdes_get_strings,
4976 .serdes_get_stats = mv88e6390_serdes_get_stats,
bf3504ce
AL
4977 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
4978 .serdes_get_regs = mv88e6390_serdes_get_regs,
6d2ac8ee
AL
4979 .avb_ops = &mv88e6390_avb_ops,
4980 .ptp_ops = &mv88e6352_ptp_ops,
d4ebf12b 4981 .phylink_get_caps = mv88e6390_phylink_get_caps,
1a3b39ec
AL
4982};
4983
b3469dd8 4984static const struct mv88e6xxx_ops mv88e6240_ops = {
4b325d8c 4985 /* MV88E6XXX_FAMILY_6352 */
93e18d61
VD
4986 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
4987 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 4988 .irl_init_all = mv88e6352_g2_irl_init_all,
ee4dc2e7
VD
4989 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
4990 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
b073d4e2 4991 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
4992 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
4993 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
4994 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
4995 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 4996 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 4997 .port_sync_link = mv88e6xxx_port_sync_link,
a0a0f622 4998 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 4999 .port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
ef0a7318 5000 .port_tag_remap = mv88e6095_port_tag_remap,
f3a2cd32 5001 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 5002 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5003 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5004 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5005 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5006 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5007 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5008 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 5009 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5010 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5011 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 5012 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 5013 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 5014 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
5015 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
5016 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 5017 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
5018 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5019 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 5020 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 5021 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 5022 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5023 .reset = mv88e6352_g1_reset,
9e5baf9b 5024 .rmu_disable = mv88e6352_g1_rmu_disable,
23e8b470
AL
5025 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5026 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 5027 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 5028 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
5029 .stu_getnext = mv88e6352_g1_stu_getnext,
5030 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
9db4a725 5031 .serdes_get_lane = mv88e6352_serdes_get_lane,
a5a6858b
RK
5032 .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state,
5033 .serdes_pcs_config = mv88e6352_serdes_pcs_config,
5034 .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart,
5035 .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up,
6d91782f 5036 .serdes_power = mv88e6352_serdes_power,
4241ef52 5037 .serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
61a46b41 5038 .serdes_irq_enable = mv88e6352_serdes_irq_enable,
907b9b9f 5039 .serdes_irq_status = mv88e6352_serdes_irq_status,
d3f88a24
AL
5040 .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
5041 .serdes_get_regs = mv88e6352_serdes_get_regs,
926eae60 5042 .serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
a73ccd61 5043 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5044 .avb_ops = &mv88e6352_avb_ops,
6d2ac8ee 5045 .ptp_ops = &mv88e6352_ptp_ops,
d4ebf12b 5046 .phylink_get_caps = mv88e6352_phylink_get_caps,
b3469dd8
VD
5047};
5048
1f71836f
RV
5049static const struct mv88e6xxx_ops mv88e6250_ops = {
5050 /* MV88E6XXX_FAMILY_6250 */
5051 .ieee_pri_map = mv88e6250_g1_ieee_pri_map,
5052 .ip_pri_map = mv88e6085_g1_ip_pri_map,
5053 .irl_init_all = mv88e6352_g2_irl_init_all,
5054 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
5055 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
5056 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5057 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5058 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5059 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5060 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1f71836f 5061 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5062 .port_sync_link = mv88e6xxx_port_sync_link,
1f71836f 5063 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 5064 .port_set_speed_duplex = mv88e6250_port_set_speed_duplex,
1f71836f
RV
5065 .port_tag_remap = mv88e6095_port_tag_remap,
5066 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5067 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5068 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
1f71836f
RV
5069 .port_set_ether_type = mv88e6351_port_set_ether_type,
5070 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
5071 .port_pause_limit = mv88e6097_port_pause_limit,
5072 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
1f71836f
RV
5073 .stats_snapshot = mv88e6320_g1_stats_snapshot,
5074 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
5075 .stats_get_sset_count = mv88e6250_stats_get_sset_count,
5076 .stats_get_strings = mv88e6250_stats_get_strings,
5077 .stats_get_stats = mv88e6250_stats_get_stats,
5078 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5079 .set_egress_port = mv88e6095_g1_set_egress_port,
5080 .watchdog_ops = &mv88e6250_watchdog_ops,
5081 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
5082 .pot_clear = mv88e6xxx_g2_pot_clear,
5083 .reset = mv88e6250_g1_reset,
67c9ed1c 5084 .vtu_getnext = mv88e6185_g1_vtu_getnext,
b28f3f3c 5085 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
71509614
HF
5086 .avb_ops = &mv88e6352_avb_ops,
5087 .ptp_ops = &mv88e6250_ptp_ops,
d4ebf12b 5088 .phylink_get_caps = mv88e6250_phylink_get_caps,
dd4144e5 5089 .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
1f71836f
RV
5090};
5091
1a3b39ec 5092static const struct mv88e6xxx_ops mv88e6290_ops = {
4b325d8c 5093 /* MV88E6XXX_FAMILY_6390 */
ea89098e 5094 .setup_errata = mv88e6390_setup_errata,
cd8da8bb 5095 .irl_init_all = mv88e6390_g2_irl_init_all,
98fc3c6f
VD
5096 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
5097 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
1a3b39ec 5098 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5099 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5100 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5101 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5102 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1a3b39ec 5103 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5104 .port_sync_link = mv88e6xxx_port_sync_link,
1a3b39ec 5105 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 5106 .port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
7cbbee05 5107 .port_max_speed_mode = mv88e6390_port_max_speed_mode,
ef0a7318 5108 .port_tag_remap = mv88e6390_port_tag_remap,
f3a2cd32 5109 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 5110 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5111 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5112 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5113 .port_set_ether_type = mv88e6351_port_set_ether_type,
0898432c 5114 .port_pause_limit = mv88e6390_port_pause_limit,
c8c94891 5115 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5116 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5117 .port_get_cmode = mv88e6352_port_get_cmode,
fdc71eea 5118 .port_set_cmode = mv88e6390_port_set_cmode,
121b8fe2 5119 .port_setup_message_port = mv88e6xxx_setup_message_port,
79523473 5120 .stats_snapshot = mv88e6390_g1_stats_snapshot,
de227387 5121 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
dfafe449
AL
5122 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5123 .stats_get_strings = mv88e6320_stats_get_strings,
e0d8b615 5124 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
5125 .set_cpu_port = mv88e6390_g1_set_cpu_port,
5126 .set_egress_port = mv88e6390_g1_set_egress_port,
61303736 5127 .watchdog_ops = &mv88e6390_watchdog_ops,
6e55f698 5128 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 5129 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5130 .reset = mv88e6352_g1_reset,
9e5baf9b 5131 .rmu_disable = mv88e6390_g1_rmu_disable,
23e8b470
AL
5132 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5133 .atu_set_hash = mv88e6165_g1_atu_set_hash,
931d1822
VD
5134 .vtu_getnext = mv88e6390_g1_vtu_getnext,
5135 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
c050f5e9
TW
5136 .stu_getnext = mv88e6390_g1_stu_getnext,
5137 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
6335e9f2 5138 .serdes_power = mv88e6390_serdes_power,
17deaf5c 5139 .serdes_get_lane = mv88e6390_serdes_get_lane,
a5a6858b
RK
5140 /* Check status register pause & lpa register */
5141 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
5142 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
5143 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
5144 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 5145 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 5146 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 5147 .serdes_irq_status = mv88e6390_serdes_irq_status,
4262c38d
AL
5148 .serdes_get_strings = mv88e6390_serdes_get_strings,
5149 .serdes_get_stats = mv88e6390_serdes_get_stats,
bf3504ce
AL
5150 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
5151 .serdes_get_regs = mv88e6390_serdes_get_regs,
a73ccd61 5152 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5153 .avb_ops = &mv88e6390_avb_ops,
9627c981 5154 .ptp_ops = &mv88e6390_ptp_ops,
d4ebf12b 5155 .phylink_get_caps = mv88e6390_phylink_get_caps,
1a3b39ec
AL
5156};
5157
b3469dd8 5158static const struct mv88e6xxx_ops mv88e6320_ops = {
4b325d8c 5159 /* MV88E6XXX_FAMILY_6320 */
93e18d61
VD
5160 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
5161 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 5162 .irl_init_all = mv88e6352_g2_irl_init_all,
ee4dc2e7
VD
5163 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
5164 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
b073d4e2 5165 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5166 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5167 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5168 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5169 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 5170 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5171 .port_sync_link = mv88e6xxx_port_sync_link,
91e87045 5172 .port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay,
f365c6f7 5173 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 5174 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 5175 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5176 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5177 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5178 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5179 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5180 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5181 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 5182 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5183 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5184 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 5185 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 5186 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 5187 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
5188 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5189 .stats_get_strings = mv88e6320_stats_get_strings,
052f947f 5190 .stats_get_stats = mv88e6320_stats_get_stats,
fa8d1179
VD
5191 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5192 .set_egress_port = mv88e6095_g1_set_egress_port,
9c7f37e5 5193 .watchdog_ops = &mv88e6390_watchdog_ops,
51c901a7 5194 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 5195 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5196 .reset = mv88e6352_g1_reset,
f1394b78 5197 .vtu_getnext = mv88e6185_g1_vtu_getnext,
0ad5daf6 5198 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
a73ccd61 5199 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5200 .avb_ops = &mv88e6352_avb_ops,
6d2ac8ee 5201 .ptp_ops = &mv88e6352_ptp_ops,
d4ebf12b 5202 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
5203};
5204
5205static const struct mv88e6xxx_ops mv88e6321_ops = {
bd807204 5206 /* MV88E6XXX_FAMILY_6320 */
93e18d61
VD
5207 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
5208 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 5209 .irl_init_all = mv88e6352_g2_irl_init_all,
ee4dc2e7
VD
5210 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
5211 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
b073d4e2 5212 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5213 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5214 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5215 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5216 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 5217 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5218 .port_sync_link = mv88e6xxx_port_sync_link,
91e87045 5219 .port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay,
f365c6f7 5220 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 5221 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 5222 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5223 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5224 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5225 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5226 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5227 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5228 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 5229 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5230 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5231 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 5232 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 5233 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 5234 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
5235 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5236 .stats_get_strings = mv88e6320_stats_get_strings,
052f947f 5237 .stats_get_stats = mv88e6320_stats_get_stats,
fa8d1179
VD
5238 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5239 .set_egress_port = mv88e6095_g1_set_egress_port,
9c7f37e5 5240 .watchdog_ops = &mv88e6390_watchdog_ops,
66863178 5241 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
17e708ba 5242 .reset = mv88e6352_g1_reset,
f1394b78 5243 .vtu_getnext = mv88e6185_g1_vtu_getnext,
0ad5daf6 5244 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
a73ccd61 5245 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5246 .avb_ops = &mv88e6352_avb_ops,
6d2ac8ee 5247 .ptp_ops = &mv88e6352_ptp_ops,
d4ebf12b 5248 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
5249};
5250
16e329ae
VD
5251static const struct mv88e6xxx_ops mv88e6341_ops = {
5252 /* MV88E6XXX_FAMILY_6341 */
93e18d61
VD
5253 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
5254 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 5255 .irl_init_all = mv88e6352_g2_irl_init_all,
16e329ae
VD
5256 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
5257 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
5258 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5259 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5260 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5261 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5262 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
16e329ae 5263 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5264 .port_sync_link = mv88e6xxx_port_sync_link,
16e329ae 5265 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 5266 .port_set_speed_duplex = mv88e6341_port_set_speed_duplex,
7cbbee05 5267 .port_max_speed_mode = mv88e6341_port_max_speed_mode,
16e329ae 5268 .port_tag_remap = mv88e6095_port_tag_remap,
7da467d8 5269 .port_set_policy = mv88e6352_port_set_policy,
16e329ae 5270 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5271 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5272 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
16e329ae 5273 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5274 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
16e329ae 5275 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5276 .port_pause_limit = mv88e6097_port_pause_limit,
16e329ae
VD
5277 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
5278 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5279 .port_get_cmode = mv88e6352_port_get_cmode,
7a3007d2 5280 .port_set_cmode = mv88e6341_port_set_cmode,
121b8fe2 5281 .port_setup_message_port = mv88e6xxx_setup_message_port,
16e329ae 5282 .stats_snapshot = mv88e6390_g1_stats_snapshot,
11527f3c 5283 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
16e329ae
VD
5284 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5285 .stats_get_strings = mv88e6320_stats_get_strings,
5286 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
5287 .set_cpu_port = mv88e6390_g1_set_cpu_port,
5288 .set_egress_port = mv88e6390_g1_set_egress_port,
16e329ae
VD
5289 .watchdog_ops = &mv88e6390_watchdog_ops,
5290 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 5291 .pot_clear = mv88e6xxx_g2_pot_clear,
16e329ae 5292 .reset = mv88e6352_g1_reset,
37094887 5293 .rmu_disable = mv88e6390_g1_rmu_disable,
c07fff34
MB
5294 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5295 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 5296 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 5297 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
5298 .stu_getnext = mv88e6352_g1_stu_getnext,
5299 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d3cf7d8f
MB
5300 .serdes_power = mv88e6390_serdes_power,
5301 .serdes_get_lane = mv88e6341_serdes_get_lane,
a5a6858b
RK
5302 /* Check status register pause & lpa register */
5303 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
5304 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
5305 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
5306 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 5307 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 5308 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 5309 .serdes_irq_status = mv88e6390_serdes_irq_status,
a73ccd61 5310 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5311 .avb_ops = &mv88e6390_avb_ops,
6d2ac8ee 5312 .ptp_ops = &mv88e6352_ptp_ops,
a03b98d6
MB
5313 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
5314 .serdes_get_strings = mv88e6390_serdes_get_strings,
5315 .serdes_get_stats = mv88e6390_serdes_get_stats,
953b0dcb
MB
5316 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
5317 .serdes_get_regs = mv88e6390_serdes_get_regs,
d4ebf12b 5318 .phylink_get_caps = mv88e6341_phylink_get_caps,
16e329ae
VD
5319};
5320
b3469dd8 5321static const struct mv88e6xxx_ops mv88e6350_ops = {
4b325d8c 5322 /* MV88E6XXX_FAMILY_6351 */
93e18d61
VD
5323 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
5324 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 5325 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 5326 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5327 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5328 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5329 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5330 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 5331 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5332 .port_sync_link = mv88e6xxx_port_sync_link,
94d66ae6 5333 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 5334 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 5335 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 5336 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5337 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5338 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5339 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5340 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5341 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5342 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 5343 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5344 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5345 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 5346 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 5347 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 5348 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
5349 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
5350 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 5351 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
5352 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5353 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 5354 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 5355 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 5356 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5357 .reset = mv88e6352_g1_reset,
23e8b470
AL
5358 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5359 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 5360 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 5361 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
5362 .stu_getnext = mv88e6352_g1_stu_getnext,
5363 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
d4ebf12b 5364 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
5365};
5366
5367static const struct mv88e6xxx_ops mv88e6351_ops = {
4b325d8c 5368 /* MV88E6XXX_FAMILY_6351 */
93e18d61
VD
5369 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
5370 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 5371 .irl_init_all = mv88e6352_g2_irl_init_all,
b073d4e2 5372 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5373 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5374 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5375 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5376 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 5377 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5378 .port_sync_link = mv88e6xxx_port_sync_link,
94d66ae6 5379 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 5380 .port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
ef0a7318 5381 .port_tag_remap = mv88e6095_port_tag_remap,
56995cbc 5382 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5383 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5384 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5385 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5386 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5387 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5388 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 5389 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5390 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5391 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 5392 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 5393 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 5394 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
5395 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
5396 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 5397 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
5398 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5399 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 5400 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 5401 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 5402 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5403 .reset = mv88e6352_g1_reset,
23e8b470
AL
5404 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5405 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 5406 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 5407 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
c050f5e9
TW
5408 .stu_getnext = mv88e6352_g1_stu_getnext,
5409 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
0d632c3d 5410 .avb_ops = &mv88e6352_avb_ops,
6d2ac8ee 5411 .ptp_ops = &mv88e6352_ptp_ops,
d4ebf12b 5412 .phylink_get_caps = mv88e6185_phylink_get_caps,
b3469dd8
VD
5413};
5414
5415static const struct mv88e6xxx_ops mv88e6352_ops = {
4b325d8c 5416 /* MV88E6XXX_FAMILY_6352 */
93e18d61
VD
5417 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
5418 .ip_pri_map = mv88e6085_g1_ip_pri_map,
cd8da8bb 5419 .irl_init_all = mv88e6352_g2_irl_init_all,
ee4dc2e7
VD
5420 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
5421 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
b073d4e2 5422 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5423 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5424 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5425 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5426 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
08ef7f10 5427 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5428 .port_sync_link = mv88e6xxx_port_sync_link,
a0a0f622 5429 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
f365c6f7 5430 .port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
ef0a7318 5431 .port_tag_remap = mv88e6095_port_tag_remap,
f3a2cd32 5432 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 5433 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5434 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5435 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5436 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5437 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5438 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5439 .port_pause_limit = mv88e6097_port_pause_limit,
c8c94891 5440 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5441 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5442 .port_get_cmode = mv88e6352_port_get_cmode,
121b8fe2 5443 .port_setup_message_port = mv88e6xxx_setup_message_port,
a605a0fe 5444 .stats_snapshot = mv88e6320_g1_stats_snapshot,
40cff8fc 5445 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
dfafe449
AL
5446 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
5447 .stats_get_strings = mv88e6095_stats_get_strings,
052f947f 5448 .stats_get_stats = mv88e6095_stats_get_stats,
fa8d1179
VD
5449 .set_cpu_port = mv88e6095_g1_set_cpu_port,
5450 .set_egress_port = mv88e6095_g1_set_egress_port,
fcd25166 5451 .watchdog_ops = &mv88e6097_watchdog_ops,
51c901a7 5452 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
9e907d73 5453 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5454 .reset = mv88e6352_g1_reset,
9e5baf9b 5455 .rmu_disable = mv88e6352_g1_rmu_disable,
23e8b470
AL
5456 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5457 .atu_set_hash = mv88e6165_g1_atu_set_hash,
f1394b78 5458 .vtu_getnext = mv88e6352_g1_vtu_getnext,
0ad5daf6 5459 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
49c98c1d
TW
5460 .stu_getnext = mv88e6352_g1_stu_getnext,
5461 .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
9db4a725 5462 .serdes_get_lane = mv88e6352_serdes_get_lane,
a5a6858b
RK
5463 .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state,
5464 .serdes_pcs_config = mv88e6352_serdes_pcs_config,
5465 .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart,
5466 .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up,
6d91782f 5467 .serdes_power = mv88e6352_serdes_power,
4241ef52 5468 .serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
61a46b41 5469 .serdes_irq_enable = mv88e6352_serdes_irq_enable,
907b9b9f 5470 .serdes_irq_status = mv88e6352_serdes_irq_status,
a73ccd61 5471 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5472 .avb_ops = &mv88e6352_avb_ops,
6d2ac8ee 5473 .ptp_ops = &mv88e6352_ptp_ops,
cda9f4aa
AL
5474 .serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
5475 .serdes_get_strings = mv88e6352_serdes_get_strings,
5476 .serdes_get_stats = mv88e6352_serdes_get_stats,
d3f88a24
AL
5477 .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
5478 .serdes_get_regs = mv88e6352_serdes_get_regs,
926eae60 5479 .serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
d4ebf12b 5480 .phylink_get_caps = mv88e6352_phylink_get_caps,
b3469dd8
VD
5481};
5482
1a3b39ec 5483static const struct mv88e6xxx_ops mv88e6390_ops = {
4b325d8c 5484 /* MV88E6XXX_FAMILY_6390 */
ea89098e 5485 .setup_errata = mv88e6390_setup_errata,
cd8da8bb 5486 .irl_init_all = mv88e6390_g2_irl_init_all,
98fc3c6f
VD
5487 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
5488 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
1a3b39ec 5489 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5490 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5491 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5492 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5493 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1a3b39ec 5494 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5495 .port_sync_link = mv88e6xxx_port_sync_link,
1a3b39ec 5496 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 5497 .port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
7cbbee05 5498 .port_max_speed_mode = mv88e6390_port_max_speed_mode,
ef0a7318 5499 .port_tag_remap = mv88e6390_port_tag_remap,
f3a2cd32 5500 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 5501 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5502 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5503 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5504 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5505 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5506 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5507 .port_pause_limit = mv88e6390_port_pause_limit,
c8c94891 5508 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5509 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5510 .port_get_cmode = mv88e6352_port_get_cmode,
fdc71eea 5511 .port_set_cmode = mv88e6390_port_set_cmode,
121b8fe2 5512 .port_setup_message_port = mv88e6xxx_setup_message_port,
79523473 5513 .stats_snapshot = mv88e6390_g1_stats_snapshot,
de227387 5514 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
dfafe449
AL
5515 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5516 .stats_get_strings = mv88e6320_stats_get_strings,
e0d8b615 5517 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
5518 .set_cpu_port = mv88e6390_g1_set_cpu_port,
5519 .set_egress_port = mv88e6390_g1_set_egress_port,
61303736 5520 .watchdog_ops = &mv88e6390_watchdog_ops,
6e55f698 5521 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 5522 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5523 .reset = mv88e6352_g1_reset,
9e5baf9b 5524 .rmu_disable = mv88e6390_g1_rmu_disable,
23e8b470
AL
5525 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5526 .atu_set_hash = mv88e6165_g1_atu_set_hash,
931d1822
VD
5527 .vtu_getnext = mv88e6390_g1_vtu_getnext,
5528 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
49c98c1d
TW
5529 .stu_getnext = mv88e6390_g1_stu_getnext,
5530 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
6335e9f2 5531 .serdes_power = mv88e6390_serdes_power,
17deaf5c 5532 .serdes_get_lane = mv88e6390_serdes_get_lane,
a5a6858b
RK
5533 /* Check status register pause & lpa register */
5534 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
5535 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
5536 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
5537 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 5538 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 5539 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 5540 .serdes_irq_status = mv88e6390_serdes_irq_status,
a73ccd61 5541 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5542 .avb_ops = &mv88e6390_avb_ops,
9627c981 5543 .ptp_ops = &mv88e6390_ptp_ops,
0df95287
NY
5544 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
5545 .serdes_get_strings = mv88e6390_serdes_get_strings,
5546 .serdes_get_stats = mv88e6390_serdes_get_stats,
bf3504ce
AL
5547 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
5548 .serdes_get_regs = mv88e6390_serdes_get_regs,
d4ebf12b 5549 .phylink_get_caps = mv88e6390_phylink_get_caps,
1a3b39ec
AL
5550};
5551
5552static const struct mv88e6xxx_ops mv88e6390x_ops = {
4b325d8c 5553 /* MV88E6XXX_FAMILY_6390 */
ea89098e 5554 .setup_errata = mv88e6390_setup_errata,
cd8da8bb 5555 .irl_init_all = mv88e6390_g2_irl_init_all,
98fc3c6f
VD
5556 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
5557 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
1a3b39ec 5558 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5559 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5560 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5561 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5562 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
1a3b39ec 5563 .port_set_link = mv88e6xxx_port_set_link,
4efe7662 5564 .port_sync_link = mv88e6xxx_port_sync_link,
1a3b39ec 5565 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
f365c6f7 5566 .port_set_speed_duplex = mv88e6390x_port_set_speed_duplex,
7cbbee05 5567 .port_max_speed_mode = mv88e6390x_port_max_speed_mode,
ef0a7318 5568 .port_tag_remap = mv88e6390_port_tag_remap,
f3a2cd32 5569 .port_set_policy = mv88e6352_port_set_policy,
56995cbc 5570 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
a8b659e7
VO
5571 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5572 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
56995cbc 5573 .port_set_ether_type = mv88e6351_port_set_ether_type,
cd782656 5574 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
ef70b111 5575 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
0898432c 5576 .port_pause_limit = mv88e6390_port_pause_limit,
c8c94891 5577 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
9dbfb4e1 5578 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2d2e1dd2 5579 .port_get_cmode = mv88e6352_port_get_cmode,
b3dce4da 5580 .port_set_cmode = mv88e6390x_port_set_cmode,
121b8fe2 5581 .port_setup_message_port = mv88e6xxx_setup_message_port,
79523473 5582 .stats_snapshot = mv88e6390_g1_stats_snapshot,
de227387 5583 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
dfafe449
AL
5584 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5585 .stats_get_strings = mv88e6320_stats_get_strings,
e0d8b615 5586 .stats_get_stats = mv88e6390_stats_get_stats,
fa8d1179
VD
5587 .set_cpu_port = mv88e6390_g1_set_cpu_port,
5588 .set_egress_port = mv88e6390_g1_set_egress_port,
61303736 5589 .watchdog_ops = &mv88e6390_watchdog_ops,
6e55f698 5590 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
9e907d73 5591 .pot_clear = mv88e6xxx_g2_pot_clear,
17e708ba 5592 .reset = mv88e6352_g1_reset,
9e5baf9b 5593 .rmu_disable = mv88e6390_g1_rmu_disable,
23e8b470
AL
5594 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5595 .atu_set_hash = mv88e6165_g1_atu_set_hash,
931d1822
VD
5596 .vtu_getnext = mv88e6390_g1_vtu_getnext,
5597 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
49c98c1d
TW
5598 .stu_getnext = mv88e6390_g1_stu_getnext,
5599 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
d3cf7d8f 5600 .serdes_power = mv88e6390_serdes_power,
17deaf5c 5601 .serdes_get_lane = mv88e6390x_serdes_get_lane,
a5a6858b
RK
5602 .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
5603 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
5604 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
5605 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
4241ef52 5606 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
61a46b41 5607 .serdes_irq_enable = mv88e6390_serdes_irq_enable,
907b9b9f 5608 .serdes_irq_status = mv88e6390_serdes_irq_status,
4262c38d
AL
5609 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
5610 .serdes_get_strings = mv88e6390_serdes_get_strings,
5611 .serdes_get_stats = mv88e6390_serdes_get_stats,
bf3504ce
AL
5612 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
5613 .serdes_get_regs = mv88e6390_serdes_get_regs,
a73ccd61 5614 .gpio_ops = &mv88e6352_gpio_ops,
0d632c3d 5615 .avb_ops = &mv88e6390_avb_ops,
9627c981 5616 .ptp_ops = &mv88e6390_ptp_ops,
d4ebf12b 5617 .phylink_get_caps = mv88e6390x_phylink_get_caps,
1a3b39ec
AL
5618};
5619
de776d0d
PS
5620static const struct mv88e6xxx_ops mv88e6393x_ops = {
5621 /* MV88E6XXX_FAMILY_6393 */
5622 .setup_errata = mv88e6393x_serdes_setup_errata,
5623 .irl_init_all = mv88e6390_g2_irl_init_all,
5624 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
5625 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
5626 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
743a19e3
AL
5627 .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
5628 .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
5629 .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
5630 .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
de776d0d
PS
5631 .port_set_link = mv88e6xxx_port_set_link,
5632 .port_sync_link = mv88e6xxx_port_sync_link,
5633 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
5634 .port_set_speed_duplex = mv88e6393x_port_set_speed_duplex,
5635 .port_max_speed_mode = mv88e6393x_port_max_speed_mode,
5636 .port_tag_remap = mv88e6390_port_tag_remap,
6584b260 5637 .port_set_policy = mv88e6393x_port_set_policy,
de776d0d
PS
5638 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
5639 .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
5640 .port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
5641 .port_set_ether_type = mv88e6393x_port_set_ether_type,
5642 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
5643 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
5644 .port_pause_limit = mv88e6390_port_pause_limit,
5645 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
5646 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
5647 .port_get_cmode = mv88e6352_port_get_cmode,
5648 .port_set_cmode = mv88e6393x_port_set_cmode,
5649 .port_setup_message_port = mv88e6xxx_setup_message_port,
5650 .port_set_upstream_port = mv88e6393x_port_set_upstream_port,
5651 .stats_snapshot = mv88e6390_g1_stats_snapshot,
5652 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
5653 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
5654 .stats_get_strings = mv88e6320_stats_get_strings,
5655 .stats_get_stats = mv88e6390_stats_get_stats,
5656 /* .set_cpu_port is missing because this family does not support a global
5657 * CPU port, only per port CPU port which is set via
5658 * .port_set_upstream_port method.
5659 */
5660 .set_egress_port = mv88e6393x_set_egress_port,
089b91a0 5661 .watchdog_ops = &mv88e6393x_watchdog_ops,
de776d0d
PS
5662 .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
5663 .pot_clear = mv88e6xxx_g2_pot_clear,
5664 .reset = mv88e6352_g1_reset,
5665 .rmu_disable = mv88e6390_g1_rmu_disable,
5666 .atu_get_hash = mv88e6165_g1_atu_get_hash,
5667 .atu_set_hash = mv88e6165_g1_atu_set_hash,
5668 .vtu_getnext = mv88e6390_g1_vtu_getnext,
5669 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
49c98c1d
TW
5670 .stu_getnext = mv88e6390_g1_stu_getnext,
5671 .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
de776d0d
PS
5672 .serdes_power = mv88e6393x_serdes_power,
5673 .serdes_get_lane = mv88e6393x_serdes_get_lane,
5674 .serdes_pcs_get_state = mv88e6393x_serdes_pcs_get_state,
5675 .serdes_pcs_config = mv88e6390_serdes_pcs_config,
5676 .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
5677 .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
5678 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
5679 .serdes_irq_enable = mv88e6393x_serdes_irq_enable,
5680 .serdes_irq_status = mv88e6393x_serdes_irq_status,
5681 /* TODO: serdes stats */
5682 .gpio_ops = &mv88e6352_gpio_ops,
5683 .avb_ops = &mv88e6390_avb_ops,
5684 .ptp_ops = &mv88e6352_ptp_ops,
d4ebf12b 5685 .phylink_get_caps = mv88e6393x_phylink_get_caps,
de776d0d
PS
5686};
5687
f81ec90f 5688static const struct mv88e6xxx_info mv88e6xxx_table[] = {
71d94a43
MS
5689 [MV88E6020] = {
5690 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6020,
5691 .family = MV88E6XXX_FAMILY_6250,
5692 .name = "Marvell 88E6020",
5693 .num_databases = 64,
5694 .num_ports = 4,
5695 .num_internal_phys = 2,
5696 .max_vid = 4095,
5697 .port_base_addr = 0x8,
5698 .phy_base_addr = 0x0,
5699 .global1_addr = 0xf,
5700 .global2_addr = 0x7,
5701 .age_time_coeff = 15000,
5702 .g1_irqs = 9,
372188c8
LM
5703 .g2_irqs = 5,
5704 .atu_move_port_mask = 0xf,
5705 .dual_chip = true,
5706 .ops = &mv88e6250_ops,
5707 },
5708
5709 [MV88E6071] = {
5710 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6071,
5711 .family = MV88E6XXX_FAMILY_6250,
5712 .name = "Marvell 88E6071",
5713 .num_databases = 64,
5714 .num_ports = 7,
5715 .num_internal_phys = 5,
5716 .max_vid = 4095,
5717 .port_base_addr = 0x08,
5718 .phy_base_addr = 0x00,
5719 .global1_addr = 0x0f,
5720 .global2_addr = 0x07,
5721 .age_time_coeff = 15000,
5722 .g1_irqs = 9,
71d94a43
MS
5723 .g2_irqs = 5,
5724 .atu_move_port_mask = 0xf,
5725 .dual_chip = true,
5726 .ops = &mv88e6250_ops,
5727 },
5728
f81ec90f 5729 [MV88E6085] = {
107fcc10 5730 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
f81ec90f
VD
5731 .family = MV88E6XXX_FAMILY_6097,
5732 .name = "Marvell 88E6085",
5733 .num_databases = 4096,
d9ea5620 5734 .num_macs = 8192,
f81ec90f 5735 .num_ports = 10,
bc393155 5736 .num_internal_phys = 5,
3cf3c846 5737 .max_vid = 4095,
c050f5e9 5738 .max_sid = 63,
9dddd478 5739 .port_base_addr = 0x10,
9255bacd 5740 .phy_base_addr = 0x0,
a935c052 5741 .global1_addr = 0x1b,
9069c13a 5742 .global2_addr = 0x1c,
acddbd21 5743 .age_time_coeff = 15000,
dc30c35b 5744 .g1_irqs = 8,
d6c5e6af 5745 .g2_irqs = 10,
e606ca36 5746 .atu_move_port_mask = 0xf,
f3645652 5747 .pvt = true,
b3e05aa1 5748 .multi_chip = true,
b3469dd8 5749 .ops = &mv88e6085_ops,
f81ec90f
VD
5750 },
5751
5752 [MV88E6095] = {
107fcc10 5753 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095,
f81ec90f
VD
5754 .family = MV88E6XXX_FAMILY_6095,
5755 .name = "Marvell 88E6095/88E6095F",
5756 .num_databases = 256,
d9ea5620 5757 .num_macs = 8192,
f81ec90f 5758 .num_ports = 11,
bc393155 5759 .num_internal_phys = 0,
3cf3c846 5760 .max_vid = 4095,
9dddd478 5761 .port_base_addr = 0x10,
9255bacd 5762 .phy_base_addr = 0x0,
a935c052 5763 .global1_addr = 0x1b,
9069c13a 5764 .global2_addr = 0x1c,
acddbd21 5765 .age_time_coeff = 15000,
dc30c35b 5766 .g1_irqs = 8,
e606ca36 5767 .atu_move_port_mask = 0xf,
b3e05aa1 5768 .multi_chip = true,
b3469dd8 5769 .ops = &mv88e6095_ops,
f81ec90f
VD
5770 },
5771
7d381a02 5772 [MV88E6097] = {
107fcc10 5773 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097,
7d381a02
SE
5774 .family = MV88E6XXX_FAMILY_6097,
5775 .name = "Marvell 88E6097/88E6097F",
5776 .num_databases = 4096,
d9ea5620 5777 .num_macs = 8192,
7d381a02 5778 .num_ports = 11,
bc393155 5779 .num_internal_phys = 8,
3cf3c846 5780 .max_vid = 4095,
49c98c1d 5781 .max_sid = 63,
7d381a02 5782 .port_base_addr = 0x10,
9255bacd 5783 .phy_base_addr = 0x0,
7d381a02 5784 .global1_addr = 0x1b,
9069c13a 5785 .global2_addr = 0x1c,
7d381a02 5786 .age_time_coeff = 15000,
c534178b 5787 .g1_irqs = 8,
d6c5e6af 5788 .g2_irqs = 10,
e606ca36 5789 .atu_move_port_mask = 0xf,
f3645652 5790 .pvt = true,
b3e05aa1 5791 .multi_chip = true,
670bb80f 5792 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
7d381a02
SE
5793 .ops = &mv88e6097_ops,
5794 },
5795
f81ec90f 5796 [MV88E6123] = {
107fcc10 5797 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123,
f81ec90f
VD
5798 .family = MV88E6XXX_FAMILY_6165,
5799 .name = "Marvell 88E6123",
5800 .num_databases = 4096,
d9ea5620 5801 .num_macs = 1024,
f81ec90f 5802 .num_ports = 3,
bc393155 5803 .num_internal_phys = 5,
3cf3c846 5804 .max_vid = 4095,
c050f5e9 5805 .max_sid = 63,
9dddd478 5806 .port_base_addr = 0x10,
9255bacd 5807 .phy_base_addr = 0x0,
a935c052 5808 .global1_addr = 0x1b,
9069c13a 5809 .global2_addr = 0x1c,
acddbd21 5810 .age_time_coeff = 15000,
dc30c35b 5811 .g1_irqs = 9,
d6c5e6af 5812 .g2_irqs = 10,
e606ca36 5813 .atu_move_port_mask = 0xf,
f3645652 5814 .pvt = true,
b3e05aa1 5815 .multi_chip = true,
670bb80f 5816 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 5817 .ops = &mv88e6123_ops,
f81ec90f
VD
5818 },
5819
5820 [MV88E6131] = {
107fcc10 5821 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131,
f81ec90f
VD
5822 .family = MV88E6XXX_FAMILY_6185,
5823 .name = "Marvell 88E6131",
5824 .num_databases = 256,
d9ea5620 5825 .num_macs = 8192,
f81ec90f 5826 .num_ports = 8,
bc393155 5827 .num_internal_phys = 0,
3cf3c846 5828 .max_vid = 4095,
9dddd478 5829 .port_base_addr = 0x10,
9255bacd 5830 .phy_base_addr = 0x0,
a935c052 5831 .global1_addr = 0x1b,
9069c13a 5832 .global2_addr = 0x1c,
acddbd21 5833 .age_time_coeff = 15000,
dc30c35b 5834 .g1_irqs = 9,
e606ca36 5835 .atu_move_port_mask = 0xf,
b3e05aa1 5836 .multi_chip = true,
b3469dd8 5837 .ops = &mv88e6131_ops,
f81ec90f
VD
5838 },
5839
990e27b0 5840 [MV88E6141] = {
107fcc10 5841 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
990e27b0 5842 .family = MV88E6XXX_FAMILY_6341,
79a68b26 5843 .name = "Marvell 88E6141",
990e27b0 5844 .num_databases = 4096,
d9ea5620 5845 .num_macs = 2048,
990e27b0 5846 .num_ports = 6,
bc393155 5847 .num_internal_phys = 5,
a73ccd61 5848 .num_gpio = 11,
3cf3c846 5849 .max_vid = 4095,
c050f5e9 5850 .max_sid = 63,
990e27b0 5851 .port_base_addr = 0x10,
9255bacd 5852 .phy_base_addr = 0x10,
990e27b0 5853 .global1_addr = 0x1b,
9069c13a 5854 .global2_addr = 0x1c,
990e27b0
VD
5855 .age_time_coeff = 3750,
5856 .atu_move_port_mask = 0x1f,
adfccf11 5857 .g1_irqs = 9,
d6c5e6af 5858 .g2_irqs = 10,
f3645652 5859 .pvt = true,
b3e05aa1 5860 .multi_chip = true,
670bb80f 5861 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
990e27b0
VD
5862 .ops = &mv88e6141_ops,
5863 },
5864
f81ec90f 5865 [MV88E6161] = {
107fcc10 5866 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161,
f81ec90f
VD
5867 .family = MV88E6XXX_FAMILY_6165,
5868 .name = "Marvell 88E6161",
5869 .num_databases = 4096,
d9ea5620 5870 .num_macs = 1024,
f81ec90f 5871 .num_ports = 6,
bc393155 5872 .num_internal_phys = 5,
3cf3c846 5873 .max_vid = 4095,
c050f5e9 5874 .max_sid = 63,
9dddd478 5875 .port_base_addr = 0x10,
9255bacd 5876 .phy_base_addr = 0x0,
a935c052 5877 .global1_addr = 0x1b,
9069c13a 5878 .global2_addr = 0x1c,
acddbd21 5879 .age_time_coeff = 15000,
dc30c35b 5880 .g1_irqs = 9,
d6c5e6af 5881 .g2_irqs = 10,
e606ca36 5882 .atu_move_port_mask = 0xf,
f3645652 5883 .pvt = true,
b3e05aa1 5884 .multi_chip = true,
670bb80f 5885 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
dfa54348 5886 .ptp_support = true,
b3469dd8 5887 .ops = &mv88e6161_ops,
f81ec90f
VD
5888 },
5889
5890 [MV88E6165] = {
107fcc10 5891 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165,
f81ec90f
VD
5892 .family = MV88E6XXX_FAMILY_6165,
5893 .name = "Marvell 88E6165",
5894 .num_databases = 4096,
d9ea5620 5895 .num_macs = 8192,
f81ec90f 5896 .num_ports = 6,
bc393155 5897 .num_internal_phys = 0,
3cf3c846 5898 .max_vid = 4095,
c050f5e9 5899 .max_sid = 63,
9dddd478 5900 .port_base_addr = 0x10,
9255bacd 5901 .phy_base_addr = 0x0,
a935c052 5902 .global1_addr = 0x1b,
9069c13a 5903 .global2_addr = 0x1c,
acddbd21 5904 .age_time_coeff = 15000,
dc30c35b 5905 .g1_irqs = 9,
d6c5e6af 5906 .g2_irqs = 10,
e606ca36 5907 .atu_move_port_mask = 0xf,
f3645652 5908 .pvt = true,
b3e05aa1 5909 .multi_chip = true,
dfa54348 5910 .ptp_support = true,
b3469dd8 5911 .ops = &mv88e6165_ops,
f81ec90f
VD
5912 },
5913
5914 [MV88E6171] = {
107fcc10 5915 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171,
f81ec90f
VD
5916 .family = MV88E6XXX_FAMILY_6351,
5917 .name = "Marvell 88E6171",
5918 .num_databases = 4096,
d9ea5620 5919 .num_macs = 8192,
f81ec90f 5920 .num_ports = 7,
bc393155 5921 .num_internal_phys = 5,
3cf3c846 5922 .max_vid = 4095,
c050f5e9 5923 .max_sid = 63,
9dddd478 5924 .port_base_addr = 0x10,
9255bacd 5925 .phy_base_addr = 0x0,
a935c052 5926 .global1_addr = 0x1b,
9069c13a 5927 .global2_addr = 0x1c,
acddbd21 5928 .age_time_coeff = 15000,
dc30c35b 5929 .g1_irqs = 9,
d6c5e6af 5930 .g2_irqs = 10,
e606ca36 5931 .atu_move_port_mask = 0xf,
f3645652 5932 .pvt = true,
b3e05aa1 5933 .multi_chip = true,
670bb80f 5934 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 5935 .ops = &mv88e6171_ops,
f81ec90f
VD
5936 },
5937
5938 [MV88E6172] = {
107fcc10 5939 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172,
f81ec90f
VD
5940 .family = MV88E6XXX_FAMILY_6352,
5941 .name = "Marvell 88E6172",
5942 .num_databases = 4096,
d9ea5620 5943 .num_macs = 8192,
f81ec90f 5944 .num_ports = 7,
bc393155 5945 .num_internal_phys = 5,
a73ccd61 5946 .num_gpio = 15,
3cf3c846 5947 .max_vid = 4095,
c050f5e9 5948 .max_sid = 63,
9dddd478 5949 .port_base_addr = 0x10,
9255bacd 5950 .phy_base_addr = 0x0,
a935c052 5951 .global1_addr = 0x1b,
9069c13a 5952 .global2_addr = 0x1c,
acddbd21 5953 .age_time_coeff = 15000,
dc30c35b 5954 .g1_irqs = 9,
d6c5e6af 5955 .g2_irqs = 10,
e606ca36 5956 .atu_move_port_mask = 0xf,
f3645652 5957 .pvt = true,
b3e05aa1 5958 .multi_chip = true,
670bb80f 5959 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 5960 .ops = &mv88e6172_ops,
f81ec90f
VD
5961 },
5962
5963 [MV88E6175] = {
107fcc10 5964 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175,
f81ec90f
VD
5965 .family = MV88E6XXX_FAMILY_6351,
5966 .name = "Marvell 88E6175",
5967 .num_databases = 4096,
d9ea5620 5968 .num_macs = 8192,
f81ec90f 5969 .num_ports = 7,
bc393155 5970 .num_internal_phys = 5,
3cf3c846 5971 .max_vid = 4095,
c050f5e9 5972 .max_sid = 63,
9dddd478 5973 .port_base_addr = 0x10,
9255bacd 5974 .phy_base_addr = 0x0,
a935c052 5975 .global1_addr = 0x1b,
9069c13a 5976 .global2_addr = 0x1c,
acddbd21 5977 .age_time_coeff = 15000,
dc30c35b 5978 .g1_irqs = 9,
d6c5e6af 5979 .g2_irqs = 10,
e606ca36 5980 .atu_move_port_mask = 0xf,
f3645652 5981 .pvt = true,
b3e05aa1 5982 .multi_chip = true,
670bb80f 5983 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 5984 .ops = &mv88e6175_ops,
f81ec90f
VD
5985 },
5986
5987 [MV88E6176] = {
107fcc10 5988 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176,
f81ec90f
VD
5989 .family = MV88E6XXX_FAMILY_6352,
5990 .name = "Marvell 88E6176",
5991 .num_databases = 4096,
d9ea5620 5992 .num_macs = 8192,
f81ec90f 5993 .num_ports = 7,
bc393155 5994 .num_internal_phys = 5,
a73ccd61 5995 .num_gpio = 15,
3cf3c846 5996 .max_vid = 4095,
c050f5e9 5997 .max_sid = 63,
9dddd478 5998 .port_base_addr = 0x10,
9255bacd 5999 .phy_base_addr = 0x0,
a935c052 6000 .global1_addr = 0x1b,
9069c13a 6001 .global2_addr = 0x1c,
acddbd21 6002 .age_time_coeff = 15000,
dc30c35b 6003 .g1_irqs = 9,
d6c5e6af 6004 .g2_irqs = 10,
e606ca36 6005 .atu_move_port_mask = 0xf,
f3645652 6006 .pvt = true,
b3e05aa1 6007 .multi_chip = true,
670bb80f 6008 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 6009 .ops = &mv88e6176_ops,
f81ec90f
VD
6010 },
6011
6012 [MV88E6185] = {
107fcc10 6013 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185,
f81ec90f
VD
6014 .family = MV88E6XXX_FAMILY_6185,
6015 .name = "Marvell 88E6185",
6016 .num_databases = 256,
d9ea5620 6017 .num_macs = 8192,
f81ec90f 6018 .num_ports = 10,
bc393155 6019 .num_internal_phys = 0,
3cf3c846 6020 .max_vid = 4095,
9dddd478 6021 .port_base_addr = 0x10,
9255bacd 6022 .phy_base_addr = 0x0,
a935c052 6023 .global1_addr = 0x1b,
9069c13a 6024 .global2_addr = 0x1c,
acddbd21 6025 .age_time_coeff = 15000,
dc30c35b 6026 .g1_irqs = 8,
e606ca36 6027 .atu_move_port_mask = 0xf,
b3e05aa1 6028 .multi_chip = true,
670bb80f 6029 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 6030 .ops = &mv88e6185_ops,
f81ec90f
VD
6031 },
6032
1a3b39ec 6033 [MV88E6190] = {
107fcc10 6034 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190,
1a3b39ec
AL
6035 .family = MV88E6XXX_FAMILY_6390,
6036 .name = "Marvell 88E6190",
6037 .num_databases = 4096,
d9ea5620 6038 .num_macs = 16384,
1a3b39ec 6039 .num_ports = 11, /* 10 + Z80 */
95150f29 6040 .num_internal_phys = 9,
a73ccd61 6041 .num_gpio = 16,
931d1822 6042 .max_vid = 8191,
49c98c1d 6043 .max_sid = 63,
1a3b39ec 6044 .port_base_addr = 0x0,
9255bacd 6045 .phy_base_addr = 0x0,
1a3b39ec 6046 .global1_addr = 0x1b,
9069c13a 6047 .global2_addr = 0x1c,
b91e055c 6048 .age_time_coeff = 3750,
1a3b39ec 6049 .g1_irqs = 9,
d6c5e6af 6050 .g2_irqs = 14,
f3645652 6051 .pvt = true,
b3e05aa1 6052 .multi_chip = true,
e606ca36 6053 .atu_move_port_mask = 0x1f,
1a3b39ec
AL
6054 .ops = &mv88e6190_ops,
6055 },
6056
6057 [MV88E6190X] = {
107fcc10 6058 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X,
1a3b39ec
AL
6059 .family = MV88E6XXX_FAMILY_6390,
6060 .name = "Marvell 88E6190X",
6061 .num_databases = 4096,
d9ea5620 6062 .num_macs = 16384,
1a3b39ec 6063 .num_ports = 11, /* 10 + Z80 */
95150f29 6064 .num_internal_phys = 9,
a73ccd61 6065 .num_gpio = 16,
931d1822 6066 .max_vid = 8191,
49c98c1d 6067 .max_sid = 63,
1a3b39ec 6068 .port_base_addr = 0x0,
9255bacd 6069 .phy_base_addr = 0x0,
1a3b39ec 6070 .global1_addr = 0x1b,
9069c13a 6071 .global2_addr = 0x1c,
b91e055c 6072 .age_time_coeff = 3750,
1a3b39ec 6073 .g1_irqs = 9,
d6c5e6af 6074 .g2_irqs = 14,
e606ca36 6075 .atu_move_port_mask = 0x1f,
f3645652 6076 .pvt = true,
b3e05aa1 6077 .multi_chip = true,
1a3b39ec
AL
6078 .ops = &mv88e6190x_ops,
6079 },
6080
6081 [MV88E6191] = {
107fcc10 6082 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191,
1a3b39ec
AL
6083 .family = MV88E6XXX_FAMILY_6390,
6084 .name = "Marvell 88E6191",
6085 .num_databases = 4096,
d9ea5620 6086 .num_macs = 16384,
1a3b39ec 6087 .num_ports = 11, /* 10 + Z80 */
95150f29 6088 .num_internal_phys = 9,
931d1822 6089 .max_vid = 8191,
49c98c1d 6090 .max_sid = 63,
1a3b39ec 6091 .port_base_addr = 0x0,
9255bacd 6092 .phy_base_addr = 0x0,
1a3b39ec 6093 .global1_addr = 0x1b,
9069c13a 6094 .global2_addr = 0x1c,
b91e055c 6095 .age_time_coeff = 3750,
443d5a1b 6096 .g1_irqs = 9,
d6c5e6af 6097 .g2_irqs = 14,
e606ca36 6098 .atu_move_port_mask = 0x1f,
f3645652 6099 .pvt = true,
b3e05aa1 6100 .multi_chip = true,
2fa8d3af 6101 .ptp_support = true,
2cf4cefb 6102 .ops = &mv88e6191_ops,
1a3b39ec
AL
6103 },
6104
de776d0d
PS
6105 [MV88E6191X] = {
6106 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191X,
6107 .family = MV88E6XXX_FAMILY_6393,
6108 .name = "Marvell 88E6191X",
6109 .num_databases = 4096,
6110 .num_ports = 11, /* 10 + Z80 */
2f934939
AL
6111 .num_internal_phys = 8,
6112 .internal_phys_offset = 1,
de776d0d 6113 .max_vid = 8191,
49c98c1d 6114 .max_sid = 63,
de776d0d
PS
6115 .port_base_addr = 0x0,
6116 .phy_base_addr = 0x0,
6117 .global1_addr = 0x1b,
6118 .global2_addr = 0x1c,
6119 .age_time_coeff = 3750,
6120 .g1_irqs = 10,
6121 .g2_irqs = 14,
6122 .atu_move_port_mask = 0x1f,
6123 .pvt = true,
6124 .multi_chip = true,
de776d0d
PS
6125 .ptp_support = true,
6126 .ops = &mv88e6393x_ops,
6127 },
6128
6129 [MV88E6193X] = {
6130 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6193X,
6131 .family = MV88E6XXX_FAMILY_6393,
6132 .name = "Marvell 88E6193X",
6133 .num_databases = 4096,
6134 .num_ports = 11, /* 10 + Z80 */
2f934939
AL
6135 .num_internal_phys = 8,
6136 .internal_phys_offset = 1,
de776d0d 6137 .max_vid = 8191,
49c98c1d 6138 .max_sid = 63,
de776d0d
PS
6139 .port_base_addr = 0x0,
6140 .phy_base_addr = 0x0,
6141 .global1_addr = 0x1b,
6142 .global2_addr = 0x1c,
6143 .age_time_coeff = 3750,
6144 .g1_irqs = 10,
6145 .g2_irqs = 14,
6146 .atu_move_port_mask = 0x1f,
6147 .pvt = true,
6148 .multi_chip = true,
de776d0d
PS
6149 .ptp_support = true,
6150 .ops = &mv88e6393x_ops,
6151 },
6152
49022647
HF
6153 [MV88E6220] = {
6154 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6220,
6155 .family = MV88E6XXX_FAMILY_6250,
6156 .name = "Marvell 88E6220",
6157 .num_databases = 64,
6158
6159 /* Ports 2-4 are not routed to pins
6160 * => usable ports 0, 1, 5, 6
6161 */
6162 .num_ports = 7,
6163 .num_internal_phys = 2,
c857486a 6164 .invalid_port_mask = BIT(2) | BIT(3) | BIT(4),
49022647
HF
6165 .max_vid = 4095,
6166 .port_base_addr = 0x08,
6167 .phy_base_addr = 0x00,
6168 .global1_addr = 0x0f,
6169 .global2_addr = 0x07,
6170 .age_time_coeff = 15000,
6171 .g1_irqs = 9,
6172 .g2_irqs = 10,
6173 .atu_move_port_mask = 0xf,
6174 .dual_chip = true,
71509614 6175 .ptp_support = true,
49022647
HF
6176 .ops = &mv88e6250_ops,
6177 },
6178
f81ec90f 6179 [MV88E6240] = {
107fcc10 6180 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240,
f81ec90f
VD
6181 .family = MV88E6XXX_FAMILY_6352,
6182 .name = "Marvell 88E6240",
6183 .num_databases = 4096,
d9ea5620 6184 .num_macs = 8192,
f81ec90f 6185 .num_ports = 7,
bc393155 6186 .num_internal_phys = 5,
a73ccd61 6187 .num_gpio = 15,
3cf3c846 6188 .max_vid = 4095,
c050f5e9 6189 .max_sid = 63,
9dddd478 6190 .port_base_addr = 0x10,
9255bacd 6191 .phy_base_addr = 0x0,
a935c052 6192 .global1_addr = 0x1b,
9069c13a 6193 .global2_addr = 0x1c,
acddbd21 6194 .age_time_coeff = 15000,
dc30c35b 6195 .g1_irqs = 9,
d6c5e6af 6196 .g2_irqs = 10,
e606ca36 6197 .atu_move_port_mask = 0xf,
f3645652 6198 .pvt = true,
b3e05aa1 6199 .multi_chip = true,
670bb80f 6200 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
2fa8d3af 6201 .ptp_support = true,
b3469dd8 6202 .ops = &mv88e6240_ops,
f81ec90f
VD
6203 },
6204
1f71836f
RV
6205 [MV88E6250] = {
6206 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
6207 .family = MV88E6XXX_FAMILY_6250,
6208 .name = "Marvell 88E6250",
6209 .num_databases = 64,
6210 .num_ports = 7,
6211 .num_internal_phys = 5,
6212 .max_vid = 4095,
6213 .port_base_addr = 0x08,
6214 .phy_base_addr = 0x00,
6215 .global1_addr = 0x0f,
6216 .global2_addr = 0x07,
6217 .age_time_coeff = 15000,
6218 .g1_irqs = 9,
6219 .g2_irqs = 10,
6220 .atu_move_port_mask = 0xf,
6221 .dual_chip = true,
71509614 6222 .ptp_support = true,
1f71836f
RV
6223 .ops = &mv88e6250_ops,
6224 },
6225
1a3b39ec 6226 [MV88E6290] = {
107fcc10 6227 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
1a3b39ec
AL
6228 .family = MV88E6XXX_FAMILY_6390,
6229 .name = "Marvell 88E6290",
6230 .num_databases = 4096,
6231 .num_ports = 11, /* 10 + Z80 */
95150f29 6232 .num_internal_phys = 9,
a73ccd61 6233 .num_gpio = 16,
931d1822 6234 .max_vid = 8191,
c050f5e9 6235 .max_sid = 63,
1a3b39ec 6236 .port_base_addr = 0x0,
9255bacd 6237 .phy_base_addr = 0x0,
1a3b39ec 6238 .global1_addr = 0x1b,
9069c13a 6239 .global2_addr = 0x1c,
b91e055c 6240 .age_time_coeff = 3750,
1a3b39ec 6241 .g1_irqs = 9,
d6c5e6af 6242 .g2_irqs = 14,
e606ca36 6243 .atu_move_port_mask = 0x1f,
f3645652 6244 .pvt = true,
b3e05aa1 6245 .multi_chip = true,
2fa8d3af 6246 .ptp_support = true,
1a3b39ec
AL
6247 .ops = &mv88e6290_ops,
6248 },
6249
f81ec90f 6250 [MV88E6320] = {
107fcc10 6251 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320,
f81ec90f
VD
6252 .family = MV88E6XXX_FAMILY_6320,
6253 .name = "Marvell 88E6320",
6254 .num_databases = 4096,
d9ea5620 6255 .num_macs = 8192,
f81ec90f 6256 .num_ports = 7,
bc393155 6257 .num_internal_phys = 5,
a73ccd61 6258 .num_gpio = 15,
3cf3c846 6259 .max_vid = 4095,
9dddd478 6260 .port_base_addr = 0x10,
9255bacd 6261 .phy_base_addr = 0x0,
a935c052 6262 .global1_addr = 0x1b,
9069c13a 6263 .global2_addr = 0x1c,
acddbd21 6264 .age_time_coeff = 15000,
dc30c35b 6265 .g1_irqs = 8,
bc393155 6266 .g2_irqs = 10,
e606ca36 6267 .atu_move_port_mask = 0xf,
f3645652 6268 .pvt = true,
b3e05aa1 6269 .multi_chip = true,
670bb80f 6270 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
2fa8d3af 6271 .ptp_support = true,
b3469dd8 6272 .ops = &mv88e6320_ops,
f81ec90f
VD
6273 },
6274
6275 [MV88E6321] = {
107fcc10 6276 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321,
f81ec90f
VD
6277 .family = MV88E6XXX_FAMILY_6320,
6278 .name = "Marvell 88E6321",
6279 .num_databases = 4096,
d9ea5620 6280 .num_macs = 8192,
f81ec90f 6281 .num_ports = 7,
bc393155 6282 .num_internal_phys = 5,
a73ccd61 6283 .num_gpio = 15,
3cf3c846 6284 .max_vid = 4095,
9dddd478 6285 .port_base_addr = 0x10,
9255bacd 6286 .phy_base_addr = 0x0,
a935c052 6287 .global1_addr = 0x1b,
9069c13a 6288 .global2_addr = 0x1c,
acddbd21 6289 .age_time_coeff = 15000,
dc30c35b 6290 .g1_irqs = 8,
bc393155 6291 .g2_irqs = 10,
e606ca36 6292 .atu_move_port_mask = 0xf,
b3e05aa1 6293 .multi_chip = true,
670bb80f 6294 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
2fa8d3af 6295 .ptp_support = true,
b3469dd8 6296 .ops = &mv88e6321_ops,
f81ec90f
VD
6297 },
6298
a75961d0 6299 [MV88E6341] = {
107fcc10 6300 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
a75961d0
GC
6301 .family = MV88E6XXX_FAMILY_6341,
6302 .name = "Marvell 88E6341",
6303 .num_databases = 4096,
d9ea5620 6304 .num_macs = 2048,
bc393155 6305 .num_internal_phys = 5,
a75961d0 6306 .num_ports = 6,
a73ccd61 6307 .num_gpio = 11,
3cf3c846 6308 .max_vid = 4095,
c050f5e9 6309 .max_sid = 63,
a75961d0 6310 .port_base_addr = 0x10,
9255bacd 6311 .phy_base_addr = 0x10,
a75961d0 6312 .global1_addr = 0x1b,
9069c13a 6313 .global2_addr = 0x1c,
a75961d0 6314 .age_time_coeff = 3750,
e606ca36 6315 .atu_move_port_mask = 0x1f,
adfccf11 6316 .g1_irqs = 9,
d6c5e6af 6317 .g2_irqs = 10,
f3645652 6318 .pvt = true,
b3e05aa1 6319 .multi_chip = true,
670bb80f 6320 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
2fa8d3af 6321 .ptp_support = true,
a75961d0
GC
6322 .ops = &mv88e6341_ops,
6323 },
6324
f81ec90f 6325 [MV88E6350] = {
107fcc10 6326 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350,
f81ec90f
VD
6327 .family = MV88E6XXX_FAMILY_6351,
6328 .name = "Marvell 88E6350",
6329 .num_databases = 4096,
d9ea5620 6330 .num_macs = 8192,
f81ec90f 6331 .num_ports = 7,
bc393155 6332 .num_internal_phys = 5,
3cf3c846 6333 .max_vid = 4095,
c050f5e9 6334 .max_sid = 63,
9dddd478 6335 .port_base_addr = 0x10,
9255bacd 6336 .phy_base_addr = 0x0,
a935c052 6337 .global1_addr = 0x1b,
9069c13a 6338 .global2_addr = 0x1c,
acddbd21 6339 .age_time_coeff = 15000,
dc30c35b 6340 .g1_irqs = 9,
d6c5e6af 6341 .g2_irqs = 10,
e606ca36 6342 .atu_move_port_mask = 0xf,
f3645652 6343 .pvt = true,
b3e05aa1 6344 .multi_chip = true,
670bb80f 6345 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 6346 .ops = &mv88e6350_ops,
f81ec90f
VD
6347 },
6348
6349 [MV88E6351] = {
107fcc10 6350 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6351,
f81ec90f
VD
6351 .family = MV88E6XXX_FAMILY_6351,
6352 .name = "Marvell 88E6351",
6353 .num_databases = 4096,
d9ea5620 6354 .num_macs = 8192,
f81ec90f 6355 .num_ports = 7,
bc393155 6356 .num_internal_phys = 5,
3cf3c846 6357 .max_vid = 4095,
c050f5e9 6358 .max_sid = 63,
9dddd478 6359 .port_base_addr = 0x10,
9255bacd 6360 .phy_base_addr = 0x0,
a935c052 6361 .global1_addr = 0x1b,
9069c13a 6362 .global2_addr = 0x1c,
acddbd21 6363 .age_time_coeff = 15000,
dc30c35b 6364 .g1_irqs = 9,
d6c5e6af 6365 .g2_irqs = 10,
e606ca36 6366 .atu_move_port_mask = 0xf,
f3645652 6367 .pvt = true,
b3e05aa1 6368 .multi_chip = true,
670bb80f 6369 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
b3469dd8 6370 .ops = &mv88e6351_ops,
f81ec90f
VD
6371 },
6372
6373 [MV88E6352] = {
107fcc10 6374 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352,
f81ec90f
VD
6375 .family = MV88E6XXX_FAMILY_6352,
6376 .name = "Marvell 88E6352",
6377 .num_databases = 4096,
d9ea5620 6378 .num_macs = 8192,
f81ec90f 6379 .num_ports = 7,
bc393155 6380 .num_internal_phys = 5,
a73ccd61 6381 .num_gpio = 15,
3cf3c846 6382 .max_vid = 4095,
49c98c1d 6383 .max_sid = 63,
9dddd478 6384 .port_base_addr = 0x10,
9255bacd 6385 .phy_base_addr = 0x0,
a935c052 6386 .global1_addr = 0x1b,
9069c13a 6387 .global2_addr = 0x1c,
acddbd21 6388 .age_time_coeff = 15000,
dc30c35b 6389 .g1_irqs = 9,
d6c5e6af 6390 .g2_irqs = 10,
e606ca36 6391 .atu_move_port_mask = 0xf,
f3645652 6392 .pvt = true,
b3e05aa1 6393 .multi_chip = true,
670bb80f 6394 .edsa_support = MV88E6XXX_EDSA_SUPPORTED,
2fa8d3af 6395 .ptp_support = true,
b3469dd8 6396 .ops = &mv88e6352_ops,
f81ec90f 6397 },
12899f29
AL
6398 [MV88E6361] = {
6399 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361,
6400 .family = MV88E6XXX_FAMILY_6393,
6401 .name = "Marvell 88E6361",
6402 .num_databases = 4096,
6403 .num_macs = 16384,
6404 .num_ports = 11,
6405 /* Ports 1, 2 and 8 are not routed */
6406 .invalid_port_mask = BIT(1) | BIT(2) | BIT(8),
6407 .num_internal_phys = 5,
6408 .internal_phys_offset = 3,
6409 .max_vid = 4095,
6410 .max_sid = 63,
6411 .port_base_addr = 0x0,
6412 .phy_base_addr = 0x0,
6413 .global1_addr = 0x1b,
6414 .global2_addr = 0x1c,
6415 .age_time_coeff = 3750,
6416 .g1_irqs = 10,
6417 .g2_irqs = 14,
6418 .atu_move_port_mask = 0x1f,
6419 .pvt = true,
6420 .multi_chip = true,
6421 .ptp_support = true,
6422 .ops = &mv88e6393x_ops,
6423 },
1a3b39ec 6424 [MV88E6390] = {
107fcc10 6425 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
1a3b39ec
AL
6426 .family = MV88E6XXX_FAMILY_6390,
6427 .name = "Marvell 88E6390",
6428 .num_databases = 4096,
d9ea5620 6429 .num_macs = 16384,
1a3b39ec 6430 .num_ports = 11, /* 10 + Z80 */
95150f29 6431 .num_internal_phys = 9,
a73ccd61 6432 .num_gpio = 16,
931d1822 6433 .max_vid = 8191,
49c98c1d 6434 .max_sid = 63,
1a3b39ec 6435 .port_base_addr = 0x0,
9255bacd 6436 .phy_base_addr = 0x0,
1a3b39ec 6437 .global1_addr = 0x1b,
9069c13a 6438 .global2_addr = 0x1c,
b91e055c 6439 .age_time_coeff = 3750,
1a3b39ec 6440 .g1_irqs = 9,
d6c5e6af 6441 .g2_irqs = 14,
e606ca36 6442 .atu_move_port_mask = 0x1f,
f3645652 6443 .pvt = true,
b3e05aa1 6444 .multi_chip = true,
670bb80f 6445 .edsa_support = MV88E6XXX_EDSA_UNDOCUMENTED,
2fa8d3af 6446 .ptp_support = true,
1a3b39ec
AL
6447 .ops = &mv88e6390_ops,
6448 },
6449 [MV88E6390X] = {
107fcc10 6450 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X,
1a3b39ec
AL
6451 .family = MV88E6XXX_FAMILY_6390,
6452 .name = "Marvell 88E6390X",
6453 .num_databases = 4096,
d9ea5620 6454 .num_macs = 16384,
1a3b39ec 6455 .num_ports = 11, /* 10 + Z80 */
95150f29 6456 .num_internal_phys = 9,
a73ccd61 6457 .num_gpio = 16,
931d1822 6458 .max_vid = 8191,
49c98c1d 6459 .max_sid = 63,
1a3b39ec 6460 .port_base_addr = 0x0,
9255bacd 6461 .phy_base_addr = 0x0,
1a3b39ec 6462 .global1_addr = 0x1b,
9069c13a 6463 .global2_addr = 0x1c,
b91e055c 6464 .age_time_coeff = 3750,
1a3b39ec 6465 .g1_irqs = 9,
d6c5e6af 6466 .g2_irqs = 14,
e606ca36 6467 .atu_move_port_mask = 0x1f,
f3645652 6468 .pvt = true,
b3e05aa1 6469 .multi_chip = true,
670bb80f 6470 .edsa_support = MV88E6XXX_EDSA_UNDOCUMENTED,
2fa8d3af 6471 .ptp_support = true,
1a3b39ec
AL
6472 .ops = &mv88e6390x_ops,
6473 },
de776d0d
PS
6474
6475 [MV88E6393X] = {
6476 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6393X,
6477 .family = MV88E6XXX_FAMILY_6393,
6478 .name = "Marvell 88E6393X",
6479 .num_databases = 4096,
6480 .num_ports = 11, /* 10 + Z80 */
2f934939
AL
6481 .num_internal_phys = 8,
6482 .internal_phys_offset = 1,
de776d0d 6483 .max_vid = 8191,
49c98c1d 6484 .max_sid = 63,
de776d0d
PS
6485 .port_base_addr = 0x0,
6486 .phy_base_addr = 0x0,
6487 .global1_addr = 0x1b,
6488 .global2_addr = 0x1c,
6489 .age_time_coeff = 3750,
6490 .g1_irqs = 10,
6491 .g2_irqs = 14,
6492 .atu_move_port_mask = 0x1f,
6493 .pvt = true,
6494 .multi_chip = true,
de776d0d
PS
6495 .ptp_support = true,
6496 .ops = &mv88e6393x_ops,
6497 },
f81ec90f
VD
6498};
6499
5f7c0367 6500static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
b9b37713 6501{
a439c061 6502 int i;
b9b37713 6503
5f7c0367
VD
6504 for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
6505 if (mv88e6xxx_table[i].prod_num == prod_num)
6506 return &mv88e6xxx_table[i];
b9b37713 6507
b9b37713
VD
6508 return NULL;
6509}
6510
fad09c73 6511static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
bc46a3d5
VD
6512{
6513 const struct mv88e6xxx_info *info;
8f6345b2
VD
6514 unsigned int prod_num, rev;
6515 u16 id;
6516 int err;
bc46a3d5 6517
c9acece0 6518 mv88e6xxx_reg_lock(chip);
107fcc10 6519 err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id);
c9acece0 6520 mv88e6xxx_reg_unlock(chip);
8f6345b2
VD
6521 if (err)
6522 return err;
bc46a3d5 6523
107fcc10
VD
6524 prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK;
6525 rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK;
bc46a3d5
VD
6526
6527 info = mv88e6xxx_lookup_info(prod_num);
6528 if (!info)
6529 return -ENODEV;
6530
caac8545 6531 /* Update the compatible info with the probed one */
fad09c73 6532 chip->info = info;
bc46a3d5 6533
fad09c73
VD
6534 dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n",
6535 chip->info->prod_num, chip->info->name, rev);
bc46a3d5
VD
6536
6537 return 0;
6538}
6539
5da66099
NR
6540static int mv88e6xxx_single_chip_detect(struct mv88e6xxx_chip *chip,
6541 struct mdio_device *mdiodev)
6542{
6543 int err;
6544
6545 /* dual_chip takes precedence over single/multi-chip modes */
6546 if (chip->info->dual_chip)
6547 return -EINVAL;
6548
6549 /* If the mdio addr is 16 indicating the first port address of a switch
6550 * (e.g. mv88e6*41) in single chip addressing mode the device may be
6551 * configured in single chip addressing mode. Setup the smi access as
6552 * single chip addressing mode and attempt to detect the model of the
6553 * switch, if this fails the device is not configured in single chip
6554 * addressing mode.
6555 */
6556 if (mdiodev->addr != 16)
6557 return -EINVAL;
6558
6559 err = mv88e6xxx_smi_init(chip, mdiodev->bus, 0);
6560 if (err)
6561 return err;
6562
6563 return mv88e6xxx_detect(chip);
6564}
6565
fad09c73 6566static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
469d729f 6567{
fad09c73 6568 struct mv88e6xxx_chip *chip;
469d729f 6569
fad09c73
VD
6570 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
6571 if (!chip)
469d729f
VD
6572 return NULL;
6573
fad09c73 6574 chip->dev = dev;
469d729f 6575
fad09c73 6576 mutex_init(&chip->reg_lock);
a3c53be5 6577 INIT_LIST_HEAD(&chip->mdios);
da7dc875 6578 idr_init(&chip->policies);
acaf4d2e 6579 INIT_LIST_HEAD(&chip->msts);
469d729f 6580
fad09c73 6581 return chip;
469d729f
VD
6582}
6583
5ed4e3eb 6584static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
4d776482
FF
6585 int port,
6586 enum dsa_tag_protocol m)
7b314362 6587{
04bed143 6588 struct mv88e6xxx_chip *chip = ds->priv;
2bbb33be 6589
670bb80f 6590 return chip->tag_protocol;
7b314362
AL
6591}
6592
bacf93b0 6593static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,
9a99bef5
TW
6594 enum dsa_tag_protocol proto)
6595{
6596 struct mv88e6xxx_chip *chip = ds->priv;
6597 enum dsa_tag_protocol old_protocol;
bacf93b0 6598 struct dsa_port *cpu_dp;
9a99bef5
TW
6599 int err;
6600
6601 switch (proto) {
6602 case DSA_TAG_PROTO_EDSA:
6603 switch (chip->info->edsa_support) {
6604 case MV88E6XXX_EDSA_UNSUPPORTED:
6605 return -EPROTONOSUPPORT;
6606 case MV88E6XXX_EDSA_UNDOCUMENTED:
6607 dev_warn(chip->dev, "Relying on undocumented EDSA tagging behavior\n");
6608 fallthrough;
6609 case MV88E6XXX_EDSA_SUPPORTED:
6610 break;
6611 }
6612 break;
6613 case DSA_TAG_PROTO_DSA:
6614 break;
6615 default:
6616 return -EPROTONOSUPPORT;
6617 }
6618
6619 old_protocol = chip->tag_protocol;
6620 chip->tag_protocol = proto;
6621
6622 mv88e6xxx_reg_lock(chip);
bacf93b0
VO
6623 dsa_switch_for_each_cpu_port(cpu_dp, ds) {
6624 err = mv88e6xxx_setup_port_mode(chip, cpu_dp->index);
6625 if (err) {
6626 mv88e6xxx_reg_unlock(chip);
6627 goto unwind;
6628 }
6629 }
9a99bef5
TW
6630 mv88e6xxx_reg_unlock(chip);
6631
bacf93b0
VO
6632 return 0;
6633
6634unwind:
6635 chip->tag_protocol = old_protocol;
6636
6637 mv88e6xxx_reg_lock(chip);
6638 dsa_switch_for_each_cpu_port_continue_reverse(cpu_dp, ds)
6639 mv88e6xxx_setup_port_mode(chip, cpu_dp->index);
6640 mv88e6xxx_reg_unlock(chip);
9a99bef5
TW
6641
6642 return err;
6643}
6644
a52b2da7 6645static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
c2693363
VO
6646 const struct switchdev_obj_port_mdb *mdb,
6647 struct dsa_db db)
7df8fbdd 6648{
04bed143 6649 struct mv88e6xxx_chip *chip = ds->priv;
a52b2da7 6650 int err;
7df8fbdd 6651
c9acece0 6652 mv88e6xxx_reg_lock(chip);
a52b2da7
VO
6653 err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
6654 MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC);
c9acece0 6655 mv88e6xxx_reg_unlock(chip);
a52b2da7
VO
6656
6657 return err;
7df8fbdd
VD
6658}
6659
6660static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
c2693363
VO
6661 const struct switchdev_obj_port_mdb *mdb,
6662 struct dsa_db db)
7df8fbdd 6663{
04bed143 6664 struct mv88e6xxx_chip *chip = ds->priv;
7df8fbdd
VD
6665 int err;
6666
c9acece0 6667 mv88e6xxx_reg_lock(chip);
d8291a95 6668 err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, 0);
c9acece0 6669 mv88e6xxx_reg_unlock(chip);
7df8fbdd
VD
6670
6671 return err;
6672}
6673
f0942e00
IT
6674static int mv88e6xxx_port_mirror_add(struct dsa_switch *ds, int port,
6675 struct dsa_mall_mirror_tc_entry *mirror,
0148bb50
VO
6676 bool ingress,
6677 struct netlink_ext_ack *extack)
f0942e00
IT
6678{
6679 enum mv88e6xxx_egress_direction direction = ingress ?
6680 MV88E6XXX_EGRESS_DIR_INGRESS :
6681 MV88E6XXX_EGRESS_DIR_EGRESS;
6682 struct mv88e6xxx_chip *chip = ds->priv;
6683 bool other_mirrors = false;
6684 int i;
6685 int err;
6686
f0942e00
IT
6687 mutex_lock(&chip->reg_lock);
6688 if ((ingress ? chip->ingress_dest_port : chip->egress_dest_port) !=
6689 mirror->to_local_port) {
6690 for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
6691 other_mirrors |= ingress ?
6692 chip->ports[i].mirror_ingress :
6693 chip->ports[i].mirror_egress;
6694
6695 /* Can't change egress port when other mirror is active */
6696 if (other_mirrors) {
6697 err = -EBUSY;
6698 goto out;
6699 }
6700
2fda45f0
MB
6701 err = mv88e6xxx_set_egress_port(chip, direction,
6702 mirror->to_local_port);
f0942e00
IT
6703 if (err)
6704 goto out;
6705 }
6706
6707 err = mv88e6xxx_port_set_mirror(chip, port, direction, true);
6708out:
6709 mutex_unlock(&chip->reg_lock);
6710
6711 return err;
6712}
6713
6714static void mv88e6xxx_port_mirror_del(struct dsa_switch *ds, int port,
6715 struct dsa_mall_mirror_tc_entry *mirror)
6716{
6717 enum mv88e6xxx_egress_direction direction = mirror->ingress ?
6718 MV88E6XXX_EGRESS_DIR_INGRESS :
6719 MV88E6XXX_EGRESS_DIR_EGRESS;
6720 struct mv88e6xxx_chip *chip = ds->priv;
6721 bool other_mirrors = false;
6722 int i;
6723
6724 mutex_lock(&chip->reg_lock);
6725 if (mv88e6xxx_port_set_mirror(chip, port, direction, false))
6726 dev_err(ds->dev, "p%d: failed to disable mirroring\n", port);
6727
6728 for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
6729 other_mirrors |= mirror->ingress ?
6730 chip->ports[i].mirror_ingress :
6731 chip->ports[i].mirror_egress;
6732
6733 /* Reset egress port when no other mirror is active */
6734 if (!other_mirrors) {
2fda45f0
MB
6735 if (mv88e6xxx_set_egress_port(chip, direction,
6736 dsa_upstream_port(ds, port)))
f0942e00
IT
6737 dev_err(ds->dev, "failed to set egress port\n");
6738 }
6739
6740 mutex_unlock(&chip->reg_lock);
6741}
6742
a8b659e7
VO
6743static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port,
6744 struct switchdev_brport_flags flags,
6745 struct netlink_ext_ack *extack)
6746{
6747 struct mv88e6xxx_chip *chip = ds->priv;
6748 const struct mv88e6xxx_ops *ops;
6749
8d1d8298 6750 if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
830763b9 6751 BR_BCAST_FLOOD | BR_PORT_LOCKED | BR_PORT_MAB))
a8b659e7
VO
6752 return -EINVAL;
6753
6754 ops = chip->info->ops;
6755
6756 if ((flags.mask & BR_FLOOD) && !ops->port_set_ucast_flood)
6757 return -EINVAL;
6758
6759 if ((flags.mask & BR_MCAST_FLOOD) && !ops->port_set_mcast_flood)
6760 return -EINVAL;
6761
6762 return 0;
6763}
6764
6765static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
6766 struct switchdev_brport_flags flags,
6767 struct netlink_ext_ack *extack)
4f85901f
RK
6768{
6769 struct mv88e6xxx_chip *chip = ds->priv;
e06a9af0 6770 int err = 0;
4f85901f 6771
c9acece0 6772 mv88e6xxx_reg_lock(chip);
a8b659e7 6773
041bd545
TW
6774 if (flags.mask & BR_LEARNING) {
6775 bool learning = !!(flags.val & BR_LEARNING);
6776 u16 pav = learning ? (1 << port) : 0;
6777
6778 err = mv88e6xxx_port_set_assoc_vector(chip, port, pav);
6779 if (err)
6780 goto out;
041bd545
TW
6781 }
6782
a8b659e7
VO
6783 if (flags.mask & BR_FLOOD) {
6784 bool unicast = !!(flags.val & BR_FLOOD);
6785
6786 err = chip->info->ops->port_set_ucast_flood(chip, port,
6787 unicast);
6788 if (err)
6789 goto out;
6790 }
6791
6792 if (flags.mask & BR_MCAST_FLOOD) {
6793 bool multicast = !!(flags.val & BR_MCAST_FLOOD);
6794
6795 err = chip->info->ops->port_set_mcast_flood(chip, port,
6796 multicast);
6797 if (err)
6798 goto out;
6799 }
6800
8d1d8298
TW
6801 if (flags.mask & BR_BCAST_FLOOD) {
6802 bool broadcast = !!(flags.val & BR_BCAST_FLOOD);
6803
6804 err = mv88e6xxx_port_broadcast_sync(chip, port, broadcast);
6805 if (err)
6806 goto out;
6807 }
6808
830763b9
HS
6809 if (flags.mask & BR_PORT_MAB) {
6810 bool mab = !!(flags.val & BR_PORT_MAB);
6811
6812 mv88e6xxx_port_set_mab(chip, port, mab);
6813 }
6814
34ea415f
HS
6815 if (flags.mask & BR_PORT_LOCKED) {
6816 bool locked = !!(flags.val & BR_PORT_LOCKED);
6817
6818 err = mv88e6xxx_port_set_lock(chip, port, locked);
6819 if (err)
6820 goto out;
6821 }
a8b659e7
VO
6822out:
6823 mv88e6xxx_reg_unlock(chip);
6824
6825 return err;
6826}
6827
57e661aa 6828static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds,
dedd6a00 6829 struct dsa_lag lag,
2e359b00
VO
6830 struct netdev_lag_upper_info *info,
6831 struct netlink_ext_ack *extack)
57e661aa 6832{
b80dc51b 6833 struct mv88e6xxx_chip *chip = ds->priv;
57e661aa 6834 struct dsa_port *dp;
dedd6a00 6835 int members = 0;
57e661aa 6836
2e359b00
VO
6837 if (!mv88e6xxx_has_lag(chip)) {
6838 NL_SET_ERR_MSG_MOD(extack, "Chip does not support LAG offload");
b80dc51b 6839 return false;
2e359b00 6840 }
b80dc51b 6841
dedd6a00 6842 if (!lag.id)
57e661aa
TW
6843 return false;
6844
dedd6a00 6845 dsa_lag_foreach_port(dp, ds->dst, &lag)
57e661aa
TW
6846 /* Includes the port joining the LAG */
6847 members++;
6848
2e359b00
VO
6849 if (members > 8) {
6850 NL_SET_ERR_MSG_MOD(extack,
6851 "Cannot offload more than 8 LAG ports");
57e661aa 6852 return false;
2e359b00 6853 }
57e661aa
TW
6854
6855 /* We could potentially relax this to include active
6856 * backup in the future.
6857 */
2e359b00
VO
6858 if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
6859 NL_SET_ERR_MSG_MOD(extack,
6860 "Can only offload LAG using hash TX type");
57e661aa 6861 return false;
2e359b00 6862 }
57e661aa
TW
6863
6864 /* Ideally we would also validate that the hash type matches
6865 * the hardware. Alas, this is always set to unknown on team
6866 * interfaces.
6867 */
6868 return true;
6869}
6870
dedd6a00 6871static int mv88e6xxx_lag_sync_map(struct dsa_switch *ds, struct dsa_lag lag)
57e661aa
TW
6872{
6873 struct mv88e6xxx_chip *chip = ds->priv;
6874 struct dsa_port *dp;
6875 u16 map = 0;
6876 int id;
6877
3d4a0a2a 6878 /* DSA LAG IDs are one-based, hardware is zero-based */
dedd6a00 6879 id = lag.id - 1;
57e661aa
TW
6880
6881 /* Build the map of all ports to distribute flows destined for
6882 * this LAG. This can be either a local user port, or a DSA
6883 * port if the LAG port is on a remote chip.
6884 */
dedd6a00 6885 dsa_lag_foreach_port(dp, ds->dst, &lag)
57e661aa
TW
6886 map |= BIT(dsa_towards_port(ds, dp->ds->index, dp->index));
6887
6888 return mv88e6xxx_g2_trunk_mapping_write(chip, id, map);
6889}
6890
6891static const u8 mv88e6xxx_lag_mask_table[8][8] = {
6892 /* Row number corresponds to the number of active members in a
6893 * LAG. Each column states which of the eight hash buckets are
6894 * mapped to the column:th port in the LAG.
6895 *
6896 * Example: In a LAG with three active ports, the second port
6897 * ([2][1]) would be selected for traffic mapped to buckets
6898 * 3,4,5 (0x38).
6899 */
6900 { 0xff, 0, 0, 0, 0, 0, 0, 0 },
6901 { 0x0f, 0xf0, 0, 0, 0, 0, 0, 0 },
6902 { 0x07, 0x38, 0xc0, 0, 0, 0, 0, 0 },
6903 { 0x03, 0x0c, 0x30, 0xc0, 0, 0, 0, 0 },
6904 { 0x03, 0x0c, 0x30, 0x40, 0x80, 0, 0, 0 },
6905 { 0x03, 0x0c, 0x10, 0x20, 0x40, 0x80, 0, 0 },
6906 { 0x03, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0 },
6907 { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
6908};
6909
6910static void mv88e6xxx_lag_set_port_mask(u16 *mask, int port,
6911 int num_tx, int nth)
6912{
6913 u8 active = 0;
6914 int i;
6915
6916 num_tx = num_tx <= 8 ? num_tx : 8;
6917 if (nth < num_tx)
6918 active = mv88e6xxx_lag_mask_table[num_tx - 1][nth];
6919
6920 for (i = 0; i < 8; i++) {
6921 if (BIT(i) & active)
6922 mask[i] |= BIT(port);
6923 }
6924}
6925
6926static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds)
6927{
6928 struct mv88e6xxx_chip *chip = ds->priv;
6929 unsigned int id, num_tx;
57e661aa 6930 struct dsa_port *dp;
dedd6a00 6931 struct dsa_lag *lag;
57e661aa
TW
6932 int i, err, nth;
6933 u16 mask[8];
6934 u16 ivec;
6935
6936 /* Assume no port is a member of any LAG. */
6937 ivec = BIT(mv88e6xxx_num_ports(chip)) - 1;
6938
6939 /* Disable all masks for ports that _are_ members of a LAG. */
b99dbdf0 6940 dsa_switch_for_each_port(dp, ds) {
dedd6a00 6941 if (!dp->lag)
57e661aa
TW
6942 continue;
6943
6944 ivec &= ~BIT(dp->index);
6945 }
6946
6947 for (i = 0; i < 8; i++)
6948 mask[i] = ivec;
6949
6950 /* Enable the correct subset of masks for all LAG ports that
6951 * are in the Tx set.
6952 */
6953 dsa_lags_foreach_id(id, ds->dst) {
dedd6a00
VO
6954 lag = dsa_lag_by_id(ds->dst, id);
6955 if (!lag)
57e661aa
TW
6956 continue;
6957
6958 num_tx = 0;
dedd6a00 6959 dsa_lag_foreach_port(dp, ds->dst, lag) {
57e661aa
TW
6960 if (dp->lag_tx_enabled)
6961 num_tx++;
6962 }
6963
6964 if (!num_tx)
6965 continue;
6966
6967 nth = 0;
dedd6a00 6968 dsa_lag_foreach_port(dp, ds->dst, lag) {
57e661aa
TW
6969 if (!dp->lag_tx_enabled)
6970 continue;
6971
6972 if (dp->ds == ds)
6973 mv88e6xxx_lag_set_port_mask(mask, dp->index,
6974 num_tx, nth);
6975
6976 nth++;
6977 }
6978 }
6979
6980 for (i = 0; i < 8; i++) {
6981 err = mv88e6xxx_g2_trunk_mask_write(chip, i, true, mask[i]);
6982 if (err)
6983 return err;
6984 }
6985
6986 return 0;
6987}
6988
6989static int mv88e6xxx_lag_sync_masks_map(struct dsa_switch *ds,
dedd6a00 6990 struct dsa_lag lag)
57e661aa
TW
6991{
6992 int err;
6993
6994 err = mv88e6xxx_lag_sync_masks(ds);
6995
6996 if (!err)
dedd6a00 6997 err = mv88e6xxx_lag_sync_map(ds, lag);
57e661aa
TW
6998
6999 return err;
7000}
7001
7002static int mv88e6xxx_port_lag_change(struct dsa_switch *ds, int port)
7003{
7004 struct mv88e6xxx_chip *chip = ds->priv;
7005 int err;
7006
7007 mv88e6xxx_reg_lock(chip);
7008 err = mv88e6xxx_lag_sync_masks(ds);
7009 mv88e6xxx_reg_unlock(chip);
7010 return err;
7011}
7012
7013static int mv88e6xxx_port_lag_join(struct dsa_switch *ds, int port,
dedd6a00 7014 struct dsa_lag lag,
2e359b00
VO
7015 struct netdev_lag_upper_info *info,
7016 struct netlink_ext_ack *extack)
57e661aa
TW
7017{
7018 struct mv88e6xxx_chip *chip = ds->priv;
7019 int err, id;
7020
2e359b00 7021 if (!mv88e6xxx_lag_can_offload(ds, lag, info, extack))
57e661aa
TW
7022 return -EOPNOTSUPP;
7023
3d4a0a2a 7024 /* DSA LAG IDs are one-based */
dedd6a00 7025 id = lag.id - 1;
57e661aa
TW
7026
7027 mv88e6xxx_reg_lock(chip);
7028
7029 err = mv88e6xxx_port_set_trunk(chip, port, true, id);
7030 if (err)
7031 goto err_unlock;
7032
dedd6a00 7033 err = mv88e6xxx_lag_sync_masks_map(ds, lag);
57e661aa
TW
7034 if (err)
7035 goto err_clear_trunk;
7036
7037 mv88e6xxx_reg_unlock(chip);
7038 return 0;
7039
7040err_clear_trunk:
7041 mv88e6xxx_port_set_trunk(chip, port, false, 0);
7042err_unlock:
7043 mv88e6xxx_reg_unlock(chip);
7044 return err;
7045}
7046
7047static int mv88e6xxx_port_lag_leave(struct dsa_switch *ds, int port,
dedd6a00 7048 struct dsa_lag lag)
57e661aa
TW
7049{
7050 struct mv88e6xxx_chip *chip = ds->priv;
7051 int err_sync, err_trunk;
7052
7053 mv88e6xxx_reg_lock(chip);
dedd6a00 7054 err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag);
57e661aa
TW
7055 err_trunk = mv88e6xxx_port_set_trunk(chip, port, false, 0);
7056 mv88e6xxx_reg_unlock(chip);
7057 return err_sync ? : err_trunk;
7058}
7059
7060static int mv88e6xxx_crosschip_lag_change(struct dsa_switch *ds, int sw_index,
7061 int port)
7062{
7063 struct mv88e6xxx_chip *chip = ds->priv;
7064 int err;
7065
7066 mv88e6xxx_reg_lock(chip);
7067 err = mv88e6xxx_lag_sync_masks(ds);
7068 mv88e6xxx_reg_unlock(chip);
7069 return err;
7070}
7071
7072static int mv88e6xxx_crosschip_lag_join(struct dsa_switch *ds, int sw_index,
dedd6a00 7073 int port, struct dsa_lag lag,
2e359b00
VO
7074 struct netdev_lag_upper_info *info,
7075 struct netlink_ext_ack *extack)
57e661aa
TW
7076{
7077 struct mv88e6xxx_chip *chip = ds->priv;
7078 int err;
7079
2e359b00 7080 if (!mv88e6xxx_lag_can_offload(ds, lag, info, extack))
57e661aa
TW
7081 return -EOPNOTSUPP;
7082
7083 mv88e6xxx_reg_lock(chip);
7084
dedd6a00 7085 err = mv88e6xxx_lag_sync_masks_map(ds, lag);
57e661aa
TW
7086 if (err)
7087 goto unlock;
7088
7089 err = mv88e6xxx_pvt_map(chip, sw_index, port);
7090
7091unlock:
7092 mv88e6xxx_reg_unlock(chip);
7093 return err;
7094}
7095
7096static int mv88e6xxx_crosschip_lag_leave(struct dsa_switch *ds, int sw_index,
dedd6a00 7097 int port, struct dsa_lag lag)
57e661aa
TW
7098{
7099 struct mv88e6xxx_chip *chip = ds->priv;
7100 int err_sync, err_pvt;
7101
7102 mv88e6xxx_reg_lock(chip);
dedd6a00 7103 err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag);
57e661aa
TW
7104 err_pvt = mv88e6xxx_pvt_map(chip, sw_index, port);
7105 mv88e6xxx_reg_unlock(chip);
7106 return err_sync ? : err_pvt;
7107}
7108
a82f67af 7109static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
7b314362 7110 .get_tag_protocol = mv88e6xxx_get_tag_protocol,
9a99bef5 7111 .change_tag_protocol = mv88e6xxx_change_tag_protocol,
f81ec90f 7112 .setup = mv88e6xxx_setup,
23e8b470 7113 .teardown = mv88e6xxx_teardown,
fd292c18
VO
7114 .port_setup = mv88e6xxx_port_setup,
7115 .port_teardown = mv88e6xxx_port_teardown,
d4ebf12b 7116 .phylink_get_caps = mv88e6xxx_get_caps,
a5a6858b 7117 .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state,
267d7692 7118 .phylink_mac_prepare = mv88e6xxx_mac_prepare,
c9a2356f 7119 .phylink_mac_config = mv88e6xxx_mac_config,
267d7692 7120 .phylink_mac_finish = mv88e6xxx_mac_finish,
a5a6858b 7121 .phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart,
c9a2356f
RK
7122 .phylink_mac_link_down = mv88e6xxx_mac_link_down,
7123 .phylink_mac_link_up = mv88e6xxx_mac_link_up,
f81ec90f
VD
7124 .get_strings = mv88e6xxx_get_strings,
7125 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
7126 .get_sset_count = mv88e6xxx_get_sset_count,
04aca993
AL
7127 .port_enable = mv88e6xxx_port_enable,
7128 .port_disable = mv88e6xxx_port_disable,
2a550aec
AL
7129 .port_max_mtu = mv88e6xxx_get_max_mtu,
7130 .port_change_mtu = mv88e6xxx_change_mtu,
08f50061
VD
7131 .get_mac_eee = mv88e6xxx_get_mac_eee,
7132 .set_mac_eee = mv88e6xxx_set_mac_eee,
f8cd8753 7133 .get_eeprom_len = mv88e6xxx_get_eeprom_len,
f81ec90f
VD
7134 .get_eeprom = mv88e6xxx_get_eeprom,
7135 .set_eeprom = mv88e6xxx_set_eeprom,
7136 .get_regs_len = mv88e6xxx_get_regs_len,
7137 .get_regs = mv88e6xxx_get_regs,
da7dc875
VD
7138 .get_rxnfc = mv88e6xxx_get_rxnfc,
7139 .set_rxnfc = mv88e6xxx_set_rxnfc,
2cfcd964 7140 .set_ageing_time = mv88e6xxx_set_ageing_time,
f81ec90f
VD
7141 .port_bridge_join = mv88e6xxx_port_bridge_join,
7142 .port_bridge_leave = mv88e6xxx_port_bridge_leave,
a8b659e7
VO
7143 .port_pre_bridge_flags = mv88e6xxx_port_pre_bridge_flags,
7144 .port_bridge_flags = mv88e6xxx_port_bridge_flags,
f81ec90f 7145 .port_stp_state_set = mv88e6xxx_port_stp_state_set,
acaf4d2e 7146 .port_mst_state_set = mv88e6xxx_port_mst_state_set,
749efcb8 7147 .port_fast_age = mv88e6xxx_port_fast_age,
acaf4d2e 7148 .port_vlan_fast_age = mv88e6xxx_port_vlan_fast_age,
f81ec90f 7149 .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
f81ec90f
VD
7150 .port_vlan_add = mv88e6xxx_port_vlan_add,
7151 .port_vlan_del = mv88e6xxx_port_vlan_del,
acaf4d2e 7152 .vlan_msti_set = mv88e6xxx_vlan_msti_set,
411a1476
MB
7153 .port_fdb_add = mv88e6xxx_port_fdb_add,
7154 .port_fdb_del = mv88e6xxx_port_fdb_del,
7155 .port_fdb_dump = mv88e6xxx_port_fdb_dump,
7156 .port_mdb_add = mv88e6xxx_port_mdb_add,
7157 .port_mdb_del = mv88e6xxx_port_mdb_del,
f0942e00
IT
7158 .port_mirror_add = mv88e6xxx_port_mirror_add,
7159 .port_mirror_del = mv88e6xxx_port_mirror_del,
aec5ac88
VD
7160 .crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join,
7161 .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave,
c6fe0ad2
BS
7162 .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set,
7163 .port_hwtstamp_get = mv88e6xxx_port_hwtstamp_get,
7164 .port_txtstamp = mv88e6xxx_port_txtstamp,
7165 .port_rxtstamp = mv88e6xxx_port_rxtstamp,
7166 .get_ts_info = mv88e6xxx_get_ts_info,
23e8b470
AL
7167 .devlink_param_get = mv88e6xxx_devlink_param_get,
7168 .devlink_param_set = mv88e6xxx_devlink_param_set,
93157307 7169 .devlink_info_get = mv88e6xxx_devlink_info_get,
57e661aa
TW
7170 .port_lag_change = mv88e6xxx_port_lag_change,
7171 .port_lag_join = mv88e6xxx_port_lag_join,
7172 .port_lag_leave = mv88e6xxx_port_lag_leave,
7173 .crosschip_lag_change = mv88e6xxx_crosschip_lag_change,
7174 .crosschip_lag_join = mv88e6xxx_crosschip_lag_join,
7175 .crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave,
f81ec90f
VD
7176};
7177
55ed0ce0 7178static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
b7e66a5f 7179{
fad09c73 7180 struct device *dev = chip->dev;
b7e66a5f
VD
7181 struct dsa_switch *ds;
7182
7e99e347 7183 ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
b7e66a5f
VD
7184 if (!ds)
7185 return -ENOMEM;
7186
7e99e347
VD
7187 ds->dev = dev;
7188 ds->num_ports = mv88e6xxx_num_ports(chip);
fad09c73 7189 ds->priv = chip;
877b7cb0 7190 ds->dev = dev;
9d490b4e 7191 ds->ops = &mv88e6xxx_switch_ops;
9ff74f24
VD
7192 ds->ageing_time_min = chip->info->age_time_coeff;
7193 ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
b7e66a5f 7194
57e661aa
TW
7195 /* Some chips support up to 32, but that requires enabling the
7196 * 5-bit port mode, which we do not support. 640k^W16 ought to
7197 * be enough for anyone.
7198 */
b80dc51b 7199 ds->num_lag_ids = mv88e6xxx_has_lag(chip) ? 16 : 0;
57e661aa 7200
b7e66a5f
VD
7201 dev_set_drvdata(dev, ds);
7202
23c9ee49 7203 return dsa_register_switch(ds);
b7e66a5f
VD
7204}
7205
fad09c73 7206static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip)
b7e66a5f 7207{
fad09c73 7208 dsa_unregister_switch(chip->ds);
b7e66a5f
VD
7209}
7210
877b7cb0
AL
7211static const void *pdata_device_get_match_data(struct device *dev)
7212{
7213 const struct of_device_id *matches = dev->driver->of_match_table;
7214 const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data;
7215
7216 for (; matches->name[0] || matches->type[0] || matches->compatible[0];
7217 matches++) {
7218 if (!strcmp(pdata->compatible, matches->compatible))
7219 return matches->data;
7220 }
7221 return NULL;
7222}
7223
bcd3d9d9
MR
7224/* There is no suspend to RAM support at DSA level yet, the switch configuration
7225 * would be lost after a power cycle so prevent it to be suspended.
7226 */
7227static int __maybe_unused mv88e6xxx_suspend(struct device *dev)
7228{
7229 return -EOPNOTSUPP;
7230}
7231
7232static int __maybe_unused mv88e6xxx_resume(struct device *dev)
7233{
7234 return 0;
7235}
7236
7237static SIMPLE_DEV_PM_OPS(mv88e6xxx_pm_ops, mv88e6xxx_suspend, mv88e6xxx_resume);
7238
57d32310 7239static int mv88e6xxx_probe(struct mdio_device *mdiodev)
98e67308 7240{
877b7cb0 7241 struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
7ddae24f 7242 const struct mv88e6xxx_info *compat_info = NULL;
14c7b3c3 7243 struct device *dev = &mdiodev->dev;
f8cd8753 7244 struct device_node *np = dev->of_node;
fad09c73 7245 struct mv88e6xxx_chip *chip;
877b7cb0 7246 int port;
52638f71 7247 int err;
14c7b3c3 7248
7bb8c996
AL
7249 if (!np && !pdata)
7250 return -EINVAL;
7251
877b7cb0
AL
7252 if (np)
7253 compat_info = of_device_get_match_data(dev);
7254
7255 if (pdata) {
7256 compat_info = pdata_device_get_match_data(dev);
7257
7258 if (!pdata->netdev)
7259 return -EINVAL;
7260
7261 for (port = 0; port < DSA_MAX_PORTS; port++) {
7262 if (!(pdata->enabled_ports & (1 << port)))
7263 continue;
7264 if (strcmp(pdata->cd.port_names[port], "cpu"))
7265 continue;
7266 pdata->cd.netdev[port] = &pdata->netdev->dev;
7267 break;
7268 }
7269 }
7270
caac8545
VD
7271 if (!compat_info)
7272 return -EINVAL;
7273
fad09c73 7274 chip = mv88e6xxx_alloc_chip(dev);
877b7cb0
AL
7275 if (!chip) {
7276 err = -ENOMEM;
7277 goto out;
7278 }
14c7b3c3 7279
fad09c73 7280 chip->info = compat_info;
caac8545 7281
b4308f04 7282 chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
877b7cb0
AL
7283 if (IS_ERR(chip->reset)) {
7284 err = PTR_ERR(chip->reset);
7285 goto out;
7286 }
7b75e49d 7287 if (chip->reset)
3c27f3d5 7288 usleep_range(10000, 20000);
b4308f04 7289
5da66099
NR
7290 /* Detect if the device is configured in single chip addressing mode,
7291 * otherwise continue with address specific smi init/detection.
7292 */
7293 err = mv88e6xxx_single_chip_detect(chip, mdiodev);
7294 if (err) {
7295 err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
7296 if (err)
7297 goto out;
7298
7299 err = mv88e6xxx_detect(chip);
7300 if (err)
7301 goto out;
7302 }
14c7b3c3 7303
670bb80f
TW
7304 if (chip->info->edsa_support == MV88E6XXX_EDSA_SUPPORTED)
7305 chip->tag_protocol = DSA_TAG_PROTO_EDSA;
7306 else
7307 chip->tag_protocol = DSA_TAG_PROTO_DSA;
7308
e57e5e77
VD
7309 mv88e6xxx_phy_init(chip);
7310
00baabe5
AL
7311 if (chip->info->ops->get_eeprom) {
7312 if (np)
7313 of_property_read_u32(np, "eeprom-length",
7314 &chip->eeprom_len);
7315 else
7316 chip->eeprom_len = pdata->eeprom_len;
7317 }
f8cd8753 7318
c9acece0 7319 mv88e6xxx_reg_lock(chip);
dc30c35b 7320 err = mv88e6xxx_switch_reset(chip);
c9acece0 7321 mv88e6xxx_reg_unlock(chip);
dc30c35b
AL
7322 if (err)
7323 goto out;
7324
a27415de
AL
7325 if (np) {
7326 chip->irq = of_irq_get(np, 0);
7327 if (chip->irq == -EPROBE_DEFER) {
7328 err = chip->irq;
7329 goto out;
7330 }
dc30c35b
AL
7331 }
7332
a27415de
AL
7333 if (pdata)
7334 chip->irq = pdata->irq;
7335
294d711e 7336 /* Has to be performed before the MDIO bus is created, because
a708767e 7337 * the PHYs will link their interrupts to these interrupt
294d711e
AL
7338 * controllers
7339 */
c9acece0 7340 mv88e6xxx_reg_lock(chip);
294d711e 7341 if (chip->irq > 0)
dc30c35b 7342 err = mv88e6xxx_g1_irq_setup(chip);
294d711e
AL
7343 else
7344 err = mv88e6xxx_irq_poll_setup(chip);
c9acece0 7345 mv88e6xxx_reg_unlock(chip);
0977644c 7346
294d711e
AL
7347 if (err)
7348 goto out;
62eb1162 7349
294d711e
AL
7350 if (chip->info->g2_irqs > 0) {
7351 err = mv88e6xxx_g2_irq_setup(chip);
62eb1162 7352 if (err)
294d711e 7353 goto out_g1_irq;
dc30c35b
AL
7354 }
7355
294d711e
AL
7356 err = mv88e6xxx_g1_atu_prob_irq_setup(chip);
7357 if (err)
7358 goto out_g2_irq;
7359
7360 err = mv88e6xxx_g1_vtu_prob_irq_setup(chip);
7361 if (err)
7362 goto out_g1_atu_prob_irq;
7363
55ed0ce0 7364 err = mv88e6xxx_register_switch(chip);
dc30c35b 7365 if (err)
2cb0658d 7366 goto out_g1_vtu_prob_irq;
83c0afae 7367
98e67308 7368 return 0;
dc30c35b 7369
62eb1162 7370out_g1_vtu_prob_irq:
294d711e 7371 mv88e6xxx_g1_vtu_prob_irq_free(chip);
0977644c 7372out_g1_atu_prob_irq:
294d711e 7373 mv88e6xxx_g1_atu_prob_irq_free(chip);
dc30c35b 7374out_g2_irq:
294d711e 7375 if (chip->info->g2_irqs > 0)
dc30c35b
AL
7376 mv88e6xxx_g2_irq_free(chip);
7377out_g1_irq:
294d711e 7378 if (chip->irq > 0)
46712644 7379 mv88e6xxx_g1_irq_free(chip);
294d711e
AL
7380 else
7381 mv88e6xxx_irq_poll_free(chip);
dc30c35b 7382out:
877b7cb0
AL
7383 if (pdata)
7384 dev_put(pdata->netdev);
7385
dc30c35b 7386 return err;
98e67308 7387}
14c7b3c3
AL
7388
7389static void mv88e6xxx_remove(struct mdio_device *mdiodev)
7390{
7391 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
0650bf52
VO
7392 struct mv88e6xxx_chip *chip;
7393
7394 if (!ds)
7395 return;
7396
7397 chip = ds->priv;
14c7b3c3 7398
c6fe0ad2
BS
7399 if (chip->info->ptp_support) {
7400 mv88e6xxx_hwtstamp_free(chip);
2fa8d3af 7401 mv88e6xxx_ptp_free(chip);
c6fe0ad2 7402 }
2fa8d3af 7403
930188ce 7404 mv88e6xxx_phy_destroy(chip);
fad09c73 7405 mv88e6xxx_unregister_switch(chip);
dc30c35b 7406
76f38f1f
AL
7407 mv88e6xxx_g1_vtu_prob_irq_free(chip);
7408 mv88e6xxx_g1_atu_prob_irq_free(chip);
7409
7410 if (chip->info->g2_irqs > 0)
7411 mv88e6xxx_g2_irq_free(chip);
7412
76f38f1f 7413 if (chip->irq > 0)
46712644 7414 mv88e6xxx_g1_irq_free(chip);
76f38f1f
AL
7415 else
7416 mv88e6xxx_irq_poll_free(chip);
0650bf52
VO
7417}
7418
7419static void mv88e6xxx_shutdown(struct mdio_device *mdiodev)
7420{
7421 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
7422
7423 if (!ds)
7424 return;
7425
7426 dsa_switch_shutdown(ds);
7427
7428 dev_set_drvdata(&mdiodev->dev, NULL);
14c7b3c3
AL
7429}
7430
7431static const struct of_device_id mv88e6xxx_of_match[] = {
caac8545
VD
7432 {
7433 .compatible = "marvell,mv88e6085",
7434 .data = &mv88e6xxx_table[MV88E6085],
7435 },
1a3b39ec
AL
7436 {
7437 .compatible = "marvell,mv88e6190",
7438 .data = &mv88e6xxx_table[MV88E6190],
7439 },
1f71836f
RV
7440 {
7441 .compatible = "marvell,mv88e6250",
7442 .data = &mv88e6xxx_table[MV88E6250],
7443 },
14c7b3c3
AL
7444 { /* sentinel */ },
7445};
7446
7447MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);
7448
7449static struct mdio_driver mv88e6xxx_driver = {
7450 .probe = mv88e6xxx_probe,
7451 .remove = mv88e6xxx_remove,
0650bf52 7452 .shutdown = mv88e6xxx_shutdown,
14c7b3c3
AL
7453 .mdiodrv.driver = {
7454 .name = "mv88e6085",
7455 .of_match_table = mv88e6xxx_of_match,
bcd3d9d9 7456 .pm = &mv88e6xxx_pm_ops,
14c7b3c3
AL
7457 },
7458};
7459
7324d50e 7460mdio_module_driver(mv88e6xxx_driver);
3d825ede
BH
7461
7462MODULE_AUTHOR("Lennert Buytenhek <[email protected]>");
7463MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
7464MODULE_LICENSE("GPL");
This page took 3.751214 seconds and 4 git commands to generate.