blob: 0c944ed2173e3933b4721975738a16f657b2dfdc [file] [log] [blame]
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001/*
Vivien Didelot0d3cd4b2016-06-21 12:28:19 -04002 * Marvell 88e6xxx Ethernet switch single-chip support
3 *
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00004 * Copyright (c) 2008 Marvell Semiconductor
5 *
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02006 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
7 *
Vivien Didelot4333d612017-03-28 15:10:36 -04008 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
9 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
10 *
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
Barry Grussling19b2f972013-01-08 16:05:54 +000017#include <linux/delay.h>
Guenter Roeckdefb05b2015-03-26 18:36:38 -070018#include <linux/etherdevice.h>
Andrew Lunndea87022015-08-31 15:56:47 +020019#include <linux/ethtool.h>
Guenter Roeckfacd95b2015-03-26 18:36:35 -070020#include <linux/if_bridge.h>
Andrew Lunndc30c352016-10-16 19:56:49 +020021#include <linux/interrupt.h>
22#include <linux/irq.h>
23#include <linux/irqdomain.h>
Barry Grussling19b2f972013-01-08 16:05:54 +000024#include <linux/jiffies.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000025#include <linux/list.h>
Andrew Lunn14c7b3c2016-05-10 23:27:21 +020026#include <linux/mdio.h>
Paul Gortmaker2bbba272012-01-24 10:41:40 +000027#include <linux/module.h>
Vivien Didelotcaac8542016-06-20 13:14:09 -040028#include <linux/of_device.h>
Andrew Lunndc30c352016-10-16 19:56:49 +020029#include <linux/of_irq.h>
Andrew Lunnb516d452016-06-04 21:17:06 +020030#include <linux/of_mdio.h>
Andrew Lunn877b7cb2018-05-19 22:31:34 +020031#include <linux/platform_data/mv88e6xxx.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000032#include <linux/netdevice.h>
Andrew Lunnc8c1b39a2015-11-20 03:56:24 +010033#include <linux/gpio/consumer.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000034#include <linux/phy.h>
Russell Kingc9a23562018-05-10 13:17:35 -070035#include <linux/phylink.h>
Ben Hutchingsc8f0b862011-11-27 17:06:08 +000036#include <net/dsa.h>
Vivien Didelotec561272016-09-02 14:45:33 -040037
Vivien Didelot4d5f2ba72017-06-02 17:06:15 -040038#include "chip.h"
Vivien Didelota935c052016-09-29 12:21:53 -040039#include "global1.h"
Vivien Didelotec561272016-09-02 14:45:33 -040040#include "global2.h"
Brandon Streiffc6fe0ad2018-02-14 01:07:50 +010041#include "hwtstamp.h"
Andrew Lunn10fa5bf2017-05-26 01:03:20 +020042#include "phy.h"
Vivien Didelot18abed22016-11-04 03:23:26 +010043#include "port.h"
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +010044#include "ptp.h"
Andrew Lunn6d917822017-05-26 01:03:21 +020045#include "serdes.h"
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000046
Vivien Didelotfad09c72016-06-21 12:28:20 -040047static void assert_reg_lock(struct mv88e6xxx_chip *chip)
Vivien Didelot3996a4f2015-10-30 18:56:45 -040048{
Vivien Didelotfad09c72016-06-21 12:28:20 -040049 if (unlikely(!mutex_is_locked(&chip->reg_lock))) {
50 dev_err(chip->dev, "Switch registers lock not held!\n");
Vivien Didelot3996a4f2015-10-30 18:56:45 -040051 dump_stack();
52 }
53}
54
Vivien Didelot914b32f2016-06-20 13:14:11 -040055/* The switch ADDR[4:1] configuration pins define the chip SMI device address
56 * (ADDR[0] is always zero, thus only even SMI addresses can be strapped).
57 *
58 * When ADDR is all zero, the chip uses Single-chip Addressing Mode, assuming it
59 * is the only device connected to the SMI master. In this mode it responds to
60 * all 32 possible SMI addresses, and thus maps directly the internal devices.
61 *
62 * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing
63 * multiple devices to share the SMI interface. In this mode it responds to only
64 * 2 registers, used to indirectly access the internal SMI devices.
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000065 */
Vivien Didelot914b32f2016-06-20 13:14:11 -040066
Vivien Didelotfad09c72016-06-21 12:28:20 -040067static int mv88e6xxx_smi_read(struct mv88e6xxx_chip *chip,
Vivien Didelot914b32f2016-06-20 13:14:11 -040068 int addr, int reg, u16 *val)
69{
Vivien Didelotfad09c72016-06-21 12:28:20 -040070 if (!chip->smi_ops)
Vivien Didelot914b32f2016-06-20 13:14:11 -040071 return -EOPNOTSUPP;
72
Vivien Didelotfad09c72016-06-21 12:28:20 -040073 return chip->smi_ops->read(chip, addr, reg, val);
Vivien Didelot914b32f2016-06-20 13:14:11 -040074}
75
Vivien Didelotfad09c72016-06-21 12:28:20 -040076static int mv88e6xxx_smi_write(struct mv88e6xxx_chip *chip,
Vivien Didelot914b32f2016-06-20 13:14:11 -040077 int addr, int reg, u16 val)
78{
Vivien Didelotfad09c72016-06-21 12:28:20 -040079 if (!chip->smi_ops)
Vivien Didelot914b32f2016-06-20 13:14:11 -040080 return -EOPNOTSUPP;
81
Vivien Didelotfad09c72016-06-21 12:28:20 -040082 return chip->smi_ops->write(chip, addr, reg, val);
Vivien Didelot914b32f2016-06-20 13:14:11 -040083}
84
Vivien Didelotfad09c72016-06-21 12:28:20 -040085static int mv88e6xxx_smi_single_chip_read(struct mv88e6xxx_chip *chip,
Vivien Didelot914b32f2016-06-20 13:14:11 -040086 int addr, int reg, u16 *val)
87{
88 int ret;
89
Vivien Didelotfad09c72016-06-21 12:28:20 -040090 ret = mdiobus_read_nested(chip->bus, addr, reg);
Vivien Didelot914b32f2016-06-20 13:14:11 -040091 if (ret < 0)
92 return ret;
93
94 *val = ret & 0xffff;
95
96 return 0;
97}
98
Vivien Didelotfad09c72016-06-21 12:28:20 -040099static int mv88e6xxx_smi_single_chip_write(struct mv88e6xxx_chip *chip,
Vivien Didelot914b32f2016-06-20 13:14:11 -0400100 int addr, int reg, u16 val)
101{
102 int ret;
103
Vivien Didelotfad09c72016-06-21 12:28:20 -0400104 ret = mdiobus_write_nested(chip->bus, addr, reg, val);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400105 if (ret < 0)
106 return ret;
107
108 return 0;
109}
110
Vivien Didelotc08026a2016-09-29 12:21:59 -0400111static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_single_chip_ops = {
Vivien Didelot914b32f2016-06-20 13:14:11 -0400112 .read = mv88e6xxx_smi_single_chip_read,
113 .write = mv88e6xxx_smi_single_chip_write,
114};
115
Vivien Didelotfad09c72016-06-21 12:28:20 -0400116static int mv88e6xxx_smi_multi_chip_wait(struct mv88e6xxx_chip *chip)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000117{
118 int ret;
119 int i;
120
121 for (i = 0; i < 16; i++) {
Vivien Didelotfad09c72016-06-21 12:28:20 -0400122 ret = mdiobus_read_nested(chip->bus, chip->sw_addr, SMI_CMD);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000123 if (ret < 0)
124 return ret;
125
Andrew Lunncca8b132015-04-02 04:06:39 +0200126 if ((ret & SMI_CMD_BUSY) == 0)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000127 return 0;
128 }
129
130 return -ETIMEDOUT;
131}
132
Vivien Didelotfad09c72016-06-21 12:28:20 -0400133static int mv88e6xxx_smi_multi_chip_read(struct mv88e6xxx_chip *chip,
Vivien Didelot914b32f2016-06-20 13:14:11 -0400134 int addr, int reg, u16 *val)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000135{
136 int ret;
137
Barry Grussling3675c8d2013-01-08 16:05:53 +0000138 /* Wait for the bus to become free. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400139 ret = mv88e6xxx_smi_multi_chip_wait(chip);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000140 if (ret < 0)
141 return ret;
142
Barry Grussling3675c8d2013-01-08 16:05:53 +0000143 /* Transmit the read command. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400144 ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_CMD,
Neil Armstrong6e899e62015-10-22 10:37:53 +0200145 SMI_CMD_OP_22_READ | (addr << 5) | reg);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000146 if (ret < 0)
147 return ret;
148
Barry Grussling3675c8d2013-01-08 16:05:53 +0000149 /* Wait for the read command to complete. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400150 ret = mv88e6xxx_smi_multi_chip_wait(chip);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000151 if (ret < 0)
152 return ret;
153
Barry Grussling3675c8d2013-01-08 16:05:53 +0000154 /* Read the data. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400155 ret = mdiobus_read_nested(chip->bus, chip->sw_addr, SMI_DATA);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000156 if (ret < 0)
157 return ret;
158
Vivien Didelot914b32f2016-06-20 13:14:11 -0400159 *val = ret & 0xffff;
160
161 return 0;
162}
163
Vivien Didelotfad09c72016-06-21 12:28:20 -0400164static int mv88e6xxx_smi_multi_chip_write(struct mv88e6xxx_chip *chip,
Vivien Didelot914b32f2016-06-20 13:14:11 -0400165 int addr, int reg, u16 val)
166{
167 int ret;
168
169 /* Wait for the bus to become free. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400170 ret = mv88e6xxx_smi_multi_chip_wait(chip);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400171 if (ret < 0)
172 return ret;
173
174 /* Transmit the data to write. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400175 ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_DATA, val);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400176 if (ret < 0)
177 return ret;
178
179 /* Transmit the write command. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400180 ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_CMD,
Vivien Didelot914b32f2016-06-20 13:14:11 -0400181 SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
182 if (ret < 0)
183 return ret;
184
185 /* Wait for the write command to complete. */
Vivien Didelotfad09c72016-06-21 12:28:20 -0400186 ret = mv88e6xxx_smi_multi_chip_wait(chip);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400187 if (ret < 0)
188 return ret;
189
190 return 0;
191}
192
Vivien Didelotc08026a2016-09-29 12:21:59 -0400193static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_multi_chip_ops = {
Vivien Didelot914b32f2016-06-20 13:14:11 -0400194 .read = mv88e6xxx_smi_multi_chip_read,
195 .write = mv88e6xxx_smi_multi_chip_write,
196};
197
Vivien Didelotec561272016-09-02 14:45:33 -0400198int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)
Vivien Didelot914b32f2016-06-20 13:14:11 -0400199{
200 int err;
201
Vivien Didelotfad09c72016-06-21 12:28:20 -0400202 assert_reg_lock(chip);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400203
Vivien Didelotfad09c72016-06-21 12:28:20 -0400204 err = mv88e6xxx_smi_read(chip, addr, reg, val);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400205 if (err)
206 return err;
207
Vivien Didelotfad09c72016-06-21 12:28:20 -0400208 dev_dbg(chip->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
Vivien Didelot914b32f2016-06-20 13:14:11 -0400209 addr, reg, *val);
210
211 return 0;
212}
213
Vivien Didelotec561272016-09-02 14:45:33 -0400214int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
Vivien Didelot914b32f2016-06-20 13:14:11 -0400215{
216 int err;
217
Vivien Didelotfad09c72016-06-21 12:28:20 -0400218 assert_reg_lock(chip);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400219
Vivien Didelotfad09c72016-06-21 12:28:20 -0400220 err = mv88e6xxx_smi_write(chip, addr, reg, val);
Vivien Didelot914b32f2016-06-20 13:14:11 -0400221 if (err)
222 return err;
223
Vivien Didelotfad09c72016-06-21 12:28:20 -0400224 dev_dbg(chip->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
Vivien Didelot914b32f2016-06-20 13:14:11 -0400225 addr, reg, val);
226
227 return 0;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000228}
229
Andrew Lunn10fa5bf2017-05-26 01:03:20 +0200230struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
Andrew Lunna3c53be52017-01-24 14:53:50 +0100231{
232 struct mv88e6xxx_mdio_bus *mdio_bus;
233
234 mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus,
235 list);
236 if (!mdio_bus)
237 return NULL;
238
239 return mdio_bus->bus;
240}
241
Andrew Lunndc30c352016-10-16 19:56:49 +0200242static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
243{
244 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
245 unsigned int n = d->hwirq;
246
247 chip->g1_irq.masked |= (1 << n);
248}
249
250static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
251{
252 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
253 unsigned int n = d->hwirq;
254
255 chip->g1_irq.masked &= ~(1 << n);
256}
257
Andrew Lunn294d7112018-02-22 22:58:32 +0100258static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
Andrew Lunndc30c352016-10-16 19:56:49 +0200259{
Andrew Lunndc30c352016-10-16 19:56:49 +0200260 unsigned int nhandled = 0;
261 unsigned int sub_irq;
262 unsigned int n;
263 u16 reg;
John David Anglin7c0db242019-02-11 13:40:21 -0500264 u16 ctl1;
Andrew Lunndc30c352016-10-16 19:56:49 +0200265 int err;
266
267 mutex_lock(&chip->reg_lock);
Vivien Didelot82466922017-06-15 12:13:59 -0400268 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
Andrew Lunndc30c352016-10-16 19:56:49 +0200269 mutex_unlock(&chip->reg_lock);
270
271 if (err)
272 goto out;
273
John David Anglin7c0db242019-02-11 13:40:21 -0500274 do {
275 for (n = 0; n < chip->g1_irq.nirqs; ++n) {
276 if (reg & (1 << n)) {
277 sub_irq = irq_find_mapping(chip->g1_irq.domain,
278 n);
279 handle_nested_irq(sub_irq);
280 ++nhandled;
281 }
Andrew Lunndc30c352016-10-16 19:56:49 +0200282 }
John David Anglin7c0db242019-02-11 13:40:21 -0500283
284 mutex_lock(&chip->reg_lock);
285 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
286 if (err)
287 goto unlock;
288 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
289unlock:
290 mutex_unlock(&chip->reg_lock);
291 if (err)
292 goto out;
293 ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
294 } while (reg & ctl1);
295
Andrew Lunndc30c352016-10-16 19:56:49 +0200296out:
297 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
298}
299
Andrew Lunn294d7112018-02-22 22:58:32 +0100300static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
301{
302 struct mv88e6xxx_chip *chip = dev_id;
303
304 return mv88e6xxx_g1_irq_thread_work(chip);
305}
306
Andrew Lunndc30c352016-10-16 19:56:49 +0200307static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
308{
309 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
310
311 mutex_lock(&chip->reg_lock);
312}
313
314static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
315{
316 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
317 u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
318 u16 reg;
319 int err;
320
Vivien Didelotd77f4322017-06-15 12:14:03 -0400321 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &reg);
Andrew Lunndc30c352016-10-16 19:56:49 +0200322 if (err)
323 goto out;
324
325 reg &= ~mask;
326 reg |= (~chip->g1_irq.masked & mask);
327
Vivien Didelotd77f4322017-06-15 12:14:03 -0400328 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);
Andrew Lunndc30c352016-10-16 19:56:49 +0200329 if (err)
330 goto out;
331
332out:
333 mutex_unlock(&chip->reg_lock);
334}
335
Bhumika Goyal6eb15e22017-08-19 16:25:52 +0530336static const struct irq_chip mv88e6xxx_g1_irq_chip = {
Andrew Lunndc30c352016-10-16 19:56:49 +0200337 .name = "mv88e6xxx-g1",
338 .irq_mask = mv88e6xxx_g1_irq_mask,
339 .irq_unmask = mv88e6xxx_g1_irq_unmask,
340 .irq_bus_lock = mv88e6xxx_g1_irq_bus_lock,
341 .irq_bus_sync_unlock = mv88e6xxx_g1_irq_bus_sync_unlock,
342};
343
344static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
345 unsigned int irq,
346 irq_hw_number_t hwirq)
347{
348 struct mv88e6xxx_chip *chip = d->host_data;
349
350 irq_set_chip_data(irq, d->host_data);
351 irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
352 irq_set_noprobe(irq);
353
354 return 0;
355}
356
357static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
358 .map = mv88e6xxx_g1_irq_domain_map,
359 .xlate = irq_domain_xlate_twocell,
360};
361
Uwe Kleine-König3d824752018-07-20 11:53:15 +0200362/* To be called with reg_lock held */
Andrew Lunn294d7112018-02-22 22:58:32 +0100363static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)
Andrew Lunndc30c352016-10-16 19:56:49 +0200364{
365 int irq, virq;
Andrew Lunn3460a572016-11-20 20:14:16 +0100366 u16 mask;
367
Vivien Didelotd77f4322017-06-15 12:14:03 -0400368 mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
Andrew Lunn3d5fdba2017-12-07 01:05:56 +0100369 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
Vivien Didelotd77f4322017-06-15 12:14:03 -0400370 mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
Andrew Lunn3460a572016-11-20 20:14:16 +0100371
Andreas Färber5edef2f2016-11-27 23:26:28 +0100372 for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
Andrew Lunna3db3d32016-11-20 20:14:14 +0100373 virq = irq_find_mapping(chip->g1_irq.domain, irq);
Andrew Lunndc30c352016-10-16 19:56:49 +0200374 irq_dispose_mapping(virq);
375 }
376
Andrew Lunna3db3d32016-11-20 20:14:14 +0100377 irq_domain_remove(chip->g1_irq.domain);
Andrew Lunndc30c352016-10-16 19:56:49 +0200378}
379
Andrew Lunn294d7112018-02-22 22:58:32 +0100380static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
381{
Uwe Kleine-König3d824752018-07-20 11:53:15 +0200382 /*
383 * free_irq must be called without reg_lock taken because the irq
384 * handler takes this lock, too.
385 */
Andrew Lunn294d7112018-02-22 22:58:32 +0100386 free_irq(chip->irq, chip);
Uwe Kleine-König3d824752018-07-20 11:53:15 +0200387
388 mutex_lock(&chip->reg_lock);
389 mv88e6xxx_g1_irq_free_common(chip);
390 mutex_unlock(&chip->reg_lock);
Andrew Lunn294d7112018-02-22 22:58:32 +0100391}
392
393static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)
Andrew Lunndc30c352016-10-16 19:56:49 +0200394{
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100395 int err, irq, virq;
396 u16 reg, mask;
Andrew Lunndc30c352016-10-16 19:56:49 +0200397
398 chip->g1_irq.nirqs = chip->info->g1_irqs;
399 chip->g1_irq.domain = irq_domain_add_simple(
400 NULL, chip->g1_irq.nirqs, 0,
401 &mv88e6xxx_g1_irq_domain_ops, chip);
402 if (!chip->g1_irq.domain)
403 return -ENOMEM;
404
405 for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
406 irq_create_mapping(chip->g1_irq.domain, irq);
407
408 chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
409 chip->g1_irq.masked = ~0;
410
Vivien Didelotd77f4322017-06-15 12:14:03 -0400411 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
Andrew Lunndc30c352016-10-16 19:56:49 +0200412 if (err)
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100413 goto out_mapping;
Andrew Lunndc30c352016-10-16 19:56:49 +0200414
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100415 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
Andrew Lunndc30c352016-10-16 19:56:49 +0200416
Vivien Didelotd77f4322017-06-15 12:14:03 -0400417 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
Andrew Lunndc30c352016-10-16 19:56:49 +0200418 if (err)
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100419 goto out_disable;
Andrew Lunndc30c352016-10-16 19:56:49 +0200420
421 /* Reading the interrupt status clears (most of) them */
Vivien Didelot82466922017-06-15 12:13:59 -0400422 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
Andrew Lunndc30c352016-10-16 19:56:49 +0200423 if (err)
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100424 goto out_disable;
Andrew Lunndc30c352016-10-16 19:56:49 +0200425
Andrew Lunndc30c352016-10-16 19:56:49 +0200426 return 0;
427
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100428out_disable:
Andrew Lunn3d5fdba2017-12-07 01:05:56 +0100429 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
Vivien Didelotd77f4322017-06-15 12:14:03 -0400430 mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
Andrew Lunn3dd0ef02016-11-20 20:14:17 +0100431
432out_mapping:
433 for (irq = 0; irq < 16; irq++) {
434 virq = irq_find_mapping(chip->g1_irq.domain, irq);
435 irq_dispose_mapping(virq);
436 }
437
438 irq_domain_remove(chip->g1_irq.domain);
Andrew Lunndc30c352016-10-16 19:56:49 +0200439
440 return err;
441}
442
Andrew Lunn294d7112018-02-22 22:58:32 +0100443static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
444{
Andrew Lunnf6d97582019-02-23 17:43:56 +0100445 static struct lock_class_key lock_key;
446 static struct lock_class_key request_key;
Andrew Lunn294d7112018-02-22 22:58:32 +0100447 int err;
448
449 err = mv88e6xxx_g1_irq_setup_common(chip);
450 if (err)
451 return err;
452
Andrew Lunnf6d97582019-02-23 17:43:56 +0100453 /* These lock classes tells lockdep that global 1 irqs are in
454 * a different category than their parent GPIO, so it won't
455 * report false recursion.
456 */
457 irq_set_lockdep_class(chip->irq, &lock_key, &request_key);
458
Andrew Lunn342a0ee2019-02-23 17:43:57 +0100459 mutex_unlock(&chip->reg_lock);
Andrew Lunn294d7112018-02-22 22:58:32 +0100460 err = request_threaded_irq(chip->irq, NULL,
461 mv88e6xxx_g1_irq_thread_fn,
Marek Behún03403762018-08-30 02:13:50 +0200462 IRQF_ONESHOT | IRQF_SHARED,
Andrew Lunn294d7112018-02-22 22:58:32 +0100463 dev_name(chip->dev), chip);
Andrew Lunn342a0ee2019-02-23 17:43:57 +0100464 mutex_lock(&chip->reg_lock);
Andrew Lunn294d7112018-02-22 22:58:32 +0100465 if (err)
466 mv88e6xxx_g1_irq_free_common(chip);
467
468 return err;
469}
470
471static void mv88e6xxx_irq_poll(struct kthread_work *work)
472{
473 struct mv88e6xxx_chip *chip = container_of(work,
474 struct mv88e6xxx_chip,
475 irq_poll_work.work);
476 mv88e6xxx_g1_irq_thread_work(chip);
477
478 kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
479 msecs_to_jiffies(100));
480}
481
482static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)
483{
484 int err;
485
486 err = mv88e6xxx_g1_irq_setup_common(chip);
487 if (err)
488 return err;
489
490 kthread_init_delayed_work(&chip->irq_poll_work,
491 mv88e6xxx_irq_poll);
492
Florian Fainelli3f8b8692019-02-21 20:09:27 -0800493 chip->kworker = kthread_create_worker(0, "%s", dev_name(chip->dev));
Andrew Lunn294d7112018-02-22 22:58:32 +0100494 if (IS_ERR(chip->kworker))
495 return PTR_ERR(chip->kworker);
496
497 kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
498 msecs_to_jiffies(100));
499
500 return 0;
501}
502
503static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
504{
505 kthread_cancel_delayed_work_sync(&chip->irq_poll_work);
506 kthread_destroy_worker(chip->kworker);
Uwe Kleine-König3d824752018-07-20 11:53:15 +0200507
508 mutex_lock(&chip->reg_lock);
509 mv88e6xxx_g1_irq_free_common(chip);
510 mutex_unlock(&chip->reg_lock);
Andrew Lunn294d7112018-02-22 22:58:32 +0100511}
512
Vivien Didelotec561272016-09-02 14:45:33 -0400513int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
Vivien Didelot2d79af62016-08-15 17:18:57 -0400514{
Andrew Lunn6441e6692016-08-19 00:01:55 +0200515 int i;
Vivien Didelot2d79af62016-08-15 17:18:57 -0400516
Andrew Lunn6441e6692016-08-19 00:01:55 +0200517 for (i = 0; i < 16; i++) {
Vivien Didelot2d79af62016-08-15 17:18:57 -0400518 u16 val;
519 int err;
520
521 err = mv88e6xxx_read(chip, addr, reg, &val);
522 if (err)
523 return err;
524
525 if (!(val & mask))
526 return 0;
527
528 usleep_range(1000, 2000);
529 }
530
Andrew Lunn30853552016-08-19 00:01:57 +0200531 dev_err(chip->dev, "Timeout while waiting for switch\n");
Vivien Didelot2d79af62016-08-15 17:18:57 -0400532 return -ETIMEDOUT;
533}
534
Vivien Didelotf22ab642016-07-18 20:45:31 -0400535/* Indirect write to single pointer-data register with an Update bit */
Vivien Didelotec561272016-09-02 14:45:33 -0400536int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
Vivien Didelotf22ab642016-07-18 20:45:31 -0400537{
538 u16 val;
Andrew Lunn0f02b4f2016-08-19 00:01:56 +0200539 int err;
Vivien Didelotf22ab642016-07-18 20:45:31 -0400540
541 /* Wait until the previous operation is completed */
Andrew Lunn0f02b4f2016-08-19 00:01:56 +0200542 err = mv88e6xxx_wait(chip, addr, reg, BIT(15));
543 if (err)
544 return err;
Vivien Didelotf22ab642016-07-18 20:45:31 -0400545
546 /* Set the Update bit to trigger a write operation */
547 val = BIT(15) | update;
548
549 return mv88e6xxx_write(chip, addr, reg, val);
550}
551
Vivien Didelotd78343d2016-11-04 03:23:36 +0100552static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
Andrew Lunn54186b92018-08-09 15:38:37 +0200553 int link, int speed, int duplex, int pause,
Vivien Didelotd78343d2016-11-04 03:23:36 +0100554 phy_interface_t mode)
555{
556 int err;
557
558 if (!chip->info->ops->port_set_link)
559 return 0;
560
561 /* Port's MAC control must not be changed unless the link is down */
562 err = chip->info->ops->port_set_link(chip, port, 0);
563 if (err)
564 return err;
565
566 if (chip->info->ops->port_set_speed) {
567 err = chip->info->ops->port_set_speed(chip, port, speed);
568 if (err && err != -EOPNOTSUPP)
569 goto restore_link;
570 }
571
Andrew Lunn54186b92018-08-09 15:38:37 +0200572 if (chip->info->ops->port_set_pause) {
573 err = chip->info->ops->port_set_pause(chip, port, pause);
574 if (err)
575 goto restore_link;
576 }
577
Vivien Didelotd78343d2016-11-04 03:23:36 +0100578 if (chip->info->ops->port_set_duplex) {
579 err = chip->info->ops->port_set_duplex(chip, port, duplex);
580 if (err && err != -EOPNOTSUPP)
581 goto restore_link;
582 }
583
584 if (chip->info->ops->port_set_rgmii_delay) {
585 err = chip->info->ops->port_set_rgmii_delay(chip, port, mode);
586 if (err && err != -EOPNOTSUPP)
587 goto restore_link;
588 }
589
Andrew Lunnf39908d2017-02-04 20:02:50 +0100590 if (chip->info->ops->port_set_cmode) {
591 err = chip->info->ops->port_set_cmode(chip, port, mode);
592 if (err && err != -EOPNOTSUPP)
593 goto restore_link;
594 }
595
Vivien Didelotd78343d2016-11-04 03:23:36 +0100596 err = 0;
597restore_link:
598 if (chip->info->ops->port_set_link(chip, port, link))
Vivien Didelot774439e52017-06-08 18:34:08 -0400599 dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port);
Vivien Didelotd78343d2016-11-04 03:23:36 +0100600
601 return err;
602}
603
Marek Vasutd700ec42018-09-12 00:15:24 +0200604static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
605{
606 struct mv88e6xxx_chip *chip = ds->priv;
607
608 return port < chip->info->num_internal_phys;
609}
610
Andrew Lunndea87022015-08-31 15:56:47 +0200611/* We expect the switch to perform auto negotiation if there is a real
612 * phy. However, in the case of a fixed link phy, we force the port
613 * settings from the fixed link settings.
614 */
Vivien Didelotf81ec902016-05-09 13:22:58 -0400615static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
616 struct phy_device *phydev)
Andrew Lunndea87022015-08-31 15:56:47 +0200617{
Vivien Didelot04bed142016-08-31 18:06:13 -0400618 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn0e7b9922016-09-21 01:40:31 +0200619 int err;
Andrew Lunndea87022015-08-31 15:56:47 +0200620
Marek Vasutd700ec42018-09-12 00:15:24 +0200621 if (!phy_is_pseudo_fixed_link(phydev) &&
622 mv88e6xxx_phy_is_internal(ds, port))
Andrew Lunndea87022015-08-31 15:56:47 +0200623 return;
624
Vivien Didelotfad09c72016-06-21 12:28:20 -0400625 mutex_lock(&chip->reg_lock);
Vivien Didelotd78343d2016-11-04 03:23:36 +0100626 err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
Andrew Lunn54186b92018-08-09 15:38:37 +0200627 phydev->duplex, phydev->pause,
628 phydev->interface);
Vivien Didelotfad09c72016-06-21 12:28:20 -0400629 mutex_unlock(&chip->reg_lock);
Vivien Didelotd78343d2016-11-04 03:23:36 +0100630
631 if (err && err != -EOPNOTSUPP)
Vivien Didelot774439e52017-06-08 18:34:08 -0400632 dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
Andrew Lunndea87022015-08-31 15:56:47 +0200633}
634
Russell King6c422e32018-08-09 15:38:39 +0200635static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port,
636 unsigned long *mask,
637 struct phylink_link_state *state)
638{
639 if (!phy_interface_mode_is_8023z(state->interface)) {
640 /* 10M and 100M are only supported in non-802.3z mode */
641 phylink_set(mask, 10baseT_Half);
642 phylink_set(mask, 10baseT_Full);
643 phylink_set(mask, 100baseT_Half);
644 phylink_set(mask, 100baseT_Full);
645 }
646}
647
648static void mv88e6185_phylink_validate(struct mv88e6xxx_chip *chip, int port,
649 unsigned long *mask,
650 struct phylink_link_state *state)
651{
652 /* FIXME: if the port is in 1000Base-X mode, then it only supports
653 * 1000M FD speeds. In this case, CMODE will indicate 5.
654 */
655 phylink_set(mask, 1000baseT_Full);
656 phylink_set(mask, 1000baseX_Full);
657
658 mv88e6065_phylink_validate(chip, port, mask, state);
659}
660
661static void mv88e6352_phylink_validate(struct mv88e6xxx_chip *chip, int port,
662 unsigned long *mask,
663 struct phylink_link_state *state)
664{
665 /* No ethtool bits for 200Mbps */
666 phylink_set(mask, 1000baseT_Full);
667 phylink_set(mask, 1000baseX_Full);
668
669 mv88e6065_phylink_validate(chip, port, mask, state);
670}
671
672static void mv88e6390_phylink_validate(struct mv88e6xxx_chip *chip, int port,
673 unsigned long *mask,
674 struct phylink_link_state *state)
675{
Andrew Lunnec260162019-02-08 22:25:44 +0100676 if (port >= 9) {
Russell King6c422e32018-08-09 15:38:39 +0200677 phylink_set(mask, 2500baseX_Full);
Andrew Lunnec260162019-02-08 22:25:44 +0100678 phylink_set(mask, 2500baseT_Full);
679 }
Russell King6c422e32018-08-09 15:38:39 +0200680
681 /* No ethtool bits for 200Mbps */
682 phylink_set(mask, 1000baseT_Full);
683 phylink_set(mask, 1000baseX_Full);
684
685 mv88e6065_phylink_validate(chip, port, mask, state);
686}
687
688static void mv88e6390x_phylink_validate(struct mv88e6xxx_chip *chip, int port,
689 unsigned long *mask,
690 struct phylink_link_state *state)
691{
692 if (port >= 9) {
693 phylink_set(mask, 10000baseT_Full);
694 phylink_set(mask, 10000baseKR_Full);
695 }
696
697 mv88e6390_phylink_validate(chip, port, mask, state);
698}
699
Russell Kingc9a23562018-05-10 13:17:35 -0700700static void mv88e6xxx_validate(struct dsa_switch *ds, int port,
701 unsigned long *supported,
702 struct phylink_link_state *state)
703{
Russell King6c422e32018-08-09 15:38:39 +0200704 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
705 struct mv88e6xxx_chip *chip = ds->priv;
706
707 /* Allow all the expected bits */
708 phylink_set(mask, Autoneg);
709 phylink_set(mask, Pause);
710 phylink_set_port_modes(mask);
711
712 if (chip->info->ops->phylink_validate)
713 chip->info->ops->phylink_validate(chip, port, mask, state);
714
715 bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
716 bitmap_and(state->advertising, state->advertising, mask,
717 __ETHTOOL_LINK_MODE_MASK_NBITS);
718
719 /* We can only operate at 2500BaseX or 1000BaseX. If requested
720 * to advertise both, only report advertising at 2500BaseX.
721 */
722 phylink_helper_basex_speed(state);
Russell Kingc9a23562018-05-10 13:17:35 -0700723}
724
725static int mv88e6xxx_link_state(struct dsa_switch *ds, int port,
726 struct phylink_link_state *state)
727{
728 struct mv88e6xxx_chip *chip = ds->priv;
729 int err;
730
731 mutex_lock(&chip->reg_lock);
Russell King6c422e32018-08-09 15:38:39 +0200732 if (chip->info->ops->port_link_state)
733 err = chip->info->ops->port_link_state(chip, port, state);
734 else
735 err = -EOPNOTSUPP;
Russell Kingc9a23562018-05-10 13:17:35 -0700736 mutex_unlock(&chip->reg_lock);
737
738 return err;
739}
740
741static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
742 unsigned int mode,
743 const struct phylink_link_state *state)
744{
745 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn54186b92018-08-09 15:38:37 +0200746 int speed, duplex, link, pause, err;
Russell Kingc9a23562018-05-10 13:17:35 -0700747
Marek Vasutd700ec42018-09-12 00:15:24 +0200748 if ((mode == MLO_AN_PHY) && mv88e6xxx_phy_is_internal(ds, port))
Russell Kingc9a23562018-05-10 13:17:35 -0700749 return;
750
751 if (mode == MLO_AN_FIXED) {
752 link = LINK_FORCED_UP;
753 speed = state->speed;
754 duplex = state->duplex;
Marek Vasutd700ec42018-09-12 00:15:24 +0200755 } else if (!mv88e6xxx_phy_is_internal(ds, port)) {
756 link = state->link;
757 speed = state->speed;
758 duplex = state->duplex;
Russell Kingc9a23562018-05-10 13:17:35 -0700759 } else {
760 speed = SPEED_UNFORCED;
761 duplex = DUPLEX_UNFORCED;
762 link = LINK_UNFORCED;
763 }
Andrew Lunn54186b92018-08-09 15:38:37 +0200764 pause = !!phylink_test(state->advertising, Pause);
Russell Kingc9a23562018-05-10 13:17:35 -0700765
766 mutex_lock(&chip->reg_lock);
Andrew Lunn54186b92018-08-09 15:38:37 +0200767 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, pause,
Russell Kingc9a23562018-05-10 13:17:35 -0700768 state->interface);
769 mutex_unlock(&chip->reg_lock);
770
771 if (err && err != -EOPNOTSUPP)
772 dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
773}
774
775static void mv88e6xxx_mac_link_force(struct dsa_switch *ds, int port, int link)
776{
777 struct mv88e6xxx_chip *chip = ds->priv;
778 int err;
779
780 mutex_lock(&chip->reg_lock);
781 err = chip->info->ops->port_set_link(chip, port, link);
782 mutex_unlock(&chip->reg_lock);
783
784 if (err)
785 dev_err(chip->dev, "p%d: failed to force MAC link\n", port);
786}
787
788static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
789 unsigned int mode,
790 phy_interface_t interface)
791{
792 if (mode == MLO_AN_FIXED)
793 mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_DOWN);
794}
795
796static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
797 unsigned int mode, phy_interface_t interface,
798 struct phy_device *phydev)
799{
800 if (mode == MLO_AN_FIXED)
801 mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP);
802}
803
Andrew Lunna605a0f2016-11-21 23:26:58 +0100804static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000805{
Andrew Lunna605a0f2016-11-21 23:26:58 +0100806 if (!chip->info->ops->stats_snapshot)
807 return -EOPNOTSUPP;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000808
Andrew Lunna605a0f2016-11-21 23:26:58 +0100809 return chip->info->ops->stats_snapshot(chip, port);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000810}
811
Andrew Lunne413e7e2015-04-02 04:06:38 +0200812static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
Andrew Lunndfafe442016-11-21 23:27:02 +0100813 { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
814 { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
815 { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
816 { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
817 { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
818 { "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
819 { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
820 { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
821 { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
822 { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
823 { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
824 { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
825 { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
826 { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
827 { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
828 { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
829 { "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
830 { "excessive", 4, 0x11, STATS_TYPE_BANK0, },
831 { "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
832 { "deferred", 4, 0x05, STATS_TYPE_BANK0, },
833 { "single", 4, 0x14, STATS_TYPE_BANK0, },
834 { "multiple", 4, 0x17, STATS_TYPE_BANK0, },
835 { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
836 { "late", 4, 0x1f, STATS_TYPE_BANK0, },
837 { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
838 { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
839 { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
840 { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
841 { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
842 { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
843 { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
844 { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
845 { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
846 { "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
847 { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
848 { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
849 { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
850 { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
851 { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
852 { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
853 { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
854 { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
855 { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
856 { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
857 { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
858 { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
859 { "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
860 { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
861 { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
862 { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
863 { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
864 { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
865 { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
866 { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
867 { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
868 { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
869 { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
870 { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
871 { "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
Andrew Lunne413e7e2015-04-02 04:06:38 +0200872};
873
Vivien Didelotfad09c72016-06-21 12:28:20 -0400874static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100875 struct mv88e6xxx_hw_stat *s,
Andrew Lunne0d8b612016-11-21 23:27:04 +0100876 int port, u16 bank1_select,
877 u16 histogram)
Andrew Lunn80c46272015-06-20 18:42:30 +0200878{
Andrew Lunn80c46272015-06-20 18:42:30 +0200879 u32 low;
880 u32 high = 0;
Andrew Lunndfafe442016-11-21 23:27:02 +0100881 u16 reg = 0;
Andrew Lunn0e7b9922016-09-21 01:40:31 +0200882 int err;
Andrew Lunn80c46272015-06-20 18:42:30 +0200883 u64 value;
884
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100885 switch (s->type) {
Andrew Lunndfafe442016-11-21 23:27:02 +0100886 case STATS_TYPE_PORT:
Andrew Lunn0e7b9922016-09-21 01:40:31 +0200887 err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
888 if (err)
Jisheng Zhang6c3442f2018-04-27 16:18:58 +0800889 return U64_MAX;
Andrew Lunn80c46272015-06-20 18:42:30 +0200890
Andrew Lunn0e7b9922016-09-21 01:40:31 +0200891 low = reg;
Andrew Lunncda9f4a2018-03-01 02:02:31 +0100892 if (s->size == 4) {
Andrew Lunn0e7b9922016-09-21 01:40:31 +0200893 err = mv88e6xxx_port_read(chip, port, s->reg + 1, &reg);
894 if (err)
Jisheng Zhang6c3442f2018-04-27 16:18:58 +0800895 return U64_MAX;
Andrew Lunn0e7b9922016-09-21 01:40:31 +0200896 high = reg;
Andrew Lunn80c46272015-06-20 18:42:30 +0200897 }
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100898 break;
Andrew Lunndfafe442016-11-21 23:27:02 +0100899 case STATS_TYPE_BANK1:
Andrew Lunne0d8b612016-11-21 23:27:04 +0100900 reg = bank1_select;
Andrew Lunndfafe442016-11-21 23:27:02 +0100901 /* fall through */
902 case STATS_TYPE_BANK0:
Andrew Lunne0d8b612016-11-21 23:27:04 +0100903 reg |= s->reg | histogram;
Andrew Lunn7f9ef3a2016-11-21 23:27:05 +0100904 mv88e6xxx_g1_stats_read(chip, reg, &low);
Andrew Lunncda9f4a2018-03-01 02:02:31 +0100905 if (s->size == 8)
Andrew Lunn7f9ef3a2016-11-21 23:27:05 +0100906 mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
Gustavo A. R. Silva9fc3e4d2017-05-11 22:11:29 -0500907 break;
908 default:
Jisheng Zhang6c3442f2018-04-27 16:18:58 +0800909 return U64_MAX;
Andrew Lunn80c46272015-06-20 18:42:30 +0200910 }
911 value = (((u64)high) << 16) | low;
912 return value;
913}
914
Andrew Lunn436fe172018-03-01 02:02:29 +0100915static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
916 uint8_t *data, int types)
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100917{
918 struct mv88e6xxx_hw_stat *stat;
919 int i, j;
920
921 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
922 stat = &mv88e6xxx_hw_stats[i];
Andrew Lunndfafe442016-11-21 23:27:02 +0100923 if (stat->type & types) {
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100924 memcpy(data + j * ETH_GSTRING_LEN, stat->string,
925 ETH_GSTRING_LEN);
926 j++;
927 }
928 }
Andrew Lunn436fe172018-03-01 02:02:29 +0100929
930 return j;
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100931}
932
Andrew Lunn436fe172018-03-01 02:02:29 +0100933static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
934 uint8_t *data)
Andrew Lunndfafe442016-11-21 23:27:02 +0100935{
Andrew Lunn436fe172018-03-01 02:02:29 +0100936 return mv88e6xxx_stats_get_strings(chip, data,
937 STATS_TYPE_BANK0 | STATS_TYPE_PORT);
Andrew Lunndfafe442016-11-21 23:27:02 +0100938}
939
Andrew Lunn436fe172018-03-01 02:02:29 +0100940static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
941 uint8_t *data)
Andrew Lunndfafe442016-11-21 23:27:02 +0100942{
Andrew Lunn436fe172018-03-01 02:02:29 +0100943 return mv88e6xxx_stats_get_strings(chip, data,
944 STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
Andrew Lunndfafe442016-11-21 23:27:02 +0100945}
946
Andrew Lunn65f60e42018-03-28 23:50:28 +0200947static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
948 "atu_member_violation",
949 "atu_miss_violation",
950 "atu_full_violation",
951 "vtu_member_violation",
952 "vtu_miss_violation",
953};
954
955static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
956{
957 unsigned int i;
958
959 for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
960 strlcpy(data + i * ETH_GSTRING_LEN,
961 mv88e6xxx_atu_vtu_stats_strings[i],
962 ETH_GSTRING_LEN);
963}
964
Andrew Lunndfafe442016-11-21 23:27:02 +0100965static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
Florian Fainelli89f09042018-04-25 12:12:50 -0700966 u32 stringset, uint8_t *data)
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100967{
Vivien Didelot04bed142016-08-31 18:06:13 -0400968 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn436fe172018-03-01 02:02:29 +0100969 int count = 0;
Andrew Lunndfafe442016-11-21 23:27:02 +0100970
Florian Fainelli89f09042018-04-25 12:12:50 -0700971 if (stringset != ETH_SS_STATS)
972 return;
973
Andrew Lunnc6c8cd52018-03-01 02:02:28 +0100974 mutex_lock(&chip->reg_lock);
975
Andrew Lunndfafe442016-11-21 23:27:02 +0100976 if (chip->info->ops->stats_get_strings)
Andrew Lunn436fe172018-03-01 02:02:29 +0100977 count = chip->info->ops->stats_get_strings(chip, data);
978
979 if (chip->info->ops->serdes_get_strings) {
980 data += count * ETH_GSTRING_LEN;
Andrew Lunn65f60e42018-03-28 23:50:28 +0200981 count = chip->info->ops->serdes_get_strings(chip, port, data);
Andrew Lunn436fe172018-03-01 02:02:29 +0100982 }
Andrew Lunnc6c8cd52018-03-01 02:02:28 +0100983
Andrew Lunn65f60e42018-03-28 23:50:28 +0200984 data += count * ETH_GSTRING_LEN;
985 mv88e6xxx_atu_vtu_get_strings(data);
986
Andrew Lunnc6c8cd52018-03-01 02:02:28 +0100987 mutex_unlock(&chip->reg_lock);
Andrew Lunndfafe442016-11-21 23:27:02 +0100988}
989
990static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
991 int types)
992{
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100993 struct mv88e6xxx_hw_stat *stat;
994 int i, j;
995
996 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
997 stat = &mv88e6xxx_hw_stats[i];
Andrew Lunndfafe442016-11-21 23:27:02 +0100998 if (stat->type & types)
Andrew Lunnf5e2ed02015-12-23 13:23:17 +0100999 j++;
1000 }
1001 return j;
1002}
1003
Andrew Lunndfafe442016-11-21 23:27:02 +01001004static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
1005{
1006 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
1007 STATS_TYPE_PORT);
1008}
1009
1010static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
1011{
1012 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
1013 STATS_TYPE_BANK1);
1014}
1015
Florian Fainelli89f09042018-04-25 12:12:50 -07001016static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
Andrew Lunndfafe442016-11-21 23:27:02 +01001017{
1018 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn436fe172018-03-01 02:02:29 +01001019 int serdes_count = 0;
1020 int count = 0;
Andrew Lunndfafe442016-11-21 23:27:02 +01001021
Florian Fainelli89f09042018-04-25 12:12:50 -07001022 if (sset != ETH_SS_STATS)
1023 return 0;
1024
Andrew Lunnc6c8cd52018-03-01 02:02:28 +01001025 mutex_lock(&chip->reg_lock);
Andrew Lunndfafe442016-11-21 23:27:02 +01001026 if (chip->info->ops->stats_get_sset_count)
Andrew Lunn436fe172018-03-01 02:02:29 +01001027 count = chip->info->ops->stats_get_sset_count(chip);
1028 if (count < 0)
1029 goto out;
1030
1031 if (chip->info->ops->serdes_get_sset_count)
1032 serdes_count = chip->info->ops->serdes_get_sset_count(chip,
1033 port);
Andrew Lunn65f60e42018-03-28 23:50:28 +02001034 if (serdes_count < 0) {
Andrew Lunn436fe172018-03-01 02:02:29 +01001035 count = serdes_count;
Andrew Lunn65f60e42018-03-28 23:50:28 +02001036 goto out;
1037 }
1038 count += serdes_count;
1039 count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);
1040
Andrew Lunn436fe172018-03-01 02:02:29 +01001041out:
Andrew Lunnc6c8cd52018-03-01 02:02:28 +01001042 mutex_unlock(&chip->reg_lock);
Andrew Lunndfafe442016-11-21 23:27:02 +01001043
Andrew Lunn436fe172018-03-01 02:02:29 +01001044 return count;
Andrew Lunndfafe442016-11-21 23:27:02 +01001045}
1046
Andrew Lunn436fe172018-03-01 02:02:29 +01001047static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1048 uint64_t *data, int types,
1049 u16 bank1_select, u16 histogram)
Andrew Lunn052f9472016-11-21 23:27:03 +01001050{
1051 struct mv88e6xxx_hw_stat *stat;
1052 int i, j;
1053
1054 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
1055 stat = &mv88e6xxx_hw_stats[i];
1056 if (stat->type & types) {
Andrew Lunn377cda12018-02-15 14:38:34 +01001057 mutex_lock(&chip->reg_lock);
Andrew Lunne0d8b612016-11-21 23:27:04 +01001058 data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
1059 bank1_select,
1060 histogram);
Andrew Lunn377cda12018-02-15 14:38:34 +01001061 mutex_unlock(&chip->reg_lock);
1062
Andrew Lunn052f9472016-11-21 23:27:03 +01001063 j++;
1064 }
1065 }
Andrew Lunn436fe172018-03-01 02:02:29 +01001066 return j;
Andrew Lunn052f9472016-11-21 23:27:03 +01001067}
1068
Andrew Lunn436fe172018-03-01 02:02:29 +01001069static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1070 uint64_t *data)
Andrew Lunn052f9472016-11-21 23:27:03 +01001071{
1072 return mv88e6xxx_stats_get_stats(chip, port, data,
Andrew Lunne0d8b612016-11-21 23:27:04 +01001073 STATS_TYPE_BANK0 | STATS_TYPE_PORT,
Vivien Didelot57d1ef32017-06-15 12:14:05 -04001074 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
Andrew Lunn052f9472016-11-21 23:27:03 +01001075}
1076
Andrew Lunn436fe172018-03-01 02:02:29 +01001077static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1078 uint64_t *data)
Andrew Lunn052f9472016-11-21 23:27:03 +01001079{
1080 return mv88e6xxx_stats_get_stats(chip, port, data,
Andrew Lunne0d8b612016-11-21 23:27:04 +01001081 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
Vivien Didelot57d1ef32017-06-15 12:14:05 -04001082 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
1083 MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
Andrew Lunne0d8b612016-11-21 23:27:04 +01001084}
1085
Andrew Lunn436fe172018-03-01 02:02:29 +01001086static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1087 uint64_t *data)
Andrew Lunne0d8b612016-11-21 23:27:04 +01001088{
1089 return mv88e6xxx_stats_get_stats(chip, port, data,
1090 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
Vivien Didelot57d1ef32017-06-15 12:14:05 -04001091 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
1092 0);
Andrew Lunn052f9472016-11-21 23:27:03 +01001093}
1094
Andrew Lunn65f60e42018-03-28 23:50:28 +02001095static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
1096 uint64_t *data)
1097{
1098 *data++ = chip->ports[port].atu_member_violation;
1099 *data++ = chip->ports[port].atu_miss_violation;
1100 *data++ = chip->ports[port].atu_full_violation;
1101 *data++ = chip->ports[port].vtu_member_violation;
1102 *data++ = chip->ports[port].vtu_miss_violation;
1103}
1104
Andrew Lunn052f9472016-11-21 23:27:03 +01001105static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
1106 uint64_t *data)
1107{
Andrew Lunn436fe172018-03-01 02:02:29 +01001108 int count = 0;
1109
Andrew Lunn052f9472016-11-21 23:27:03 +01001110 if (chip->info->ops->stats_get_stats)
Andrew Lunn436fe172018-03-01 02:02:29 +01001111 count = chip->info->ops->stats_get_stats(chip, port, data);
1112
Andrew Lunn65f60e42018-03-28 23:50:28 +02001113 mutex_lock(&chip->reg_lock);
Andrew Lunn436fe172018-03-01 02:02:29 +01001114 if (chip->info->ops->serdes_get_stats) {
1115 data += count;
Andrew Lunn65f60e42018-03-28 23:50:28 +02001116 count = chip->info->ops->serdes_get_stats(chip, port, data);
Andrew Lunn436fe172018-03-01 02:02:29 +01001117 }
Andrew Lunn65f60e42018-03-28 23:50:28 +02001118 data += count;
1119 mv88e6xxx_atu_vtu_get_stats(chip, port, data);
1120 mutex_unlock(&chip->reg_lock);
Andrew Lunn052f9472016-11-21 23:27:03 +01001121}
1122
Vivien Didelotf81ec902016-05-09 13:22:58 -04001123static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
1124 uint64_t *data)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001125{
Vivien Didelot04bed142016-08-31 18:06:13 -04001126 struct mv88e6xxx_chip *chip = ds->priv;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001127 int ret;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001128
Vivien Didelotfad09c72016-06-21 12:28:20 -04001129 mutex_lock(&chip->reg_lock);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001130
Andrew Lunna605a0f2016-11-21 23:26:58 +01001131 ret = mv88e6xxx_stats_snapshot(chip, port);
Andrew Lunn377cda12018-02-15 14:38:34 +01001132 mutex_unlock(&chip->reg_lock);
1133
1134 if (ret < 0)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001135 return;
Andrew Lunn052f9472016-11-21 23:27:03 +01001136
1137 mv88e6xxx_get_stats(chip, port, data);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001138
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001139}
Ben Hutchings98e67302011-11-25 14:36:19 +00001140
Vivien Didelotf81ec902016-05-09 13:22:58 -04001141static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001142{
1143 return 32 * sizeof(u16);
1144}
1145
Vivien Didelotf81ec902016-05-09 13:22:58 -04001146static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
1147 struct ethtool_regs *regs, void *_p)
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001148{
Vivien Didelot04bed142016-08-31 18:06:13 -04001149 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn0e7b9922016-09-21 01:40:31 +02001150 int err;
1151 u16 reg;
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001152 u16 *p = _p;
1153 int i;
1154
Vivien Didelota5f39322018-12-17 16:05:21 -05001155 regs->version = chip->info->prod_num;
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001156
1157 memset(p, 0xff, 32 * sizeof(u16));
1158
Vivien Didelotfad09c72016-06-21 12:28:20 -04001159 mutex_lock(&chip->reg_lock);
Vivien Didelot23062512016-05-09 13:22:45 -04001160
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001161 for (i = 0; i < 32; i++) {
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001162
Andrew Lunn0e7b9922016-09-21 01:40:31 +02001163 err = mv88e6xxx_port_read(chip, port, i, &reg);
1164 if (!err)
1165 p[i] = reg;
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001166 }
Vivien Didelot23062512016-05-09 13:22:45 -04001167
Vivien Didelotfad09c72016-06-21 12:28:20 -04001168 mutex_unlock(&chip->reg_lock);
Guenter Roecka1ab91f2014-10-29 10:45:05 -07001169}
1170
Vivien Didelot08f50062017-08-01 16:32:41 -04001171static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
1172 struct ethtool_eee *e)
Guenter Roeck11b3b452015-03-06 22:23:51 -08001173{
Vivien Didelot5480db62017-08-01 16:32:40 -04001174 /* Nothing to do on the port's MAC */
1175 return 0;
Guenter Roeck11b3b452015-03-06 22:23:51 -08001176}
1177
Vivien Didelot08f50062017-08-01 16:32:41 -04001178static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
1179 struct ethtool_eee *e)
Guenter Roeck11b3b452015-03-06 22:23:51 -08001180{
Vivien Didelot5480db62017-08-01 16:32:40 -04001181 /* Nothing to do on the port's MAC */
1182 return 0;
Guenter Roeck11b3b452015-03-06 22:23:51 -08001183}
1184
Vivien Didelote5887a22017-03-30 17:37:11 -04001185static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001186{
Vivien Didelote5887a22017-03-30 17:37:11 -04001187 struct dsa_switch *ds = NULL;
1188 struct net_device *br;
1189 u16 pvlan;
Vivien Didelotb7666ef2016-02-26 13:16:06 -05001190 int i;
1191
Vivien Didelote5887a22017-03-30 17:37:11 -04001192 if (dev < DSA_MAX_SWITCHES)
1193 ds = chip->ds->dst->ds[dev];
Vivien Didelotb7666ef2016-02-26 13:16:06 -05001194
Vivien Didelote5887a22017-03-30 17:37:11 -04001195 /* Prevent frames from unknown switch or port */
1196 if (!ds || port >= ds->num_ports)
1197 return 0;
1198
1199 /* Frames from DSA links and CPU ports can egress any local port */
1200 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
1201 return mv88e6xxx_port_mask(chip);
1202
1203 br = ds->ports[port].bridge_dev;
1204 pvlan = 0;
1205
1206 /* Frames from user ports can egress any local DSA links and CPU ports,
1207 * as well as any local member of their bridge group.
1208 */
1209 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
1210 if (dsa_is_cpu_port(chip->ds, i) ||
1211 dsa_is_dsa_port(chip->ds, i) ||
Vivien Didelotc8652c82017-10-16 11:12:19 -04001212 (br && dsa_to_port(chip->ds, i)->bridge_dev == br))
Vivien Didelote5887a22017-03-30 17:37:11 -04001213 pvlan |= BIT(i);
1214
1215 return pvlan;
1216}
1217
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001218static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
Vivien Didelote5887a22017-03-30 17:37:11 -04001219{
1220 u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
Vivien Didelotb7666ef2016-02-26 13:16:06 -05001221
1222 /* prevent frames from going back out of the port they came in on */
1223 output_ports &= ~BIT(port);
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001224
Vivien Didelot5a7921f2016-11-04 03:23:28 +01001225 return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001226}
1227
Vivien Didelotf81ec902016-05-09 13:22:58 -04001228static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
1229 u8 state)
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001230{
Vivien Didelot04bed142016-08-31 18:06:13 -04001231 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot553eb542016-05-13 20:38:23 -04001232 int err;
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001233
Vivien Didelotfad09c72016-06-21 12:28:20 -04001234 mutex_lock(&chip->reg_lock);
Vivien Didelotf894c292017-06-08 18:34:10 -04001235 err = mv88e6xxx_port_set_state(chip, port, state);
Vivien Didelotfad09c72016-06-21 12:28:20 -04001236 mutex_unlock(&chip->reg_lock);
Vivien Didelot553eb542016-05-13 20:38:23 -04001237
1238 if (err)
Vivien Didelot774439e52017-06-08 18:34:08 -04001239 dev_err(ds->dev, "p%d: failed to update state\n", port);
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001240}
1241
Vivien Didelot93e18d62018-05-11 17:16:35 -04001242static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip)
1243{
1244 int err;
1245
1246 if (chip->info->ops->ieee_pri_map) {
1247 err = chip->info->ops->ieee_pri_map(chip);
1248 if (err)
1249 return err;
1250 }
1251
1252 if (chip->info->ops->ip_pri_map) {
1253 err = chip->info->ops->ip_pri_map(chip);
1254 if (err)
1255 return err;
1256 }
1257
1258 return 0;
1259}
1260
Vivien Didelotc7f047b2018-04-26 21:56:45 -04001261static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
1262{
1263 int target, port;
1264 int err;
1265
1266 if (!chip->info->global2_addr)
1267 return 0;
1268
1269 /* Initialize the routing port to the 32 possible target devices */
1270 for (target = 0; target < 32; target++) {
1271 port = 0x1f;
1272 if (target < DSA_MAX_SWITCHES)
1273 if (chip->ds->rtable[target] != DSA_RTABLE_NONE)
1274 port = chip->ds->rtable[target];
1275
1276 err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
1277 if (err)
1278 return err;
1279 }
1280
Vivien Didelot02317e62018-05-09 11:38:49 -04001281 if (chip->info->ops->set_cascade_port) {
1282 port = MV88E6XXX_CASCADE_PORT_MULTIPLE;
1283 err = chip->info->ops->set_cascade_port(chip, port);
1284 if (err)
1285 return err;
1286 }
1287
Vivien Didelot23c98912018-05-09 11:38:50 -04001288 err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index);
1289 if (err)
1290 return err;
1291
Vivien Didelotc7f047b2018-04-26 21:56:45 -04001292 return 0;
1293}
1294
Vivien Didelotb28f8722018-04-26 21:56:44 -04001295static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip)
1296{
1297 /* Clear all trunk masks and mapping */
1298 if (chip->info->global2_addr)
1299 return mv88e6xxx_g2_trunk_clear(chip);
1300
1301 return 0;
1302}
1303
Vivien Didelot9e5baf92018-05-09 11:38:51 -04001304static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip)
1305{
1306 if (chip->info->ops->rmu_disable)
1307 return chip->info->ops->rmu_disable(chip);
1308
1309 return 0;
1310}
1311
Vivien Didelot9e907d72017-07-17 13:03:43 -04001312static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
1313{
1314 if (chip->info->ops->pot_clear)
1315 return chip->info->ops->pot_clear(chip);
1316
1317 return 0;
1318}
1319
Vivien Didelot51c901a2017-07-17 13:03:41 -04001320static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip)
1321{
1322 if (chip->info->ops->mgmt_rsvd2cpu)
1323 return chip->info->ops->mgmt_rsvd2cpu(chip);
1324
1325 return 0;
1326}
1327
Vivien Didelota2ac29d2017-03-11 16:12:49 -05001328static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
1329{
Vivien Didelotc3a7d4a2017-03-11 16:12:51 -05001330 int err;
1331
Vivien Didelotdaefc942017-03-11 16:12:54 -05001332 err = mv88e6xxx_g1_atu_flush(chip, 0, true);
1333 if (err)
1334 return err;
1335
Vivien Didelotc3a7d4a2017-03-11 16:12:51 -05001336 err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
1337 if (err)
1338 return err;
1339
Vivien Didelota2ac29d2017-03-11 16:12:49 -05001340 return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
1341}
1342
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04001343static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
1344{
1345 int port;
1346 int err;
1347
1348 if (!chip->info->ops->irl_init_all)
1349 return 0;
1350
1351 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
1352 /* Disable ingress rate limiting by resetting all per port
1353 * ingress rate limit resources to their initial state.
1354 */
1355 err = chip->info->ops->irl_init_all(chip, port);
1356 if (err)
1357 return err;
1358 }
1359
1360 return 0;
1361}
1362
Vivien Didelot04a69a12017-10-13 14:18:05 -04001363static int mv88e6xxx_mac_setup(struct mv88e6xxx_chip *chip)
1364{
1365 if (chip->info->ops->set_switch_mac) {
1366 u8 addr[ETH_ALEN];
1367
1368 eth_random_addr(addr);
1369
1370 return chip->info->ops->set_switch_mac(chip, addr);
1371 }
1372
1373 return 0;
1374}
1375
Vivien Didelot17a15942017-03-30 17:37:09 -04001376static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
1377{
1378 u16 pvlan = 0;
1379
1380 if (!mv88e6xxx_has_pvt(chip))
1381 return -EOPNOTSUPP;
1382
1383 /* Skip the local source device, which uses in-chip port VLAN */
1384 if (dev != chip->ds->index)
Vivien Didelotaec5ac82017-03-30 17:37:15 -04001385 pvlan = mv88e6xxx_port_vlan(chip, dev, port);
Vivien Didelot17a15942017-03-30 17:37:09 -04001386
1387 return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan);
1388}
1389
Vivien Didelot81228992017-03-30 17:37:08 -04001390static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
1391{
Vivien Didelot17a15942017-03-30 17:37:09 -04001392 int dev, port;
1393 int err;
1394
Vivien Didelot81228992017-03-30 17:37:08 -04001395 if (!mv88e6xxx_has_pvt(chip))
1396 return 0;
1397
1398 /* Clear 5 Bit Port for usage with Marvell Link Street devices:
1399 * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev.
1400 */
Vivien Didelot17a15942017-03-30 17:37:09 -04001401 err = mv88e6xxx_g2_misc_4_bit_port(chip);
1402 if (err)
1403 return err;
1404
1405 for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; ++dev) {
1406 for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; ++port) {
1407 err = mv88e6xxx_pvt_map(chip, dev, port);
1408 if (err)
1409 return err;
1410 }
1411 }
1412
1413 return 0;
Vivien Didelot81228992017-03-30 17:37:08 -04001414}
1415
Vivien Didelot749efcb2016-09-22 16:49:24 -04001416static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
1417{
1418 struct mv88e6xxx_chip *chip = ds->priv;
1419 int err;
1420
1421 mutex_lock(&chip->reg_lock);
Vivien Didelote606ca32017-03-11 16:12:55 -05001422 err = mv88e6xxx_g1_atu_remove(chip, 0, port, false);
Vivien Didelot749efcb2016-09-22 16:49:24 -04001423 mutex_unlock(&chip->reg_lock);
1424
1425 if (err)
Vivien Didelot774439e52017-06-08 18:34:08 -04001426 dev_err(ds->dev, "p%d: failed to flush ATU\n", port);
Vivien Didelot749efcb2016-09-22 16:49:24 -04001427}
1428
Vivien Didelotb486d7c2017-05-01 14:05:13 -04001429static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
1430{
1431 if (!chip->info->max_vid)
1432 return 0;
1433
1434 return mv88e6xxx_g1_vtu_flush(chip);
1435}
1436
Vivien Didelotf1394b782017-05-01 14:05:22 -04001437static int mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip,
1438 struct mv88e6xxx_vtu_entry *entry)
1439{
1440 if (!chip->info->ops->vtu_getnext)
1441 return -EOPNOTSUPP;
1442
1443 return chip->info->ops->vtu_getnext(chip, entry);
1444}
1445
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04001446static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
1447 struct mv88e6xxx_vtu_entry *entry)
1448{
1449 if (!chip->info->ops->vtu_loadpurge)
1450 return -EOPNOTSUPP;
1451
1452 return chip->info->ops->vtu_loadpurge(chip, entry);
1453}
1454
Vivien Didelotd7f435f2017-03-11 16:12:56 -05001455static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001456{
1457 DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
Vivien Didelot3afb4bd2017-05-01 14:05:16 -04001458 struct mv88e6xxx_vtu_entry vlan = {
1459 .vid = chip->info->max_vid,
1460 };
Vivien Didelot2db9ce12016-02-26 13:16:04 -05001461 int i, err;
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001462
1463 bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
1464
Vivien Didelot2db9ce12016-02-26 13:16:04 -05001465 /* Set every FID bit used by the (un)bridged ports */
Vivien Didelot370b4ff2016-09-29 12:21:57 -04001466 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
Vivien Didelotb4e48c52016-11-04 03:23:29 +01001467 err = mv88e6xxx_port_get_fid(chip, i, fid);
Vivien Didelot2db9ce12016-02-26 13:16:04 -05001468 if (err)
1469 return err;
1470
1471 set_bit(*fid, fid_bitmap);
1472 }
1473
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001474 /* Set every FID bit used by the VLAN entries */
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001475 do {
Vivien Didelotf1394b782017-05-01 14:05:22 -04001476 err = mv88e6xxx_vtu_getnext(chip, &vlan);
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001477 if (err)
1478 return err;
1479
1480 if (!vlan.valid)
1481 break;
1482
1483 set_bit(vlan.fid, fid_bitmap);
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001484 } while (vlan.vid < chip->info->max_vid);
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001485
1486 /* The reset value 0x000 is used to indicate that multiple address
1487 * databases are not needed. Return the next positive available.
1488 */
1489 *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
Vivien Didelotfad09c72016-06-21 12:28:20 -04001490 if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001491 return -ENOSPC;
1492
1493 /* Clear the database */
Vivien Didelotdaefc942017-03-11 16:12:54 -05001494 return mv88e6xxx_g1_atu_flush(chip, *fid, true);
Vivien Didelot3285f9e2016-02-26 13:16:03 -05001495}
1496
Vivien Didelot567aa592017-05-01 14:05:25 -04001497static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
1498 struct mv88e6xxx_vtu_entry *entry, bool new)
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001499{
1500 int err;
1501
1502 if (!vid)
1503 return -EINVAL;
1504
Vivien Didelot3afb4bd2017-05-01 14:05:16 -04001505 entry->vid = vid - 1;
1506 entry->valid = false;
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001507
Vivien Didelotf1394b782017-05-01 14:05:22 -04001508 err = mv88e6xxx_vtu_getnext(chip, entry);
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001509 if (err)
1510 return err;
1511
Vivien Didelot567aa592017-05-01 14:05:25 -04001512 if (entry->vid == vid && entry->valid)
1513 return 0;
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001514
Vivien Didelot567aa592017-05-01 14:05:25 -04001515 if (new) {
1516 int i;
1517
1518 /* Initialize a fresh VLAN entry */
1519 memset(entry, 0, sizeof(*entry));
1520 entry->valid = true;
1521 entry->vid = vid;
1522
Vivien Didelot553a7682017-06-07 18:12:16 -04001523 /* Exclude all ports */
Vivien Didelot567aa592017-05-01 14:05:25 -04001524 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
Vivien Didelot553a7682017-06-07 18:12:16 -04001525 entry->member[i] =
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001526 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
Vivien Didelot567aa592017-05-01 14:05:25 -04001527
1528 return mv88e6xxx_atu_new(chip, &entry->fid);
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001529 }
1530
Vivien Didelot567aa592017-05-01 14:05:25 -04001531 /* switchdev expects -EOPNOTSUPP to honor software VLANs */
1532 return -EOPNOTSUPP;
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001533}
1534
Vivien Didelotda9c3592016-02-12 12:09:40 -05001535static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
1536 u16 vid_begin, u16 vid_end)
1537{
Vivien Didelot04bed142016-08-31 18:06:13 -04001538 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot3afb4bd2017-05-01 14:05:16 -04001539 struct mv88e6xxx_vtu_entry vlan = {
1540 .vid = vid_begin - 1,
1541 };
Vivien Didelotda9c3592016-02-12 12:09:40 -05001542 int i, err;
1543
Andrew Lunndb06ae412017-09-25 23:32:20 +02001544 /* DSA and CPU ports have to be members of multiple vlans */
1545 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
1546 return 0;
1547
Vivien Didelotda9c3592016-02-12 12:09:40 -05001548 if (!vid_begin)
1549 return -EOPNOTSUPP;
1550
Vivien Didelotfad09c72016-06-21 12:28:20 -04001551 mutex_lock(&chip->reg_lock);
Vivien Didelotda9c3592016-02-12 12:09:40 -05001552
Vivien Didelotda9c3592016-02-12 12:09:40 -05001553 do {
Vivien Didelotf1394b782017-05-01 14:05:22 -04001554 err = mv88e6xxx_vtu_getnext(chip, &vlan);
Vivien Didelotda9c3592016-02-12 12:09:40 -05001555 if (err)
1556 goto unlock;
1557
1558 if (!vlan.valid)
1559 break;
1560
1561 if (vlan.vid > vid_end)
1562 break;
1563
Vivien Didelot370b4ff2016-09-29 12:21:57 -04001564 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
Vivien Didelotda9c3592016-02-12 12:09:40 -05001565 if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
1566 continue;
1567
Andrew Lunncd886462017-11-09 22:29:53 +01001568 if (!ds->ports[i].slave)
Andrew Lunn66e28092016-12-11 21:07:19 +01001569 continue;
1570
Vivien Didelotbd00e052017-05-01 14:05:11 -04001571 if (vlan.member[i] ==
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001572 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
Vivien Didelotda9c3592016-02-12 12:09:40 -05001573 continue;
1574
Vivien Didelotc8652c82017-10-16 11:12:19 -04001575 if (dsa_to_port(ds, i)->bridge_dev ==
Vivien Didelotfae8a252017-01-27 15:29:42 -05001576 ds->ports[port].bridge_dev)
Vivien Didelotda9c3592016-02-12 12:09:40 -05001577 break; /* same bridge, check next VLAN */
1578
Vivien Didelotc8652c82017-10-16 11:12:19 -04001579 if (!dsa_to_port(ds, i)->bridge_dev)
Andrew Lunn66e28092016-12-11 21:07:19 +01001580 continue;
1581
Andrew Lunn743fcc22017-11-09 22:29:54 +01001582 dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n",
1583 port, vlan.vid, i,
Vivien Didelotc8652c82017-10-16 11:12:19 -04001584 netdev_name(dsa_to_port(ds, i)->bridge_dev));
Vivien Didelotda9c3592016-02-12 12:09:40 -05001585 err = -EOPNOTSUPP;
1586 goto unlock;
1587 }
1588 } while (vlan.vid < vid_end);
1589
1590unlock:
Vivien Didelotfad09c72016-06-21 12:28:20 -04001591 mutex_unlock(&chip->reg_lock);
Vivien Didelotda9c3592016-02-12 12:09:40 -05001592
1593 return err;
1594}
1595
Vivien Didelotf81ec902016-05-09 13:22:58 -04001596static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
1597 bool vlan_filtering)
Vivien Didelot214cdb92016-02-26 13:16:08 -05001598{
Vivien Didelot04bed142016-08-31 18:06:13 -04001599 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot81c6edb2017-06-12 12:37:41 -04001600 u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
1601 MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
Andrew Lunn0e7b9922016-09-21 01:40:31 +02001602 int err;
Vivien Didelot214cdb92016-02-26 13:16:08 -05001603
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001604 if (!chip->info->max_vid)
Vivien Didelot54d77b52016-05-09 13:22:47 -04001605 return -EOPNOTSUPP;
1606
Vivien Didelotfad09c72016-06-21 12:28:20 -04001607 mutex_lock(&chip->reg_lock);
Vivien Didelot385a0992016-11-04 03:23:31 +01001608 err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
Vivien Didelotfad09c72016-06-21 12:28:20 -04001609 mutex_unlock(&chip->reg_lock);
Vivien Didelot214cdb92016-02-26 13:16:08 -05001610
Andrew Lunn0e7b9922016-09-21 01:40:31 +02001611 return err;
Vivien Didelot214cdb92016-02-26 13:16:08 -05001612}
1613
Vivien Didelot57d32312016-06-20 13:13:58 -04001614static int
1615mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
Vivien Didelot80e02362017-11-30 11:23:57 -05001616 const struct switchdev_obj_port_vlan *vlan)
Vivien Didelot0d3b33e2015-08-13 12:52:22 -04001617{
Vivien Didelot04bed142016-08-31 18:06:13 -04001618 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelotda9c3592016-02-12 12:09:40 -05001619 int err;
1620
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001621 if (!chip->info->max_vid)
Vivien Didelot54d77b52016-05-09 13:22:47 -04001622 return -EOPNOTSUPP;
1623
Vivien Didelotda9c3592016-02-12 12:09:40 -05001624 /* If the requested port doesn't belong to the same bridge as the VLAN
1625 * members, do not support it (yet) and fallback to software VLAN.
1626 */
1627 err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin,
1628 vlan->vid_end);
1629 if (err)
1630 return err;
1631
Vivien Didelot76e398a2015-11-01 12:33:55 -05001632 /* We don't need any dynamic resource from the kernel (yet),
1633 * so skip the prepare phase.
1634 */
1635 return 0;
1636}
1637
Andrew Lunna4c93ae2017-11-09 22:29:55 +01001638static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
1639 const unsigned char *addr, u16 vid,
1640 u8 state)
1641{
1642 struct mv88e6xxx_vtu_entry vlan;
1643 struct mv88e6xxx_atu_entry entry;
1644 int err;
1645
1646 /* Null VLAN ID corresponds to the port private database */
1647 if (vid == 0)
1648 err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
1649 else
1650 err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
1651 if (err)
1652 return err;
1653
1654 entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
1655 ether_addr_copy(entry.mac, addr);
1656 eth_addr_dec(entry.mac);
1657
1658 err = mv88e6xxx_g1_atu_getnext(chip, vlan.fid, &entry);
1659 if (err)
1660 return err;
1661
1662 /* Initialize a fresh ATU entry if it isn't found */
1663 if (entry.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ||
1664 !ether_addr_equal(entry.mac, addr)) {
1665 memset(&entry, 0, sizeof(entry));
1666 ether_addr_copy(entry.mac, addr);
1667 }
1668
1669 /* Purge the ATU entry only if no port is using it anymore */
1670 if (state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED) {
1671 entry.portvec &= ~BIT(port);
1672 if (!entry.portvec)
1673 entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
1674 } else {
1675 entry.portvec |= BIT(port);
1676 entry.state = state;
1677 }
1678
1679 return mv88e6xxx_g1_atu_loadpurge(chip, vlan.fid, &entry);
1680}
1681
Andrew Lunn87fa8862017-11-09 22:29:56 +01001682static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port,
1683 u16 vid)
1684{
1685 const char broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1686 u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC;
1687
1688 return mv88e6xxx_port_db_load_purge(chip, port, broadcast, vid, state);
1689}
1690
1691static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid)
1692{
1693 int port;
1694 int err;
1695
1696 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
1697 err = mv88e6xxx_port_add_broadcast(chip, port, vid);
1698 if (err)
1699 return err;
1700 }
1701
1702 return 0;
1703}
1704
Vivien Didelotfad09c72016-06-21 12:28:20 -04001705static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
Vivien Didelotc91498e2017-06-07 18:12:13 -04001706 u16 vid, u8 member)
Vivien Didelot76e398a2015-11-01 12:33:55 -05001707{
Vivien Didelotb4e47c02016-09-29 12:21:58 -04001708 struct mv88e6xxx_vtu_entry vlan;
Vivien Didelot0d3b33e2015-08-13 12:52:22 -04001709 int err;
1710
Vivien Didelot567aa592017-05-01 14:05:25 -04001711 err = mv88e6xxx_vtu_get(chip, vid, &vlan, true);
Vivien Didelot36d04ba2015-10-22 09:34:39 -04001712 if (err)
Vivien Didelot76e398a2015-11-01 12:33:55 -05001713 return err;
Vivien Didelot36d04ba2015-10-22 09:34:39 -04001714
Vivien Didelotc91498e2017-06-07 18:12:13 -04001715 vlan.member[port] = member;
Vivien Didelot0d3b33e2015-08-13 12:52:22 -04001716
Andrew Lunn87fa8862017-11-09 22:29:56 +01001717 err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
1718 if (err)
1719 return err;
1720
1721 return mv88e6xxx_broadcast_setup(chip, vid);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001722}
1723
Vivien Didelotf81ec902016-05-09 13:22:58 -04001724static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
Vivien Didelot80e02362017-11-30 11:23:57 -05001725 const struct switchdev_obj_port_vlan *vlan)
Vivien Didelot76e398a2015-11-01 12:33:55 -05001726{
Vivien Didelot04bed142016-08-31 18:06:13 -04001727 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot76e398a2015-11-01 12:33:55 -05001728 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
1729 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
Vivien Didelotc91498e2017-06-07 18:12:13 -04001730 u8 member;
Vivien Didelot76e398a2015-11-01 12:33:55 -05001731 u16 vid;
Vivien Didelot76e398a2015-11-01 12:33:55 -05001732
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001733 if (!chip->info->max_vid)
Vivien Didelot54d77b52016-05-09 13:22:47 -04001734 return;
1735
Vivien Didelotc91498e2017-06-07 18:12:13 -04001736 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001737 member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED;
Vivien Didelotc91498e2017-06-07 18:12:13 -04001738 else if (untagged)
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001739 member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED;
Vivien Didelotc91498e2017-06-07 18:12:13 -04001740 else
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001741 member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED;
Vivien Didelotc91498e2017-06-07 18:12:13 -04001742
Vivien Didelotfad09c72016-06-21 12:28:20 -04001743 mutex_lock(&chip->reg_lock);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001744
Vivien Didelot4d5770b2016-04-06 11:55:05 -04001745 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
Vivien Didelotc91498e2017-06-07 18:12:13 -04001746 if (_mv88e6xxx_port_vlan_add(chip, port, vid, member))
Vivien Didelot774439e52017-06-08 18:34:08 -04001747 dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
1748 vid, untagged ? 'u' : 't');
Vivien Didelot76e398a2015-11-01 12:33:55 -05001749
Vivien Didelot77064f32016-11-04 03:23:30 +01001750 if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
Vivien Didelot774439e52017-06-08 18:34:08 -04001751 dev_err(ds->dev, "p%d: failed to set PVID %d\n", port,
1752 vlan->vid_end);
Vivien Didelot4d5770b2016-04-06 11:55:05 -04001753
Vivien Didelotfad09c72016-06-21 12:28:20 -04001754 mutex_unlock(&chip->reg_lock);
Vivien Didelot0d3b33e2015-08-13 12:52:22 -04001755}
1756
Vivien Didelotfad09c72016-06-21 12:28:20 -04001757static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
Andrew Lunn158bc062016-04-28 21:24:06 -04001758 int port, u16 vid)
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001759{
Vivien Didelotb4e47c02016-09-29 12:21:58 -04001760 struct mv88e6xxx_vtu_entry vlan;
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001761 int i, err;
1762
Vivien Didelot567aa592017-05-01 14:05:25 -04001763 err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
Vivien Didelot36d04ba2015-10-22 09:34:39 -04001764 if (err)
Vivien Didelot76e398a2015-11-01 12:33:55 -05001765 return err;
Vivien Didelot36d04ba2015-10-22 09:34:39 -04001766
Vivien Didelot2fb5ef02016-02-26 13:16:01 -05001767 /* Tell switchdev if this VLAN is handled in software */
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001768 if (vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
Vivien Didelot3c06f082016-02-05 14:04:39 -05001769 return -EOPNOTSUPP;
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001770
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001771 vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001772
1773 /* keep the VLAN unless all ports are excluded */
Vivien Didelotf02bdff2015-10-11 18:08:36 -04001774 vlan.valid = false;
Vivien Didelot370b4ff2016-09-29 12:21:57 -04001775 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
Vivien Didelot7ec60d6e2017-06-15 12:14:02 -04001776 if (vlan.member[i] !=
1777 MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
Vivien Didelotf02bdff2015-10-11 18:08:36 -04001778 vlan.valid = true;
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001779 break;
1780 }
1781 }
1782
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04001783 err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001784 if (err)
Vivien Didelot76e398a2015-11-01 12:33:55 -05001785 return err;
1786
Vivien Didelote606ca32017-03-11 16:12:55 -05001787 return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001788}
1789
Vivien Didelotf81ec902016-05-09 13:22:58 -04001790static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
1791 const struct switchdev_obj_port_vlan *vlan)
Vivien Didelot76e398a2015-11-01 12:33:55 -05001792{
Vivien Didelot04bed142016-08-31 18:06:13 -04001793 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot76e398a2015-11-01 12:33:55 -05001794 u16 pvid, vid;
1795 int err = 0;
1796
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001797 if (!chip->info->max_vid)
Vivien Didelot54d77b52016-05-09 13:22:47 -04001798 return -EOPNOTSUPP;
1799
Vivien Didelotfad09c72016-06-21 12:28:20 -04001800 mutex_lock(&chip->reg_lock);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001801
Vivien Didelot77064f32016-11-04 03:23:30 +01001802 err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001803 if (err)
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001804 goto unlock;
1805
Vivien Didelot76e398a2015-11-01 12:33:55 -05001806 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
Vivien Didelotfad09c72016-06-21 12:28:20 -04001807 err = _mv88e6xxx_port_vlan_del(chip, port, vid);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001808 if (err)
1809 goto unlock;
1810
1811 if (vid == pvid) {
Vivien Didelot77064f32016-11-04 03:23:30 +01001812 err = mv88e6xxx_port_set_pvid(chip, port, 0);
Vivien Didelot76e398a2015-11-01 12:33:55 -05001813 if (err)
1814 goto unlock;
1815 }
1816 }
1817
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001818unlock:
Vivien Didelotfad09c72016-06-21 12:28:20 -04001819 mutex_unlock(&chip->reg_lock);
Vivien Didelot7dad08d2015-08-13 12:52:21 -04001820
1821 return err;
1822}
1823
Arkadi Sharshevsky1b6dd552017-08-06 16:15:40 +03001824static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
1825 const unsigned char *addr, u16 vid)
Guenter Roeckdefb05b2015-03-26 18:36:38 -07001826{
Vivien Didelot04bed142016-08-31 18:06:13 -04001827 struct mv88e6xxx_chip *chip = ds->priv;
Arkadi Sharshevsky1b6dd552017-08-06 16:15:40 +03001828 int err;
Vivien Didelot6630e232015-08-06 01:44:07 -04001829
Vivien Didelotfad09c72016-06-21 12:28:20 -04001830 mutex_lock(&chip->reg_lock);
Arkadi Sharshevsky1b6dd552017-08-06 16:15:40 +03001831 err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
1832 MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
Vivien Didelotfad09c72016-06-21 12:28:20 -04001833 mutex_unlock(&chip->reg_lock);
Arkadi Sharshevsky1b6dd552017-08-06 16:15:40 +03001834
1835 return err;
David S. Millercdf09692015-08-11 12:00:37 -07001836}
1837
Vivien Didelotf81ec902016-05-09 13:22:58 -04001838static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
Arkadi Sharshevsky6c2c1dc2017-08-06 16:15:39 +03001839 const unsigned char *addr, u16 vid)
David S. Millercdf09692015-08-11 12:00:37 -07001840{
Vivien Didelot04bed142016-08-31 18:06:13 -04001841 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot83dabd12016-08-31 11:50:04 -04001842 int err;
David S. Millercdf09692015-08-11 12:00:37 -07001843
Vivien Didelotfad09c72016-06-21 12:28:20 -04001844 mutex_lock(&chip->reg_lock);
Arkadi Sharshevsky6c2c1dc2017-08-06 16:15:39 +03001845 err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
Vivien Didelot27c0e602017-06-15 12:14:01 -04001846 MV88E6XXX_G1_ATU_DATA_STATE_UNUSED);
Vivien Didelotfad09c72016-06-21 12:28:20 -04001847 mutex_unlock(&chip->reg_lock);
David S. Millercdf09692015-08-11 12:00:37 -07001848
Vivien Didelot83dabd12016-08-31 11:50:04 -04001849 return err;
David S. Millercdf09692015-08-11 12:00:37 -07001850}
1851
Vivien Didelot83dabd12016-08-31 11:50:04 -04001852static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
1853 u16 fid, u16 vid, int port,
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001854 dsa_fdb_dump_cb_t *cb, void *data)
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001855{
Vivien Didelotdabc1a92017-03-11 16:12:53 -05001856 struct mv88e6xxx_atu_entry addr;
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001857 bool is_static;
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001858 int err;
1859
Vivien Didelot27c0e602017-06-15 12:14:01 -04001860 addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
Vivien Didelotdabc1a92017-03-11 16:12:53 -05001861 eth_broadcast_addr(addr.mac);
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001862
1863 do {
Andrew Lunna61e5402018-02-15 14:38:35 +01001864 mutex_lock(&chip->reg_lock);
Vivien Didelotdabc1a92017-03-11 16:12:53 -05001865 err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
Andrew Lunna61e5402018-02-15 14:38:35 +01001866 mutex_unlock(&chip->reg_lock);
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001867 if (err)
Vivien Didelot83dabd12016-08-31 11:50:04 -04001868 return err;
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001869
Vivien Didelot27c0e602017-06-15 12:14:01 -04001870 if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED)
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001871 break;
1872
Vivien Didelot01bd96c2017-03-11 16:12:57 -05001873 if (addr.trunk || (addr.portvec & BIT(port)) == 0)
Vivien Didelot83dabd12016-08-31 11:50:04 -04001874 continue;
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001875
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001876 if (!is_unicast_ether_addr(addr.mac))
1877 continue;
Vivien Didelot83dabd12016-08-31 11:50:04 -04001878
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001879 is_static = (addr.state ==
1880 MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
1881 err = cb(addr.mac, vid, is_static, data);
Vivien Didelot83dabd12016-08-31 11:50:04 -04001882 if (err)
1883 return err;
Vivien Didelot74b6ba02016-02-26 13:16:02 -05001884 } while (!is_broadcast_ether_addr(addr.mac));
1885
1886 return err;
1887}
1888
Vivien Didelot83dabd12016-08-31 11:50:04 -04001889static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001890 dsa_fdb_dump_cb_t *cb, void *data)
Vivien Didelot83dabd12016-08-31 11:50:04 -04001891{
Vivien Didelotb4e47c02016-09-29 12:21:58 -04001892 struct mv88e6xxx_vtu_entry vlan = {
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001893 .vid = chip->info->max_vid,
Vivien Didelot83dabd12016-08-31 11:50:04 -04001894 };
1895 u16 fid;
1896 int err;
1897
1898 /* Dump port's default Filtering Information Database (VLAN ID 0) */
Andrew Lunna61e5402018-02-15 14:38:35 +01001899 mutex_lock(&chip->reg_lock);
Vivien Didelotb4e48c52016-11-04 03:23:29 +01001900 err = mv88e6xxx_port_get_fid(chip, port, &fid);
Andrew Lunna61e5402018-02-15 14:38:35 +01001901 mutex_unlock(&chip->reg_lock);
1902
Vivien Didelot83dabd12016-08-31 11:50:04 -04001903 if (err)
1904 return err;
1905
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001906 err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data);
Vivien Didelot83dabd12016-08-31 11:50:04 -04001907 if (err)
1908 return err;
1909
1910 /* Dump VLANs' Filtering Information Databases */
Vivien Didelot83dabd12016-08-31 11:50:04 -04001911 do {
Andrew Lunna61e5402018-02-15 14:38:35 +01001912 mutex_lock(&chip->reg_lock);
Vivien Didelotf1394b782017-05-01 14:05:22 -04001913 err = mv88e6xxx_vtu_getnext(chip, &vlan);
Andrew Lunna61e5402018-02-15 14:38:35 +01001914 mutex_unlock(&chip->reg_lock);
Vivien Didelot83dabd12016-08-31 11:50:04 -04001915 if (err)
1916 return err;
1917
1918 if (!vlan.valid)
1919 break;
1920
1921 err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001922 cb, data);
Vivien Didelot83dabd12016-08-31 11:50:04 -04001923 if (err)
1924 return err;
Vivien Didelot3cf3c842017-05-01 14:05:10 -04001925 } while (vlan.vid < chip->info->max_vid);
Vivien Didelot83dabd12016-08-31 11:50:04 -04001926
1927 return err;
1928}
1929
Vivien Didelotf81ec902016-05-09 13:22:58 -04001930static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
Arkadi Sharshevsky2bedde12017-08-06 16:15:49 +03001931 dsa_fdb_dump_cb_t *cb, void *data)
Vivien Didelotf33475b2015-10-22 09:34:41 -04001932{
Vivien Didelot04bed142016-08-31 18:06:13 -04001933 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelotf33475b2015-10-22 09:34:41 -04001934
Andrew Lunna61e5402018-02-15 14:38:35 +01001935 return mv88e6xxx_port_db_dump(chip, port, cb, data);
Vivien Didelotf33475b2015-10-22 09:34:41 -04001936}
1937
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001938static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
1939 struct net_device *br)
1940{
Vivien Didelote96a6e02017-03-30 17:37:13 -04001941 struct dsa_switch *ds;
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001942 int port;
Vivien Didelote96a6e02017-03-30 17:37:13 -04001943 int dev;
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001944 int err;
1945
1946 /* Remap the Port VLAN of each local bridge group member */
1947 for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
1948 if (chip->ds->ports[port].bridge_dev == br) {
1949 err = mv88e6xxx_port_vlan_map(chip, port);
1950 if (err)
1951 return err;
1952 }
1953 }
1954
Vivien Didelote96a6e02017-03-30 17:37:13 -04001955 if (!mv88e6xxx_has_pvt(chip))
1956 return 0;
1957
1958 /* Remap the Port VLAN of each cross-chip bridge group member */
1959 for (dev = 0; dev < DSA_MAX_SWITCHES; ++dev) {
1960 ds = chip->ds->dst->ds[dev];
1961 if (!ds)
1962 break;
1963
1964 for (port = 0; port < ds->num_ports; ++port) {
1965 if (ds->ports[port].bridge_dev == br) {
1966 err = mv88e6xxx_pvt_map(chip, dev, port);
1967 if (err)
1968 return err;
1969 }
1970 }
1971 }
1972
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001973 return 0;
1974}
1975
Vivien Didelotf81ec902016-05-09 13:22:58 -04001976static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
Vivien Didelotfae8a252017-01-27 15:29:42 -05001977 struct net_device *br)
Vivien Didelote79a8bc2015-11-04 17:23:40 -05001978{
Vivien Didelot04bed142016-08-31 18:06:13 -04001979 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001980 int err;
Vivien Didelot466dfa02016-02-26 13:16:05 -05001981
Vivien Didelotfad09c72016-06-21 12:28:20 -04001982 mutex_lock(&chip->reg_lock);
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001983 err = mv88e6xxx_bridge_map(chip, br);
Vivien Didelotfad09c72016-06-21 12:28:20 -04001984 mutex_unlock(&chip->reg_lock);
Vivien Didelota6692752016-02-12 12:09:39 -05001985
Vivien Didelot466dfa02016-02-26 13:16:05 -05001986 return err;
Vivien Didelote79a8bc2015-11-04 17:23:40 -05001987}
1988
Vivien Didelotf123f2f2017-01-27 15:29:41 -05001989static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
1990 struct net_device *br)
Vivien Didelote79a8bc2015-11-04 17:23:40 -05001991{
Vivien Didelot04bed142016-08-31 18:06:13 -04001992 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot466dfa02016-02-26 13:16:05 -05001993
Vivien Didelotfad09c72016-06-21 12:28:20 -04001994 mutex_lock(&chip->reg_lock);
Vivien Didelot240ea3e2017-03-30 17:37:12 -04001995 if (mv88e6xxx_bridge_map(chip, br) ||
1996 mv88e6xxx_port_vlan_map(chip, port))
1997 dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
Vivien Didelotfad09c72016-06-21 12:28:20 -04001998 mutex_unlock(&chip->reg_lock);
Vivien Didelot66d9cd02016-02-05 14:07:14 -05001999}
2000
Vivien Didelotaec5ac82017-03-30 17:37:15 -04002001static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev,
2002 int port, struct net_device *br)
2003{
2004 struct mv88e6xxx_chip *chip = ds->priv;
2005 int err;
2006
2007 if (!mv88e6xxx_has_pvt(chip))
2008 return 0;
2009
2010 mutex_lock(&chip->reg_lock);
2011 err = mv88e6xxx_pvt_map(chip, dev, port);
2012 mutex_unlock(&chip->reg_lock);
2013
2014 return err;
2015}
2016
2017static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev,
2018 int port, struct net_device *br)
2019{
2020 struct mv88e6xxx_chip *chip = ds->priv;
2021
2022 if (!mv88e6xxx_has_pvt(chip))
2023 return;
2024
2025 mutex_lock(&chip->reg_lock);
2026 if (mv88e6xxx_pvt_map(chip, dev, port))
2027 dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
2028 mutex_unlock(&chip->reg_lock);
2029}
2030
Vivien Didelot17e708b2016-12-05 17:30:27 -05002031static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
2032{
2033 if (chip->info->ops->reset)
2034 return chip->info->ops->reset(chip);
2035
2036 return 0;
2037}
2038
Vivien Didelot309eca62016-12-05 17:30:26 -05002039static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
2040{
2041 struct gpio_desc *gpiod = chip->reset;
2042
2043 /* If there is a GPIO connected to the reset pin, toggle it */
2044 if (gpiod) {
2045 gpiod_set_value_cansleep(gpiod, 1);
2046 usleep_range(10000, 20000);
2047 gpiod_set_value_cansleep(gpiod, 0);
2048 usleep_range(10000, 20000);
2049 }
2050}
2051
Vivien Didelot4ac4b5a2016-12-05 17:30:25 -05002052static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
2053{
2054 int i, err;
2055
2056 /* Set all ports to the Disabled state */
2057 for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
Vivien Didelotf894c292017-06-08 18:34:10 -04002058 err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED);
Vivien Didelot4ac4b5a2016-12-05 17:30:25 -05002059 if (err)
2060 return err;
2061 }
2062
2063 /* Wait for transmit queues to drain,
2064 * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
2065 */
2066 usleep_range(2000, 4000);
2067
2068 return 0;
2069}
2070
Vivien Didelotfad09c72016-06-21 12:28:20 -04002071static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
Vivien Didelot552238b2016-05-09 13:22:49 -04002072{
Vivien Didelota935c052016-09-29 12:21:53 -04002073 int err;
Vivien Didelot552238b2016-05-09 13:22:49 -04002074
Vivien Didelot4ac4b5a2016-12-05 17:30:25 -05002075 err = mv88e6xxx_disable_ports(chip);
2076 if (err)
2077 return err;
Vivien Didelot552238b2016-05-09 13:22:49 -04002078
Vivien Didelot309eca62016-12-05 17:30:26 -05002079 mv88e6xxx_hardware_reset(chip);
Vivien Didelot552238b2016-05-09 13:22:49 -04002080
Vivien Didelot17e708b2016-12-05 17:30:27 -05002081 return mv88e6xxx_software_reset(chip);
Vivien Didelot552238b2016-05-09 13:22:49 -04002082}
2083
Vivien Didelot43145572017-03-11 16:12:59 -05002084static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
Vivien Didelot31bef4e2017-06-08 18:34:09 -04002085 enum mv88e6xxx_frame_mode frame,
2086 enum mv88e6xxx_egress_mode egress, u16 etype)
Andrew Lunn56995cb2016-12-03 04:35:19 +01002087{
2088 int err;
2089
Vivien Didelot43145572017-03-11 16:12:59 -05002090 if (!chip->info->ops->port_set_frame_mode)
2091 return -EOPNOTSUPP;
2092
2093 err = mv88e6xxx_port_set_egress_mode(chip, port, egress);
Andrew Lunn56995cb2016-12-03 04:35:19 +01002094 if (err)
2095 return err;
2096
Vivien Didelot43145572017-03-11 16:12:59 -05002097 err = chip->info->ops->port_set_frame_mode(chip, port, frame);
2098 if (err)
2099 return err;
2100
2101 if (chip->info->ops->port_set_ether_type)
2102 return chip->info->ops->port_set_ether_type(chip, port, etype);
2103
2104 return 0;
2105}
2106
2107static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port)
2108{
2109 return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
Vivien Didelot31bef4e2017-06-08 18:34:09 -04002110 MV88E6XXX_EGRESS_MODE_UNMODIFIED,
Vivien Didelotb8109592017-06-12 12:37:45 -04002111 MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
Vivien Didelot43145572017-03-11 16:12:59 -05002112}
2113
2114static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
2115{
2116 return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
Vivien Didelot31bef4e2017-06-08 18:34:09 -04002117 MV88E6XXX_EGRESS_MODE_UNMODIFIED,
Vivien Didelotb8109592017-06-12 12:37:45 -04002118 MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
Vivien Didelot43145572017-03-11 16:12:59 -05002119}
2120
2121static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
2122{
2123 return mv88e6xxx_set_port_mode(chip, port,
2124 MV88E6XXX_FRAME_MODE_ETHERTYPE,
Vivien Didelot31bef4e2017-06-08 18:34:09 -04002125 MV88E6XXX_EGRESS_MODE_ETHERTYPE,
2126 ETH_P_EDSA);
Vivien Didelot43145572017-03-11 16:12:59 -05002127}
2128
2129static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
2130{
2131 if (dsa_is_dsa_port(chip->ds, port))
2132 return mv88e6xxx_set_port_mode_dsa(chip, port);
2133
Vivien Didelot2b3e9892017-10-26 11:22:54 -04002134 if (dsa_is_user_port(chip->ds, port))
Vivien Didelot43145572017-03-11 16:12:59 -05002135 return mv88e6xxx_set_port_mode_normal(chip, port);
2136
2137 /* Setup CPU port mode depending on its supported tag format */
2138 if (chip->info->tag_protocol == DSA_TAG_PROTO_DSA)
2139 return mv88e6xxx_set_port_mode_dsa(chip, port);
2140
2141 if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA)
2142 return mv88e6xxx_set_port_mode_edsa(chip, port);
2143
2144 return -EINVAL;
2145}
2146
Vivien Didelotea698f42017-03-11 16:12:50 -05002147static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
2148{
2149 bool message = dsa_is_dsa_port(chip->ds, port);
2150
2151 return mv88e6xxx_port_set_message_port(chip, port, message);
2152}
2153
Vivien Didelot601aeed2017-03-11 16:13:00 -05002154static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
2155{
Vivien Didelot3ee50cb2017-12-05 15:34:09 -05002156 struct dsa_switch *ds = chip->ds;
2157 bool flood;
Vivien Didelot601aeed2017-03-11 16:13:00 -05002158
2159 /* Upstream ports flood frames with unknown unicast or multicast DA */
Vivien Didelot3ee50cb2017-12-05 15:34:09 -05002160 flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port);
Vivien Didelot601aeed2017-03-11 16:13:00 -05002161 if (chip->info->ops->port_set_egress_floods)
2162 return chip->info->ops->port_set_egress_floods(chip, port,
2163 flood, flood);
2164
2165 return 0;
2166}
2167
Andrew Lunn6d917822017-05-26 01:03:21 +02002168static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
2169 bool on)
2170{
Vivien Didelot523a8902017-05-26 18:02:42 -04002171 if (chip->info->ops->serdes_power)
2172 return chip->info->ops->serdes_power(chip, port, on);
Andrew Lunn6d917822017-05-26 01:03:21 +02002173
Vivien Didelot523a8902017-05-26 18:02:42 -04002174 return 0;
Andrew Lunn6d917822017-05-26 01:03:21 +02002175}
2176
Vivien Didelotfa371c82017-12-05 15:34:10 -05002177static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
2178{
2179 struct dsa_switch *ds = chip->ds;
2180 int upstream_port;
2181 int err;
2182
Vivien Didelot07073c72017-12-05 15:34:13 -05002183 upstream_port = dsa_upstream_port(ds, port);
Vivien Didelotfa371c82017-12-05 15:34:10 -05002184 if (chip->info->ops->port_set_upstream_port) {
2185 err = chip->info->ops->port_set_upstream_port(chip, port,
2186 upstream_port);
2187 if (err)
2188 return err;
2189 }
2190
Vivien Didelot0ea54dd2017-12-05 15:34:11 -05002191 if (port == upstream_port) {
2192 if (chip->info->ops->set_cpu_port) {
2193 err = chip->info->ops->set_cpu_port(chip,
2194 upstream_port);
2195 if (err)
2196 return err;
2197 }
2198
2199 if (chip->info->ops->set_egress_port) {
2200 err = chip->info->ops->set_egress_port(chip,
2201 upstream_port);
2202 if (err)
2203 return err;
2204 }
2205 }
2206
Vivien Didelotfa371c82017-12-05 15:34:10 -05002207 return 0;
2208}
2209
Vivien Didelotfad09c72016-06-21 12:28:20 -04002210static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
Guenter Roeckd827e882015-03-26 18:36:29 -07002211{
Vivien Didelotfad09c72016-06-21 12:28:20 -04002212 struct dsa_switch *ds = chip->ds;
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002213 int err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002214 u16 reg;
Guenter Roeckd827e882015-03-26 18:36:29 -07002215
Andrew Lunn7b898462018-08-09 15:38:47 +02002216 chip->ports[port].chip = chip;
2217 chip->ports[port].port = port;
2218
Vivien Didelotd78343d2016-11-04 03:23:36 +01002219 /* MAC Forcing register: don't force link, speed, duplex or flow control
2220 * state to any particular values on physical ports, but force the CPU
2221 * port and all DSA ports to their maximum bandwidth and full duplex.
2222 */
2223 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
2224 err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
2225 SPEED_MAX, DUPLEX_FULL,
Andrew Lunn54186b92018-08-09 15:38:37 +02002226 PAUSE_OFF,
Vivien Didelotd78343d2016-11-04 03:23:36 +01002227 PHY_INTERFACE_MODE_NA);
2228 else
2229 err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
2230 SPEED_UNFORCED, DUPLEX_UNFORCED,
Andrew Lunn54186b92018-08-09 15:38:37 +02002231 PAUSE_ON,
Vivien Didelotd78343d2016-11-04 03:23:36 +01002232 PHY_INTERFACE_MODE_NA);
2233 if (err)
2234 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002235
2236 /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
2237 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
2238 * tunneling, determine priority by looking at 802.1p and IP
2239 * priority fields (IP prio has precedence), and set STP state
2240 * to Forwarding.
2241 *
2242 * If this is the CPU link, use DSA or EDSA tagging depending
2243 * on which tagging mode was configured.
2244 *
2245 * If this is a link to another switch, use DSA tagging mode.
2246 *
2247 * If this is the upstream port for this switch, enable
2248 * forwarding of unknown unicasts and multicasts.
2249 */
Vivien Didelota89b433be2017-06-12 12:37:37 -04002250 reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
2251 MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
2252 MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
2253 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
Andrew Lunn56995cb2016-12-03 04:35:19 +01002254 if (err)
2255 return err;
Andrew Lunn6083ce72015-08-17 23:52:52 +02002256
Vivien Didelot601aeed2017-03-11 16:13:00 -05002257 err = mv88e6xxx_setup_port_mode(chip, port);
Andrew Lunn56995cb2016-12-03 04:35:19 +01002258 if (err)
2259 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002260
Vivien Didelot601aeed2017-03-11 16:13:00 -05002261 err = mv88e6xxx_setup_egress_floods(chip, port);
Vivien Didelot43145572017-03-11 16:12:59 -05002262 if (err)
2263 return err;
2264
Andrew Lunn04aca992017-05-26 01:03:24 +02002265 /* Enable the SERDES interface for DSA and CPU ports. Normal
2266 * ports SERDES are enabled when the port is enabled, thus
2267 * saving a bit of power.
Patrick Uiterwijk13a7ebb2016-03-30 01:39:41 +00002268 */
Andrew Lunn04aca992017-05-26 01:03:24 +02002269 if ((dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))) {
2270 err = mv88e6xxx_serdes_power(chip, port, true);
2271 if (err)
2272 return err;
2273 }
Patrick Uiterwijk13a7ebb2016-03-30 01:39:41 +00002274
Vivien Didelot8efdda42015-08-13 12:52:23 -04002275 /* Port Control 2: don't force a good FCS, set the maximum frame size to
Vivien Didelot46fbe5e2016-02-26 13:16:07 -05002276 * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
Vivien Didelot8efdda42015-08-13 12:52:23 -04002277 * untagged frames on this port, do a destination address lookup on all
2278 * received packets as usual, disable ARP mirroring and don't send a
2279 * copy of all transmitted/received frames on this port to the CPU.
Andrew Lunn54d792f2015-05-06 01:09:47 +02002280 */
Andrew Lunna23b2962017-02-04 20:15:28 +01002281 err = mv88e6xxx_port_set_map_da(chip, port);
2282 if (err)
2283 return err;
2284
Vivien Didelotfa371c82017-12-05 15:34:10 -05002285 err = mv88e6xxx_setup_upstream_port(chip, port);
2286 if (err)
2287 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002288
Andrew Lunna23b2962017-02-04 20:15:28 +01002289 err = mv88e6xxx_port_set_8021q_mode(chip, port,
Vivien Didelot81c6edb2017-06-12 12:37:41 -04002290 MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED);
Andrew Lunna23b2962017-02-04 20:15:28 +01002291 if (err)
2292 return err;
2293
Vivien Didelotcd782652017-06-08 18:34:13 -04002294 if (chip->info->ops->port_set_jumbo_size) {
2295 err = chip->info->ops->port_set_jumbo_size(chip, port, 10240);
Andrew Lunn5f436662016-12-03 04:45:17 +01002296 if (err)
2297 return err;
2298 }
2299
Andrew Lunn54d792f2015-05-06 01:09:47 +02002300 /* Port Association Vector: when learning source addresses
2301 * of packets, add the address to the address database using
2302 * a port bitmap that has only the bit for this port set and
2303 * the other bits clear.
2304 */
Andrew Lunn4c7ea3c2015-11-03 10:52:36 -05002305 reg = 1 << port;
Vivien Didelot996ecb82016-04-14 14:42:08 -04002306 /* Disable learning for CPU port */
2307 if (dsa_is_cpu_port(ds, port))
Vivien Didelot65fa4022016-04-14 14:42:07 -04002308 reg = 0;
Andrew Lunn4c7ea3c2015-11-03 10:52:36 -05002309
Vivien Didelot2a4614e2017-06-12 12:37:43 -04002310 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
2311 reg);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002312 if (err)
2313 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002314
2315 /* Egress rate control 2: disable egress rate control. */
Vivien Didelot2cb8cb12017-06-12 12:37:42 -04002316 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2,
2317 0x0000);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002318 if (err)
2319 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002320
Vivien Didelot08984322017-06-08 18:34:12 -04002321 if (chip->info->ops->port_pause_limit) {
2322 err = chip->info->ops->port_pause_limit(chip, port, 0, 0);
Andrew Lunnb35d322a2016-12-03 04:45:19 +01002323 if (err)
2324 return err;
2325 }
2326
Vivien Didelotc8c94892017-03-11 16:13:01 -05002327 if (chip->info->ops->port_disable_learn_limit) {
2328 err = chip->info->ops->port_disable_learn_limit(chip, port);
2329 if (err)
2330 return err;
2331 }
2332
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05002333 if (chip->info->ops->port_disable_pri_override) {
2334 err = chip->info->ops->port_disable_pri_override(chip, port);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002335 if (err)
2336 return err;
Andrew Lunnef0a7312016-12-03 04:35:16 +01002337 }
Andrew Lunn2bbb33b2016-08-22 16:01:02 +02002338
Andrew Lunnef0a7312016-12-03 04:35:16 +01002339 if (chip->info->ops->port_tag_remap) {
2340 err = chip->info->ops->port_tag_remap(chip, port);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002341 if (err)
2342 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002343 }
2344
Andrew Lunnef70b112016-12-03 04:45:18 +01002345 if (chip->info->ops->port_egress_rate_limiting) {
2346 err = chip->info->ops->port_egress_rate_limiting(chip, port);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002347 if (err)
2348 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002349 }
2350
Vivien Didelotea698f42017-03-11 16:12:50 -05002351 err = mv88e6xxx_setup_message_port(chip, port);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002352 if (err)
2353 return err;
Guenter Roeckd827e882015-03-26 18:36:29 -07002354
Vivien Didelot207afda2016-04-14 14:42:09 -04002355 /* Port based VLAN map: give each port the same default address
Vivien Didelotb7666ef2016-02-26 13:16:06 -05002356 * database, and allow bidirectional communication between the
2357 * CPU and DSA port(s), and the other ports.
Guenter Roeckd827e882015-03-26 18:36:29 -07002358 */
Vivien Didelotb4e48c52016-11-04 03:23:29 +01002359 err = mv88e6xxx_port_set_fid(chip, port, 0);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002360 if (err)
2361 return err;
Vivien Didelot2db9ce12016-02-26 13:16:04 -05002362
Vivien Didelot240ea3e2017-03-30 17:37:12 -04002363 err = mv88e6xxx_port_vlan_map(chip, port);
Andrew Lunn0e7b9922016-09-21 01:40:31 +02002364 if (err)
2365 return err;
Guenter Roeckd827e882015-03-26 18:36:29 -07002366
2367 /* Default VLAN ID and priority: don't set a default VLAN
2368 * ID, and set the default packet priority to zero.
2369 */
Vivien Didelotb7929fb2017-06-12 12:37:40 -04002370 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
Andrew Lunndbde9e62015-05-06 01:09:48 +02002371}
2372
Andrew Lunn04aca992017-05-26 01:03:24 +02002373static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
2374 struct phy_device *phydev)
2375{
2376 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot523a8902017-05-26 18:02:42 -04002377 int err;
Andrew Lunn04aca992017-05-26 01:03:24 +02002378
2379 mutex_lock(&chip->reg_lock);
Andrew Lunnefd1ba62018-08-09 15:38:48 +02002380
Vivien Didelot523a8902017-05-26 18:02:42 -04002381 err = mv88e6xxx_serdes_power(chip, port, true);
Andrew Lunnefd1ba62018-08-09 15:38:48 +02002382
2383 if (!err && chip->info->ops->serdes_irq_setup)
2384 err = chip->info->ops->serdes_irq_setup(chip, port);
2385
Andrew Lunn04aca992017-05-26 01:03:24 +02002386 mutex_unlock(&chip->reg_lock);
2387
2388 return err;
2389}
2390
Andrew Lunn75104db2019-02-24 20:44:43 +01002391static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port)
Andrew Lunn04aca992017-05-26 01:03:24 +02002392{
2393 struct mv88e6xxx_chip *chip = ds->priv;
2394
2395 mutex_lock(&chip->reg_lock);
Andrew Lunnefd1ba62018-08-09 15:38:48 +02002396
2397 if (chip->info->ops->serdes_irq_free)
2398 chip->info->ops->serdes_irq_free(chip, port);
2399
Vivien Didelot523a8902017-05-26 18:02:42 -04002400 if (mv88e6xxx_serdes_power(chip, port, false))
2401 dev_err(chip->dev, "failed to power off SERDES\n");
Andrew Lunnefd1ba62018-08-09 15:38:48 +02002402
Andrew Lunn04aca992017-05-26 01:03:24 +02002403 mutex_unlock(&chip->reg_lock);
2404}
2405
Vivien Didelot2cfcd962016-07-18 20:45:40 -04002406static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds,
2407 unsigned int ageing_time)
2408{
Vivien Didelot04bed142016-08-31 18:06:13 -04002409 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot2cfcd962016-07-18 20:45:40 -04002410 int err;
2411
2412 mutex_lock(&chip->reg_lock);
Vivien Didelot720c6342017-03-11 16:12:48 -05002413 err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time);
Vivien Didelot2cfcd962016-07-18 20:45:40 -04002414 mutex_unlock(&chip->reg_lock);
2415
2416 return err;
2417}
2418
Vivien Didelot447b1bb2018-05-11 17:16:36 -04002419static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
Vivien Didelot08a01262016-05-09 13:22:50 -04002420{
2421 int err;
Vivien Didelot08a01262016-05-09 13:22:50 -04002422
Andrew Lunnde2273872016-11-21 23:27:01 +01002423 /* Initialize the statistics unit */
Vivien Didelot447b1bb2018-05-11 17:16:36 -04002424 if (chip->info->ops->stats_set_histogram) {
2425 err = chip->info->ops->stats_set_histogram(chip);
2426 if (err)
2427 return err;
2428 }
Andrew Lunnde2273872016-11-21 23:27:01 +01002429
Andrew Lunn40cff8f2017-11-10 00:36:41 +01002430 return mv88e6xxx_g1_stats_clear(chip);
Vivien Didelot97299342016-07-18 20:45:30 -04002431}
2432
Andrew Lunnea890982019-01-09 00:24:03 +01002433/* The mv88e6390 has some hidden registers used for debug and
2434 * development. The errata also makes use of them.
2435 */
2436static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
2437 int reg, u16 val)
2438{
2439 u16 ctrl;
2440 int err;
2441
2442 err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
2443 PORT_RESERVED_1A, val);
2444 if (err)
2445 return err;
2446
2447 ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
2448 PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
2449 reg;
2450
2451 return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
2452 PORT_RESERVED_1A, ctrl);
2453}
2454
2455static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
2456{
2457 return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
2458 PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
2459}
2460
2461
2462static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
2463 int reg, u16 *val)
2464{
2465 u16 ctrl;
2466 int err;
2467
2468 ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
2469 PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
2470 reg;
2471
2472 err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
2473 PORT_RESERVED_1A, ctrl);
2474 if (err)
2475 return err;
2476
2477 err = mv88e6390_hidden_wait(chip);
2478 if (err)
2479 return err;
2480
2481 return mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
2482 PORT_RESERVED_1A, val);
2483}
2484
2485/* Check if the errata has already been applied. */
2486static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
2487{
2488 int port;
2489 int err;
2490 u16 val;
2491
2492 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
2493 err = mv88e6390_hidden_read(chip, port, 0, &val);
2494 if (err) {
2495 dev_err(chip->dev,
2496 "Error reading hidden register: %d\n", err);
2497 return false;
2498 }
2499 if (val != 0x01c0)
2500 return false;
2501 }
2502
2503 return true;
2504}
2505
2506/* The 6390 copper ports have an errata which require poking magic
2507 * values into undocumented hidden registers and then performing a
2508 * software reset.
2509 */
2510static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
2511{
2512 int port;
2513 int err;
2514
2515 if (mv88e6390_setup_errata_applied(chip))
2516 return 0;
2517
2518 /* Set the ports into blocking mode */
2519 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
2520 err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
2521 if (err)
2522 return err;
2523 }
2524
2525 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
2526 err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
2527 if (err)
2528 return err;
2529 }
2530
2531 return mv88e6xxx_software_reset(chip);
2532}
2533
Vivien Didelotf81ec902016-05-09 13:22:58 -04002534static int mv88e6xxx_setup(struct dsa_switch *ds)
Guenter Roeckacdaffc2015-03-26 18:36:28 -07002535{
Vivien Didelot04bed142016-08-31 18:06:13 -04002536 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002537 u8 cmode;
Vivien Didelot552238b2016-05-09 13:22:49 -04002538 int err;
Vivien Didelota1a6a4d2016-05-09 13:22:56 -04002539 int i;
2540
Vivien Didelotfad09c72016-06-21 12:28:20 -04002541 chip->ds = ds;
Andrew Lunna3c53be52017-01-24 14:53:50 +01002542 ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
Vivien Didelot552238b2016-05-09 13:22:49 -04002543
Vivien Didelotfad09c72016-06-21 12:28:20 -04002544 mutex_lock(&chip->reg_lock);
Vivien Didelot552238b2016-05-09 13:22:49 -04002545
Andrew Lunnea890982019-01-09 00:24:03 +01002546 if (chip->info->ops->setup_errata) {
2547 err = chip->info->ops->setup_errata(chip);
2548 if (err)
2549 goto unlock;
2550 }
2551
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002552 /* Cache the cmode of each port. */
2553 for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
2554 if (chip->info->ops->port_get_cmode) {
2555 err = chip->info->ops->port_get_cmode(chip, i, &cmode);
2556 if (err)
Dan Carpentere29129f2018-08-14 12:09:05 +03002557 goto unlock;
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002558
2559 chip->ports[i].cmode = cmode;
2560 }
2561 }
2562
Vivien Didelot97299342016-07-18 20:45:30 -04002563 /* Setup Switch Port Registers */
Vivien Didelot370b4ff2016-09-29 12:21:57 -04002564 for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
Vivien Didelot91dee142017-10-26 11:22:52 -04002565 if (dsa_is_unused_port(ds, i))
2566 continue;
2567
Vivien Didelot97299342016-07-18 20:45:30 -04002568 err = mv88e6xxx_setup_port(chip, i);
2569 if (err)
2570 goto unlock;
2571 }
2572
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04002573 err = mv88e6xxx_irl_setup(chip);
2574 if (err)
2575 goto unlock;
2576
Vivien Didelot04a69a12017-10-13 14:18:05 -04002577 err = mv88e6xxx_mac_setup(chip);
2578 if (err)
2579 goto unlock;
2580
Vivien Didelot1b17aed2017-05-26 18:03:05 -04002581 err = mv88e6xxx_phy_setup(chip);
2582 if (err)
2583 goto unlock;
2584
Vivien Didelotb486d7c2017-05-01 14:05:13 -04002585 err = mv88e6xxx_vtu_setup(chip);
2586 if (err)
2587 goto unlock;
2588
Vivien Didelot81228992017-03-30 17:37:08 -04002589 err = mv88e6xxx_pvt_setup(chip);
2590 if (err)
2591 goto unlock;
2592
Vivien Didelota2ac29d2017-03-11 16:12:49 -05002593 err = mv88e6xxx_atu_setup(chip);
2594 if (err)
2595 goto unlock;
2596
Andrew Lunn87fa8862017-11-09 22:29:56 +01002597 err = mv88e6xxx_broadcast_setup(chip, 0);
2598 if (err)
2599 goto unlock;
2600
Vivien Didelot9e907d72017-07-17 13:03:43 -04002601 err = mv88e6xxx_pot_setup(chip);
2602 if (err)
2603 goto unlock;
2604
Vivien Didelot9e5baf92018-05-09 11:38:51 -04002605 err = mv88e6xxx_rmu_setup(chip);
2606 if (err)
2607 goto unlock;
2608
Vivien Didelot51c901a2017-07-17 13:03:41 -04002609 err = mv88e6xxx_rsvd2cpu_setup(chip);
2610 if (err)
2611 goto unlock;
Andrew Lunn6e55f692016-12-03 04:45:16 +01002612
Vivien Didelotb28f8722018-04-26 21:56:44 -04002613 err = mv88e6xxx_trunk_setup(chip);
2614 if (err)
2615 goto unlock;
2616
Vivien Didelotc7f047b2018-04-26 21:56:45 -04002617 err = mv88e6xxx_devmap_setup(chip);
2618 if (err)
2619 goto unlock;
2620
Vivien Didelot93e18d62018-05-11 17:16:35 -04002621 err = mv88e6xxx_pri_setup(chip);
2622 if (err)
2623 goto unlock;
2624
Brandon Streiffc6fe0ad2018-02-14 01:07:50 +01002625 /* Setup PTP Hardware Clock and timestamping */
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01002626 if (chip->info->ptp_support) {
2627 err = mv88e6xxx_ptp_setup(chip);
2628 if (err)
2629 goto unlock;
Brandon Streiffc6fe0ad2018-02-14 01:07:50 +01002630
2631 err = mv88e6xxx_hwtstamp_setup(chip);
2632 if (err)
2633 goto unlock;
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01002634 }
2635
Vivien Didelot447b1bb2018-05-11 17:16:36 -04002636 err = mv88e6xxx_stats_setup(chip);
2637 if (err)
2638 goto unlock;
2639
Vivien Didelot6b17e862015-08-13 12:52:18 -04002640unlock:
Vivien Didelotfad09c72016-06-21 12:28:20 -04002641 mutex_unlock(&chip->reg_lock);
Andrew Lunndb687a52015-06-20 21:31:29 +02002642
Andrew Lunn48ace4e2016-04-14 23:47:12 +02002643 return err;
Andrew Lunn54d792f2015-05-06 01:09:47 +02002644}
2645
Vivien Didelote57e5e72016-08-15 17:19:00 -04002646static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02002647{
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002648 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
2649 struct mv88e6xxx_chip *chip = mdio_bus->chip;
Vivien Didelote57e5e72016-08-15 17:19:00 -04002650 u16 val;
2651 int err;
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02002652
Andrew Lunnee26a222017-01-24 14:53:48 +01002653 if (!chip->info->ops->phy_read)
2654 return -EOPNOTSUPP;
2655
Vivien Didelotfad09c72016-06-21 12:28:20 -04002656 mutex_lock(&chip->reg_lock);
Andrew Lunnee26a222017-01-24 14:53:48 +01002657 err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
Vivien Didelotfad09c72016-06-21 12:28:20 -04002658 mutex_unlock(&chip->reg_lock);
Vivien Didelote57e5e72016-08-15 17:19:00 -04002659
Andrew Lunnda9f3302017-02-01 03:40:05 +01002660 if (reg == MII_PHYSID2) {
Andrew Lunnddc49ac2018-11-12 18:51:01 +01002661 /* Some internal PHYs don't have a model number. */
2662 if (chip->info->family != MV88E6XXX_FAMILY_6165)
2663 /* Then there is the 6165 family. It gets is
2664 * PHYs correct. But it can also have two
2665 * SERDES interfaces in the PHY address
2666 * space. And these don't have a model
2667 * number. But they are not PHYs, so we don't
2668 * want to give them something a PHY driver
2669 * will recognise.
2670 *
2671 * Use the mv88e6390 family model number
2672 * instead, for anything which really could be
2673 * a PHY,
2674 */
2675 if (!(val & 0x3f0))
2676 val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
Andrew Lunnda9f3302017-02-01 03:40:05 +01002677 }
2678
Vivien Didelote57e5e72016-08-15 17:19:00 -04002679 return err ? err : val;
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02002680}
2681
Vivien Didelote57e5e72016-08-15 17:19:00 -04002682static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02002683{
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002684 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
2685 struct mv88e6xxx_chip *chip = mdio_bus->chip;
Vivien Didelote57e5e72016-08-15 17:19:00 -04002686 int err;
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02002687
Andrew Lunnee26a222017-01-24 14:53:48 +01002688 if (!chip->info->ops->phy_write)
2689 return -EOPNOTSUPP;
2690
Vivien Didelotfad09c72016-06-21 12:28:20 -04002691 mutex_lock(&chip->reg_lock);
Andrew Lunnee26a222017-01-24 14:53:48 +01002692 err = chip->info->ops->phy_write(chip, bus, phy, reg, val);
Vivien Didelotfad09c72016-06-21 12:28:20 -04002693 mutex_unlock(&chip->reg_lock);
Vivien Didelote57e5e72016-08-15 17:19:00 -04002694
2695 return err;
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02002696}
2697
Vivien Didelotfad09c72016-06-21 12:28:20 -04002698static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
Andrew Lunna3c53be52017-01-24 14:53:50 +01002699 struct device_node *np,
2700 bool external)
Andrew Lunnb516d452016-06-04 21:17:06 +02002701{
2702 static int index;
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002703 struct mv88e6xxx_mdio_bus *mdio_bus;
Andrew Lunnb516d452016-06-04 21:17:06 +02002704 struct mii_bus *bus;
2705 int err;
2706
Andrew Lunn2510bab2018-02-22 01:51:49 +01002707 if (external) {
2708 mutex_lock(&chip->reg_lock);
2709 err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true);
2710 mutex_unlock(&chip->reg_lock);
2711
2712 if (err)
2713 return err;
2714 }
2715
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002716 bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus));
Andrew Lunnb516d452016-06-04 21:17:06 +02002717 if (!bus)
2718 return -ENOMEM;
2719
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002720 mdio_bus = bus->priv;
Andrew Lunna3c53be52017-01-24 14:53:50 +01002721 mdio_bus->bus = bus;
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002722 mdio_bus->chip = chip;
Andrew Lunna3c53be52017-01-24 14:53:50 +01002723 INIT_LIST_HEAD(&mdio_bus->list);
2724 mdio_bus->external = external;
Andrew Lunn0dd12d52017-01-24 14:53:49 +01002725
Andrew Lunnb516d452016-06-04 21:17:06 +02002726 if (np) {
2727 bus->name = np->full_name;
Rob Herringf7ce9102017-07-18 16:43:19 -05002728 snprintf(bus->id, MII_BUS_ID_SIZE, "%pOF", np);
Andrew Lunnb516d452016-06-04 21:17:06 +02002729 } else {
2730 bus->name = "mv88e6xxx SMI";
2731 snprintf(bus->id, MII_BUS_ID_SIZE, "mv88e6xxx-%d", index++);
2732 }
2733
2734 bus->read = mv88e6xxx_mdio_read;
2735 bus->write = mv88e6xxx_mdio_write;
Vivien Didelotfad09c72016-06-21 12:28:20 -04002736 bus->parent = chip->dev;
Andrew Lunnb516d452016-06-04 21:17:06 +02002737
Andrew Lunn6f882842018-03-17 20:32:05 +01002738 if (!external) {
2739 err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
2740 if (err)
2741 return err;
2742 }
2743
Florian Fainelli00e798c2018-05-15 16:56:19 -07002744 err = of_mdiobus_register(bus, np);
Andrew Lunnb516d452016-06-04 21:17:06 +02002745 if (err) {
Vivien Didelotfad09c72016-06-21 12:28:20 -04002746 dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
Andrew Lunn6f882842018-03-17 20:32:05 +01002747 mv88e6xxx_g2_irq_mdio_free(chip, bus);
Andrew Lunna3c53be52017-01-24 14:53:50 +01002748 return err;
Andrew Lunnb516d452016-06-04 21:17:06 +02002749 }
Andrew Lunna3c53be52017-01-24 14:53:50 +01002750
2751 if (external)
2752 list_add_tail(&mdio_bus->list, &chip->mdios);
2753 else
2754 list_add(&mdio_bus->list, &chip->mdios);
Andrew Lunnb516d452016-06-04 21:17:06 +02002755
2756 return 0;
Andrew Lunnb516d452016-06-04 21:17:06 +02002757}
2758
Andrew Lunna3c53be52017-01-24 14:53:50 +01002759static const struct of_device_id mv88e6xxx_mdio_external_match[] = {
2760 { .compatible = "marvell,mv88e6xxx-mdio-external",
2761 .data = (void *)true },
2762 { },
2763};
2764
Andrew Lunn3126aee2017-12-07 01:05:57 +01002765static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)
2766
2767{
2768 struct mv88e6xxx_mdio_bus *mdio_bus;
2769 struct mii_bus *bus;
2770
2771 list_for_each_entry(mdio_bus, &chip->mdios, list) {
2772 bus = mdio_bus->bus;
2773
Andrew Lunn6f882842018-03-17 20:32:05 +01002774 if (!mdio_bus->external)
2775 mv88e6xxx_g2_irq_mdio_free(chip, bus);
2776
Andrew Lunn3126aee2017-12-07 01:05:57 +01002777 mdiobus_unregister(bus);
2778 }
2779}
2780
Andrew Lunna3c53be52017-01-24 14:53:50 +01002781static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
2782 struct device_node *np)
2783{
2784 const struct of_device_id *match;
2785 struct device_node *child;
2786 int err;
2787
2788 /* Always register one mdio bus for the internal/default mdio
2789 * bus. This maybe represented in the device tree, but is
2790 * optional.
2791 */
2792 child = of_get_child_by_name(np, "mdio");
2793 err = mv88e6xxx_mdio_register(chip, child, false);
2794 if (err)
2795 return err;
2796
2797 /* Walk the device tree, and see if there are any other nodes
2798 * which say they are compatible with the external mdio
2799 * bus.
2800 */
2801 for_each_available_child_of_node(np, child) {
2802 match = of_match_node(mv88e6xxx_mdio_external_match, child);
2803 if (match) {
2804 err = mv88e6xxx_mdio_register(chip, child, true);
Andrew Lunn3126aee2017-12-07 01:05:57 +01002805 if (err) {
2806 mv88e6xxx_mdios_unregister(chip);
Andrew Lunna3c53be52017-01-24 14:53:50 +01002807 return err;
Andrew Lunn3126aee2017-12-07 01:05:57 +01002808 }
Andrew Lunna3c53be52017-01-24 14:53:50 +01002809 }
2810 }
2811
2812 return 0;
2813}
2814
Vivien Didelot855b1932016-07-20 18:18:35 -04002815static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
2816{
Vivien Didelot04bed142016-08-31 18:06:13 -04002817 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot855b1932016-07-20 18:18:35 -04002818
2819 return chip->eeprom_len;
2820}
2821
Vivien Didelot855b1932016-07-20 18:18:35 -04002822static int mv88e6xxx_get_eeprom(struct dsa_switch *ds,
2823 struct ethtool_eeprom *eeprom, u8 *data)
2824{
Vivien Didelot04bed142016-08-31 18:06:13 -04002825 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot855b1932016-07-20 18:18:35 -04002826 int err;
2827
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04002828 if (!chip->info->ops->get_eeprom)
2829 return -EOPNOTSUPP;
2830
Vivien Didelot855b1932016-07-20 18:18:35 -04002831 mutex_lock(&chip->reg_lock);
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04002832 err = chip->info->ops->get_eeprom(chip, eeprom, data);
Vivien Didelot855b1932016-07-20 18:18:35 -04002833 mutex_unlock(&chip->reg_lock);
2834
2835 if (err)
2836 return err;
2837
2838 eeprom->magic = 0xc3ec4951;
2839
2840 return 0;
2841}
2842
Vivien Didelot855b1932016-07-20 18:18:35 -04002843static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
2844 struct ethtool_eeprom *eeprom, u8 *data)
2845{
Vivien Didelot04bed142016-08-31 18:06:13 -04002846 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot855b1932016-07-20 18:18:35 -04002847 int err;
2848
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04002849 if (!chip->info->ops->set_eeprom)
2850 return -EOPNOTSUPP;
2851
Vivien Didelot855b1932016-07-20 18:18:35 -04002852 if (eeprom->magic != 0xc3ec4951)
2853 return -EINVAL;
2854
2855 mutex_lock(&chip->reg_lock);
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04002856 err = chip->info->ops->set_eeprom(chip, eeprom, data);
Vivien Didelot855b1932016-07-20 18:18:35 -04002857 mutex_unlock(&chip->reg_lock);
2858
2859 return err;
2860}
2861
Vivien Didelotb3469dd2016-09-29 12:22:00 -04002862static const struct mv88e6xxx_ops mv88e6085_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01002863 /* MV88E6XXX_FAMILY_6097 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04002864 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2865 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04002866 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04002867 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
Vivien Didelot7e20cfb2017-05-26 18:03:06 -04002868 .phy_read = mv88e6185_phy_ppu_read,
2869 .phy_write = mv88e6185_phy_ppu_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01002870 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01002871 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01002872 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01002873 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01002874 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05002875 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01002876 .port_set_ether_type = mv88e6351_port_set_ether_type,
Andrew Lunnef70b112016-12-03 04:45:18 +01002877 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04002878 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05002879 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05002880 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02002881 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002882 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01002883 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01002884 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01002885 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2886 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01002887 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04002888 .set_cpu_port = mv88e6095_g1_set_cpu_port,
2889 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01002890 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04002891 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04002892 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelota199d8b2016-12-05 17:30:28 -05002893 .ppu_enable = mv88e6185_g1_ppu_enable,
2894 .ppu_disable = mv88e6185_g1_ppu_disable,
Vivien Didelot17e708b2016-12-05 17:30:27 -05002895 .reset = mv88e6185_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04002896 .rmu_disable = mv88e6085_g1_rmu_disable,
Vivien Didelotf1394b782017-05-01 14:05:22 -04002897 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04002898 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02002899 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04002900};
2901
2902static const struct mv88e6xxx_ops mv88e6095_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01002903 /* MV88E6XXX_FAMILY_6095 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04002904 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2905 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04002906 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
Vivien Didelot7e20cfb2017-05-26 18:03:06 -04002907 .phy_read = mv88e6185_phy_ppu_read,
2908 .phy_write = mv88e6185_phy_ppu_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01002909 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01002910 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01002911 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunn56995cb2016-12-03 04:35:19 +01002912 .port_set_frame_mode = mv88e6085_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05002913 .port_set_egress_floods = mv88e6185_port_set_egress_floods,
Andrew Lunna23b2962017-02-04 20:15:28 +01002914 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
Russell King6c422e32018-08-09 15:38:39 +02002915 .port_link_state = mv88e6185_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002916 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01002917 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01002918 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01002919 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2920 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01002921 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelot51c901a2017-07-17 13:03:41 -04002922 .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
Vivien Didelota199d8b2016-12-05 17:30:28 -05002923 .ppu_enable = mv88e6185_g1_ppu_enable,
2924 .ppu_disable = mv88e6185_g1_ppu_disable,
Vivien Didelot17e708b2016-12-05 17:30:27 -05002925 .reset = mv88e6185_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04002926 .vtu_getnext = mv88e6185_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04002927 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02002928 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04002929};
2930
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01002931static const struct mv88e6xxx_ops mv88e6097_ops = {
Stefan Eichenberger15da3cc2016-11-25 09:41:30 +01002932 /* MV88E6XXX_FAMILY_6097 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04002933 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2934 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04002935 .irl_init_all = mv88e6352_g2_irl_init_all,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01002936 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2937 .phy_read = mv88e6xxx_g2_smi_phy_read,
2938 .phy_write = mv88e6xxx_g2_smi_phy_write,
2939 .port_set_link = mv88e6xxx_port_set_link,
2940 .port_set_duplex = mv88e6xxx_port_set_duplex,
2941 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01002942 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01002943 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05002944 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01002945 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04002946 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01002947 .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04002948 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05002949 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05002950 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02002951 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002952 .port_get_cmode = mv88e6185_port_get_cmode,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01002953 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01002954 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01002955 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2956 .stats_get_strings = mv88e6095_stats_get_strings,
2957 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04002958 .set_cpu_port = mv88e6095_g1_set_cpu_port,
2959 .set_egress_port = mv88e6095_g1_set_egress_port,
Volodymyr Bendiuga91eaa472017-02-14 11:29:30 +01002960 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04002961 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04002962 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05002963 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04002964 .rmu_disable = mv88e6085_g1_rmu_disable,
Vivien Didelotf1394b782017-05-01 14:05:22 -04002965 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04002966 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02002967 .phylink_validate = mv88e6185_phylink_validate,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01002968};
2969
Vivien Didelotb3469dd2016-09-29 12:22:00 -04002970static const struct mv88e6xxx_ops mv88e6123_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01002971 /* MV88E6XXX_FAMILY_6165 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04002972 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2973 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04002974 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04002975 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Andrew Lunnec8378b2017-06-02 23:22:45 +02002976 .phy_read = mv88e6xxx_g2_smi_phy_read,
2977 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01002978 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01002979 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01002980 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunn56995cb2016-12-03 04:35:19 +01002981 .port_set_frame_mode = mv88e6085_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05002982 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Vivien Didelotc8c94892017-03-11 16:13:01 -05002983 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05002984 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02002985 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02002986 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunn0ac64c32017-06-02 23:22:46 +02002987 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01002988 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01002989 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2990 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01002991 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04002992 .set_cpu_port = mv88e6095_g1_set_cpu_port,
2993 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01002994 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04002995 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04002996 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05002997 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04002998 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04002999 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02003000 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003001};
3002
3003static const struct mv88e6xxx_ops mv88e6131_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003004 /* MV88E6XXX_FAMILY_6185 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003005 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3006 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003007 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
Vivien Didelot7e20cfb2017-05-26 18:03:06 -04003008 .phy_read = mv88e6185_phy_ppu_read,
3009 .phy_write = mv88e6185_phy_ppu_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003010 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003011 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003012 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003013 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003014 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003015 .port_set_egress_floods = mv88e6185_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003016 .port_set_ether_type = mv88e6351_port_set_ether_type,
Andrew Lunna23b2962017-02-04 20:15:28 +01003017 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
Vivien Didelotcd782652017-06-08 18:34:13 -04003018 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003019 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003020 .port_pause_limit = mv88e6097_port_pause_limit,
Andrew Lunn54186b92018-08-09 15:38:37 +02003021 .port_set_pause = mv88e6185_port_set_pause,
Russell King6c422e32018-08-09 15:38:39 +02003022 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003023 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003024 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003025 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003026 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3027 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003028 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003029 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3030 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003031 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003032 .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
Vivien Didelota199d8b2016-12-05 17:30:28 -05003033 .ppu_enable = mv88e6185_g1_ppu_enable,
Vivien Didelot02317e62018-05-09 11:38:49 -04003034 .set_cascade_port = mv88e6185_g1_set_cascade_port,
Vivien Didelota199d8b2016-12-05 17:30:28 -05003035 .ppu_disable = mv88e6185_g1_ppu_disable,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003036 .reset = mv88e6185_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003037 .vtu_getnext = mv88e6185_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003038 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02003039 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003040};
3041
Vivien Didelot990e27b2017-03-28 13:50:32 -04003042static const struct mv88e6xxx_ops mv88e6141_ops = {
3043 /* MV88E6XXX_FAMILY_6341 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003044 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3045 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003046 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003047 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3048 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3049 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3050 .phy_read = mv88e6xxx_g2_smi_phy_read,
3051 .phy_write = mv88e6xxx_g2_smi_phy_write,
3052 .port_set_link = mv88e6xxx_port_set_link,
3053 .port_set_duplex = mv88e6xxx_port_set_duplex,
3054 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
Marek Behún26422342018-10-13 14:40:31 +02003055 .port_set_speed = mv88e6341_port_set_speed,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003056 .port_tag_remap = mv88e6095_port_tag_remap,
3057 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3058 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3059 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003060 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003061 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003062 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003063 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3064 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003065 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003066 .port_get_cmode = mv88e6352_port_get_cmode,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003067 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003068 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003069 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3070 .stats_get_strings = mv88e6320_stats_get_strings,
3071 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003072 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3073 .set_egress_port = mv88e6390_g1_set_egress_port,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003074 .watchdog_ops = &mv88e6390_watchdog_ops,
3075 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003076 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003077 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003078 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003079 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunn6751e7c2018-07-31 19:19:50 +02003080 .serdes_power = mv88e6341_serdes_power,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003081 .gpio_ops = &mv88e6352_gpio_ops,
Russell King6c422e32018-08-09 15:38:39 +02003082 .phylink_validate = mv88e6390_phylink_validate,
Vivien Didelot990e27b2017-03-28 13:50:32 -04003083};
3084
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003085static const struct mv88e6xxx_ops mv88e6161_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003086 /* MV88E6XXX_FAMILY_6165 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003087 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3088 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003089 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003090 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Andrew Lunnec8378b2017-06-02 23:22:45 +02003091 .phy_read = mv88e6xxx_g2_smi_phy_read,
3092 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003093 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003094 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003095 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003096 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003097 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003098 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003099 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003100 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003101 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003102 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003103 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003104 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003105 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003106 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunn0ac64c32017-06-02 23:22:46 +02003107 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003108 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003109 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3110 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003111 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003112 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3113 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003114 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003115 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003116 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003117 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003118 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003119 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunna469a612018-07-18 22:38:21 +02003120 .avb_ops = &mv88e6165_avb_ops,
Andrew Lunndfa54342018-07-18 22:38:22 +02003121 .ptp_ops = &mv88e6165_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003122 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003123};
3124
3125static const struct mv88e6xxx_ops mv88e6165_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003126 /* MV88E6XXX_FAMILY_6165 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003127 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3128 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003129 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003130 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Andrew Lunnefb3e742017-01-24 14:53:47 +01003131 .phy_read = mv88e6165_phy_read,
3132 .phy_write = mv88e6165_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003133 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003134 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003135 .port_set_speed = mv88e6185_port_set_speed,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003136 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003137 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003138 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003139 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003140 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003141 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003142 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3143 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003144 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003145 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3146 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003147 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003148 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003149 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003150 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003151 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003152 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunna469a612018-07-18 22:38:21 +02003153 .avb_ops = &mv88e6165_avb_ops,
Andrew Lunndfa54342018-07-18 22:38:22 +02003154 .ptp_ops = &mv88e6165_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003155 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003156};
3157
3158static const struct mv88e6xxx_ops mv88e6171_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003159 /* MV88E6XXX_FAMILY_6351 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003160 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3161 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003162 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003163 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003164 .phy_read = mv88e6xxx_g2_smi_phy_read,
3165 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003166 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003167 .port_set_duplex = mv88e6xxx_port_set_duplex,
Andrew Lunn94d66ae2016-11-10 15:44:01 +01003168 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003169 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003170 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003171 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003172 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003173 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003174 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003175 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003176 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003177 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003178 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003179 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003180 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003181 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003182 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003183 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3184 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003185 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003186 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3187 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003188 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003189 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003190 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003191 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003192 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003193 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02003194 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003195};
3196
3197static const struct mv88e6xxx_ops mv88e6172_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003198 /* MV88E6XXX_FAMILY_6352 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003199 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3200 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003201 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04003202 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3203 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003204 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003205 .phy_read = mv88e6xxx_g2_smi_phy_read,
3206 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003207 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003208 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelota0a0f622016-11-04 03:23:34 +01003209 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003210 .port_set_speed = mv88e6352_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003211 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003212 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003213 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003214 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003215 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003216 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003217 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003218 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003219 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003220 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003221 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003222 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003223 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003224 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3225 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003226 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003227 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3228 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003229 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003230 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003231 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003232 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003233 .rmu_disable = mv88e6352_g1_rmu_disable,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003234 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003235 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunn6d917822017-05-26 01:03:21 +02003236 .serdes_power = mv88e6352_serdes_power,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003237 .gpio_ops = &mv88e6352_gpio_ops,
Russell King6c422e32018-08-09 15:38:39 +02003238 .phylink_validate = mv88e6352_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003239};
3240
3241static const struct mv88e6xxx_ops mv88e6175_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003242 /* MV88E6XXX_FAMILY_6351 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003243 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3244 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003245 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003246 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003247 .phy_read = mv88e6xxx_g2_smi_phy_read,
3248 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003249 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003250 .port_set_duplex = mv88e6xxx_port_set_duplex,
Andrew Lunn94d66ae2016-11-10 15:44:01 +01003251 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003252 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003253 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003254 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003255 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003256 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003257 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003258 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003259 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003260 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003261 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003262 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003263 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003264 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003265 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003266 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3267 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003268 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003269 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3270 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003271 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003272 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003273 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003274 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003275 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003276 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02003277 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003278};
3279
3280static const struct mv88e6xxx_ops mv88e6176_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003281 /* MV88E6XXX_FAMILY_6352 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003282 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3283 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003284 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04003285 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3286 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003287 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003288 .phy_read = mv88e6xxx_g2_smi_phy_read,
3289 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003290 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003291 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelota0a0f622016-11-04 03:23:34 +01003292 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003293 .port_set_speed = mv88e6352_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003294 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003295 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003296 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003297 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003298 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003299 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003300 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003301 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003302 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003303 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003304 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003305 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003306 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003307 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3308 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003309 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003310 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3311 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003312 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003313 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003314 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003315 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003316 .rmu_disable = mv88e6352_g1_rmu_disable,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003317 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003318 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunn6d917822017-05-26 01:03:21 +02003319 .serdes_power = mv88e6352_serdes_power,
Andrew Lunn43821722018-09-02 18:13:15 +02003320 .serdes_irq_setup = mv88e6352_serdes_irq_setup,
3321 .serdes_irq_free = mv88e6352_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003322 .gpio_ops = &mv88e6352_gpio_ops,
Russell King6c422e32018-08-09 15:38:39 +02003323 .phylink_validate = mv88e6352_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003324};
3325
3326static const struct mv88e6xxx_ops mv88e6185_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003327 /* MV88E6XXX_FAMILY_6185 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003328 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3329 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003330 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
Vivien Didelot7e20cfb2017-05-26 18:03:06 -04003331 .phy_read = mv88e6185_phy_ppu_read,
3332 .phy_write = mv88e6185_phy_ppu_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003333 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003334 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003335 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003336 .port_set_frame_mode = mv88e6085_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003337 .port_set_egress_floods = mv88e6185_port_set_egress_floods,
Andrew Lunnef70b112016-12-03 04:45:18 +01003338 .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
Andrew Lunna23b2962017-02-04 20:15:28 +01003339 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
Andrew Lunn54186b92018-08-09 15:38:37 +02003340 .port_set_pause = mv88e6185_port_set_pause,
Russell King6c422e32018-08-09 15:38:39 +02003341 .port_link_state = mv88e6185_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003342 .port_get_cmode = mv88e6185_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003343 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003344 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003345 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3346 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003347 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003348 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3349 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003350 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003351 .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
Vivien Didelot02317e62018-05-09 11:38:49 -04003352 .set_cascade_port = mv88e6185_g1_set_cascade_port,
Vivien Didelota199d8b2016-12-05 17:30:28 -05003353 .ppu_enable = mv88e6185_g1_ppu_enable,
3354 .ppu_disable = mv88e6185_g1_ppu_disable,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003355 .reset = mv88e6185_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003356 .vtu_getnext = mv88e6185_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003357 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02003358 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003359};
3360
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003361static const struct mv88e6xxx_ops mv88e6190_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003362 /* MV88E6XXX_FAMILY_6390 */
Andrew Lunnea890982019-01-09 00:24:03 +01003363 .setup_errata = mv88e6390_setup_errata,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003364 .irl_init_all = mv88e6390_g2_irl_init_all,
Vivien Didelot98fc3c62017-01-12 18:07:16 -05003365 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3366 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003367 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3368 .phy_read = mv88e6xxx_g2_smi_phy_read,
3369 .phy_write = mv88e6xxx_g2_smi_phy_write,
3370 .port_set_link = mv88e6xxx_port_set_link,
3371 .port_set_duplex = mv88e6xxx_port_set_duplex,
3372 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3373 .port_set_speed = mv88e6390_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003374 .port_tag_remap = mv88e6390_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003375 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003376 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003377 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelot08984322017-06-08 18:34:12 -04003378 .port_pause_limit = mv88e6390_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003379 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003380 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003381 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003382 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunnfdc71ee2018-11-11 00:32:15 +01003383 .port_set_cmode = mv88e6390_port_set_cmode,
Andrew Lunn79523472016-11-21 23:27:00 +01003384 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunnde2273872016-11-21 23:27:01 +01003385 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003386 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3387 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunne0d8b612016-11-21 23:27:04 +01003388 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003389 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3390 .set_egress_port = mv88e6390_g1_set_egress_port,
Andrew Lunn61303732017-02-09 00:03:43 +01003391 .watchdog_ops = &mv88e6390_watchdog_ops,
Andrew Lunn6e55f692016-12-03 04:45:16 +01003392 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003393 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003394 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003395 .rmu_disable = mv88e6390_g1_rmu_disable,
Vivien Didelot931d1822017-05-01 14:05:27 -04003396 .vtu_getnext = mv88e6390_g1_vtu_getnext,
3397 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
Andrew Lunn6335e9f2017-05-26 01:03:23 +02003398 .serdes_power = mv88e6390_serdes_power,
Andrew Lunnefd1ba62018-08-09 15:38:48 +02003399 .serdes_irq_setup = mv88e6390_serdes_irq_setup,
3400 .serdes_irq_free = mv88e6390_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003401 .gpio_ops = &mv88e6352_gpio_ops,
Russell King6c422e32018-08-09 15:38:39 +02003402 .phylink_validate = mv88e6390_phylink_validate,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003403};
3404
3405static const struct mv88e6xxx_ops mv88e6190x_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003406 /* MV88E6XXX_FAMILY_6390 */
Andrew Lunnea890982019-01-09 00:24:03 +01003407 .setup_errata = mv88e6390_setup_errata,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003408 .irl_init_all = mv88e6390_g2_irl_init_all,
Vivien Didelot98fc3c62017-01-12 18:07:16 -05003409 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3410 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003411 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3412 .phy_read = mv88e6xxx_g2_smi_phy_read,
3413 .phy_write = mv88e6xxx_g2_smi_phy_write,
3414 .port_set_link = mv88e6xxx_port_set_link,
3415 .port_set_duplex = mv88e6xxx_port_set_duplex,
3416 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3417 .port_set_speed = mv88e6390x_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003418 .port_tag_remap = mv88e6390_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003419 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003420 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003421 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelot08984322017-06-08 18:34:12 -04003422 .port_pause_limit = mv88e6390_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003423 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003424 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003425 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003426 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunnfdc71ee2018-11-11 00:32:15 +01003427 .port_set_cmode = mv88e6390x_port_set_cmode,
Andrew Lunn79523472016-11-21 23:27:00 +01003428 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunnde2273872016-11-21 23:27:01 +01003429 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003430 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3431 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunne0d8b612016-11-21 23:27:04 +01003432 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003433 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3434 .set_egress_port = mv88e6390_g1_set_egress_port,
Andrew Lunn61303732017-02-09 00:03:43 +01003435 .watchdog_ops = &mv88e6390_watchdog_ops,
Andrew Lunn6e55f692016-12-03 04:45:16 +01003436 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003437 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003438 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003439 .rmu_disable = mv88e6390_g1_rmu_disable,
Vivien Didelot931d1822017-05-01 14:05:27 -04003440 .vtu_getnext = mv88e6390_g1_vtu_getnext,
3441 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
Andrew Lunn07ffbd72018-08-09 15:38:41 +02003442 .serdes_power = mv88e6390x_serdes_power,
Andrew Lunn2defda12018-11-11 00:32:17 +01003443 .serdes_irq_setup = mv88e6390x_serdes_irq_setup,
3444 .serdes_irq_free = mv88e6390x_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003445 .gpio_ops = &mv88e6352_gpio_ops,
Russell King6c422e32018-08-09 15:38:39 +02003446 .phylink_validate = mv88e6390x_phylink_validate,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003447};
3448
3449static const struct mv88e6xxx_ops mv88e6191_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003450 /* MV88E6XXX_FAMILY_6390 */
Andrew Lunnea890982019-01-09 00:24:03 +01003451 .setup_errata = mv88e6390_setup_errata,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003452 .irl_init_all = mv88e6390_g2_irl_init_all,
Vivien Didelot98fc3c62017-01-12 18:07:16 -05003453 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3454 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003455 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3456 .phy_read = mv88e6xxx_g2_smi_phy_read,
3457 .phy_write = mv88e6xxx_g2_smi_phy_write,
3458 .port_set_link = mv88e6xxx_port_set_link,
3459 .port_set_duplex = mv88e6xxx_port_set_duplex,
3460 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3461 .port_set_speed = mv88e6390_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003462 .port_tag_remap = mv88e6390_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003463 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003464 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003465 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelot08984322017-06-08 18:34:12 -04003466 .port_pause_limit = mv88e6390_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003467 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003468 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003469 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003470 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunnfdc71ee2018-11-11 00:32:15 +01003471 .port_set_cmode = mv88e6390_port_set_cmode,
Andrew Lunn79523472016-11-21 23:27:00 +01003472 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunnde2273872016-11-21 23:27:01 +01003473 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003474 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3475 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunne0d8b612016-11-21 23:27:04 +01003476 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003477 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3478 .set_egress_port = mv88e6390_g1_set_egress_port,
Andrew Lunn61303732017-02-09 00:03:43 +01003479 .watchdog_ops = &mv88e6390_watchdog_ops,
Andrew Lunn6e55f692016-12-03 04:45:16 +01003480 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003481 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003482 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003483 .rmu_disable = mv88e6390_g1_rmu_disable,
Vivien Didelot931d1822017-05-01 14:05:27 -04003484 .vtu_getnext = mv88e6390_g1_vtu_getnext,
3485 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
Andrew Lunn6335e9f2017-05-26 01:03:23 +02003486 .serdes_power = mv88e6390_serdes_power,
Andrew Lunnefd1ba62018-08-09 15:38:48 +02003487 .serdes_irq_setup = mv88e6390_serdes_irq_setup,
3488 .serdes_irq_free = mv88e6390_serdes_irq_free,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003489 .avb_ops = &mv88e6390_avb_ops,
3490 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003491 .phylink_validate = mv88e6390_phylink_validate,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003492};
3493
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003494static const struct mv88e6xxx_ops mv88e6240_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003495 /* MV88E6XXX_FAMILY_6352 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003496 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3497 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003498 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04003499 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3500 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003501 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003502 .phy_read = mv88e6xxx_g2_smi_phy_read,
3503 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003504 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003505 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelota0a0f622016-11-04 03:23:34 +01003506 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003507 .port_set_speed = mv88e6352_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003508 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003509 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003510 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003511 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003512 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003513 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003514 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003515 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003516 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003517 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003518 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003519 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003520 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003521 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3522 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003523 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003524 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3525 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003526 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003527 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003528 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003529 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003530 .rmu_disable = mv88e6352_g1_rmu_disable,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003531 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003532 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunn6d917822017-05-26 01:03:21 +02003533 .serdes_power = mv88e6352_serdes_power,
Andrew Lunn43821722018-09-02 18:13:15 +02003534 .serdes_irq_setup = mv88e6352_serdes_irq_setup,
3535 .serdes_irq_free = mv88e6352_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003536 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003537 .avb_ops = &mv88e6352_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003538 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003539 .phylink_validate = mv88e6352_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003540};
3541
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003542static const struct mv88e6xxx_ops mv88e6290_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003543 /* MV88E6XXX_FAMILY_6390 */
Andrew Lunnea890982019-01-09 00:24:03 +01003544 .setup_errata = mv88e6390_setup_errata,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003545 .irl_init_all = mv88e6390_g2_irl_init_all,
Vivien Didelot98fc3c62017-01-12 18:07:16 -05003546 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3547 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003548 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3549 .phy_read = mv88e6xxx_g2_smi_phy_read,
3550 .phy_write = mv88e6xxx_g2_smi_phy_write,
3551 .port_set_link = mv88e6xxx_port_set_link,
3552 .port_set_duplex = mv88e6xxx_port_set_duplex,
3553 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3554 .port_set_speed = mv88e6390_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003555 .port_tag_remap = mv88e6390_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003556 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003557 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003558 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelot08984322017-06-08 18:34:12 -04003559 .port_pause_limit = mv88e6390_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003560 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003561 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003562 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003563 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunnfdc71ee2018-11-11 00:32:15 +01003564 .port_set_cmode = mv88e6390_port_set_cmode,
Andrew Lunn79523472016-11-21 23:27:00 +01003565 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunnde2273872016-11-21 23:27:01 +01003566 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003567 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3568 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunne0d8b612016-11-21 23:27:04 +01003569 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003570 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3571 .set_egress_port = mv88e6390_g1_set_egress_port,
Andrew Lunn61303732017-02-09 00:03:43 +01003572 .watchdog_ops = &mv88e6390_watchdog_ops,
Andrew Lunn6e55f692016-12-03 04:45:16 +01003573 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003574 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003575 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003576 .rmu_disable = mv88e6390_g1_rmu_disable,
Vivien Didelot931d1822017-05-01 14:05:27 -04003577 .vtu_getnext = mv88e6390_g1_vtu_getnext,
3578 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
Andrew Lunn6335e9f2017-05-26 01:03:23 +02003579 .serdes_power = mv88e6390_serdes_power,
Andrew Lunnefd1ba62018-08-09 15:38:48 +02003580 .serdes_irq_setup = mv88e6390_serdes_irq_setup,
3581 .serdes_irq_free = mv88e6390_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003582 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003583 .avb_ops = &mv88e6390_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003584 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003585 .phylink_validate = mv88e6390_phylink_validate,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003586};
3587
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003588static const struct mv88e6xxx_ops mv88e6320_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003589 /* MV88E6XXX_FAMILY_6320 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003590 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3591 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003592 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04003593 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3594 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003595 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003596 .phy_read = mv88e6xxx_g2_smi_phy_read,
3597 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003598 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003599 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003600 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003601 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003602 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003603 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003604 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003605 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003606 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003607 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003608 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003609 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003610 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003611 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003612 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003613 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003614 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3615 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003616 .stats_get_stats = mv88e6320_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003617 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3618 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunn9c7f37e2018-12-19 18:28:54 +01003619 .watchdog_ops = &mv88e6390_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003620 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003621 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003622 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003623 .vtu_getnext = mv88e6185_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003624 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003625 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003626 .avb_ops = &mv88e6352_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003627 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003628 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003629};
3630
3631static const struct mv88e6xxx_ops mv88e6321_ops = {
Vivien Didelotbd807202017-07-17 13:03:37 -04003632 /* MV88E6XXX_FAMILY_6320 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003633 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3634 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003635 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04003636 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3637 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003638 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003639 .phy_read = mv88e6xxx_g2_smi_phy_read,
3640 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003641 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003642 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003643 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003644 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003645 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003646 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003647 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003648 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003649 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003650 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003651 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003652 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003653 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003654 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003655 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003656 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003657 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3658 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003659 .stats_get_stats = mv88e6320_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003660 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3661 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunn9c7f37e2018-12-19 18:28:54 +01003662 .watchdog_ops = &mv88e6390_watchdog_ops,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003663 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003664 .vtu_getnext = mv88e6185_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003665 .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003666 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003667 .avb_ops = &mv88e6352_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003668 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003669 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003670};
3671
Vivien Didelot16e329a2017-03-28 13:50:33 -04003672static const struct mv88e6xxx_ops mv88e6341_ops = {
3673 /* MV88E6XXX_FAMILY_6341 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003674 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3675 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003676 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003677 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3678 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3679 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3680 .phy_read = mv88e6xxx_g2_smi_phy_read,
3681 .phy_write = mv88e6xxx_g2_smi_phy_write,
3682 .port_set_link = mv88e6xxx_port_set_link,
3683 .port_set_duplex = mv88e6xxx_port_set_duplex,
3684 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
Marek Behún26422342018-10-13 14:40:31 +02003685 .port_set_speed = mv88e6341_port_set_speed,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003686 .port_tag_remap = mv88e6095_port_tag_remap,
3687 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3688 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3689 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003690 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003691 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003692 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003693 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3694 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003695 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003696 .port_get_cmode = mv88e6352_port_get_cmode,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003697 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003698 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003699 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3700 .stats_get_strings = mv88e6320_stats_get_strings,
3701 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003702 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3703 .set_egress_port = mv88e6390_g1_set_egress_port,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003704 .watchdog_ops = &mv88e6390_watchdog_ops,
3705 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003706 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003707 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003708 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003709 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunn6751e7c2018-07-31 19:19:50 +02003710 .serdes_power = mv88e6341_serdes_power,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003711 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003712 .avb_ops = &mv88e6390_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003713 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003714 .phylink_validate = mv88e6390_phylink_validate,
Vivien Didelot16e329a2017-03-28 13:50:33 -04003715};
3716
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003717static const struct mv88e6xxx_ops mv88e6350_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003718 /* MV88E6XXX_FAMILY_6351 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003719 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3720 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003721 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003722 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003723 .phy_read = mv88e6xxx_g2_smi_phy_read,
3724 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003725 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003726 .port_set_duplex = mv88e6xxx_port_set_duplex,
Andrew Lunn94d66ae2016-11-10 15:44:01 +01003727 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003728 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003729 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003730 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003731 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003732 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003733 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003734 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003735 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003736 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003737 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003738 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003739 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003740 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003741 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003742 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3743 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003744 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003745 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3746 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003747 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003748 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003749 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003750 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003751 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003752 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Russell King6c422e32018-08-09 15:38:39 +02003753 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003754};
3755
3756static const struct mv88e6xxx_ops mv88e6351_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003757 /* MV88E6XXX_FAMILY_6351 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003758 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3759 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003760 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003761 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003762 .phy_read = mv88e6xxx_g2_smi_phy_read,
3763 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003764 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003765 .port_set_duplex = mv88e6xxx_port_set_duplex,
Andrew Lunn94d66ae2016-11-10 15:44:01 +01003766 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003767 .port_set_speed = mv88e6185_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003768 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003769 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003770 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003771 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003772 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003773 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003774 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003775 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003776 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003777 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003778 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003779 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003780 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003781 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3782 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003783 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003784 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3785 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003786 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003787 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003788 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003789 .reset = mv88e6352_g1_reset,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003790 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003791 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003792 .avb_ops = &mv88e6352_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003793 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003794 .phylink_validate = mv88e6185_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003795};
3796
3797static const struct mv88e6xxx_ops mv88e6352_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003798 /* MV88E6XXX_FAMILY_6352 */
Vivien Didelot93e18d62018-05-11 17:16:35 -04003799 .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3800 .ip_pri_map = mv88e6085_g1_ip_pri_map,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003801 .irl_init_all = mv88e6352_g2_irl_init_all,
Vivien Didelotee4dc2e72016-09-29 12:22:02 -04003802 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3803 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
Vivien Didelotb073d4e2016-09-29 12:22:01 -04003804 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003805 .phy_read = mv88e6xxx_g2_smi_phy_read,
3806 .phy_write = mv88e6xxx_g2_smi_phy_write,
Vivien Didelot08ef7f12016-11-04 03:23:32 +01003807 .port_set_link = mv88e6xxx_port_set_link,
Vivien Didelot7f1ae072016-11-04 03:23:33 +01003808 .port_set_duplex = mv88e6xxx_port_set_duplex,
Vivien Didelota0a0f622016-11-04 03:23:34 +01003809 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
Vivien Didelot96a2b402016-11-04 03:23:35 +01003810 .port_set_speed = mv88e6352_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003811 .port_tag_remap = mv88e6095_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003812 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003813 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003814 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003815 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003816 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003817 .port_pause_limit = mv88e6097_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003818 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003819 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003820 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003821 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunna605a0f2016-11-21 23:26:58 +01003822 .stats_snapshot = mv88e6320_g1_stats_snapshot,
Andrew Lunn40cff8f2017-11-10 00:36:41 +01003823 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003824 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3825 .stats_get_strings = mv88e6095_stats_get_strings,
Andrew Lunn052f9472016-11-21 23:27:03 +01003826 .stats_get_stats = mv88e6095_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003827 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3828 .set_egress_port = mv88e6095_g1_set_egress_port,
Andrew Lunnfcd25162017-02-09 00:03:42 +01003829 .watchdog_ops = &mv88e6097_watchdog_ops,
Vivien Didelot51c901a2017-07-17 13:03:41 -04003830 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003831 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003832 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003833 .rmu_disable = mv88e6352_g1_rmu_disable,
Vivien Didelotf1394b782017-05-01 14:05:22 -04003834 .vtu_getnext = mv88e6352_g1_vtu_getnext,
Vivien Didelot0ad5daf2017-05-01 14:05:23 -04003835 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
Andrew Lunn6d917822017-05-26 01:03:21 +02003836 .serdes_power = mv88e6352_serdes_power,
Andrew Lunn43821722018-09-02 18:13:15 +02003837 .serdes_irq_setup = mv88e6352_serdes_irq_setup,
3838 .serdes_irq_free = mv88e6352_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003839 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003840 .avb_ops = &mv88e6352_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003841 .ptp_ops = &mv88e6352_ptp_ops,
Andrew Lunncda9f4a2018-03-01 02:02:31 +01003842 .serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
3843 .serdes_get_strings = mv88e6352_serdes_get_strings,
3844 .serdes_get_stats = mv88e6352_serdes_get_stats,
Russell King6c422e32018-08-09 15:38:39 +02003845 .phylink_validate = mv88e6352_phylink_validate,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003846};
3847
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003848static const struct mv88e6xxx_ops mv88e6390_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003849 /* MV88E6XXX_FAMILY_6390 */
Andrew Lunnea890982019-01-09 00:24:03 +01003850 .setup_errata = mv88e6390_setup_errata,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003851 .irl_init_all = mv88e6390_g2_irl_init_all,
Vivien Didelot98fc3c62017-01-12 18:07:16 -05003852 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3853 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003854 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3855 .phy_read = mv88e6xxx_g2_smi_phy_read,
3856 .phy_write = mv88e6xxx_g2_smi_phy_write,
3857 .port_set_link = mv88e6xxx_port_set_link,
3858 .port_set_duplex = mv88e6xxx_port_set_duplex,
3859 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3860 .port_set_speed = mv88e6390_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003861 .port_tag_remap = mv88e6390_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003862 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003863 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003864 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003865 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003866 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003867 .port_pause_limit = mv88e6390_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003868 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003869 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003870 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003871 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunnfdc71ee2018-11-11 00:32:15 +01003872 .port_set_cmode = mv88e6390_port_set_cmode,
Andrew Lunn79523472016-11-21 23:27:00 +01003873 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunnde2273872016-11-21 23:27:01 +01003874 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003875 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3876 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunne0d8b612016-11-21 23:27:04 +01003877 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003878 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3879 .set_egress_port = mv88e6390_g1_set_egress_port,
Andrew Lunn61303732017-02-09 00:03:43 +01003880 .watchdog_ops = &mv88e6390_watchdog_ops,
Andrew Lunn6e55f692016-12-03 04:45:16 +01003881 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003882 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003883 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003884 .rmu_disable = mv88e6390_g1_rmu_disable,
Vivien Didelot931d1822017-05-01 14:05:27 -04003885 .vtu_getnext = mv88e6390_g1_vtu_getnext,
3886 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
Andrew Lunn6335e9f2017-05-26 01:03:23 +02003887 .serdes_power = mv88e6390_serdes_power,
Andrew Lunnefd1ba62018-08-09 15:38:48 +02003888 .serdes_irq_setup = mv88e6390_serdes_irq_setup,
3889 .serdes_irq_free = mv88e6390_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003890 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003891 .avb_ops = &mv88e6390_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003892 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003893 .phylink_validate = mv88e6390_phylink_validate,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003894};
3895
3896static const struct mv88e6xxx_ops mv88e6390x_ops = {
Andrew Lunn4b325d82016-11-21 23:26:59 +01003897 /* MV88E6XXX_FAMILY_6390 */
Andrew Lunnea890982019-01-09 00:24:03 +01003898 .setup_errata = mv88e6390_setup_errata,
Vivien Didelotcd8da8b2017-06-19 10:55:36 -04003899 .irl_init_all = mv88e6390_g2_irl_init_all,
Vivien Didelot98fc3c62017-01-12 18:07:16 -05003900 .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3901 .set_eeprom = mv88e6xxx_g2_set_eeprom8,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003902 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3903 .phy_read = mv88e6xxx_g2_smi_phy_read,
3904 .phy_write = mv88e6xxx_g2_smi_phy_write,
3905 .port_set_link = mv88e6xxx_port_set_link,
3906 .port_set_duplex = mv88e6xxx_port_set_duplex,
3907 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3908 .port_set_speed = mv88e6390x_port_set_speed,
Andrew Lunnef0a7312016-12-03 04:35:16 +01003909 .port_tag_remap = mv88e6390_port_tag_remap,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003910 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
Vivien Didelot601aeed2017-03-11 16:13:00 -05003911 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
Andrew Lunn56995cb2016-12-03 04:35:19 +01003912 .port_set_ether_type = mv88e6351_port_set_ether_type,
Vivien Didelotcd782652017-06-08 18:34:13 -04003913 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
Andrew Lunnef70b112016-12-03 04:45:18 +01003914 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
Vivien Didelot08984322017-06-08 18:34:12 -04003915 .port_pause_limit = mv88e6390_port_pause_limit,
Vivien Didelotc8c94892017-03-11 16:13:01 -05003916 .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
Vivien Didelot9dbfb4e2017-03-11 16:13:02 -05003917 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
Russell King6c422e32018-08-09 15:38:39 +02003918 .port_link_state = mv88e6352_port_link_state,
Andrew Lunn2d2e1dd2018-08-09 15:38:45 +02003919 .port_get_cmode = mv88e6352_port_get_cmode,
Andrew Lunnb3dce4d2018-11-11 00:32:14 +01003920 .port_set_cmode = mv88e6390x_port_set_cmode,
Andrew Lunn79523472016-11-21 23:27:00 +01003921 .stats_snapshot = mv88e6390_g1_stats_snapshot,
Andrew Lunnde2273872016-11-21 23:27:01 +01003922 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
Andrew Lunndfafe442016-11-21 23:27:02 +01003923 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3924 .stats_get_strings = mv88e6320_stats_get_strings,
Andrew Lunne0d8b612016-11-21 23:27:04 +01003925 .stats_get_stats = mv88e6390_stats_get_stats,
Vivien Didelotfa8d1172017-06-08 18:34:11 -04003926 .set_cpu_port = mv88e6390_g1_set_cpu_port,
3927 .set_egress_port = mv88e6390_g1_set_egress_port,
Andrew Lunn61303732017-02-09 00:03:43 +01003928 .watchdog_ops = &mv88e6390_watchdog_ops,
Andrew Lunn6e55f692016-12-03 04:45:16 +01003929 .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
Vivien Didelot9e907d72017-07-17 13:03:43 -04003930 .pot_clear = mv88e6xxx_g2_pot_clear,
Vivien Didelot17e708b2016-12-05 17:30:27 -05003931 .reset = mv88e6352_g1_reset,
Vivien Didelot9e5baf92018-05-09 11:38:51 -04003932 .rmu_disable = mv88e6390_g1_rmu_disable,
Vivien Didelot931d1822017-05-01 14:05:27 -04003933 .vtu_getnext = mv88e6390_g1_vtu_getnext,
3934 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
Andrew Lunn07ffbd72018-08-09 15:38:41 +02003935 .serdes_power = mv88e6390x_serdes_power,
Andrew Lunn2defda12018-11-11 00:32:17 +01003936 .serdes_irq_setup = mv88e6390x_serdes_irq_setup,
3937 .serdes_irq_free = mv88e6390x_serdes_irq_free,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01003938 .gpio_ops = &mv88e6352_gpio_ops,
Brandon Streiff0d632c32018-02-14 01:07:44 +01003939 .avb_ops = &mv88e6390_avb_ops,
Andrew Lunn6d2ac8e2018-07-18 22:38:20 +02003940 .ptp_ops = &mv88e6352_ptp_ops,
Russell King6c422e32018-08-09 15:38:39 +02003941 .phylink_validate = mv88e6390x_phylink_validate,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01003942};
3943
Vivien Didelotf81ec902016-05-09 13:22:58 -04003944static const struct mv88e6xxx_info mv88e6xxx_table[] = {
3945 [MV88E6085] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04003946 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
Vivien Didelotf81ec902016-05-09 13:22:58 -04003947 .family = MV88E6XXX_FAMILY_6097,
3948 .name = "Marvell 88E6085",
3949 .num_databases = 4096,
3950 .num_ports = 10,
Andrew Lunnbc393152018-03-17 20:32:04 +01003951 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04003952 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04003953 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02003954 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04003955 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04003956 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04003957 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02003958 .g1_irqs = 8,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04003959 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05003960 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04003961 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04003962 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01003963 .tag_protocol = DSA_TAG_PROTO_DSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003964 .ops = &mv88e6085_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04003965 },
3966
3967 [MV88E6095] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04003968 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095,
Vivien Didelotf81ec902016-05-09 13:22:58 -04003969 .family = MV88E6XXX_FAMILY_6095,
3970 .name = "Marvell 88E6095/88E6095F",
3971 .num_databases = 256,
3972 .num_ports = 11,
Andrew Lunnbc393152018-03-17 20:32:04 +01003973 .num_internal_phys = 0,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04003974 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04003975 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02003976 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04003977 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04003978 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04003979 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02003980 .g1_irqs = 8,
Vivien Didelote606ca32017-03-11 16:12:55 -05003981 .atu_move_port_mask = 0xf,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04003982 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01003983 .tag_protocol = DSA_TAG_PROTO_DSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04003984 .ops = &mv88e6095_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04003985 },
3986
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01003987 [MV88E6097] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04003988 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01003989 .family = MV88E6XXX_FAMILY_6097,
3990 .name = "Marvell 88E6097/88E6097F",
3991 .num_databases = 4096,
3992 .num_ports = 11,
Andrew Lunnbc393152018-03-17 20:32:04 +01003993 .num_internal_phys = 8,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04003994 .max_vid = 4095,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01003995 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02003996 .phy_base_addr = 0x0,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01003997 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04003998 .global2_addr = 0x1c,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01003999 .age_time_coeff = 15000,
Stefan Eichenbergerc5341782016-11-25 09:41:29 +01004000 .g1_irqs = 8,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004001 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004002 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004003 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004004 .multi_chip = true,
Stefan Eichenberger2bfcfcd2016-12-05 14:12:42 +01004005 .tag_protocol = DSA_TAG_PROTO_EDSA,
Stefan Eichenberger7d381a02016-11-22 17:47:21 +01004006 .ops = &mv88e6097_ops,
4007 },
4008
Vivien Didelotf81ec902016-05-09 13:22:58 -04004009 [MV88E6123] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004010 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004011 .family = MV88E6XXX_FAMILY_6165,
4012 .name = "Marvell 88E6123",
4013 .num_databases = 4096,
4014 .num_ports = 3,
Andrew Lunnbc393152018-03-17 20:32:04 +01004015 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004016 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004017 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004018 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004019 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004020 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004021 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004022 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004023 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004024 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004025 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004026 .multi_chip = true,
Andrew Lunn5ebe31d2017-06-07 15:06:19 +02004027 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004028 .ops = &mv88e6123_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004029 },
4030
4031 [MV88E6131] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004032 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004033 .family = MV88E6XXX_FAMILY_6185,
4034 .name = "Marvell 88E6131",
4035 .num_databases = 256,
4036 .num_ports = 8,
Andrew Lunnbc393152018-03-17 20:32:04 +01004037 .num_internal_phys = 0,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004038 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004039 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004040 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004041 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004042 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004043 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004044 .g1_irqs = 9,
Vivien Didelote606ca32017-03-11 16:12:55 -05004045 .atu_move_port_mask = 0xf,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004046 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004047 .tag_protocol = DSA_TAG_PROTO_DSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004048 .ops = &mv88e6131_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004049 },
4050
Vivien Didelot990e27b2017-03-28 13:50:32 -04004051 [MV88E6141] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004052 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
Vivien Didelot990e27b2017-03-28 13:50:32 -04004053 .family = MV88E6XXX_FAMILY_6341,
Uwe Kleine-König79a68b22018-03-20 10:44:40 +01004054 .name = "Marvell 88E6141",
Vivien Didelot990e27b2017-03-28 13:50:32 -04004055 .num_databases = 4096,
4056 .num_ports = 6,
Andrew Lunnbc393152018-03-17 20:32:04 +01004057 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004058 .num_gpio = 11,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004059 .max_vid = 4095,
Vivien Didelot990e27b2017-03-28 13:50:32 -04004060 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004061 .phy_base_addr = 0x10,
Vivien Didelot990e27b2017-03-28 13:50:32 -04004062 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004063 .global2_addr = 0x1c,
Vivien Didelot990e27b2017-03-28 13:50:32 -04004064 .age_time_coeff = 3750,
4065 .atu_move_port_mask = 0x1f,
Andrew Lunnadfccf12018-03-17 20:32:03 +01004066 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004067 .g2_irqs = 10,
Vivien Didelotf3645652017-03-30 17:37:07 -04004068 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004069 .multi_chip = true,
Vivien Didelot990e27b2017-03-28 13:50:32 -04004070 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelot990e27b2017-03-28 13:50:32 -04004071 .ops = &mv88e6141_ops,
4072 },
4073
Vivien Didelotf81ec902016-05-09 13:22:58 -04004074 [MV88E6161] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004075 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004076 .family = MV88E6XXX_FAMILY_6165,
4077 .name = "Marvell 88E6161",
4078 .num_databases = 4096,
4079 .num_ports = 6,
Andrew Lunnbc393152018-03-17 20:32:04 +01004080 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004081 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004082 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004083 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004084 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004085 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004086 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004087 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004088 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004089 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004090 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004091 .multi_chip = true,
Andrew Lunn5ebe31d2017-06-07 15:06:19 +02004092 .tag_protocol = DSA_TAG_PROTO_EDSA,
Andrew Lunndfa54342018-07-18 22:38:22 +02004093 .ptp_support = true,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004094 .ops = &mv88e6161_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004095 },
4096
4097 [MV88E6165] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004098 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004099 .family = MV88E6XXX_FAMILY_6165,
4100 .name = "Marvell 88E6165",
4101 .num_databases = 4096,
4102 .num_ports = 6,
Andrew Lunnbc393152018-03-17 20:32:04 +01004103 .num_internal_phys = 0,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004104 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004105 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004106 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004107 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004108 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004109 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004110 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004111 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004112 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004113 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004114 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004115 .tag_protocol = DSA_TAG_PROTO_DSA,
Andrew Lunndfa54342018-07-18 22:38:22 +02004116 .ptp_support = true,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004117 .ops = &mv88e6165_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004118 },
4119
4120 [MV88E6171] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004121 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004122 .family = MV88E6XXX_FAMILY_6351,
4123 .name = "Marvell 88E6171",
4124 .num_databases = 4096,
4125 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004126 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004127 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004128 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004129 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004130 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004131 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004132 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004133 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004134 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004135 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004136 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004137 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004138 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004139 .ops = &mv88e6171_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004140 },
4141
4142 [MV88E6172] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004143 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004144 .family = MV88E6XXX_FAMILY_6352,
4145 .name = "Marvell 88E6172",
4146 .num_databases = 4096,
4147 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004148 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004149 .num_gpio = 15,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004150 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004151 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004152 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004153 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004154 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004155 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004156 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004157 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004158 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004159 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004160 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004161 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004162 .ops = &mv88e6172_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004163 },
4164
4165 [MV88E6175] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004166 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004167 .family = MV88E6XXX_FAMILY_6351,
4168 .name = "Marvell 88E6175",
4169 .num_databases = 4096,
4170 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004171 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004172 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004173 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004174 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004175 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004176 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004177 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004178 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004179 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004180 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004181 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004182 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004183 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004184 .ops = &mv88e6175_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004185 },
4186
4187 [MV88E6176] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004188 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004189 .family = MV88E6XXX_FAMILY_6352,
4190 .name = "Marvell 88E6176",
4191 .num_databases = 4096,
4192 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004193 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004194 .num_gpio = 15,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004195 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004196 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004197 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004198 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004199 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004200 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004201 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004202 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004203 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004204 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004205 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004206 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004207 .ops = &mv88e6176_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004208 },
4209
4210 [MV88E6185] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004211 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004212 .family = MV88E6XXX_FAMILY_6185,
4213 .name = "Marvell 88E6185",
4214 .num_databases = 256,
4215 .num_ports = 10,
Andrew Lunnbc393152018-03-17 20:32:04 +01004216 .num_internal_phys = 0,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004217 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004218 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004219 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004220 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004221 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004222 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004223 .g1_irqs = 8,
Vivien Didelote606ca32017-03-11 16:12:55 -05004224 .atu_move_port_mask = 0xf,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004225 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004226 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004227 .ops = &mv88e6185_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004228 },
4229
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004230 [MV88E6190] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004231 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004232 .family = MV88E6XXX_FAMILY_6390,
4233 .name = "Marvell 88E6190",
4234 .num_databases = 4096,
4235 .num_ports = 11, /* 10 + Z80 */
Andrew Lunnbc393152018-03-17 20:32:04 +01004236 .num_internal_phys = 11,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004237 .num_gpio = 16,
Vivien Didelot931d1822017-05-01 14:05:27 -04004238 .max_vid = 8191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004239 .port_base_addr = 0x0,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004240 .phy_base_addr = 0x0,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004241 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004242 .global2_addr = 0x1c,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004243 .tag_protocol = DSA_TAG_PROTO_DSA,
Andrew Lunnb91e0552017-02-02 00:46:15 +01004244 .age_time_coeff = 3750,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004245 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004246 .g2_irqs = 14,
Vivien Didelotf3645652017-03-30 17:37:07 -04004247 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004248 .multi_chip = true,
Vivien Didelote606ca32017-03-11 16:12:55 -05004249 .atu_move_port_mask = 0x1f,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004250 .ops = &mv88e6190_ops,
4251 },
4252
4253 [MV88E6190X] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004254 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004255 .family = MV88E6XXX_FAMILY_6390,
4256 .name = "Marvell 88E6190X",
4257 .num_databases = 4096,
4258 .num_ports = 11, /* 10 + Z80 */
Andrew Lunnbc393152018-03-17 20:32:04 +01004259 .num_internal_phys = 11,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004260 .num_gpio = 16,
Vivien Didelot931d1822017-05-01 14:05:27 -04004261 .max_vid = 8191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004262 .port_base_addr = 0x0,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004263 .phy_base_addr = 0x0,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004264 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004265 .global2_addr = 0x1c,
Andrew Lunnb91e0552017-02-02 00:46:15 +01004266 .age_time_coeff = 3750,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004267 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004268 .g2_irqs = 14,
Vivien Didelote606ca32017-03-11 16:12:55 -05004269 .atu_move_port_mask = 0x1f,
Vivien Didelotf3645652017-03-30 17:37:07 -04004270 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004271 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004272 .tag_protocol = DSA_TAG_PROTO_DSA,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004273 .ops = &mv88e6190x_ops,
4274 },
4275
4276 [MV88E6191] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004277 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004278 .family = MV88E6XXX_FAMILY_6390,
4279 .name = "Marvell 88E6191",
4280 .num_databases = 4096,
4281 .num_ports = 11, /* 10 + Z80 */
Andrew Lunnbc393152018-03-17 20:32:04 +01004282 .num_internal_phys = 11,
Vivien Didelot931d1822017-05-01 14:05:27 -04004283 .max_vid = 8191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004284 .port_base_addr = 0x0,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004285 .phy_base_addr = 0x0,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004286 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004287 .global2_addr = 0x1c,
Andrew Lunnb91e0552017-02-02 00:46:15 +01004288 .age_time_coeff = 3750,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004289 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004290 .g2_irqs = 14,
Vivien Didelote606ca32017-03-11 16:12:55 -05004291 .atu_move_port_mask = 0x1f,
Vivien Didelotf3645652017-03-30 17:37:07 -04004292 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004293 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004294 .tag_protocol = DSA_TAG_PROTO_DSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004295 .ptp_support = true,
Vivien Didelot2cf4cefb2017-03-28 13:50:34 -04004296 .ops = &mv88e6191_ops,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004297 },
4298
Vivien Didelotf81ec902016-05-09 13:22:58 -04004299 [MV88E6240] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004300 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004301 .family = MV88E6XXX_FAMILY_6352,
4302 .name = "Marvell 88E6240",
4303 .num_databases = 4096,
4304 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004305 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004306 .num_gpio = 15,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004307 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004308 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004309 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004310 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004311 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004312 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004313 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004314 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004315 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004316 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004317 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004318 .tag_protocol = DSA_TAG_PROTO_EDSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004319 .ptp_support = true,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004320 .ops = &mv88e6240_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004321 },
4322
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004323 [MV88E6290] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004324 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004325 .family = MV88E6XXX_FAMILY_6390,
4326 .name = "Marvell 88E6290",
4327 .num_databases = 4096,
4328 .num_ports = 11, /* 10 + Z80 */
Andrew Lunnbc393152018-03-17 20:32:04 +01004329 .num_internal_phys = 11,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004330 .num_gpio = 16,
Vivien Didelot931d1822017-05-01 14:05:27 -04004331 .max_vid = 8191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004332 .port_base_addr = 0x0,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004333 .phy_base_addr = 0x0,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004334 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004335 .global2_addr = 0x1c,
Andrew Lunnb91e0552017-02-02 00:46:15 +01004336 .age_time_coeff = 3750,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004337 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004338 .g2_irqs = 14,
Vivien Didelote606ca32017-03-11 16:12:55 -05004339 .atu_move_port_mask = 0x1f,
Vivien Didelotf3645652017-03-30 17:37:07 -04004340 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004341 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004342 .tag_protocol = DSA_TAG_PROTO_DSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004343 .ptp_support = true,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004344 .ops = &mv88e6290_ops,
4345 },
4346
Vivien Didelotf81ec902016-05-09 13:22:58 -04004347 [MV88E6320] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004348 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004349 .family = MV88E6XXX_FAMILY_6320,
4350 .name = "Marvell 88E6320",
4351 .num_databases = 4096,
4352 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004353 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004354 .num_gpio = 15,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004355 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004356 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004357 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004358 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004359 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004360 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004361 .g1_irqs = 8,
Andrew Lunnbc393152018-03-17 20:32:04 +01004362 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004363 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004364 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004365 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004366 .tag_protocol = DSA_TAG_PROTO_EDSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004367 .ptp_support = true,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004368 .ops = &mv88e6320_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004369 },
4370
4371 [MV88E6321] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004372 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004373 .family = MV88E6XXX_FAMILY_6320,
4374 .name = "Marvell 88E6321",
4375 .num_databases = 4096,
4376 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004377 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004378 .num_gpio = 15,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004379 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004380 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004381 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004382 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004383 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004384 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004385 .g1_irqs = 8,
Andrew Lunnbc393152018-03-17 20:32:04 +01004386 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004387 .atu_move_port_mask = 0xf,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004388 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004389 .tag_protocol = DSA_TAG_PROTO_EDSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004390 .ptp_support = true,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004391 .ops = &mv88e6321_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004392 },
4393
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004394 [MV88E6341] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004395 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004396 .family = MV88E6XXX_FAMILY_6341,
4397 .name = "Marvell 88E6341",
4398 .num_databases = 4096,
Andrew Lunnbc393152018-03-17 20:32:04 +01004399 .num_internal_phys = 5,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004400 .num_ports = 6,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004401 .num_gpio = 11,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004402 .max_vid = 4095,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004403 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004404 .phy_base_addr = 0x10,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004405 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004406 .global2_addr = 0x1c,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004407 .age_time_coeff = 3750,
Vivien Didelote606ca32017-03-11 16:12:55 -05004408 .atu_move_port_mask = 0x1f,
Andrew Lunnadfccf12018-03-17 20:32:03 +01004409 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004410 .g2_irqs = 10,
Vivien Didelotf3645652017-03-30 17:37:07 -04004411 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004412 .multi_chip = true,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004413 .tag_protocol = DSA_TAG_PROTO_EDSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004414 .ptp_support = true,
Gregory CLEMENTa75961d2017-01-30 20:29:34 +01004415 .ops = &mv88e6341_ops,
4416 },
4417
Vivien Didelotf81ec902016-05-09 13:22:58 -04004418 [MV88E6350] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004419 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004420 .family = MV88E6XXX_FAMILY_6351,
4421 .name = "Marvell 88E6350",
4422 .num_databases = 4096,
4423 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004424 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004425 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004426 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004427 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004428 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004429 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004430 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004431 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004432 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004433 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004434 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004435 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004436 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004437 .ops = &mv88e6350_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004438 },
4439
4440 [MV88E6351] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004441 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6351,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004442 .family = MV88E6XXX_FAMILY_6351,
4443 .name = "Marvell 88E6351",
4444 .num_databases = 4096,
4445 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004446 .num_internal_phys = 5,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004447 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004448 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004449 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004450 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004451 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004452 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004453 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004454 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004455 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004456 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004457 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004458 .tag_protocol = DSA_TAG_PROTO_EDSA,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004459 .ops = &mv88e6351_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004460 },
4461
4462 [MV88E6352] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004463 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004464 .family = MV88E6XXX_FAMILY_6352,
4465 .name = "Marvell 88E6352",
4466 .num_databases = 4096,
4467 .num_ports = 7,
Andrew Lunnbc393152018-03-17 20:32:04 +01004468 .num_internal_phys = 5,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004469 .num_gpio = 15,
Vivien Didelot3cf3c842017-05-01 14:05:10 -04004470 .max_vid = 4095,
Vivien Didelot9dddd472016-06-20 13:14:10 -04004471 .port_base_addr = 0x10,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004472 .phy_base_addr = 0x0,
Vivien Didelota935c052016-09-29 12:21:53 -04004473 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004474 .global2_addr = 0x1c,
Vivien Didelotacddbd22016-07-18 20:45:39 -04004475 .age_time_coeff = 15000,
Andrew Lunndc30c352016-10-16 19:56:49 +02004476 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004477 .g2_irqs = 10,
Vivien Didelote606ca32017-03-11 16:12:55 -05004478 .atu_move_port_mask = 0xf,
Vivien Didelotf3645652017-03-30 17:37:07 -04004479 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004480 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004481 .tag_protocol = DSA_TAG_PROTO_EDSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004482 .ptp_support = true,
Vivien Didelotb3469dd2016-09-29 12:22:00 -04004483 .ops = &mv88e6352_ops,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004484 },
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004485 [MV88E6390] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004486 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004487 .family = MV88E6XXX_FAMILY_6390,
4488 .name = "Marvell 88E6390",
4489 .num_databases = 4096,
4490 .num_ports = 11, /* 10 + Z80 */
Andrew Lunnbc393152018-03-17 20:32:04 +01004491 .num_internal_phys = 11,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004492 .num_gpio = 16,
Vivien Didelot931d1822017-05-01 14:05:27 -04004493 .max_vid = 8191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004494 .port_base_addr = 0x0,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004495 .phy_base_addr = 0x0,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004496 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004497 .global2_addr = 0x1c,
Andrew Lunnb91e0552017-02-02 00:46:15 +01004498 .age_time_coeff = 3750,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004499 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004500 .g2_irqs = 14,
Vivien Didelote606ca32017-03-11 16:12:55 -05004501 .atu_move_port_mask = 0x1f,
Vivien Didelotf3645652017-03-30 17:37:07 -04004502 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004503 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004504 .tag_protocol = DSA_TAG_PROTO_DSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004505 .ptp_support = true,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004506 .ops = &mv88e6390_ops,
4507 },
4508 [MV88E6390X] = {
Vivien Didelot107fcc12017-06-12 12:37:36 -04004509 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004510 .family = MV88E6XXX_FAMILY_6390,
4511 .name = "Marvell 88E6390X",
4512 .num_databases = 4096,
4513 .num_ports = 11, /* 10 + Z80 */
Andrew Lunnbc393152018-03-17 20:32:04 +01004514 .num_internal_phys = 11,
Brandon Streiffa73ccd62018-02-14 01:07:46 +01004515 .num_gpio = 16,
Vivien Didelot931d1822017-05-01 14:05:27 -04004516 .max_vid = 8191,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004517 .port_base_addr = 0x0,
Andrew Lunn9255bac2018-05-05 20:58:22 +02004518 .phy_base_addr = 0x0,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004519 .global1_addr = 0x1b,
Vivien Didelot9069c132017-07-17 13:03:44 -04004520 .global2_addr = 0x1c,
Andrew Lunnb91e0552017-02-02 00:46:15 +01004521 .age_time_coeff = 3750,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004522 .g1_irqs = 9,
Vivien Didelotd6c5e6a2017-07-17 13:03:40 -04004523 .g2_irqs = 14,
Vivien Didelote606ca32017-03-11 16:12:55 -05004524 .atu_move_port_mask = 0x1f,
Vivien Didelotf3645652017-03-30 17:37:07 -04004525 .pvt = true,
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004526 .multi_chip = true,
Andrew Lunn443d5a12016-12-03 04:35:18 +01004527 .tag_protocol = DSA_TAG_PROTO_DSA,
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004528 .ptp_support = true,
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004529 .ops = &mv88e6390x_ops,
4530 },
Vivien Didelotf81ec902016-05-09 13:22:58 -04004531};
4532
Vivien Didelot5f7c0362016-06-20 13:14:04 -04004533static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
Vivien Didelotb9b37712015-10-30 19:39:48 -04004534{
Vivien Didelota439c062016-04-17 13:23:58 -04004535 int i;
Vivien Didelotb9b37712015-10-30 19:39:48 -04004536
Vivien Didelot5f7c0362016-06-20 13:14:04 -04004537 for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
4538 if (mv88e6xxx_table[i].prod_num == prod_num)
4539 return &mv88e6xxx_table[i];
Vivien Didelotb9b37712015-10-30 19:39:48 -04004540
Vivien Didelotb9b37712015-10-30 19:39:48 -04004541 return NULL;
4542}
4543
Vivien Didelotfad09c72016-06-21 12:28:20 -04004544static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004545{
4546 const struct mv88e6xxx_info *info;
Vivien Didelot8f6345b2016-07-20 18:18:36 -04004547 unsigned int prod_num, rev;
4548 u16 id;
4549 int err;
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004550
Vivien Didelot8f6345b2016-07-20 18:18:36 -04004551 mutex_lock(&chip->reg_lock);
Vivien Didelot107fcc12017-06-12 12:37:36 -04004552 err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id);
Vivien Didelot8f6345b2016-07-20 18:18:36 -04004553 mutex_unlock(&chip->reg_lock);
4554 if (err)
4555 return err;
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004556
Vivien Didelot107fcc12017-06-12 12:37:36 -04004557 prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK;
4558 rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK;
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004559
4560 info = mv88e6xxx_lookup_info(prod_num);
4561 if (!info)
4562 return -ENODEV;
4563
Vivien Didelotcaac8542016-06-20 13:14:09 -04004564 /* Update the compatible info with the probed one */
Vivien Didelotfad09c72016-06-21 12:28:20 -04004565 chip->info = info;
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004566
Vivien Didelotca070c12016-09-02 14:45:34 -04004567 err = mv88e6xxx_g2_require(chip);
4568 if (err)
4569 return err;
4570
Vivien Didelotfad09c72016-06-21 12:28:20 -04004571 dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n",
4572 chip->info->prod_num, chip->info->name, rev);
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004573
4574 return 0;
4575}
4576
Vivien Didelotfad09c72016-06-21 12:28:20 -04004577static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
Vivien Didelot469d7292016-06-20 13:14:06 -04004578{
Vivien Didelotfad09c72016-06-21 12:28:20 -04004579 struct mv88e6xxx_chip *chip;
Vivien Didelot469d7292016-06-20 13:14:06 -04004580
Vivien Didelotfad09c72016-06-21 12:28:20 -04004581 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
4582 if (!chip)
Vivien Didelot469d7292016-06-20 13:14:06 -04004583 return NULL;
4584
Vivien Didelotfad09c72016-06-21 12:28:20 -04004585 chip->dev = dev;
Vivien Didelot469d7292016-06-20 13:14:06 -04004586
Vivien Didelotfad09c72016-06-21 12:28:20 -04004587 mutex_init(&chip->reg_lock);
Andrew Lunna3c53be52017-01-24 14:53:50 +01004588 INIT_LIST_HEAD(&chip->mdios);
Vivien Didelot469d7292016-06-20 13:14:06 -04004589
Vivien Didelotfad09c72016-06-21 12:28:20 -04004590 return chip;
Vivien Didelot469d7292016-06-20 13:14:06 -04004591}
4592
Vivien Didelotfad09c72016-06-21 12:28:20 -04004593static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
Vivien Didelot4a70c4a2016-06-20 13:14:07 -04004594 struct mii_bus *bus, int sw_addr)
4595{
Vivien Didelot914b32f2016-06-20 13:14:11 -04004596 if (sw_addr == 0)
Vivien Didelotfad09c72016-06-21 12:28:20 -04004597 chip->smi_ops = &mv88e6xxx_smi_single_chip_ops;
Vivien Didelotb3e05aa2017-07-17 13:03:46 -04004598 else if (chip->info->multi_chip)
Vivien Didelotfad09c72016-06-21 12:28:20 -04004599 chip->smi_ops = &mv88e6xxx_smi_multi_chip_ops;
Vivien Didelot914b32f2016-06-20 13:14:11 -04004600 else
4601 return -EINVAL;
4602
Vivien Didelotfad09c72016-06-21 12:28:20 -04004603 chip->bus = bus;
4604 chip->sw_addr = sw_addr;
Vivien Didelot4a70c4a2016-06-20 13:14:07 -04004605
4606 return 0;
4607}
4608
Florian Fainelli5ed4e3e2017-11-10 15:22:52 -08004609static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
4610 int port)
Andrew Lunn7b314362016-08-22 16:01:01 +02004611{
Vivien Didelot04bed142016-08-31 18:06:13 -04004612 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn2bbb33b2016-08-22 16:01:02 +02004613
Andrew Lunn443d5a12016-12-03 04:35:18 +01004614 return chip->info->tag_protocol;
Andrew Lunn7b314362016-08-22 16:01:01 +02004615}
4616
Florian Fainelli2a93c1a2017-12-06 15:03:33 -08004617#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
Andrew Lunnfcdce7d2016-05-10 23:27:20 +02004618static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
4619 struct device *host_dev, int sw_addr,
4620 void **priv)
Andrew Lunna77d43f2016-04-13 02:40:42 +02004621{
Vivien Didelotfad09c72016-06-21 12:28:20 -04004622 struct mv88e6xxx_chip *chip;
Vivien Didelota439c062016-04-17 13:23:58 -04004623 struct mii_bus *bus;
Andrew Lunnb516d452016-06-04 21:17:06 +02004624 int err;
Andrew Lunna77d43f2016-04-13 02:40:42 +02004625
Vivien Didelota439c062016-04-17 13:23:58 -04004626 bus = dsa_host_dev_to_mii_bus(host_dev);
Andrew Lunnc1569132016-04-13 02:40:45 +02004627 if (!bus)
4628 return NULL;
4629
Vivien Didelotfad09c72016-06-21 12:28:20 -04004630 chip = mv88e6xxx_alloc_chip(dsa_dev);
4631 if (!chip)
Vivien Didelot469d7292016-06-20 13:14:06 -04004632 return NULL;
4633
Vivien Didelotcaac8542016-06-20 13:14:09 -04004634 /* Legacy SMI probing will only support chips similar to 88E6085 */
Vivien Didelotfad09c72016-06-21 12:28:20 -04004635 chip->info = &mv88e6xxx_table[MV88E6085];
Vivien Didelotcaac8542016-06-20 13:14:09 -04004636
Vivien Didelotfad09c72016-06-21 12:28:20 -04004637 err = mv88e6xxx_smi_init(chip, bus, sw_addr);
Vivien Didelot4a70c4a2016-06-20 13:14:07 -04004638 if (err)
4639 goto free;
4640
Vivien Didelotfad09c72016-06-21 12:28:20 -04004641 err = mv88e6xxx_detect(chip);
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004642 if (err)
Vivien Didelot469d7292016-06-20 13:14:06 -04004643 goto free;
Vivien Didelota439c062016-04-17 13:23:58 -04004644
Andrew Lunndc30c352016-10-16 19:56:49 +02004645 mutex_lock(&chip->reg_lock);
4646 err = mv88e6xxx_switch_reset(chip);
4647 mutex_unlock(&chip->reg_lock);
4648 if (err)
4649 goto free;
4650
Vivien Didelote57e5e72016-08-15 17:19:00 -04004651 mv88e6xxx_phy_init(chip);
4652
Andrew Lunna3c53be52017-01-24 14:53:50 +01004653 err = mv88e6xxx_mdios_register(chip, NULL);
Andrew Lunnb516d452016-06-04 21:17:06 +02004654 if (err)
Vivien Didelot469d7292016-06-20 13:14:06 -04004655 goto free;
Andrew Lunnb516d452016-06-04 21:17:06 +02004656
Vivien Didelotfad09c72016-06-21 12:28:20 -04004657 *priv = chip;
Vivien Didelota439c062016-04-17 13:23:58 -04004658
Vivien Didelotfad09c72016-06-21 12:28:20 -04004659 return chip->info->name;
Vivien Didelot469d7292016-06-20 13:14:06 -04004660free:
Vivien Didelotfad09c72016-06-21 12:28:20 -04004661 devm_kfree(dsa_dev, chip);
Vivien Didelot469d7292016-06-20 13:14:06 -04004662
4663 return NULL;
Andrew Lunna77d43f2016-04-13 02:40:42 +02004664}
Florian Fainelli2a93c1a2017-12-06 15:03:33 -08004665#endif
Andrew Lunna77d43f2016-04-13 02:40:42 +02004666
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004667static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port,
Vivien Didelot3709aad2017-11-30 11:23:58 -05004668 const struct switchdev_obj_port_mdb *mdb)
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004669{
4670 /* We don't need any dynamic resource from the kernel (yet),
4671 * so skip the prepare phase.
4672 */
4673
4674 return 0;
4675}
4676
4677static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
Vivien Didelot3709aad2017-11-30 11:23:58 -05004678 const struct switchdev_obj_port_mdb *mdb)
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004679{
Vivien Didelot04bed142016-08-31 18:06:13 -04004680 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004681
4682 mutex_lock(&chip->reg_lock);
4683 if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
Vivien Didelot27c0e602017-06-15 12:14:01 -04004684 MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC))
Vivien Didelot774439e52017-06-08 18:34:08 -04004685 dev_err(ds->dev, "p%d: failed to load multicast MAC address\n",
4686 port);
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004687 mutex_unlock(&chip->reg_lock);
4688}
4689
4690static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
4691 const struct switchdev_obj_port_mdb *mdb)
4692{
Vivien Didelot04bed142016-08-31 18:06:13 -04004693 struct mv88e6xxx_chip *chip = ds->priv;
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004694 int err;
4695
4696 mutex_lock(&chip->reg_lock);
4697 err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
Vivien Didelot27c0e602017-06-15 12:14:01 -04004698 MV88E6XXX_G1_ATU_DATA_STATE_UNUSED);
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004699 mutex_unlock(&chip->reg_lock);
4700
4701 return err;
4702}
4703
Russell King4f859012019-02-20 15:35:05 -08004704static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
4705 bool unicast, bool multicast)
4706{
4707 struct mv88e6xxx_chip *chip = ds->priv;
4708 int err = -EOPNOTSUPP;
4709
4710 mutex_lock(&chip->reg_lock);
4711 if (chip->info->ops->port_set_egress_floods)
4712 err = chip->info->ops->port_set_egress_floods(chip, port,
4713 unicast,
4714 multicast);
4715 mutex_unlock(&chip->reg_lock);
4716
4717 return err;
4718}
4719
Florian Fainellia82f67a2017-01-08 14:52:08 -08004720static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
Florian Fainelli2a93c1a2017-12-06 15:03:33 -08004721#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
Andrew Lunnfcdce7d2016-05-10 23:27:20 +02004722 .probe = mv88e6xxx_drv_probe,
Florian Fainelli2a93c1a2017-12-06 15:03:33 -08004723#endif
Andrew Lunn7b314362016-08-22 16:01:01 +02004724 .get_tag_protocol = mv88e6xxx_get_tag_protocol,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004725 .setup = mv88e6xxx_setup,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004726 .adjust_link = mv88e6xxx_adjust_link,
Russell Kingc9a23562018-05-10 13:17:35 -07004727 .phylink_validate = mv88e6xxx_validate,
4728 .phylink_mac_link_state = mv88e6xxx_link_state,
4729 .phylink_mac_config = mv88e6xxx_mac_config,
4730 .phylink_mac_link_down = mv88e6xxx_mac_link_down,
4731 .phylink_mac_link_up = mv88e6xxx_mac_link_up,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004732 .get_strings = mv88e6xxx_get_strings,
4733 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
4734 .get_sset_count = mv88e6xxx_get_sset_count,
Andrew Lunn04aca992017-05-26 01:03:24 +02004735 .port_enable = mv88e6xxx_port_enable,
4736 .port_disable = mv88e6xxx_port_disable,
Vivien Didelot08f50062017-08-01 16:32:41 -04004737 .get_mac_eee = mv88e6xxx_get_mac_eee,
4738 .set_mac_eee = mv88e6xxx_set_mac_eee,
Andrew Lunnf8cd8752016-05-10 23:27:25 +02004739 .get_eeprom_len = mv88e6xxx_get_eeprom_len,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004740 .get_eeprom = mv88e6xxx_get_eeprom,
4741 .set_eeprom = mv88e6xxx_set_eeprom,
4742 .get_regs_len = mv88e6xxx_get_regs_len,
4743 .get_regs = mv88e6xxx_get_regs,
Vivien Didelot2cfcd962016-07-18 20:45:40 -04004744 .set_ageing_time = mv88e6xxx_set_ageing_time,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004745 .port_bridge_join = mv88e6xxx_port_bridge_join,
4746 .port_bridge_leave = mv88e6xxx_port_bridge_leave,
Russell King4f859012019-02-20 15:35:05 -08004747 .port_egress_floods = mv88e6xxx_port_egress_floods,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004748 .port_stp_state_set = mv88e6xxx_port_stp_state_set,
Vivien Didelot749efcb2016-09-22 16:49:24 -04004749 .port_fast_age = mv88e6xxx_port_fast_age,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004750 .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
4751 .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
4752 .port_vlan_add = mv88e6xxx_port_vlan_add,
4753 .port_vlan_del = mv88e6xxx_port_vlan_del,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004754 .port_fdb_add = mv88e6xxx_port_fdb_add,
4755 .port_fdb_del = mv88e6xxx_port_fdb_del,
4756 .port_fdb_dump = mv88e6xxx_port_fdb_dump,
Vivien Didelot7df8fbd2016-08-31 11:50:05 -04004757 .port_mdb_prepare = mv88e6xxx_port_mdb_prepare,
4758 .port_mdb_add = mv88e6xxx_port_mdb_add,
4759 .port_mdb_del = mv88e6xxx_port_mdb_del,
Vivien Didelotaec5ac82017-03-30 17:37:15 -04004760 .crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join,
4761 .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave,
Brandon Streiffc6fe0ad2018-02-14 01:07:50 +01004762 .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set,
4763 .port_hwtstamp_get = mv88e6xxx_port_hwtstamp_get,
4764 .port_txtstamp = mv88e6xxx_port_txtstamp,
4765 .port_rxtstamp = mv88e6xxx_port_rxtstamp,
4766 .get_ts_info = mv88e6xxx_get_ts_info,
Vivien Didelotf81ec902016-05-09 13:22:58 -04004767};
4768
Florian Fainelliab3d4082017-01-08 14:52:07 -08004769static struct dsa_switch_driver mv88e6xxx_switch_drv = {
4770 .ops = &mv88e6xxx_switch_ops,
4771};
4772
Florian Fainelli55ed0ce2017-01-26 10:45:51 -08004773static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004774{
Vivien Didelotfad09c72016-06-21 12:28:20 -04004775 struct device *dev = chip->dev;
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004776 struct dsa_switch *ds;
4777
Vivien Didelot73b12042017-03-30 17:37:10 -04004778 ds = dsa_switch_alloc(dev, mv88e6xxx_num_ports(chip));
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004779 if (!ds)
4780 return -ENOMEM;
4781
Vivien Didelotfad09c72016-06-21 12:28:20 -04004782 ds->priv = chip;
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004783 ds->dev = dev;
Vivien Didelot9d490b42016-08-23 12:38:56 -04004784 ds->ops = &mv88e6xxx_switch_ops;
Vivien Didelot9ff74f22017-03-15 15:53:50 -04004785 ds->ageing_time_min = chip->info->age_time_coeff;
4786 ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004787
4788 dev_set_drvdata(dev, ds);
4789
Vivien Didelot23c9ee42017-05-26 18:12:51 -04004790 return dsa_register_switch(ds);
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004791}
4792
Vivien Didelotfad09c72016-06-21 12:28:20 -04004793static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip)
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004794{
Vivien Didelotfad09c72016-06-21 12:28:20 -04004795 dsa_unregister_switch(chip->ds);
Vivien Didelotb7e66a52016-06-20 13:14:02 -04004796}
4797
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004798static const void *pdata_device_get_match_data(struct device *dev)
4799{
4800 const struct of_device_id *matches = dev->driver->of_match_table;
4801 const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data;
4802
4803 for (; matches->name[0] || matches->type[0] || matches->compatible[0];
4804 matches++) {
4805 if (!strcmp(pdata->compatible, matches->compatible))
4806 return matches->data;
4807 }
4808 return NULL;
4809}
4810
Miquel Raynalbcd3d9d2019-02-05 12:07:28 +01004811/* There is no suspend to RAM support at DSA level yet, the switch configuration
4812 * would be lost after a power cycle so prevent it to be suspended.
4813 */
4814static int __maybe_unused mv88e6xxx_suspend(struct device *dev)
4815{
4816 return -EOPNOTSUPP;
4817}
4818
4819static int __maybe_unused mv88e6xxx_resume(struct device *dev)
4820{
4821 return 0;
4822}
4823
4824static SIMPLE_DEV_PM_OPS(mv88e6xxx_pm_ops, mv88e6xxx_suspend, mv88e6xxx_resume);
4825
Vivien Didelot57d32312016-06-20 13:13:58 -04004826static int mv88e6xxx_probe(struct mdio_device *mdiodev)
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004827{
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004828 struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
David S. Miller7ddae242018-05-20 19:04:24 -04004829 const struct mv88e6xxx_info *compat_info = NULL;
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004830 struct device *dev = &mdiodev->dev;
Andrew Lunnf8cd8752016-05-10 23:27:25 +02004831 struct device_node *np = dev->of_node;
Vivien Didelotfad09c72016-06-21 12:28:20 -04004832 struct mv88e6xxx_chip *chip;
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004833 int port;
Andrew Lunn52638f72016-05-10 23:27:22 +02004834 int err;
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004835
Andrew Lunn7bb8c992018-05-31 00:15:42 +02004836 if (!np && !pdata)
4837 return -EINVAL;
4838
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004839 if (np)
4840 compat_info = of_device_get_match_data(dev);
4841
4842 if (pdata) {
4843 compat_info = pdata_device_get_match_data(dev);
4844
4845 if (!pdata->netdev)
4846 return -EINVAL;
4847
4848 for (port = 0; port < DSA_MAX_PORTS; port++) {
4849 if (!(pdata->enabled_ports & (1 << port)))
4850 continue;
4851 if (strcmp(pdata->cd.port_names[port], "cpu"))
4852 continue;
4853 pdata->cd.netdev[port] = &pdata->netdev->dev;
4854 break;
4855 }
4856 }
4857
Vivien Didelotcaac8542016-06-20 13:14:09 -04004858 if (!compat_info)
4859 return -EINVAL;
4860
Vivien Didelotfad09c72016-06-21 12:28:20 -04004861 chip = mv88e6xxx_alloc_chip(dev);
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004862 if (!chip) {
4863 err = -ENOMEM;
4864 goto out;
4865 }
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004866
Vivien Didelotfad09c72016-06-21 12:28:20 -04004867 chip->info = compat_info;
Vivien Didelotcaac8542016-06-20 13:14:09 -04004868
Vivien Didelotfad09c72016-06-21 12:28:20 -04004869 err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
Vivien Didelot4a70c4a2016-06-20 13:14:07 -04004870 if (err)
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004871 goto out;
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004872
Andrew Lunnb4308f02016-11-21 23:26:55 +01004873 chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004874 if (IS_ERR(chip->reset)) {
4875 err = PTR_ERR(chip->reset);
4876 goto out;
4877 }
Andrew Lunnb4308f02016-11-21 23:26:55 +01004878
Vivien Didelotfad09c72016-06-21 12:28:20 -04004879 err = mv88e6xxx_detect(chip);
Vivien Didelotbc46a3d2016-06-20 13:14:08 -04004880 if (err)
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004881 goto out;
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004882
Vivien Didelote57e5e72016-08-15 17:19:00 -04004883 mv88e6xxx_phy_init(chip);
4884
Andrew Lunn00baabe2018-05-19 22:31:35 +02004885 if (chip->info->ops->get_eeprom) {
4886 if (np)
4887 of_property_read_u32(np, "eeprom-length",
4888 &chip->eeprom_len);
4889 else
4890 chip->eeprom_len = pdata->eeprom_len;
4891 }
Andrew Lunnf8cd8752016-05-10 23:27:25 +02004892
Andrew Lunndc30c352016-10-16 19:56:49 +02004893 mutex_lock(&chip->reg_lock);
4894 err = mv88e6xxx_switch_reset(chip);
4895 mutex_unlock(&chip->reg_lock);
Andrew Lunnb516d452016-06-04 21:17:06 +02004896 if (err)
Andrew Lunndc30c352016-10-16 19:56:49 +02004897 goto out;
Andrew Lunnb516d452016-06-04 21:17:06 +02004898
Andrew Lunndc30c352016-10-16 19:56:49 +02004899 chip->irq = of_irq_get(np, 0);
4900 if (chip->irq == -EPROBE_DEFER) {
4901 err = chip->irq;
4902 goto out;
Andrew Lunn83c0afa2016-06-04 21:17:07 +02004903 }
4904
Andrew Lunn294d7112018-02-22 22:58:32 +01004905 /* Has to be performed before the MDIO bus is created, because
Uwe Kleine-Königa7087672018-03-20 10:44:41 +01004906 * the PHYs will link their interrupts to these interrupt
Andrew Lunn294d7112018-02-22 22:58:32 +01004907 * controllers
4908 */
4909 mutex_lock(&chip->reg_lock);
4910 if (chip->irq > 0)
Andrew Lunndc30c352016-10-16 19:56:49 +02004911 err = mv88e6xxx_g1_irq_setup(chip);
Andrew Lunn294d7112018-02-22 22:58:32 +01004912 else
4913 err = mv88e6xxx_irq_poll_setup(chip);
4914 mutex_unlock(&chip->reg_lock);
Andrew Lunndc30c352016-10-16 19:56:49 +02004915
Andrew Lunn294d7112018-02-22 22:58:32 +01004916 if (err)
4917 goto out;
4918
4919 if (chip->info->g2_irqs > 0) {
4920 err = mv88e6xxx_g2_irq_setup(chip);
Andrew Lunndc30c352016-10-16 19:56:49 +02004921 if (err)
Andrew Lunn294d7112018-02-22 22:58:32 +01004922 goto out_g1_irq;
Andrew Lunndc30c352016-10-16 19:56:49 +02004923 }
4924
Andrew Lunn294d7112018-02-22 22:58:32 +01004925 err = mv88e6xxx_g1_atu_prob_irq_setup(chip);
4926 if (err)
4927 goto out_g2_irq;
4928
4929 err = mv88e6xxx_g1_vtu_prob_irq_setup(chip);
4930 if (err)
4931 goto out_g1_atu_prob_irq;
4932
Andrew Lunna3c53be52017-01-24 14:53:50 +01004933 err = mv88e6xxx_mdios_register(chip, np);
Andrew Lunndc30c352016-10-16 19:56:49 +02004934 if (err)
Andrew Lunn62eb1162018-01-14 02:32:45 +01004935 goto out_g1_vtu_prob_irq;
Andrew Lunndc30c352016-10-16 19:56:49 +02004936
Florian Fainelli55ed0ce2017-01-26 10:45:51 -08004937 err = mv88e6xxx_register_switch(chip);
Andrew Lunndc30c352016-10-16 19:56:49 +02004938 if (err)
4939 goto out_mdio;
4940
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004941 return 0;
Andrew Lunndc30c352016-10-16 19:56:49 +02004942
4943out_mdio:
Andrew Lunna3c53be52017-01-24 14:53:50 +01004944 mv88e6xxx_mdios_unregister(chip);
Andrew Lunn62eb1162018-01-14 02:32:45 +01004945out_g1_vtu_prob_irq:
Andrew Lunn294d7112018-02-22 22:58:32 +01004946 mv88e6xxx_g1_vtu_prob_irq_free(chip);
Andrew Lunn09776442018-01-14 02:32:44 +01004947out_g1_atu_prob_irq:
Andrew Lunn294d7112018-02-22 22:58:32 +01004948 mv88e6xxx_g1_atu_prob_irq_free(chip);
Andrew Lunndc30c352016-10-16 19:56:49 +02004949out_g2_irq:
Andrew Lunn294d7112018-02-22 22:58:32 +01004950 if (chip->info->g2_irqs > 0)
Andrew Lunndc30c352016-10-16 19:56:49 +02004951 mv88e6xxx_g2_irq_free(chip);
4952out_g1_irq:
Andrew Lunn294d7112018-02-22 22:58:32 +01004953 if (chip->irq > 0)
Andrew Lunn467126442016-11-20 20:14:15 +01004954 mv88e6xxx_g1_irq_free(chip);
Andrew Lunn294d7112018-02-22 22:58:32 +01004955 else
4956 mv88e6xxx_irq_poll_free(chip);
Andrew Lunndc30c352016-10-16 19:56:49 +02004957out:
Andrew Lunn877b7cb2018-05-19 22:31:34 +02004958 if (pdata)
4959 dev_put(pdata->netdev);
4960
Andrew Lunndc30c352016-10-16 19:56:49 +02004961 return err;
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004962}
4963
4964static void mv88e6xxx_remove(struct mdio_device *mdiodev)
4965{
4966 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
Vivien Didelot04bed142016-08-31 18:06:13 -04004967 struct mv88e6xxx_chip *chip = ds->priv;
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004968
Brandon Streiffc6fe0ad2018-02-14 01:07:50 +01004969 if (chip->info->ptp_support) {
4970 mv88e6xxx_hwtstamp_free(chip);
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004971 mv88e6xxx_ptp_free(chip);
Brandon Streiffc6fe0ad2018-02-14 01:07:50 +01004972 }
Brandon Streiff2fa8d3a2018-02-14 01:07:45 +01004973
Andrew Lunn930188c2016-08-22 16:01:03 +02004974 mv88e6xxx_phy_destroy(chip);
Vivien Didelotfad09c72016-06-21 12:28:20 -04004975 mv88e6xxx_unregister_switch(chip);
Andrew Lunna3c53be52017-01-24 14:53:50 +01004976 mv88e6xxx_mdios_unregister(chip);
Andrew Lunndc30c352016-10-16 19:56:49 +02004977
Andrew Lunn76f38f12018-03-17 20:21:09 +01004978 mv88e6xxx_g1_vtu_prob_irq_free(chip);
4979 mv88e6xxx_g1_atu_prob_irq_free(chip);
4980
4981 if (chip->info->g2_irqs > 0)
4982 mv88e6xxx_g2_irq_free(chip);
4983
Andrew Lunn76f38f12018-03-17 20:21:09 +01004984 if (chip->irq > 0)
Andrew Lunn467126442016-11-20 20:14:15 +01004985 mv88e6xxx_g1_irq_free(chip);
Andrew Lunn76f38f12018-03-17 20:21:09 +01004986 else
4987 mv88e6xxx_irq_poll_free(chip);
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004988}
4989
4990static const struct of_device_id mv88e6xxx_of_match[] = {
Vivien Didelotcaac8542016-06-20 13:14:09 -04004991 {
4992 .compatible = "marvell,mv88e6085",
4993 .data = &mv88e6xxx_table[MV88E6085],
4994 },
Andrew Lunn1a3b39e2016-11-21 23:26:57 +01004995 {
4996 .compatible = "marvell,mv88e6190",
4997 .data = &mv88e6xxx_table[MV88E6190],
4998 },
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02004999 { /* sentinel */ },
5000};
5001
5002MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);
5003
5004static struct mdio_driver mv88e6xxx_driver = {
5005 .probe = mv88e6xxx_probe,
5006 .remove = mv88e6xxx_remove,
5007 .mdiodrv.driver = {
5008 .name = "mv88e6085",
5009 .of_match_table = mv88e6xxx_of_match,
Miquel Raynalbcd3d9d2019-02-05 12:07:28 +01005010 .pm = &mv88e6xxx_pm_ops,
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02005011 },
5012};
5013
Ben Hutchings98e67302011-11-25 14:36:19 +00005014static int __init mv88e6xxx_init(void)
5015{
Florian Fainelliab3d4082017-01-08 14:52:07 -08005016 register_switch_driver(&mv88e6xxx_switch_drv);
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02005017 return mdio_driver_register(&mv88e6xxx_driver);
Ben Hutchings98e67302011-11-25 14:36:19 +00005018}
5019module_init(mv88e6xxx_init);
5020
5021static void __exit mv88e6xxx_cleanup(void)
5022{
Andrew Lunn14c7b3c2016-05-10 23:27:21 +02005023 mdio_driver_unregister(&mv88e6xxx_driver);
Florian Fainelliab3d4082017-01-08 14:52:07 -08005024 unregister_switch_driver(&mv88e6xxx_switch_drv);
Ben Hutchings98e67302011-11-25 14:36:19 +00005025}
5026module_exit(mv88e6xxx_cleanup);
Ben Hutchings3d825ed2011-11-25 14:37:16 +00005027
5028MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
5029MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
5030MODULE_LICENSE("GPL");