chip.c 148.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3 4
 * Marvell 88e6xxx Ethernet switch single-chip support
 *
5 6
 * Copyright (c) 2008 Marvell Semiconductor
 *
7 8
 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
 *
V
Vivien Didelot 已提交
9 10
 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
11 12
 */

13
#include <linux/bitfield.h>
14
#include <linux/delay.h>
15
#include <linux/etherdevice.h>
16
#include <linux/ethtool.h>
17
#include <linux/if_bridge.h>
18 19 20
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
21
#include <linux/jiffies.h>
22
#include <linux/list.h>
23
#include <linux/mdio.h>
24
#include <linux/module.h>
25
#include <linux/of_device.h>
26
#include <linux/of_irq.h>
27
#include <linux/of_mdio.h>
28
#include <linux/platform_data/mv88e6xxx.h>
29
#include <linux/netdevice.h>
30
#include <linux/gpio/consumer.h>
31
#include <linux/phylink.h>
32
#include <net/dsa.h>
33

34
#include "chip.h"
35
#include "global1.h"
36
#include "global2.h"
37
#include "hwtstamp.h"
38
#include "phy.h"
39
#include "port.h"
40
#include "ptp.h"
41
#include "serdes.h"
42
#include "smi.h"
43

44
static void assert_reg_lock(struct mv88e6xxx_chip *chip)
45
{
46 47
	if (unlikely(!mutex_is_locked(&chip->reg_lock))) {
		dev_err(chip->dev, "Switch registers lock not held!\n");
48 49 50 51
		dump_stack();
	}
}

52
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)
53 54 55
{
	int err;

56
	assert_reg_lock(chip);
57

58
	err = mv88e6xxx_smi_read(chip, addr, reg, val);
59 60 61
	if (err)
		return err;

62
	dev_dbg(chip->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
63 64 65 66 67
		addr, reg, *val);

	return 0;
}

68
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
69
{
70 71
	int err;

72
	assert_reg_lock(chip);
73

74
	err = mv88e6xxx_smi_write(chip, addr, reg, val);
75 76 77
	if (err)
		return err;

78
	dev_dbg(chip->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
79 80
		addr, reg, val);

81 82 83
	return 0;
}

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
			u16 mask, u16 val)
{
	u16 data;
	int err;
	int i;

	/* There's no bus specific operation to wait for a mask */
	for (i = 0; i < 16; i++) {
		err = mv88e6xxx_read(chip, addr, reg, &data);
		if (err)
			return err;

		if ((data & mask) == val)
			return 0;

		usleep_range(1000, 2000);
	}

	dev_err(chip->dev, "Timeout while waiting for switch\n");
	return -ETIMEDOUT;
}

107 108 109 110 111 112 113
int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
		       int bit, int val)
{
	return mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit),
				   val ? BIT(bit) : 0x0000);
}

114
struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
115 116 117 118 119 120 121 122 123 124 125
{
	struct mv88e6xxx_mdio_bus *mdio_bus;

	mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus,
				    list);
	if (!mdio_bus)
		return NULL;

	return mdio_bus->bus;
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
{
	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
	unsigned int n = d->hwirq;

	chip->g1_irq.masked |= (1 << n);
}

static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
{
	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
	unsigned int n = d->hwirq;

	chip->g1_irq.masked &= ~(1 << n);
}

142
static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
143 144 145 146 147
{
	unsigned int nhandled = 0;
	unsigned int sub_irq;
	unsigned int n;
	u16 reg;
148
	u16 ctl1;
149 150
	int err;

151
	mv88e6xxx_reg_lock(chip);
152
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
153
	mv88e6xxx_reg_unlock(chip);
154 155 156 157

	if (err)
		goto out;

158 159 160 161 162 163 164 165
	do {
		for (n = 0; n < chip->g1_irq.nirqs; ++n) {
			if (reg & (1 << n)) {
				sub_irq = irq_find_mapping(chip->g1_irq.domain,
							   n);
				handle_nested_irq(sub_irq);
				++nhandled;
			}
166
		}
167

168
		mv88e6xxx_reg_lock(chip);
169 170 171 172 173
		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
		if (err)
			goto unlock;
		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
unlock:
174
		mv88e6xxx_reg_unlock(chip);
175 176 177 178 179
		if (err)
			goto out;
		ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
	} while (reg & ctl1);

180 181 182 183
out:
	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
}

184 185 186 187 188 189 190
static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
{
	struct mv88e6xxx_chip *chip = dev_id;

	return mv88e6xxx_g1_irq_thread_work(chip);
}

191 192 193 194
static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
{
	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);

195
	mv88e6xxx_reg_lock(chip);
196 197 198 199 200 201 202 203 204
}

static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
{
	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
	u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
	u16 reg;
	int err;

205
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &reg);
206 207 208 209 210 211
	if (err)
		goto out;

	reg &= ~mask;
	reg |= (~chip->g1_irq.masked & mask);

212
	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);
213 214 215 216
	if (err)
		goto out;

out:
217
	mv88e6xxx_reg_unlock(chip);
218 219
}

220
static const struct irq_chip mv88e6xxx_g1_irq_chip = {
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
	.name			= "mv88e6xxx-g1",
	.irq_mask		= mv88e6xxx_g1_irq_mask,
	.irq_unmask		= mv88e6xxx_g1_irq_unmask,
	.irq_bus_lock		= mv88e6xxx_g1_irq_bus_lock,
	.irq_bus_sync_unlock	= mv88e6xxx_g1_irq_bus_sync_unlock,
};

static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
				       unsigned int irq,
				       irq_hw_number_t hwirq)
{
	struct mv88e6xxx_chip *chip = d->host_data;

	irq_set_chip_data(irq, d->host_data);
	irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
	irq_set_noprobe(irq);

	return 0;
}

static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
	.map	= mv88e6xxx_g1_irq_domain_map,
	.xlate	= irq_domain_xlate_twocell,
};

246
/* To be called with reg_lock held */
247
static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)
248 249
{
	int irq, virq;
250 251
	u16 mask;

252
	mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
253
	mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
254
	mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
255

256
	for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
257
		virq = irq_find_mapping(chip->g1_irq.domain, irq);
258 259 260
		irq_dispose_mapping(virq);
	}

261
	irq_domain_remove(chip->g1_irq.domain);
262 263
}

264 265
static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
{
266 267 268 269
	/*
	 * free_irq must be called without reg_lock taken because the irq
	 * handler takes this lock, too.
	 */
270
	free_irq(chip->irq, chip);
271

272
	mv88e6xxx_reg_lock(chip);
273
	mv88e6xxx_g1_irq_free_common(chip);
274
	mv88e6xxx_reg_unlock(chip);
275 276 277
}

static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)
278
{
279 280
	int err, irq, virq;
	u16 reg, mask;
281 282 283 284 285 286 287 288 289 290 291 292 293 294

	chip->g1_irq.nirqs = chip->info->g1_irqs;
	chip->g1_irq.domain = irq_domain_add_simple(
		NULL, chip->g1_irq.nirqs, 0,
		&mv88e6xxx_g1_irq_domain_ops, chip);
	if (!chip->g1_irq.domain)
		return -ENOMEM;

	for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
		irq_create_mapping(chip->g1_irq.domain, irq);

	chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
	chip->g1_irq.masked = ~0;

295
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
296
	if (err)
297
		goto out_mapping;
298

299
	mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
300

301
	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
302
	if (err)
303
		goto out_disable;
304 305

	/* Reading the interrupt status clears (most of) them */
306
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
307
	if (err)
308
		goto out_disable;
309 310 311

	return 0;

312
out_disable:
313
	mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
314
	mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
315 316 317 318 319 320 321 322

out_mapping:
	for (irq = 0; irq < 16; irq++) {
		virq = irq_find_mapping(chip->g1_irq.domain, irq);
		irq_dispose_mapping(virq);
	}

	irq_domain_remove(chip->g1_irq.domain);
323 324 325 326

	return err;
}

327 328
static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
{
329 330
	static struct lock_class_key lock_key;
	static struct lock_class_key request_key;
331 332 333 334 335 336
	int err;

	err = mv88e6xxx_g1_irq_setup_common(chip);
	if (err)
		return err;

337 338 339 340 341 342
	/* These lock classes tells lockdep that global 1 irqs are in
	 * a different category than their parent GPIO, so it won't
	 * report false recursion.
	 */
	irq_set_lockdep_class(chip->irq, &lock_key, &request_key);

343
	mv88e6xxx_reg_unlock(chip);
344 345
	err = request_threaded_irq(chip->irq, NULL,
				   mv88e6xxx_g1_irq_thread_fn,
346
				   IRQF_ONESHOT | IRQF_SHARED,
347
				   dev_name(chip->dev), chip);
348
	mv88e6xxx_reg_lock(chip);
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
	if (err)
		mv88e6xxx_g1_irq_free_common(chip);

	return err;
}

static void mv88e6xxx_irq_poll(struct kthread_work *work)
{
	struct mv88e6xxx_chip *chip = container_of(work,
						   struct mv88e6xxx_chip,
						   irq_poll_work.work);
	mv88e6xxx_g1_irq_thread_work(chip);

	kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
				   msecs_to_jiffies(100));
}

static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)
{
	int err;

	err = mv88e6xxx_g1_irq_setup_common(chip);
	if (err)
		return err;

	kthread_init_delayed_work(&chip->irq_poll_work,
				  mv88e6xxx_irq_poll);

377
	chip->kworker = kthread_create_worker(0, "%s", dev_name(chip->dev));
378 379 380 381 382 383 384 385 386 387 388 389 390
	if (IS_ERR(chip->kworker))
		return PTR_ERR(chip->kworker);

	kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
				   msecs_to_jiffies(100));

	return 0;
}

static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
{
	kthread_cancel_delayed_work_sync(&chip->irq_poll_work);
	kthread_destroy_worker(chip->kworker);
391

392
	mv88e6xxx_reg_lock(chip);
393
	mv88e6xxx_g1_irq_free_common(chip);
394
	mv88e6xxx_reg_unlock(chip);
395 396
}

397 398 399
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
			     int speed, int duplex, int pause,
			     phy_interface_t mode)
400
{
401
	struct phylink_link_state state;
402 403 404 405 406
	int err;

	if (!chip->info->ops->port_set_link)
		return 0;

407 408 409 410 411 412 413 414 415 416 417 418 419
	if (!chip->info->ops->port_link_state)
		return 0;

	err = chip->info->ops->port_link_state(chip, port, &state);
	if (err)
		return err;

	/* Has anything actually changed? We don't expect the
	 * interface mode to change without one of the other
	 * parameters also changing
	 */
	if (state.link == link &&
	    state.speed == speed &&
420 421 422
	    state.duplex == duplex &&
	    (state.interface == mode ||
	     state.interface == PHY_INTERFACE_MODE_NA))
423 424
		return 0;

425
	/* Port's MAC control must not be changed unless the link is down */
426
	err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
427 428 429 430 431 432 433 434 435
	if (err)
		return err;

	if (chip->info->ops->port_set_speed) {
		err = chip->info->ops->port_set_speed(chip, port, speed);
		if (err && err != -EOPNOTSUPP)
			goto restore_link;
	}

436 437 438
	if (speed == SPEED_MAX && chip->info->ops->port_max_speed_mode)
		mode = chip->info->ops->port_max_speed_mode(port);

439 440 441 442 443 444
	if (chip->info->ops->port_set_pause) {
		err = chip->info->ops->port_set_pause(chip, port, pause);
		if (err)
			goto restore_link;
	}

445 446 447 448 449 450 451 452 453 454 455 456
	if (chip->info->ops->port_set_duplex) {
		err = chip->info->ops->port_set_duplex(chip, port, duplex);
		if (err && err != -EOPNOTSUPP)
			goto restore_link;
	}

	if (chip->info->ops->port_set_rgmii_delay) {
		err = chip->info->ops->port_set_rgmii_delay(chip, port, mode);
		if (err && err != -EOPNOTSUPP)
			goto restore_link;
	}

457 458 459 460 461 462
	if (chip->info->ops->port_set_cmode) {
		err = chip->info->ops->port_set_cmode(chip, port, mode);
		if (err && err != -EOPNOTSUPP)
			goto restore_link;
	}

463 464 465
	err = 0;
restore_link:
	if (chip->info->ops->port_set_link(chip, port, link))
466
		dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port);
467 468 469 470

	return err;
}

471 472 473 474 475 476 477
static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
{
	struct mv88e6xxx_chip *chip = ds->priv;

	return port < chip->info->num_internal_phys;
}

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	if (!phy_interface_mode_is_8023z(state->interface)) {
		/* 10M and 100M are only supported in non-802.3z mode */
		phylink_set(mask, 10baseT_Half);
		phylink_set(mask, 10baseT_Full);
		phylink_set(mask, 100baseT_Half);
		phylink_set(mask, 100baseT_Full);
	}
}

static void mv88e6185_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	/* FIXME: if the port is in 1000Base-X mode, then it only supports
	 * 1000M FD speeds.  In this case, CMODE will indicate 5.
	 */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

504 505 506 507 508 509 510 511 512 513 514 515 516 517
static void mv88e6341_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	if (port >= 5)
		phylink_set(mask, 2500baseX_Full);

	/* No ethtool bits for 200Mbps */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
static void mv88e6352_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	/* No ethtool bits for 200Mbps */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

static void mv88e6390_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
533
	if (port >= 9) {
534
		phylink_set(mask, 2500baseX_Full);
535 536
		phylink_set(mask, 2500baseT_Full);
	}
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

	/* No ethtool bits for 200Mbps */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

static void mv88e6390x_phylink_validate(struct mv88e6xxx_chip *chip, int port,
					unsigned long *mask,
					struct phylink_link_state *state)
{
	if (port >= 9) {
		phylink_set(mask, 10000baseT_Full);
		phylink_set(mask, 10000baseKR_Full);
	}

	mv88e6390_phylink_validate(chip, port, mask, state);
}

557 558 559 560
static void mv88e6xxx_validate(struct dsa_switch *ds, int port,
			       unsigned long *supported,
			       struct phylink_link_state *state)
{
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
	struct mv88e6xxx_chip *chip = ds->priv;

	/* Allow all the expected bits */
	phylink_set(mask, Autoneg);
	phylink_set(mask, Pause);
	phylink_set_port_modes(mask);

	if (chip->info->ops->phylink_validate)
		chip->info->ops->phylink_validate(chip, port, mask, state);

	bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
	bitmap_and(state->advertising, state->advertising, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);

	/* We can only operate at 2500BaseX or 1000BaseX.  If requested
	 * to advertise both, only report advertising at 2500BaseX.
	 */
	phylink_helper_basex_speed(state);
580 581 582 583 584 585 586 587
}

static int mv88e6xxx_link_state(struct dsa_switch *ds, int port,
				struct phylink_link_state *state)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

588
	mv88e6xxx_reg_lock(chip);
589 590 591 592
	if (chip->info->ops->port_link_state)
		err = chip->info->ops->port_link_state(chip, port, state);
	else
		err = -EOPNOTSUPP;
593
	mv88e6xxx_reg_unlock(chip);
594 595 596 597 598 599 600 601 602

	return err;
}

static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
				 unsigned int mode,
				 const struct phylink_link_state *state)
{
	struct mv88e6xxx_chip *chip = ds->priv;
603
	int speed, duplex, link, pause, err;
604

605
	if ((mode == MLO_AN_PHY) && mv88e6xxx_phy_is_internal(ds, port))
606 607 608 609 610 611
		return;

	if (mode == MLO_AN_FIXED) {
		link = LINK_FORCED_UP;
		speed = state->speed;
		duplex = state->duplex;
612 613 614 615
	} else if (!mv88e6xxx_phy_is_internal(ds, port)) {
		link = state->link;
		speed = state->speed;
		duplex = state->duplex;
616 617 618 619 620
	} else {
		speed = SPEED_UNFORCED;
		duplex = DUPLEX_UNFORCED;
		link = LINK_UNFORCED;
	}
621
	pause = !!phylink_test(state->advertising, Pause);
622

623
	mv88e6xxx_reg_lock(chip);
624
	err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, pause,
625
				       state->interface);
626
	mv88e6xxx_reg_unlock(chip);
627 628 629 630 631 632 633 634 635 636

	if (err && err != -EOPNOTSUPP)
		dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
}

static void mv88e6xxx_mac_link_force(struct dsa_switch *ds, int port, int link)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

637
	mv88e6xxx_reg_lock(chip);
638
	err = chip->info->ops->port_set_link(chip, port, link);
639
	mv88e6xxx_reg_unlock(chip);
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660

	if (err)
		dev_err(chip->dev, "p%d: failed to force MAC link\n", port);
}

static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
				    unsigned int mode,
				    phy_interface_t interface)
{
	if (mode == MLO_AN_FIXED)
		mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_DOWN);
}

static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
				  unsigned int mode, phy_interface_t interface,
				  struct phy_device *phydev)
{
	if (mode == MLO_AN_FIXED)
		mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP);
}

661
static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
662
{
663 664
	if (!chip->info->ops->stats_snapshot)
		return -EOPNOTSUPP;
665

666
	return chip->info->ops->stats_snapshot(chip, port);
667 668
}

669
static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
	{ "in_good_octets",		8, 0x00, STATS_TYPE_BANK0, },
	{ "in_bad_octets",		4, 0x02, STATS_TYPE_BANK0, },
	{ "in_unicast",			4, 0x04, STATS_TYPE_BANK0, },
	{ "in_broadcasts",		4, 0x06, STATS_TYPE_BANK0, },
	{ "in_multicasts",		4, 0x07, STATS_TYPE_BANK0, },
	{ "in_pause",			4, 0x16, STATS_TYPE_BANK0, },
	{ "in_undersize",		4, 0x18, STATS_TYPE_BANK0, },
	{ "in_fragments",		4, 0x19, STATS_TYPE_BANK0, },
	{ "in_oversize",		4, 0x1a, STATS_TYPE_BANK0, },
	{ "in_jabber",			4, 0x1b, STATS_TYPE_BANK0, },
	{ "in_rx_error",		4, 0x1c, STATS_TYPE_BANK0, },
	{ "in_fcs_error",		4, 0x1d, STATS_TYPE_BANK0, },
	{ "out_octets",			8, 0x0e, STATS_TYPE_BANK0, },
	{ "out_unicast",		4, 0x10, STATS_TYPE_BANK0, },
	{ "out_broadcasts",		4, 0x13, STATS_TYPE_BANK0, },
	{ "out_multicasts",		4, 0x12, STATS_TYPE_BANK0, },
	{ "out_pause",			4, 0x15, STATS_TYPE_BANK0, },
	{ "excessive",			4, 0x11, STATS_TYPE_BANK0, },
	{ "collisions",			4, 0x1e, STATS_TYPE_BANK0, },
	{ "deferred",			4, 0x05, STATS_TYPE_BANK0, },
	{ "single",			4, 0x14, STATS_TYPE_BANK0, },
	{ "multiple",			4, 0x17, STATS_TYPE_BANK0, },
	{ "out_fcs_error",		4, 0x03, STATS_TYPE_BANK0, },
	{ "late",			4, 0x1f, STATS_TYPE_BANK0, },
	{ "hist_64bytes",		4, 0x08, STATS_TYPE_BANK0, },
	{ "hist_65_127bytes",		4, 0x09, STATS_TYPE_BANK0, },
	{ "hist_128_255bytes",		4, 0x0a, STATS_TYPE_BANK0, },
	{ "hist_256_511bytes",		4, 0x0b, STATS_TYPE_BANK0, },
	{ "hist_512_1023bytes",		4, 0x0c, STATS_TYPE_BANK0, },
	{ "hist_1024_max_bytes",	4, 0x0d, STATS_TYPE_BANK0, },
	{ "sw_in_discards",		4, 0x10, STATS_TYPE_PORT, },
	{ "sw_in_filtered",		2, 0x12, STATS_TYPE_PORT, },
	{ "sw_out_filtered",		2, 0x13, STATS_TYPE_PORT, },
	{ "in_discards",		4, 0x00, STATS_TYPE_BANK1, },
	{ "in_filtered",		4, 0x01, STATS_TYPE_BANK1, },
	{ "in_accepted",		4, 0x02, STATS_TYPE_BANK1, },
	{ "in_bad_accepted",		4, 0x03, STATS_TYPE_BANK1, },
	{ "in_good_avb_class_a",	4, 0x04, STATS_TYPE_BANK1, },
	{ "in_good_avb_class_b",	4, 0x05, STATS_TYPE_BANK1, },
	{ "in_bad_avb_class_a",		4, 0x06, STATS_TYPE_BANK1, },
	{ "in_bad_avb_class_b",		4, 0x07, STATS_TYPE_BANK1, },
	{ "tcam_counter_0",		4, 0x08, STATS_TYPE_BANK1, },
	{ "tcam_counter_1",		4, 0x09, STATS_TYPE_BANK1, },
	{ "tcam_counter_2",		4, 0x0a, STATS_TYPE_BANK1, },
	{ "tcam_counter_3",		4, 0x0b, STATS_TYPE_BANK1, },
	{ "in_da_unknown",		4, 0x0e, STATS_TYPE_BANK1, },
	{ "in_management",		4, 0x0f, STATS_TYPE_BANK1, },
	{ "out_queue_0",		4, 0x10, STATS_TYPE_BANK1, },
	{ "out_queue_1",		4, 0x11, STATS_TYPE_BANK1, },
	{ "out_queue_2",		4, 0x12, STATS_TYPE_BANK1, },
	{ "out_queue_3",		4, 0x13, STATS_TYPE_BANK1, },
	{ "out_queue_4",		4, 0x14, STATS_TYPE_BANK1, },
	{ "out_queue_5",		4, 0x15, STATS_TYPE_BANK1, },
	{ "out_queue_6",		4, 0x16, STATS_TYPE_BANK1, },
	{ "out_queue_7",		4, 0x17, STATS_TYPE_BANK1, },
	{ "out_cut_through",		4, 0x18, STATS_TYPE_BANK1, },
	{ "out_octets_a",		4, 0x1a, STATS_TYPE_BANK1, },
	{ "out_octets_b",		4, 0x1b, STATS_TYPE_BANK1, },
	{ "out_management",		4, 0x1f, STATS_TYPE_BANK1, },
729 730
};

731
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
732
					    struct mv88e6xxx_hw_stat *s,
733 734
					    int port, u16 bank1_select,
					    u16 histogram)
735 736 737
{
	u32 low;
	u32 high = 0;
738
	u16 reg = 0;
739
	int err;
740 741
	u64 value;

742
	switch (s->type) {
743
	case STATS_TYPE_PORT:
744 745
		err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
		if (err)
746
			return U64_MAX;
747

748
		low = reg;
749
		if (s->size == 4) {
750 751
			err = mv88e6xxx_port_read(chip, port, s->reg + 1, &reg);
			if (err)
752
				return U64_MAX;
753
			low |= ((u32)reg) << 16;
754
		}
755
		break;
756
	case STATS_TYPE_BANK1:
757
		reg = bank1_select;
758 759
		/* fall through */
	case STATS_TYPE_BANK0:
760
		reg |= s->reg | histogram;
761
		mv88e6xxx_g1_stats_read(chip, reg, &low);
762
		if (s->size == 8)
763
			mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
764 765
		break;
	default:
766
		return U64_MAX;
767
	}
768
	value = (((u64)high) << 32) | low;
769 770 771
	return value;
}

772 773
static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data, int types)
774
{
775 776
	struct mv88e6xxx_hw_stat *stat;
	int i, j;
777

778 779
	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
		stat = &mv88e6xxx_hw_stats[i];
780
		if (stat->type & types) {
781 782 783 784
			memcpy(data + j * ETH_GSTRING_LEN, stat->string,
			       ETH_GSTRING_LEN);
			j++;
		}
785
	}
786 787

	return j;
788 789
}

790 791
static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data)
792
{
793 794
	return mv88e6xxx_stats_get_strings(chip, data,
					   STATS_TYPE_BANK0 | STATS_TYPE_PORT);
795 796
}

797 798 799 800 801 802
static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data)
{
	return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
}

803 804
static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data)
805
{
806 807
	return mv88e6xxx_stats_get_strings(chip, data,
					   STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
808 809
}

810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
	"atu_member_violation",
	"atu_miss_violation",
	"atu_full_violation",
	"vtu_member_violation",
	"vtu_miss_violation",
};

static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
		strlcpy(data + i * ETH_GSTRING_LEN,
			mv88e6xxx_atu_vtu_stats_strings[i],
			ETH_GSTRING_LEN);
}

828
static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
829
				  u32 stringset, uint8_t *data)
830
{
V
Vivien Didelot 已提交
831
	struct mv88e6xxx_chip *chip = ds->priv;
832
	int count = 0;
833

834 835 836
	if (stringset != ETH_SS_STATS)
		return;

837
	mv88e6xxx_reg_lock(chip);
838

839
	if (chip->info->ops->stats_get_strings)
840 841 842 843
		count = chip->info->ops->stats_get_strings(chip, data);

	if (chip->info->ops->serdes_get_strings) {
		data += count * ETH_GSTRING_LEN;
844
		count = chip->info->ops->serdes_get_strings(chip, port, data);
845
	}
846

847 848 849
	data += count * ETH_GSTRING_LEN;
	mv88e6xxx_atu_vtu_get_strings(data);

850
	mv88e6xxx_reg_unlock(chip);
851 852 853 854 855
}

static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
					  int types)
{
856 857 858 859 860
	struct mv88e6xxx_hw_stat *stat;
	int i, j;

	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
		stat = &mv88e6xxx_hw_stats[i];
861
		if (stat->type & types)
862 863 864
			j++;
	}
	return j;
865 866
}

867 868 869 870 871 872
static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
					      STATS_TYPE_PORT);
}

873 874 875 876 877
static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0);
}

878 879 880 881 882 883
static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
					      STATS_TYPE_BANK1);
}

884
static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
885 886
{
	struct mv88e6xxx_chip *chip = ds->priv;
887 888
	int serdes_count = 0;
	int count = 0;
889

890 891 892
	if (sset != ETH_SS_STATS)
		return 0;

893
	mv88e6xxx_reg_lock(chip);
894
	if (chip->info->ops->stats_get_sset_count)
895 896 897 898 899 900 901
		count = chip->info->ops->stats_get_sset_count(chip);
	if (count < 0)
		goto out;

	if (chip->info->ops->serdes_get_sset_count)
		serdes_count = chip->info->ops->serdes_get_sset_count(chip,
								      port);
902
	if (serdes_count < 0) {
903
		count = serdes_count;
904 905 906 907 908
		goto out;
	}
	count += serdes_count;
	count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);

909
out:
910
	mv88e6xxx_reg_unlock(chip);
911

912
	return count;
913 914
}

915 916 917
static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data, int types,
				     u16 bank1_select, u16 histogram)
918 919 920 921 922 923 924
{
	struct mv88e6xxx_hw_stat *stat;
	int i, j;

	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
		stat = &mv88e6xxx_hw_stats[i];
		if (stat->type & types) {
925
			mv88e6xxx_reg_lock(chip);
926 927 928
			data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
							      bank1_select,
							      histogram);
929
			mv88e6xxx_reg_unlock(chip);
930

931 932 933
			j++;
		}
	}
934
	return j;
935 936
}

937 938
static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
939 940
{
	return mv88e6xxx_stats_get_stats(chip, port, data,
941
					 STATS_TYPE_BANK0 | STATS_TYPE_PORT,
942
					 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
943 944
}

945 946 947 948 949 950 951
static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
{
	return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
					 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
}

952 953
static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
954 955
{
	return mv88e6xxx_stats_get_stats(chip, port, data,
956
					 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
957 958
					 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
					 MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
959 960
}

961 962
static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
963 964 965
{
	return mv88e6xxx_stats_get_stats(chip, port, data,
					 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
966 967
					 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
					 0);
968 969
}

970 971 972 973 974 975 976 977 978 979
static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
					uint64_t *data)
{
	*data++ = chip->ports[port].atu_member_violation;
	*data++ = chip->ports[port].atu_miss_violation;
	*data++ = chip->ports[port].atu_full_violation;
	*data++ = chip->ports[port].vtu_member_violation;
	*data++ = chip->ports[port].vtu_miss_violation;
}

980 981 982
static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
				uint64_t *data)
{
983 984
	int count = 0;

985
	if (chip->info->ops->stats_get_stats)
986 987
		count = chip->info->ops->stats_get_stats(chip, port, data);

988
	mv88e6xxx_reg_lock(chip);
989 990
	if (chip->info->ops->serdes_get_stats) {
		data += count;
991
		count = chip->info->ops->serdes_get_stats(chip, port, data);
992
	}
993 994
	data += count;
	mv88e6xxx_atu_vtu_get_stats(chip, port, data);
995
	mv88e6xxx_reg_unlock(chip);
996 997
}

998 999
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
					uint64_t *data)
1000
{
V
Vivien Didelot 已提交
1001
	struct mv88e6xxx_chip *chip = ds->priv;
1002 1003
	int ret;

1004
	mv88e6xxx_reg_lock(chip);
1005

1006
	ret = mv88e6xxx_stats_snapshot(chip, port);
1007
	mv88e6xxx_reg_unlock(chip);
1008 1009

	if (ret < 0)
1010
		return;
1011 1012

	mv88e6xxx_get_stats(chip, port, data);
1013

1014 1015
}

1016
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
1017 1018 1019 1020
{
	return 32 * sizeof(u16);
}

1021 1022
static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
			       struct ethtool_regs *regs, void *_p)
1023
{
V
Vivien Didelot 已提交
1024
	struct mv88e6xxx_chip *chip = ds->priv;
1025 1026
	int err;
	u16 reg;
1027 1028 1029
	u16 *p = _p;
	int i;

1030
	regs->version = chip->info->prod_num;
1031 1032 1033

	memset(p, 0xff, 32 * sizeof(u16));

1034
	mv88e6xxx_reg_lock(chip);
1035

1036 1037
	for (i = 0; i < 32; i++) {

1038 1039 1040
		err = mv88e6xxx_port_read(chip, port, i, &reg);
		if (!err)
			p[i] = reg;
1041
	}
1042

1043
	mv88e6xxx_reg_unlock(chip);
1044 1045
}

V
Vivien Didelot 已提交
1046 1047
static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
				 struct ethtool_eee *e)
1048
{
1049 1050
	/* Nothing to do on the port's MAC */
	return 0;
1051 1052
}

V
Vivien Didelot 已提交
1053 1054
static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
				 struct ethtool_eee *e)
1055
{
1056 1057
	/* Nothing to do on the port's MAC */
	return 0;
1058 1059
}

1060
/* Mask of the local ports allowed to receive frames from a given fabric port */
1061
static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
1062
{
1063 1064
	struct dsa_switch *ds = chip->ds;
	struct dsa_switch_tree *dst = ds->dst;
1065
	struct net_device *br;
1066 1067
	struct dsa_port *dp;
	bool found = false;
1068
	u16 pvlan;
1069

1070 1071 1072 1073 1074 1075
	list_for_each_entry(dp, &dst->ports, list) {
		if (dp->ds->index == dev && dp->index == port) {
			found = true;
			break;
		}
	}
1076 1077

	/* Prevent frames from unknown switch or port */
1078
	if (!found)
1079 1080 1081
		return 0;

	/* Frames from DSA links and CPU ports can egress any local port */
1082
	if (dp->type == DSA_PORT_TYPE_CPU || dp->type == DSA_PORT_TYPE_DSA)
1083 1084
		return mv88e6xxx_port_mask(chip);

1085
	br = dp->bridge_dev;
1086 1087 1088 1089 1090
	pvlan = 0;

	/* Frames from user ports can egress any local DSA links and CPU ports,
	 * as well as any local member of their bridge group.
	 */
1091 1092 1093 1094 1095 1096
	list_for_each_entry(dp, &dst->ports, list)
		if (dp->ds == ds &&
		    (dp->type == DSA_PORT_TYPE_CPU ||
		     dp->type == DSA_PORT_TYPE_DSA ||
		     (br && dp->bridge_dev == br)))
			pvlan |= BIT(dp->index);
1097 1098 1099 1100

	return pvlan;
}

1101
static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
1102 1103
{
	u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
1104 1105 1106

	/* prevent frames from going back out of the port they came in on */
	output_ports &= ~BIT(port);
1107

1108
	return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
1109 1110
}

1111 1112
static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
					 u8 state)
1113
{
V
Vivien Didelot 已提交
1114
	struct mv88e6xxx_chip *chip = ds->priv;
1115
	int err;
1116

1117
	mv88e6xxx_reg_lock(chip);
1118
	err = mv88e6xxx_port_set_state(chip, port, state);
1119
	mv88e6xxx_reg_unlock(chip);
1120 1121

	if (err)
1122
		dev_err(ds->dev, "p%d: failed to update state\n", port);
1123 1124
}

1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip)
{
	int err;

	if (chip->info->ops->ieee_pri_map) {
		err = chip->info->ops->ieee_pri_map(chip);
		if (err)
			return err;
	}

	if (chip->info->ops->ip_pri_map) {
		err = chip->info->ops->ip_pri_map(chip);
		if (err)
			return err;
	}

	return 0;
}

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
{
	int target, port;
	int err;

	if (!chip->info->global2_addr)
		return 0;

	/* Initialize the routing port to the 32 possible target devices */
	for (target = 0; target < 32; target++) {
		port = 0x1f;
		if (target < DSA_MAX_SWITCHES)
			if (chip->ds->rtable[target] != DSA_RTABLE_NONE)
				port = chip->ds->rtable[target];

		err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
		if (err)
			return err;
	}

1164 1165 1166 1167 1168 1169 1170
	if (chip->info->ops->set_cascade_port) {
		port = MV88E6XXX_CASCADE_PORT_MULTIPLE;
		err = chip->info->ops->set_cascade_port(chip, port);
		if (err)
			return err;
	}

1171 1172 1173 1174
	err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index);
	if (err)
		return err;

1175 1176 1177
	return 0;
}

1178 1179 1180 1181 1182 1183 1184 1185 1186
static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip)
{
	/* Clear all trunk masks and mapping */
	if (chip->info->global2_addr)
		return mv88e6xxx_g2_trunk_clear(chip);

	return 0;
}

1187 1188 1189 1190 1191 1192 1193 1194
static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->rmu_disable)
		return chip->info->ops->rmu_disable(chip);

	return 0;
}

1195 1196 1197 1198 1199 1200 1201 1202
static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->pot_clear)
		return chip->info->ops->pot_clear(chip);

	return 0;
}

1203 1204 1205 1206 1207 1208 1209 1210
static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->mgmt_rsvd2cpu)
		return chip->info->ops->mgmt_rsvd2cpu(chip);

	return 0;
}

1211 1212
static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
{
1213 1214
	int err;

1215 1216 1217 1218
	err = mv88e6xxx_g1_atu_flush(chip, 0, true);
	if (err)
		return err;

1219 1220 1221 1222
	err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
	if (err)
		return err;

1223 1224 1225
	return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
}

1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
{
	int port;
	int err;

	if (!chip->info->ops->irl_init_all)
		return 0;

	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
		/* Disable ingress rate limiting by resetting all per port
		 * ingress rate limit resources to their initial state.
		 */
		err = chip->info->ops->irl_init_all(chip, port);
		if (err)
			return err;
	}

	return 0;
}

1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
static int mv88e6xxx_mac_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->set_switch_mac) {
		u8 addr[ETH_ALEN];

		eth_random_addr(addr);

		return chip->info->ops->set_switch_mac(chip, addr);
	}

	return 0;
}

1259 1260 1261 1262 1263
static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
{
	u16 pvlan = 0;

	if (!mv88e6xxx_has_pvt(chip))
1264
		return 0;
1265 1266 1267

	/* Skip the local source device, which uses in-chip port VLAN */
	if (dev != chip->ds->index)
1268
		pvlan = mv88e6xxx_port_vlan(chip, dev, port);
1269 1270 1271 1272

	return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan);
}

1273 1274
static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
{
1275 1276 1277
	int dev, port;
	int err;

1278 1279 1280 1281 1282 1283
	if (!mv88e6xxx_has_pvt(chip))
		return 0;

	/* Clear 5 Bit Port for usage with Marvell Link Street devices:
	 * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev.
	 */
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
	err = mv88e6xxx_g2_misc_4_bit_port(chip);
	if (err)
		return err;

	for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; ++dev) {
		for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; ++port) {
			err = mv88e6xxx_pvt_map(chip, dev, port);
			if (err)
				return err;
		}
	}

	return 0;
1297 1298
}

1299 1300 1301 1302 1303
static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

1304
	mv88e6xxx_reg_lock(chip);
1305
	err = mv88e6xxx_g1_atu_remove(chip, 0, port, false);
1306
	mv88e6xxx_reg_unlock(chip);
1307 1308

	if (err)
1309
		dev_err(ds->dev, "p%d: failed to flush ATU\n", port);
1310 1311
}

1312 1313 1314 1315 1316 1317 1318 1319
static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
{
	if (!chip->info->max_vid)
		return 0;

	return mv88e6xxx_g1_vtu_flush(chip);
}

1320 1321 1322 1323 1324 1325 1326 1327 1328
static int mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip,
				 struct mv88e6xxx_vtu_entry *entry)
{
	if (!chip->info->ops->vtu_getnext)
		return -EOPNOTSUPP;

	return chip->info->ops->vtu_getnext(chip, entry);
}

1329 1330 1331 1332 1333 1334 1335 1336 1337
static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
				   struct mv88e6xxx_vtu_entry *entry)
{
	if (!chip->info->ops->vtu_loadpurge)
		return -EOPNOTSUPP;

	return chip->info->ops->vtu_loadpurge(chip, entry);
}

1338
static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
1339 1340
{
	DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
1341
	struct mv88e6xxx_vtu_entry vlan;
1342
	int i, err;
1343 1344 1345

	bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);

1346
	/* Set every FID bit used by the (un)bridged ports */
1347
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1348
		err = mv88e6xxx_port_get_fid(chip, i, fid);
1349 1350 1351 1352 1353 1354
		if (err)
			return err;

		set_bit(*fid, fid_bitmap);
	}

1355
	/* Set every FID bit used by the VLAN entries */
1356 1357 1358
	vlan.vid = chip->info->max_vid;
	vlan.valid = false;

1359
	do {
1360
		err = mv88e6xxx_vtu_getnext(chip, &vlan);
1361 1362 1363 1364 1365 1366 1367
		if (err)
			return err;

		if (!vlan.valid)
			break;

		set_bit(vlan.fid, fid_bitmap);
1368
	} while (vlan.vid < chip->info->max_vid);
1369 1370 1371 1372 1373

	/* The reset value 0x000 is used to indicate that multiple address
	 * databases are not needed. Return the next positive available.
	 */
	*fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
1374
	if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
1375 1376 1377
		return -ENOSPC;

	/* Clear the database */
1378
	return mv88e6xxx_g1_atu_flush(chip, *fid, true);
1379 1380
}

1381 1382 1383
static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
					u16 vid_begin, u16 vid_end)
{
V
Vivien Didelot 已提交
1384
	struct mv88e6xxx_chip *chip = ds->priv;
1385
	struct mv88e6xxx_vtu_entry vlan;
1386 1387
	int i, err;

1388 1389 1390 1391
	/* DSA and CPU ports have to be members of multiple vlans */
	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
		return 0;

1392 1393 1394
	if (!vid_begin)
		return -EOPNOTSUPP;

1395 1396 1397
	vlan.vid = vid_begin - 1;
	vlan.valid = false;

1398
	do {
1399
		err = mv88e6xxx_vtu_getnext(chip, &vlan);
1400
		if (err)
1401
			return err;
1402 1403 1404 1405 1406 1407 1408

		if (!vlan.valid)
			break;

		if (vlan.vid > vid_end)
			break;

1409
		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1410 1411 1412
			if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
				continue;

1413
			if (!dsa_to_port(ds, i)->slave)
1414 1415
				continue;

1416
			if (vlan.member[i] ==
1417
			    MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1418 1419
				continue;

V
Vivien Didelot 已提交
1420
			if (dsa_to_port(ds, i)->bridge_dev ==
1421
			    dsa_to_port(ds, port)->bridge_dev)
1422 1423
				break; /* same bridge, check next VLAN */

V
Vivien Didelot 已提交
1424
			if (!dsa_to_port(ds, i)->bridge_dev)
1425 1426
				continue;

1427 1428
			dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n",
				port, vlan.vid, i,
V
Vivien Didelot 已提交
1429
				netdev_name(dsa_to_port(ds, i)->bridge_dev));
1430
			return -EOPNOTSUPP;
1431 1432 1433
		}
	} while (vlan.vid < vid_end);

1434
	return 0;
1435 1436
}

1437 1438
static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
					 bool vlan_filtering)
1439
{
V
Vivien Didelot 已提交
1440
	struct mv88e6xxx_chip *chip = ds->priv;
1441 1442
	u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
		MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
1443
	int err;
1444

1445
	if (!chip->info->max_vid)
1446 1447
		return -EOPNOTSUPP;

1448
	mv88e6xxx_reg_lock(chip);
1449
	err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
1450
	mv88e6xxx_reg_unlock(chip);
1451

1452
	return err;
1453 1454
}

1455 1456
static int
mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
1457
			    const struct switchdev_obj_port_vlan *vlan)
1458
{
V
Vivien Didelot 已提交
1459
	struct mv88e6xxx_chip *chip = ds->priv;
1460 1461
	int err;

1462
	if (!chip->info->max_vid)
1463 1464
		return -EOPNOTSUPP;

1465 1466 1467
	/* If the requested port doesn't belong to the same bridge as the VLAN
	 * members, do not support it (yet) and fallback to software VLAN.
	 */
1468
	mv88e6xxx_reg_lock(chip);
1469 1470
	err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin,
					   vlan->vid_end);
1471
	mv88e6xxx_reg_unlock(chip);
1472

1473 1474 1475
	/* We don't need any dynamic resource from the kernel (yet),
	 * so skip the prepare phase.
	 */
1476
	return err;
1477 1478
}

1479 1480 1481 1482 1483
static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
					const unsigned char *addr, u16 vid,
					u8 state)
{
	struct mv88e6xxx_atu_entry entry;
1484 1485
	struct mv88e6xxx_vtu_entry vlan;
	u16 fid;
1486 1487 1488
	int err;

	/* Null VLAN ID corresponds to the port private database */
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
	if (vid == 0) {
		err = mv88e6xxx_port_get_fid(chip, port, &fid);
		if (err)
			return err;
	} else {
		vlan.vid = vid - 1;
		vlan.valid = false;

		err = mv88e6xxx_vtu_getnext(chip, &vlan);
		if (err)
			return err;

		/* switchdev expects -EOPNOTSUPP to honor software VLANs */
		if (vlan.vid != vid || !vlan.valid)
			return -EOPNOTSUPP;

		fid = vlan.fid;
	}
1507

1508
	entry.state = 0;
1509 1510 1511
	ether_addr_copy(entry.mac, addr);
	eth_addr_dec(entry.mac);

1512
	err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry);
1513 1514 1515 1516
	if (err)
		return err;

	/* Initialize a fresh ATU entry if it isn't found */
1517
	if (!entry.state || !ether_addr_equal(entry.mac, addr)) {
1518 1519 1520 1521 1522
		memset(&entry, 0, sizeof(entry));
		ether_addr_copy(entry.mac, addr);
	}

	/* Purge the ATU entry only if no port is using it anymore */
1523
	if (!state) {
1524 1525
		entry.portvec &= ~BIT(port);
		if (!entry.portvec)
1526
			entry.state = 0;
1527 1528 1529 1530 1531
	} else {
		entry.portvec |= BIT(port);
		entry.state = state;
	}

1532
	return mv88e6xxx_g1_atu_loadpurge(chip, fid, &entry);
1533 1534
}

1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
static int mv88e6xxx_policy_apply(struct mv88e6xxx_chip *chip, int port,
				  const struct mv88e6xxx_policy *policy)
{
	enum mv88e6xxx_policy_mapping mapping = policy->mapping;
	enum mv88e6xxx_policy_action action = policy->action;
	const u8 *addr = policy->addr;
	u16 vid = policy->vid;
	u8 state;
	int err;
	int id;

	if (!chip->info->ops->port_set_policy)
		return -EOPNOTSUPP;

	switch (mapping) {
	case MV88E6XXX_POLICY_MAPPING_DA:
	case MV88E6XXX_POLICY_MAPPING_SA:
		if (action == MV88E6XXX_POLICY_ACTION_NORMAL)
			state = 0; /* Dissociate the port and address */
		else if (action == MV88E6XXX_POLICY_ACTION_DISCARD &&
			 is_multicast_ether_addr(addr))
			state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC_POLICY;
		else if (action == MV88E6XXX_POLICY_ACTION_DISCARD &&
			 is_unicast_ether_addr(addr))
			state = MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC_POLICY;
		else
			return -EOPNOTSUPP;

		err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
						   state);
		if (err)
			return err;
		break;
	default:
		return -EOPNOTSUPP;
	}

	/* Skip the port's policy clearing if the mapping is still in use */
	if (action == MV88E6XXX_POLICY_ACTION_NORMAL)
		idr_for_each_entry(&chip->policies, policy, id)
			if (policy->port == port &&
			    policy->mapping == mapping &&
			    policy->action != action)
				return 0;

	return chip->info->ops->port_set_policy(chip, port, mapping, action);
}

static int mv88e6xxx_policy_insert(struct mv88e6xxx_chip *chip, int port,
				   struct ethtool_rx_flow_spec *fs)
{
	struct ethhdr *mac_entry = &fs->h_u.ether_spec;
	struct ethhdr *mac_mask = &fs->m_u.ether_spec;
	enum mv88e6xxx_policy_mapping mapping;
	enum mv88e6xxx_policy_action action;
	struct mv88e6xxx_policy *policy;
	u16 vid = 0;
	u8 *addr;
	int err;
	int id;

	if (fs->location != RX_CLS_LOC_ANY)
		return -EINVAL;

	if (fs->ring_cookie == RX_CLS_FLOW_DISC)
		action = MV88E6XXX_POLICY_ACTION_DISCARD;
	else
		return -EOPNOTSUPP;

	switch (fs->flow_type & ~FLOW_EXT) {
	case ETHER_FLOW:
		if (!is_zero_ether_addr(mac_mask->h_dest) &&
		    is_zero_ether_addr(mac_mask->h_source)) {
			mapping = MV88E6XXX_POLICY_MAPPING_DA;
			addr = mac_entry->h_dest;
		} else if (is_zero_ether_addr(mac_mask->h_dest) &&
		    !is_zero_ether_addr(mac_mask->h_source)) {
			mapping = MV88E6XXX_POLICY_MAPPING_SA;
			addr = mac_entry->h_source;
		} else {
			/* Cannot support DA and SA mapping in the same rule */
			return -EOPNOTSUPP;
		}
		break;
	default:
		return -EOPNOTSUPP;
	}

	if ((fs->flow_type & FLOW_EXT) && fs->m_ext.vlan_tci) {
		if (fs->m_ext.vlan_tci != 0xffff)
			return -EOPNOTSUPP;
		vid = be16_to_cpu(fs->h_ext.vlan_tci) & VLAN_VID_MASK;
	}

	idr_for_each_entry(&chip->policies, policy, id) {
		if (policy->port == port && policy->mapping == mapping &&
		    policy->action == action && policy->vid == vid &&
		    ether_addr_equal(policy->addr, addr))
			return -EEXIST;
	}

	policy = devm_kzalloc(chip->dev, sizeof(*policy), GFP_KERNEL);
	if (!policy)
		return -ENOMEM;

	fs->location = 0;
	err = idr_alloc_u32(&chip->policies, policy, &fs->location, 0xffffffff,
			    GFP_KERNEL);
	if (err) {
		devm_kfree(chip->dev, policy);
		return err;
	}

	memcpy(&policy->fs, fs, sizeof(*fs));
	ether_addr_copy(policy->addr, addr);
	policy->mapping = mapping;
	policy->action = action;
	policy->port = port;
	policy->vid = vid;

	err = mv88e6xxx_policy_apply(chip, port, policy);
	if (err) {
		idr_remove(&chip->policies, fs->location);
		devm_kfree(chip->dev, policy);
		return err;
	}

	return 0;
}

static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port,
			       struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
{
	struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
	struct mv88e6xxx_chip *chip = ds->priv;
	struct mv88e6xxx_policy *policy;
	int err;
	int id;

	mv88e6xxx_reg_lock(chip);

	switch (rxnfc->cmd) {
	case ETHTOOL_GRXCLSRLCNT:
		rxnfc->data = 0;
		rxnfc->data |= RX_CLS_LOC_SPECIAL;
		rxnfc->rule_cnt = 0;
		idr_for_each_entry(&chip->policies, policy, id)
			if (policy->port == port)
				rxnfc->rule_cnt++;
		err = 0;
		break;
	case ETHTOOL_GRXCLSRULE:
		err = -ENOENT;
		policy = idr_find(&chip->policies, fs->location);
		if (policy) {
			memcpy(fs, &policy->fs, sizeof(*fs));
			err = 0;
		}
		break;
	case ETHTOOL_GRXCLSRLALL:
		rxnfc->data = 0;
		rxnfc->rule_cnt = 0;
		idr_for_each_entry(&chip->policies, policy, id)
			if (policy->port == port)
				rule_locs[rxnfc->rule_cnt++] = id;
		err = 0;
		break;
	default:
		err = -EOPNOTSUPP;
		break;
	}

	mv88e6xxx_reg_unlock(chip);

	return err;
}

static int mv88e6xxx_set_rxnfc(struct dsa_switch *ds, int port,
			       struct ethtool_rxnfc *rxnfc)
{
	struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
	struct mv88e6xxx_chip *chip = ds->priv;
	struct mv88e6xxx_policy *policy;
	int err;

	mv88e6xxx_reg_lock(chip);

	switch (rxnfc->cmd) {
	case ETHTOOL_SRXCLSRLINS:
		err = mv88e6xxx_policy_insert(chip, port, fs);
		break;
	case ETHTOOL_SRXCLSRLDEL:
		err = -ENOENT;
		policy = idr_remove(&chip->policies, fs->location);
		if (policy) {
			policy->action = MV88E6XXX_POLICY_ACTION_NORMAL;
			err = mv88e6xxx_policy_apply(chip, port, policy);
			devm_kfree(chip->dev, policy);
		}
		break;
	default:
		err = -EOPNOTSUPP;
		break;
	}

	mv88e6xxx_reg_unlock(chip);

	return err;
}

1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767
static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port,
					u16 vid)
{
	const char broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC;

	return mv88e6xxx_port_db_load_purge(chip, port, broadcast, vid, state);
}

static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid)
{
	int port;
	int err;

	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
		err = mv88e6xxx_port_add_broadcast(chip, port, vid);
		if (err)
			return err;
	}

	return 0;
}

1768
static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
1769
				    u16 vid, u8 member)
1770
{
1771
	const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1772
	struct mv88e6xxx_vtu_entry vlan;
1773
	int i, err;
1774

1775 1776
	if (!vid)
		return -EOPNOTSUPP;
1777

1778 1779
	vlan.vid = vid - 1;
	vlan.valid = false;
1780

1781
	err = mv88e6xxx_vtu_getnext(chip, &vlan);
1782 1783 1784
	if (err)
		return err;

1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
	if (vlan.vid != vid || !vlan.valid) {
		memset(&vlan, 0, sizeof(vlan));

		err = mv88e6xxx_atu_new(chip, &vlan.fid);
		if (err)
			return err;

		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
			if (i == port)
				vlan.member[i] = member;
			else
				vlan.member[i] = non_member;

		vlan.vid = vid;
		vlan.valid = true;

		err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
		if (err)
			return err;

		err = mv88e6xxx_broadcast_setup(chip, vlan.vid);
		if (err)
			return err;
	} else if (vlan.member[port] != member) {
		vlan.member[port] = member;

		err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
		if (err)
			return err;
	} else {
		dev_info(chip->dev, "p%d: already a member of VLAN %d\n",
			 port, vid);
	}

	return 0;
1820 1821
}

1822
static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
1823
				    const struct switchdev_obj_port_vlan *vlan)
1824
{
V
Vivien Didelot 已提交
1825
	struct mv88e6xxx_chip *chip = ds->priv;
1826 1827
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1828
	u8 member;
1829 1830
	u16 vid;

1831
	if (!chip->info->max_vid)
1832 1833
		return;

1834
	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
1835
		member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED;
1836
	else if (untagged)
1837
		member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED;
1838
	else
1839
		member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED;
1840

1841
	mv88e6xxx_reg_lock(chip);
1842

1843
	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
1844
		if (mv88e6xxx_port_vlan_join(chip, port, vid, member))
1845 1846
			dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
				vid, untagged ? 'u' : 't');
1847

1848
	if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
1849 1850
		dev_err(ds->dev, "p%d: failed to set PVID %d\n", port,
			vlan->vid_end);
1851

1852
	mv88e6xxx_reg_unlock(chip);
1853 1854
}

1855 1856
static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip,
				     int port, u16 vid)
1857
{
1858
	struct mv88e6xxx_vtu_entry vlan;
1859 1860
	int i, err;

1861 1862 1863 1864 1865 1866 1867
	if (!vid)
		return -EOPNOTSUPP;

	vlan.vid = vid - 1;
	vlan.valid = false;

	err = mv88e6xxx_vtu_getnext(chip, &vlan);
1868
	if (err)
1869
		return err;
1870

1871 1872 1873 1874 1875
	/* If the VLAN doesn't exist in hardware or the port isn't a member,
	 * tell switchdev that this VLAN is likely handled in software.
	 */
	if (vlan.vid != vid || !vlan.valid ||
	    vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1876
		return -EOPNOTSUPP;
1877

1878
	vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1879 1880

	/* keep the VLAN unless all ports are excluded */
1881
	vlan.valid = false;
1882
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1883 1884
		if (vlan.member[i] !=
		    MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
1885
			vlan.valid = true;
1886 1887 1888 1889
			break;
		}
	}

1890
	err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
1891 1892 1893
	if (err)
		return err;

1894
	return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
1895 1896
}

1897 1898
static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
				   const struct switchdev_obj_port_vlan *vlan)
1899
{
V
Vivien Didelot 已提交
1900
	struct mv88e6xxx_chip *chip = ds->priv;
1901 1902 1903
	u16 pvid, vid;
	int err = 0;

1904
	if (!chip->info->max_vid)
1905 1906
		return -EOPNOTSUPP;

1907
	mv88e6xxx_reg_lock(chip);
1908

1909
	err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
1910 1911 1912
	if (err)
		goto unlock;

1913
	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
1914
		err = mv88e6xxx_port_vlan_leave(chip, port, vid);
1915 1916 1917 1918
		if (err)
			goto unlock;

		if (vid == pvid) {
1919
			err = mv88e6xxx_port_set_pvid(chip, port, 0);
1920 1921 1922 1923 1924
			if (err)
				goto unlock;
		}
	}

1925
unlock:
1926
	mv88e6xxx_reg_unlock(chip);
1927 1928 1929 1930

	return err;
}

1931 1932
static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
				  const unsigned char *addr, u16 vid)
1933
{
V
Vivien Didelot 已提交
1934
	struct mv88e6xxx_chip *chip = ds->priv;
1935
	int err;
1936

1937
	mv88e6xxx_reg_lock(chip);
1938 1939
	err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
					   MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
1940
	mv88e6xxx_reg_unlock(chip);
1941 1942

	return err;
1943 1944
}

1945
static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1946
				  const unsigned char *addr, u16 vid)
1947
{
V
Vivien Didelot 已提交
1948
	struct mv88e6xxx_chip *chip = ds->priv;
1949
	int err;
1950

1951
	mv88e6xxx_reg_lock(chip);
1952
	err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 0);
1953
	mv88e6xxx_reg_unlock(chip);
1954

1955
	return err;
1956 1957
}

1958 1959
static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
				      u16 fid, u16 vid, int port,
1960
				      dsa_fdb_dump_cb_t *cb, void *data)
1961
{
1962
	struct mv88e6xxx_atu_entry addr;
1963
	bool is_static;
1964 1965
	int err;

1966
	addr.state = 0;
1967
	eth_broadcast_addr(addr.mac);
1968 1969

	do {
1970
		err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
1971
		if (err)
1972
			return err;
1973

1974
		if (!addr.state)
1975 1976
			break;

1977
		if (addr.trunk || (addr.portvec & BIT(port)) == 0)
1978 1979
			continue;

1980 1981
		if (!is_unicast_ether_addr(addr.mac))
			continue;
1982

1983 1984 1985
		is_static = (addr.state ==
			     MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
		err = cb(addr.mac, vid, is_static, data);
1986 1987
		if (err)
			return err;
1988 1989 1990 1991 1992
	} while (!is_broadcast_ether_addr(addr.mac));

	return err;
}

1993
static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1994
				  dsa_fdb_dump_cb_t *cb, void *data)
1995
{
1996
	struct mv88e6xxx_vtu_entry vlan;
1997
	u16 fid;
1998 1999
	int err;

2000
	/* Dump port's default Filtering Information Database (VLAN ID 0) */
2001
	err = mv88e6xxx_port_get_fid(chip, port, &fid);
2002
	if (err)
2003
		return err;
2004

2005
	err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data);
2006
	if (err)
2007
		return err;
2008

2009
	/* Dump VLANs' Filtering Information Databases */
2010 2011 2012
	vlan.vid = chip->info->max_vid;
	vlan.valid = false;

2013
	do {
2014
		err = mv88e6xxx_vtu_getnext(chip, &vlan);
2015
		if (err)
2016
			return err;
2017 2018 2019 2020

		if (!vlan.valid)
			break;

2021
		err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
2022
						 cb, data);
2023
		if (err)
2024
			return err;
2025
	} while (vlan.vid < chip->info->max_vid);
2026

2027 2028 2029 2030
	return err;
}

static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2031
				   dsa_fdb_dump_cb_t *cb, void *data)
2032
{
V
Vivien Didelot 已提交
2033
	struct mv88e6xxx_chip *chip = ds->priv;
2034 2035
	int err;

2036
	mv88e6xxx_reg_lock(chip);
2037
	err = mv88e6xxx_port_db_dump(chip, port, cb, data);
2038
	mv88e6xxx_reg_unlock(chip);
2039

2040
	return err;
2041 2042
}

2043 2044
static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
				struct net_device *br)
2045
{
2046 2047 2048
	struct dsa_switch *ds = chip->ds;
	struct dsa_switch_tree *dst = ds->dst;
	struct dsa_port *dp;
2049
	int err;
2050

2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
	list_for_each_entry(dp, &dst->ports, list) {
		if (dp->bridge_dev == br) {
			if (dp->ds == ds) {
				/* This is a local bridge group member,
				 * remap its Port VLAN Map.
				 */
				err = mv88e6xxx_port_vlan_map(chip, dp->index);
				if (err)
					return err;
			} else {
				/* This is an external bridge group member,
				 * remap its cross-chip Port VLAN Table entry.
				 */
				err = mv88e6xxx_pvt_map(chip, dp->ds->index,
							dp->index);
2066 2067 2068 2069 2070 2071
				if (err)
					return err;
			}
		}
	}

2072 2073 2074 2075 2076 2077 2078 2079 2080
	return 0;
}

static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
				      struct net_device *br)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

2081
	mv88e6xxx_reg_lock(chip);
2082
	err = mv88e6xxx_bridge_map(chip, br);
2083
	mv88e6xxx_reg_unlock(chip);
2084

2085
	return err;
2086 2087
}

2088 2089
static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
					struct net_device *br)
2090
{
V
Vivien Didelot 已提交
2091
	struct mv88e6xxx_chip *chip = ds->priv;
2092

2093
	mv88e6xxx_reg_lock(chip);
2094 2095 2096
	if (mv88e6xxx_bridge_map(chip, br) ||
	    mv88e6xxx_port_vlan_map(chip, port))
		dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
2097
	mv88e6xxx_reg_unlock(chip);
2098 2099
}

2100 2101 2102 2103 2104 2105
static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev,
					   int port, struct net_device *br)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

2106
	mv88e6xxx_reg_lock(chip);
2107
	err = mv88e6xxx_pvt_map(chip, dev, port);
2108
	mv88e6xxx_reg_unlock(chip);
2109 2110 2111 2112 2113 2114 2115 2116 2117

	return err;
}

static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev,
					     int port, struct net_device *br)
{
	struct mv88e6xxx_chip *chip = ds->priv;

2118
	mv88e6xxx_reg_lock(chip);
2119 2120
	if (mv88e6xxx_pvt_map(chip, dev, port))
		dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
2121
	mv88e6xxx_reg_unlock(chip);
2122 2123
}

2124 2125 2126 2127 2128 2129 2130 2131
static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->reset)
		return chip->info->ops->reset(chip);

	return 0;
}

2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
{
	struct gpio_desc *gpiod = chip->reset;

	/* If there is a GPIO connected to the reset pin, toggle it */
	if (gpiod) {
		gpiod_set_value_cansleep(gpiod, 1);
		usleep_range(10000, 20000);
		gpiod_set_value_cansleep(gpiod, 0);
		usleep_range(10000, 20000);
	}
}

2145
static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
2146
{
2147
	int i, err;
2148

2149
	/* Set all ports to the Disabled state */
2150
	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
2151
		err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED);
2152 2153
		if (err)
			return err;
2154 2155
	}

2156 2157 2158
	/* Wait for transmit queues to drain,
	 * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
	 */
2159 2160
	usleep_range(2000, 4000);

2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
	return 0;
}

static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
{
	int err;

	err = mv88e6xxx_disable_ports(chip);
	if (err)
		return err;

2172
	mv88e6xxx_hardware_reset(chip);
2173

2174
	return mv88e6xxx_software_reset(chip);
2175 2176
}

2177
static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
2178 2179
				   enum mv88e6xxx_frame_mode frame,
				   enum mv88e6xxx_egress_mode egress, u16 etype)
2180 2181 2182
{
	int err;

2183 2184 2185 2186
	if (!chip->info->ops->port_set_frame_mode)
		return -EOPNOTSUPP;

	err = mv88e6xxx_port_set_egress_mode(chip, port, egress);
2187 2188 2189
	if (err)
		return err;

2190 2191 2192 2193 2194 2195 2196 2197
	err = chip->info->ops->port_set_frame_mode(chip, port, frame);
	if (err)
		return err;

	if (chip->info->ops->port_set_ether_type)
		return chip->info->ops->port_set_ether_type(chip, port, etype);

	return 0;
2198 2199
}

2200
static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port)
2201
{
2202
	return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
2203
				       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
2204
				       MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
2205
}
2206

2207 2208 2209
static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
2210
				       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
2211
				       MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
2212
}
2213

2214 2215 2216 2217
static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6xxx_set_port_mode(chip, port,
				       MV88E6XXX_FRAME_MODE_ETHERTYPE,
2218 2219
				       MV88E6XXX_EGRESS_MODE_ETHERTYPE,
				       ETH_P_EDSA);
2220
}
2221

2222 2223 2224 2225
static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
{
	if (dsa_is_dsa_port(chip->ds, port))
		return mv88e6xxx_set_port_mode_dsa(chip, port);
2226

2227
	if (dsa_is_user_port(chip->ds, port))
2228
		return mv88e6xxx_set_port_mode_normal(chip, port);
2229

2230 2231 2232
	/* Setup CPU port mode depending on its supported tag format */
	if (chip->info->tag_protocol == DSA_TAG_PROTO_DSA)
		return mv88e6xxx_set_port_mode_dsa(chip, port);
2233

2234 2235
	if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA)
		return mv88e6xxx_set_port_mode_edsa(chip, port);
2236

2237
	return -EINVAL;
2238 2239
}

2240
static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
2241
{
2242
	bool message = dsa_is_dsa_port(chip->ds, port);
2243

2244
	return mv88e6xxx_port_set_message_port(chip, port, message);
2245
}
2246

2247
static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
2248
{
2249
	struct dsa_switch *ds = chip->ds;
2250
	bool flood;
2251

2252 2253 2254 2255 2256
	/* Upstream ports flood frames with unknown unicast or multicast DA */
	flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port);
	if (chip->info->ops->port_set_egress_floods)
		return chip->info->ops->port_set_egress_floods(chip, port,
							       flood, flood);
2257

2258
	return 0;
2259 2260
}

2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
static irqreturn_t mv88e6xxx_serdes_irq_thread_fn(int irq, void *dev_id)
{
	struct mv88e6xxx_port *mvp = dev_id;
	struct mv88e6xxx_chip *chip = mvp->chip;
	irqreturn_t ret = IRQ_NONE;
	int port = mvp->port;
	u8 lane;

	mv88e6xxx_reg_lock(chip);
	lane = mv88e6xxx_serdes_get_lane(chip, port);
	if (lane)
		ret = mv88e6xxx_serdes_irq_status(chip, port, lane);
	mv88e6xxx_reg_unlock(chip);

	return ret;
}

static int mv88e6xxx_serdes_irq_request(struct mv88e6xxx_chip *chip, int port,
					u8 lane)
{
	struct mv88e6xxx_port *dev_id = &chip->ports[port];
	unsigned int irq;
	int err;

	/* Nothing to request if this SERDES port has no IRQ */
	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
	if (!irq)
		return 0;

	/* Requesting the IRQ will trigger IRQ callbacks, so release the lock */
	mv88e6xxx_reg_unlock(chip);
	err = request_threaded_irq(irq, NULL, mv88e6xxx_serdes_irq_thread_fn,
				   IRQF_ONESHOT, "mv88e6xxx-serdes", dev_id);
	mv88e6xxx_reg_lock(chip);
	if (err)
		return err;

	dev_id->serdes_irq = irq;

	return mv88e6xxx_serdes_irq_enable(chip, port, lane);
}

static int mv88e6xxx_serdes_irq_free(struct mv88e6xxx_chip *chip, int port,
				     u8 lane)
{
	struct mv88e6xxx_port *dev_id = &chip->ports[port];
	unsigned int irq = dev_id->serdes_irq;
	int err;

	/* Nothing to free if no IRQ has been requested */
	if (!irq)
		return 0;

	err = mv88e6xxx_serdes_irq_disable(chip, port, lane);

	/* Freeing the IRQ will trigger IRQ callbacks, so release the lock */
	mv88e6xxx_reg_unlock(chip);
	free_irq(irq, dev_id);
	mv88e6xxx_reg_lock(chip);

	dev_id->serdes_irq = 0;

	return err;
}

2326 2327 2328
static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
				  bool on)
{
2329
	u8 lane;
2330
	int err;
2331

2332 2333
	lane = mv88e6xxx_serdes_get_lane(chip, port);
	if (!lane)
2334 2335 2336
		return 0;

	if (on) {
2337
		err = mv88e6xxx_serdes_power_up(chip, port, lane);
2338 2339 2340
		if (err)
			return err;

2341
		err = mv88e6xxx_serdes_irq_request(chip, port, lane);
2342
	} else {
2343 2344 2345
		err = mv88e6xxx_serdes_irq_free(chip, port, lane);
		if (err)
			return err;
2346

2347
		err = mv88e6xxx_serdes_power_down(chip, port, lane);
2348 2349 2350
	}

	return err;
2351 2352
}

2353 2354 2355 2356 2357 2358
static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
{
	struct dsa_switch *ds = chip->ds;
	int upstream_port;
	int err;

2359
	upstream_port = dsa_upstream_port(ds, port);
2360 2361 2362 2363 2364 2365 2366
	if (chip->info->ops->port_set_upstream_port) {
		err = chip->info->ops->port_set_upstream_port(chip, port,
							      upstream_port);
		if (err)
			return err;
	}

2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382
	if (port == upstream_port) {
		if (chip->info->ops->set_cpu_port) {
			err = chip->info->ops->set_cpu_port(chip,
							    upstream_port);
			if (err)
				return err;
		}

		if (chip->info->ops->set_egress_port) {
			err = chip->info->ops->set_egress_port(chip,
							       upstream_port);
			if (err)
				return err;
		}
	}

2383 2384 2385
	return 0;
}

2386
static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
2387
{
2388
	struct dsa_switch *ds = chip->ds;
2389
	int err;
2390
	u16 reg;
2391

2392 2393 2394
	chip->ports[port].chip = chip;
	chip->ports[port].port = port;

2395 2396 2397 2398 2399 2400 2401
	/* MAC Forcing register: don't force link, speed, duplex or flow control
	 * state to any particular values on physical ports, but force the CPU
	 * port and all DSA ports to their maximum bandwidth and full duplex.
	 */
	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
		err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
					       SPEED_MAX, DUPLEX_FULL,
2402
					       PAUSE_OFF,
2403 2404 2405 2406
					       PHY_INTERFACE_MODE_NA);
	else
		err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
					       SPEED_UNFORCED, DUPLEX_UNFORCED,
2407
					       PAUSE_ON,
2408 2409 2410
					       PHY_INTERFACE_MODE_NA);
	if (err)
		return err;
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425

	/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
	 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
	 * tunneling, determine priority by looking at 802.1p and IP
	 * priority fields (IP prio has precedence), and set STP state
	 * to Forwarding.
	 *
	 * If this is the CPU link, use DSA or EDSA tagging depending
	 * on which tagging mode was configured.
	 *
	 * If this is a link to another switch, use DSA tagging mode.
	 *
	 * If this is the upstream port for this switch, enable
	 * forwarding of unknown unicasts and multicasts.
	 */
2426 2427 2428 2429
	reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
		MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
		MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
2430 2431
	if (err)
		return err;
2432

2433
	err = mv88e6xxx_setup_port_mode(chip, port);
2434 2435
	if (err)
		return err;
2436

2437
	err = mv88e6xxx_setup_egress_floods(chip, port);
2438 2439 2440
	if (err)
		return err;

2441
	/* Port Control 2: don't force a good FCS, set the maximum frame size to
2442
	 * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
2443 2444 2445
	 * untagged frames on this port, do a destination address lookup on all
	 * received packets as usual, disable ARP mirroring and don't send a
	 * copy of all transmitted/received frames on this port to the CPU.
2446
	 */
2447 2448 2449
	err = mv88e6xxx_port_set_map_da(chip, port);
	if (err)
		return err;
2450

2451 2452 2453
	err = mv88e6xxx_setup_upstream_port(chip, port);
	if (err)
		return err;
2454

2455
	err = mv88e6xxx_port_set_8021q_mode(chip, port,
2456
				MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED);
2457 2458 2459
	if (err)
		return err;

2460 2461
	if (chip->info->ops->port_set_jumbo_size) {
		err = chip->info->ops->port_set_jumbo_size(chip, port, 10240);
2462 2463 2464 2465
		if (err)
			return err;
	}

2466 2467 2468 2469 2470
	/* Port Association Vector: when learning source addresses
	 * of packets, add the address to the address database using
	 * a port bitmap that has only the bit for this port set and
	 * the other bits clear.
	 */
2471
	reg = 1 << port;
2472 2473
	/* Disable learning for CPU port */
	if (dsa_is_cpu_port(ds, port))
2474
		reg = 0;
2475

2476 2477
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
				   reg);
2478 2479
	if (err)
		return err;
2480 2481

	/* Egress rate control 2: disable egress rate control. */
2482 2483
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2,
				   0x0000);
2484 2485
	if (err)
		return err;
2486

2487 2488
	if (chip->info->ops->port_pause_limit) {
		err = chip->info->ops->port_pause_limit(chip, port, 0, 0);
2489 2490
		if (err)
			return err;
2491
	}
2492

2493 2494 2495 2496 2497 2498
	if (chip->info->ops->port_disable_learn_limit) {
		err = chip->info->ops->port_disable_learn_limit(chip, port);
		if (err)
			return err;
	}

2499 2500
	if (chip->info->ops->port_disable_pri_override) {
		err = chip->info->ops->port_disable_pri_override(chip, port);
2501 2502
		if (err)
			return err;
2503
	}
2504

2505 2506
	if (chip->info->ops->port_tag_remap) {
		err = chip->info->ops->port_tag_remap(chip, port);
2507 2508
		if (err)
			return err;
2509 2510
	}

2511 2512
	if (chip->info->ops->port_egress_rate_limiting) {
		err = chip->info->ops->port_egress_rate_limiting(chip, port);
2513 2514
		if (err)
			return err;
2515 2516
	}

2517 2518 2519 2520 2521
	if (chip->info->ops->port_setup_message_port) {
		err = chip->info->ops->port_setup_message_port(chip, port);
		if (err)
			return err;
	}
2522

2523
	/* Port based VLAN map: give each port the same default address
2524 2525
	 * database, and allow bidirectional communication between the
	 * CPU and DSA port(s), and the other ports.
2526
	 */
2527
	err = mv88e6xxx_port_set_fid(chip, port, 0);
2528 2529
	if (err)
		return err;
2530

2531
	err = mv88e6xxx_port_vlan_map(chip, port);
2532 2533
	if (err)
		return err;
2534 2535 2536 2537

	/* Default VLAN ID and priority: don't set a default VLAN
	 * ID, and set the default packet priority to zero.
	 */
2538
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
2539 2540
}

2541 2542 2543 2544
static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
				 struct phy_device *phydev)
{
	struct mv88e6xxx_chip *chip = ds->priv;
2545
	int err;
2546

2547
	mv88e6xxx_reg_lock(chip);
2548
	err = mv88e6xxx_serdes_power(chip, port, true);
2549
	mv88e6xxx_reg_unlock(chip);
2550 2551 2552 2553

	return err;
}

2554
static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port)
2555 2556 2557
{
	struct mv88e6xxx_chip *chip = ds->priv;

2558
	mv88e6xxx_reg_lock(chip);
2559 2560
	if (mv88e6xxx_serdes_power(chip, port, false))
		dev_err(chip->dev, "failed to power off SERDES\n");
2561
	mv88e6xxx_reg_unlock(chip);
2562 2563
}

2564 2565 2566
static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds,
				     unsigned int ageing_time)
{
V
Vivien Didelot 已提交
2567
	struct mv88e6xxx_chip *chip = ds->priv;
2568 2569
	int err;

2570
	mv88e6xxx_reg_lock(chip);
2571
	err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time);
2572
	mv88e6xxx_reg_unlock(chip);
2573 2574 2575 2576

	return err;
}

2577
static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
2578
{
2579
	int err;
2580

2581
	/* Initialize the statistics unit */
2582 2583 2584 2585 2586
	if (chip->info->ops->stats_set_histogram) {
		err = chip->info->ops->stats_set_histogram(chip);
		if (err)
			return err;
	}
2587

2588
	return mv88e6xxx_g1_stats_clear(chip);
2589 2590
}

2591 2592 2593 2594 2595 2596 2597 2598
/* Check if the errata has already been applied. */
static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
{
	int port;
	int err;
	u16 val;

	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
2599
		err = mv88e6xxx_port_hidden_read(chip, 0xf, port, 0, &val);
2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631
		if (err) {
			dev_err(chip->dev,
				"Error reading hidden register: %d\n", err);
			return false;
		}
		if (val != 0x01c0)
			return false;
	}

	return true;
}

/* The 6390 copper ports have an errata which require poking magic
 * values into undocumented hidden registers and then performing a
 * software reset.
 */
static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
{
	int port;
	int err;

	if (mv88e6390_setup_errata_applied(chip))
		return 0;

	/* Set the ports into blocking mode */
	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
		err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
		if (err)
			return err;
	}

	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
2632
		err = mv88e6xxx_port_hidden_write(chip, 0xf, port, 0, 0x01c0);
2633 2634 2635 2636 2637 2638 2639
		if (err)
			return err;
	}

	return mv88e6xxx_software_reset(chip);
}

2640
static int mv88e6xxx_setup(struct dsa_switch *ds)
2641
{
V
Vivien Didelot 已提交
2642
	struct mv88e6xxx_chip *chip = ds->priv;
2643
	u8 cmode;
2644
	int err;
2645 2646
	int i;

2647
	chip->ds = ds;
2648
	ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
2649

2650
	mv88e6xxx_reg_lock(chip);
2651

2652 2653 2654 2655 2656 2657
	if (chip->info->ops->setup_errata) {
		err = chip->info->ops->setup_errata(chip);
		if (err)
			goto unlock;
	}

2658 2659 2660 2661 2662
	/* Cache the cmode of each port. */
	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
		if (chip->info->ops->port_get_cmode) {
			err = chip->info->ops->port_get_cmode(chip, i, &cmode);
			if (err)
2663
				goto unlock;
2664 2665 2666 2667 2668

			chip->ports[i].cmode = cmode;
		}
	}

2669
	/* Setup Switch Port Registers */
2670
	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
2671 2672 2673
		if (dsa_is_unused_port(ds, i))
			continue;

2674
		/* Prevent the use of an invalid port. */
2675
		if (mv88e6xxx_is_invalid_port(chip, i)) {
2676 2677 2678 2679 2680
			dev_err(chip->dev, "port %d is invalid\n", i);
			err = -EINVAL;
			goto unlock;
		}

2681 2682 2683 2684 2685
		err = mv88e6xxx_setup_port(chip, i);
		if (err)
			goto unlock;
	}

2686 2687 2688 2689
	err = mv88e6xxx_irl_setup(chip);
	if (err)
		goto unlock;

2690 2691 2692 2693
	err = mv88e6xxx_mac_setup(chip);
	if (err)
		goto unlock;

2694 2695 2696 2697
	err = mv88e6xxx_phy_setup(chip);
	if (err)
		goto unlock;

2698 2699 2700 2701
	err = mv88e6xxx_vtu_setup(chip);
	if (err)
		goto unlock;

2702 2703 2704 2705
	err = mv88e6xxx_pvt_setup(chip);
	if (err)
		goto unlock;

2706 2707 2708 2709
	err = mv88e6xxx_atu_setup(chip);
	if (err)
		goto unlock;

2710 2711 2712 2713
	err = mv88e6xxx_broadcast_setup(chip, 0);
	if (err)
		goto unlock;

2714 2715 2716 2717
	err = mv88e6xxx_pot_setup(chip);
	if (err)
		goto unlock;

2718 2719 2720 2721
	err = mv88e6xxx_rmu_setup(chip);
	if (err)
		goto unlock;

2722 2723 2724
	err = mv88e6xxx_rsvd2cpu_setup(chip);
	if (err)
		goto unlock;
2725

2726 2727 2728 2729
	err = mv88e6xxx_trunk_setup(chip);
	if (err)
		goto unlock;

2730 2731 2732 2733
	err = mv88e6xxx_devmap_setup(chip);
	if (err)
		goto unlock;

2734 2735 2736 2737
	err = mv88e6xxx_pri_setup(chip);
	if (err)
		goto unlock;

2738
	/* Setup PTP Hardware Clock and timestamping */
2739 2740 2741 2742
	if (chip->info->ptp_support) {
		err = mv88e6xxx_ptp_setup(chip);
		if (err)
			goto unlock;
2743 2744 2745 2746

		err = mv88e6xxx_hwtstamp_setup(chip);
		if (err)
			goto unlock;
2747 2748
	}

2749 2750 2751 2752
	err = mv88e6xxx_stats_setup(chip);
	if (err)
		goto unlock;

2753
unlock:
2754
	mv88e6xxx_reg_unlock(chip);
2755

2756
	return err;
2757 2758
}

2759
static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
2760
{
2761 2762
	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
	struct mv88e6xxx_chip *chip = mdio_bus->chip;
2763 2764
	u16 val;
	int err;
2765

2766 2767 2768
	if (!chip->info->ops->phy_read)
		return -EOPNOTSUPP;

2769
	mv88e6xxx_reg_lock(chip);
2770
	err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
2771
	mv88e6xxx_reg_unlock(chip);
2772

2773
	if (reg == MII_PHYSID2) {
2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789
		/* Some internal PHYs don't have a model number. */
		if (chip->info->family != MV88E6XXX_FAMILY_6165)
			/* Then there is the 6165 family. It gets is
			 * PHYs correct. But it can also have two
			 * SERDES interfaces in the PHY address
			 * space. And these don't have a model
			 * number. But they are not PHYs, so we don't
			 * want to give them something a PHY driver
			 * will recognise.
			 *
			 * Use the mv88e6390 family model number
			 * instead, for anything which really could be
			 * a PHY,
			 */
			if (!(val & 0x3f0))
				val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
2790 2791
	}

2792
	return err ? err : val;
2793 2794
}

2795
static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
2796
{
2797 2798
	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
	struct mv88e6xxx_chip *chip = mdio_bus->chip;
2799
	int err;
2800

2801 2802 2803
	if (!chip->info->ops->phy_write)
		return -EOPNOTSUPP;

2804
	mv88e6xxx_reg_lock(chip);
2805
	err = chip->info->ops->phy_write(chip, bus, phy, reg, val);
2806
	mv88e6xxx_reg_unlock(chip);
2807 2808

	return err;
2809 2810
}

2811
static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
2812 2813
				   struct device_node *np,
				   bool external)
2814 2815
{
	static int index;
2816
	struct mv88e6xxx_mdio_bus *mdio_bus;
2817 2818 2819
	struct mii_bus *bus;
	int err;

2820
	if (external) {
2821
		mv88e6xxx_reg_lock(chip);
2822
		err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true);
2823
		mv88e6xxx_reg_unlock(chip);
2824 2825 2826 2827 2828

		if (err)
			return err;
	}

2829
	bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus));
2830 2831 2832
	if (!bus)
		return -ENOMEM;

2833
	mdio_bus = bus->priv;
2834
	mdio_bus->bus = bus;
2835
	mdio_bus->chip = chip;
2836 2837
	INIT_LIST_HEAD(&mdio_bus->list);
	mdio_bus->external = external;
2838

2839 2840
	if (np) {
		bus->name = np->full_name;
2841
		snprintf(bus->id, MII_BUS_ID_SIZE, "%pOF", np);
2842 2843 2844 2845 2846 2847 2848
	} else {
		bus->name = "mv88e6xxx SMI";
		snprintf(bus->id, MII_BUS_ID_SIZE, "mv88e6xxx-%d", index++);
	}

	bus->read = mv88e6xxx_mdio_read;
	bus->write = mv88e6xxx_mdio_write;
2849
	bus->parent = chip->dev;
2850

2851 2852 2853 2854 2855 2856
	if (!external) {
		err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
		if (err)
			return err;
	}

2857
	err = of_mdiobus_register(bus, np);
2858
	if (err) {
2859
		dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
2860
		mv88e6xxx_g2_irq_mdio_free(chip, bus);
2861
		return err;
2862
	}
2863 2864 2865 2866 2867

	if (external)
		list_add_tail(&mdio_bus->list, &chip->mdios);
	else
		list_add(&mdio_bus->list, &chip->mdios);
2868 2869

	return 0;
2870
}
2871

2872 2873 2874 2875 2876
static const struct of_device_id mv88e6xxx_mdio_external_match[] = {
	{ .compatible = "marvell,mv88e6xxx-mdio-external",
	  .data = (void *)true },
	{ },
};
2877

2878 2879 2880 2881 2882 2883 2884 2885 2886
static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)

{
	struct mv88e6xxx_mdio_bus *mdio_bus;
	struct mii_bus *bus;

	list_for_each_entry(mdio_bus, &chip->mdios, list) {
		bus = mdio_bus->bus;

2887 2888 2889
		if (!mdio_bus->external)
			mv88e6xxx_g2_irq_mdio_free(chip, bus);

2890 2891 2892 2893
		mdiobus_unregister(bus);
	}
}

2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
				    struct device_node *np)
{
	const struct of_device_id *match;
	struct device_node *child;
	int err;

	/* Always register one mdio bus for the internal/default mdio
	 * bus. This maybe represented in the device tree, but is
	 * optional.
	 */
	child = of_get_child_by_name(np, "mdio");
	err = mv88e6xxx_mdio_register(chip, child, false);
	if (err)
		return err;

	/* Walk the device tree, and see if there are any other nodes
	 * which say they are compatible with the external mdio
	 * bus.
	 */
	for_each_available_child_of_node(np, child) {
		match = of_match_node(mv88e6xxx_mdio_external_match, child);
		if (match) {
			err = mv88e6xxx_mdio_register(chip, child, true);
2918 2919
			if (err) {
				mv88e6xxx_mdios_unregister(chip);
2920
				of_node_put(child);
2921
				return err;
2922
			}
2923 2924 2925 2926
		}
	}

	return 0;
2927 2928
}

2929 2930
static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
{
V
Vivien Didelot 已提交
2931
	struct mv88e6xxx_chip *chip = ds->priv;
2932 2933 2934 2935 2936 2937 2938

	return chip->eeprom_len;
}

static int mv88e6xxx_get_eeprom(struct dsa_switch *ds,
				struct ethtool_eeprom *eeprom, u8 *data)
{
V
Vivien Didelot 已提交
2939
	struct mv88e6xxx_chip *chip = ds->priv;
2940 2941
	int err;

2942 2943
	if (!chip->info->ops->get_eeprom)
		return -EOPNOTSUPP;
2944

2945
	mv88e6xxx_reg_lock(chip);
2946
	err = chip->info->ops->get_eeprom(chip, eeprom, data);
2947
	mv88e6xxx_reg_unlock(chip);
2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959

	if (err)
		return err;

	eeprom->magic = 0xc3ec4951;

	return 0;
}

static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
				struct ethtool_eeprom *eeprom, u8 *data)
{
V
Vivien Didelot 已提交
2960
	struct mv88e6xxx_chip *chip = ds->priv;
2961 2962
	int err;

2963 2964 2965
	if (!chip->info->ops->set_eeprom)
		return -EOPNOTSUPP;

2966 2967 2968
	if (eeprom->magic != 0xc3ec4951)
		return -EINVAL;

2969
	mv88e6xxx_reg_lock(chip);
2970
	err = chip->info->ops->set_eeprom(chip, eeprom, data);
2971
	mv88e6xxx_reg_unlock(chip);
2972 2973 2974 2975

	return err;
}

2976
static const struct mv88e6xxx_ops mv88e6085_ops = {
2977
	/* MV88E6XXX_FAMILY_6097 */
2978 2979
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
2980
	.irl_init_all = mv88e6352_g2_irl_init_all,
2981
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2982 2983
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
2984
	.port_set_link = mv88e6xxx_port_set_link,
2985
	.port_set_duplex = mv88e6xxx_port_set_duplex,
2986
	.port_set_speed = mv88e6185_port_set_speed,
2987
	.port_tag_remap = mv88e6095_port_tag_remap,
2988
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
2989
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
2990
	.port_set_ether_type = mv88e6351_port_set_ether_type,
2991
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2992
	.port_pause_limit = mv88e6097_port_pause_limit,
2993
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2994
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2995
	.port_link_state = mv88e6352_port_link_state,
2996
	.port_get_cmode = mv88e6185_port_get_cmode,
2997
	.port_setup_message_port = mv88e6xxx_setup_message_port,
2998
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2999
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3000 3001
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3002
	.stats_get_stats = mv88e6095_stats_get_stats,
3003 3004
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3005
	.watchdog_ops = &mv88e6097_watchdog_ops,
3006
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3007
	.pot_clear = mv88e6xxx_g2_pot_clear,
3008 3009
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
3010
	.reset = mv88e6185_g1_reset,
3011
	.rmu_disable = mv88e6085_g1_rmu_disable,
3012
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3013
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3014
	.phylink_validate = mv88e6185_phylink_validate,
3015 3016 3017
};

static const struct mv88e6xxx_ops mv88e6095_ops = {
3018
	/* MV88E6XXX_FAMILY_6095 */
3019 3020
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3021
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3022 3023
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
3024
	.port_set_link = mv88e6xxx_port_set_link,
3025
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3026
	.port_set_speed = mv88e6185_port_set_speed,
3027
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
3028
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
3029
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
3030
	.port_link_state = mv88e6185_port_link_state,
3031
	.port_get_cmode = mv88e6185_port_get_cmode,
3032
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3033
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3034
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3035 3036
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3037
	.stats_get_stats = mv88e6095_stats_get_stats,
3038
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
3039 3040
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
3041
	.reset = mv88e6185_g1_reset,
3042
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3043
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3044
	.phylink_validate = mv88e6185_phylink_validate,
3045 3046
};

3047
static const struct mv88e6xxx_ops mv88e6097_ops = {
3048
	/* MV88E6XXX_FAMILY_6097 */
3049 3050
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3051
	.irl_init_all = mv88e6352_g2_irl_init_all,
3052 3053 3054 3055 3056 3057
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_speed = mv88e6185_port_set_speed,
3058
	.port_tag_remap = mv88e6095_port_tag_remap,
3059
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3060
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3061
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3062
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3063
	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
3064
	.port_pause_limit = mv88e6097_port_pause_limit,
3065
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3066
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3067
	.port_link_state = mv88e6352_port_link_state,
3068
	.port_get_cmode = mv88e6185_port_get_cmode,
3069
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3070
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3071
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3072 3073 3074
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
	.stats_get_stats = mv88e6095_stats_get_stats,
3075 3076
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3077
	.watchdog_ops = &mv88e6097_watchdog_ops,
3078
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3079
	.pot_clear = mv88e6xxx_g2_pot_clear,
3080
	.reset = mv88e6352_g1_reset,
3081
	.rmu_disable = mv88e6085_g1_rmu_disable,
3082
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3083
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3084
	.phylink_validate = mv88e6185_phylink_validate,
3085 3086
};

3087
static const struct mv88e6xxx_ops mv88e6123_ops = {
3088
	/* MV88E6XXX_FAMILY_6165 */
3089 3090
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3091
	.irl_init_all = mv88e6352_g2_irl_init_all,
3092
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3093 3094
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3095
	.port_set_link = mv88e6xxx_port_set_link,
3096
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3097
	.port_set_speed = mv88e6185_port_set_speed,
3098
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
3099
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3100
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3101
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3102
	.port_link_state = mv88e6352_port_link_state,
3103
	.port_get_cmode = mv88e6185_port_get_cmode,
3104
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3105
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3106
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3107 3108
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3109
	.stats_get_stats = mv88e6095_stats_get_stats,
3110 3111
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3112
	.watchdog_ops = &mv88e6097_watchdog_ops,
3113
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3114
	.pot_clear = mv88e6xxx_g2_pot_clear,
3115
	.reset = mv88e6352_g1_reset,
3116
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3117
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3118
	.phylink_validate = mv88e6185_phylink_validate,
3119 3120 3121
};

static const struct mv88e6xxx_ops mv88e6131_ops = {
3122
	/* MV88E6XXX_FAMILY_6185 */
3123 3124
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3125
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3126 3127
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
3128
	.port_set_link = mv88e6xxx_port_set_link,
3129
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3130
	.port_set_speed = mv88e6185_port_set_speed,
3131
	.port_tag_remap = mv88e6095_port_tag_remap,
3132
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3133
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
3134
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3135
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
3136
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3137
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3138
	.port_pause_limit = mv88e6097_port_pause_limit,
3139
	.port_set_pause = mv88e6185_port_set_pause,
3140
	.port_link_state = mv88e6352_port_link_state,
3141
	.port_get_cmode = mv88e6185_port_get_cmode,
3142
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3143
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3144
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3145 3146
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3147
	.stats_get_stats = mv88e6095_stats_get_stats,
3148 3149
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3150
	.watchdog_ops = &mv88e6097_watchdog_ops,
3151
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
3152
	.ppu_enable = mv88e6185_g1_ppu_enable,
3153
	.set_cascade_port = mv88e6185_g1_set_cascade_port,
3154
	.ppu_disable = mv88e6185_g1_ppu_disable,
3155
	.reset = mv88e6185_g1_reset,
3156
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3157
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3158
	.phylink_validate = mv88e6185_phylink_validate,
3159 3160
};

3161 3162
static const struct mv88e6xxx_ops mv88e6141_ops = {
	/* MV88E6XXX_FAMILY_6341 */
3163 3164
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3165
	.irl_init_all = mv88e6352_g2_irl_init_all,
3166 3167 3168 3169 3170 3171 3172 3173
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3174
	.port_set_speed = mv88e6341_port_set_speed,
3175
	.port_max_speed_mode = mv88e6341_port_max_speed_mode,
3176 3177 3178 3179
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3180
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3181
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3182
	.port_pause_limit = mv88e6097_port_pause_limit,
3183 3184
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3185
	.port_link_state = mv88e6352_port_link_state,
3186
	.port_get_cmode = mv88e6352_port_get_cmode,
3187
	.port_set_cmode = mv88e6341_port_set_cmode,
3188
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3189
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3190
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3191 3192 3193
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
	.stats_get_stats = mv88e6390_stats_get_stats,
3194 3195
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3196 3197
	.watchdog_ops = &mv88e6390_watchdog_ops,
	.mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
3198
	.pot_clear = mv88e6xxx_g2_pot_clear,
3199
	.reset = mv88e6352_g1_reset,
3200
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3201
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3202 3203
	.serdes_power = mv88e6390_serdes_power,
	.serdes_get_lane = mv88e6341_serdes_get_lane,
3204
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
3205
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
3206
	.serdes_irq_status = mv88e6390_serdes_irq_status,
3207
	.gpio_ops = &mv88e6352_gpio_ops,
3208
	.phylink_validate = mv88e6341_phylink_validate,
3209 3210
};

3211
static const struct mv88e6xxx_ops mv88e6161_ops = {
3212
	/* MV88E6XXX_FAMILY_6165 */
3213 3214
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3215
	.irl_init_all = mv88e6352_g2_irl_init_all,
3216
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3217 3218
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3219
	.port_set_link = mv88e6xxx_port_set_link,
3220
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3221
	.port_set_speed = mv88e6185_port_set_speed,
3222
	.port_tag_remap = mv88e6095_port_tag_remap,
3223
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3224
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3225
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3226
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3227
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3228
	.port_pause_limit = mv88e6097_port_pause_limit,
3229
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3230
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3231
	.port_link_state = mv88e6352_port_link_state,
3232
	.port_get_cmode = mv88e6185_port_get_cmode,
3233
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3234
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3235
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3236 3237
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3238
	.stats_get_stats = mv88e6095_stats_get_stats,
3239 3240
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3241
	.watchdog_ops = &mv88e6097_watchdog_ops,
3242
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3243
	.pot_clear = mv88e6xxx_g2_pot_clear,
3244
	.reset = mv88e6352_g1_reset,
3245
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3246
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3247
	.avb_ops = &mv88e6165_avb_ops,
3248
	.ptp_ops = &mv88e6165_ptp_ops,
3249
	.phylink_validate = mv88e6185_phylink_validate,
3250 3251 3252
};

static const struct mv88e6xxx_ops mv88e6165_ops = {
3253
	/* MV88E6XXX_FAMILY_6165 */
3254 3255
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3256
	.irl_init_all = mv88e6352_g2_irl_init_all,
3257
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3258 3259
	.phy_read = mv88e6165_phy_read,
	.phy_write = mv88e6165_phy_write,
3260
	.port_set_link = mv88e6xxx_port_set_link,
3261
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3262
	.port_set_speed = mv88e6185_port_set_speed,
3263
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3264
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3265
	.port_link_state = mv88e6352_port_link_state,
3266
	.port_get_cmode = mv88e6185_port_get_cmode,
3267
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3268
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3269
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3270 3271
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3272
	.stats_get_stats = mv88e6095_stats_get_stats,
3273 3274
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3275
	.watchdog_ops = &mv88e6097_watchdog_ops,
3276
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3277
	.pot_clear = mv88e6xxx_g2_pot_clear,
3278
	.reset = mv88e6352_g1_reset,
3279
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3280
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3281
	.avb_ops = &mv88e6165_avb_ops,
3282
	.ptp_ops = &mv88e6165_ptp_ops,
3283
	.phylink_validate = mv88e6185_phylink_validate,
3284 3285 3286
};

static const struct mv88e6xxx_ops mv88e6171_ops = {
3287
	/* MV88E6XXX_FAMILY_6351 */
3288 3289
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3290
	.irl_init_all = mv88e6352_g2_irl_init_all,
3291
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3292 3293
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3294
	.port_set_link = mv88e6xxx_port_set_link,
3295
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3296
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3297
	.port_set_speed = mv88e6185_port_set_speed,
3298
	.port_tag_remap = mv88e6095_port_tag_remap,
3299
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3300
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3301
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3302
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3303
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3304
	.port_pause_limit = mv88e6097_port_pause_limit,
3305
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3306
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3307
	.port_link_state = mv88e6352_port_link_state,
3308
	.port_get_cmode = mv88e6352_port_get_cmode,
3309
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3310
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3311
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3312 3313
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3314
	.stats_get_stats = mv88e6095_stats_get_stats,
3315 3316
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3317
	.watchdog_ops = &mv88e6097_watchdog_ops,
3318
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3319
	.pot_clear = mv88e6xxx_g2_pot_clear,
3320
	.reset = mv88e6352_g1_reset,
3321
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3322
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3323
	.phylink_validate = mv88e6185_phylink_validate,
3324 3325 3326
};

static const struct mv88e6xxx_ops mv88e6172_ops = {
3327
	/* MV88E6XXX_FAMILY_6352 */
3328 3329
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3330
	.irl_init_all = mv88e6352_g2_irl_init_all,
3331 3332
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3333
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3334 3335
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3336
	.port_set_link = mv88e6xxx_port_set_link,
3337
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3338
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3339
	.port_set_speed = mv88e6352_port_set_speed,
3340
	.port_tag_remap = mv88e6095_port_tag_remap,
3341
	.port_set_policy = mv88e6352_port_set_policy,
3342
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3343
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3344
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3345
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3346
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3347
	.port_pause_limit = mv88e6097_port_pause_limit,
3348
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3349
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3350
	.port_link_state = mv88e6352_port_link_state,
3351
	.port_get_cmode = mv88e6352_port_get_cmode,
3352
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3353
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3354
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3355 3356
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3357
	.stats_get_stats = mv88e6095_stats_get_stats,
3358 3359
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3360
	.watchdog_ops = &mv88e6097_watchdog_ops,
3361
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3362
	.pot_clear = mv88e6xxx_g2_pot_clear,
3363
	.reset = mv88e6352_g1_reset,
3364
	.rmu_disable = mv88e6352_g1_rmu_disable,
3365
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3366
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3367
	.serdes_get_lane = mv88e6352_serdes_get_lane,
3368
	.serdes_power = mv88e6352_serdes_power,
3369
	.gpio_ops = &mv88e6352_gpio_ops,
3370
	.phylink_validate = mv88e6352_phylink_validate,
3371 3372 3373
};

static const struct mv88e6xxx_ops mv88e6175_ops = {
3374
	/* MV88E6XXX_FAMILY_6351 */
3375 3376
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3377
	.irl_init_all = mv88e6352_g2_irl_init_all,
3378
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3379 3380
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3381
	.port_set_link = mv88e6xxx_port_set_link,
3382
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3383
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3384
	.port_set_speed = mv88e6185_port_set_speed,
3385
	.port_tag_remap = mv88e6095_port_tag_remap,
3386
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3387
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3388
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3389
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3390
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3391
	.port_pause_limit = mv88e6097_port_pause_limit,
3392
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3393
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3394
	.port_link_state = mv88e6352_port_link_state,
3395
	.port_get_cmode = mv88e6352_port_get_cmode,
3396
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3397
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3398
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3399 3400
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3401
	.stats_get_stats = mv88e6095_stats_get_stats,
3402 3403
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3404
	.watchdog_ops = &mv88e6097_watchdog_ops,
3405
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3406
	.pot_clear = mv88e6xxx_g2_pot_clear,
3407
	.reset = mv88e6352_g1_reset,
3408
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3409
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3410
	.phylink_validate = mv88e6185_phylink_validate,
3411 3412 3413
};

static const struct mv88e6xxx_ops mv88e6176_ops = {
3414
	/* MV88E6XXX_FAMILY_6352 */
3415 3416
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3417
	.irl_init_all = mv88e6352_g2_irl_init_all,
3418 3419
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3420
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3421 3422
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3423
	.port_set_link = mv88e6xxx_port_set_link,
3424
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3425
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3426
	.port_set_speed = mv88e6352_port_set_speed,
3427
	.port_tag_remap = mv88e6095_port_tag_remap,
3428
	.port_set_policy = mv88e6352_port_set_policy,
3429
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3430
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3431
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3432
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3433
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3434
	.port_pause_limit = mv88e6097_port_pause_limit,
3435
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3436
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3437
	.port_link_state = mv88e6352_port_link_state,
3438
	.port_get_cmode = mv88e6352_port_get_cmode,
3439
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3440
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3441
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3442 3443
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3444
	.stats_get_stats = mv88e6095_stats_get_stats,
3445 3446
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3447
	.watchdog_ops = &mv88e6097_watchdog_ops,
3448
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3449
	.pot_clear = mv88e6xxx_g2_pot_clear,
3450
	.reset = mv88e6352_g1_reset,
3451
	.rmu_disable = mv88e6352_g1_rmu_disable,
3452
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3453
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3454
	.serdes_get_lane = mv88e6352_serdes_get_lane,
3455
	.serdes_power = mv88e6352_serdes_power,
3456
	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
3457
	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
3458
	.serdes_irq_status = mv88e6352_serdes_irq_status,
3459
	.gpio_ops = &mv88e6352_gpio_ops,
3460
	.phylink_validate = mv88e6352_phylink_validate,
3461 3462 3463
};

static const struct mv88e6xxx_ops mv88e6185_ops = {
3464
	/* MV88E6XXX_FAMILY_6185 */
3465 3466
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3467
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3468 3469
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
3470
	.port_set_link = mv88e6xxx_port_set_link,
3471
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3472
	.port_set_speed = mv88e6185_port_set_speed,
3473
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
3474
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
3475
	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
3476
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
3477
	.port_set_pause = mv88e6185_port_set_pause,
3478
	.port_link_state = mv88e6185_port_link_state,
3479
	.port_get_cmode = mv88e6185_port_get_cmode,
3480
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3481
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3482
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3483 3484
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3485
	.stats_get_stats = mv88e6095_stats_get_stats,
3486 3487
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3488
	.watchdog_ops = &mv88e6097_watchdog_ops,
3489
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
3490
	.set_cascade_port = mv88e6185_g1_set_cascade_port,
3491 3492
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
3493
	.reset = mv88e6185_g1_reset,
3494
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3495
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3496
	.phylink_validate = mv88e6185_phylink_validate,
3497 3498
};

3499
static const struct mv88e6xxx_ops mv88e6190_ops = {
3500
	/* MV88E6XXX_FAMILY_6390 */
3501
	.setup_errata = mv88e6390_setup_errata,
3502
	.irl_init_all = mv88e6390_g2_irl_init_all,
3503 3504
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3505 3506 3507 3508 3509 3510 3511
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed = mv88e6390_port_set_speed,
3512
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
3513
	.port_tag_remap = mv88e6390_port_tag_remap,
3514
	.port_set_policy = mv88e6352_port_set_policy,
3515
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3516
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3517
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3518
	.port_pause_limit = mv88e6390_port_pause_limit,
3519
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3520
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3521
	.port_link_state = mv88e6352_port_link_state,
3522
	.port_get_cmode = mv88e6352_port_get_cmode,
3523
	.port_set_cmode = mv88e6390_port_set_cmode,
3524
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3525
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3526
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3527 3528
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3529
	.stats_get_stats = mv88e6390_stats_get_stats,
3530 3531
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3532
	.watchdog_ops = &mv88e6390_watchdog_ops,
3533
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3534
	.pot_clear = mv88e6xxx_g2_pot_clear,
3535
	.reset = mv88e6352_g1_reset,
3536
	.rmu_disable = mv88e6390_g1_rmu_disable,
3537 3538
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3539
	.serdes_power = mv88e6390_serdes_power,
3540
	.serdes_get_lane = mv88e6390_serdes_get_lane,
3541
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
3542
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
3543
	.serdes_irq_status = mv88e6390_serdes_irq_status,
3544
	.gpio_ops = &mv88e6352_gpio_ops,
3545
	.phylink_validate = mv88e6390_phylink_validate,
3546 3547 3548
};

static const struct mv88e6xxx_ops mv88e6190x_ops = {
3549
	/* MV88E6XXX_FAMILY_6390 */
3550
	.setup_errata = mv88e6390_setup_errata,
3551
	.irl_init_all = mv88e6390_g2_irl_init_all,
3552 3553
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3554 3555 3556 3557 3558 3559 3560
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed = mv88e6390x_port_set_speed,
3561
	.port_max_speed_mode = mv88e6390x_port_max_speed_mode,
3562
	.port_tag_remap = mv88e6390_port_tag_remap,
3563
	.port_set_policy = mv88e6352_port_set_policy,
3564
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3565
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3566
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3567
	.port_pause_limit = mv88e6390_port_pause_limit,
3568
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3569
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3570
	.port_link_state = mv88e6352_port_link_state,
3571
	.port_get_cmode = mv88e6352_port_get_cmode,
3572
	.port_set_cmode = mv88e6390x_port_set_cmode,
3573
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3574
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3575
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3576 3577
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3578
	.stats_get_stats = mv88e6390_stats_get_stats,
3579 3580
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3581
	.watchdog_ops = &mv88e6390_watchdog_ops,
3582
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3583
	.pot_clear = mv88e6xxx_g2_pot_clear,
3584
	.reset = mv88e6352_g1_reset,
3585
	.rmu_disable = mv88e6390_g1_rmu_disable,
3586 3587
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3588
	.serdes_power = mv88e6390_serdes_power,
3589
	.serdes_get_lane = mv88e6390x_serdes_get_lane,
3590
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
3591
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
3592
	.serdes_irq_status = mv88e6390_serdes_irq_status,
3593
	.gpio_ops = &mv88e6352_gpio_ops,
3594
	.phylink_validate = mv88e6390x_phylink_validate,
3595 3596 3597
};

static const struct mv88e6xxx_ops mv88e6191_ops = {
3598
	/* MV88E6XXX_FAMILY_6390 */
3599
	.setup_errata = mv88e6390_setup_errata,
3600
	.irl_init_all = mv88e6390_g2_irl_init_all,
3601 3602
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3603 3604 3605 3606 3607 3608 3609
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed = mv88e6390_port_set_speed,
3610
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
3611
	.port_tag_remap = mv88e6390_port_tag_remap,
3612
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3613
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3614
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3615
	.port_pause_limit = mv88e6390_port_pause_limit,
3616
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3617
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3618
	.port_link_state = mv88e6352_port_link_state,
3619
	.port_get_cmode = mv88e6352_port_get_cmode,
3620
	.port_set_cmode = mv88e6390_port_set_cmode,
3621
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3622
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3623
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3624 3625
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3626
	.stats_get_stats = mv88e6390_stats_get_stats,
3627 3628
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3629
	.watchdog_ops = &mv88e6390_watchdog_ops,
3630
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3631
	.pot_clear = mv88e6xxx_g2_pot_clear,
3632
	.reset = mv88e6352_g1_reset,
3633
	.rmu_disable = mv88e6390_g1_rmu_disable,
3634 3635
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3636
	.serdes_power = mv88e6390_serdes_power,
3637
	.serdes_get_lane = mv88e6390_serdes_get_lane,
3638
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
3639
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
3640
	.serdes_irq_status = mv88e6390_serdes_irq_status,
3641 3642
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
3643
	.phylink_validate = mv88e6390_phylink_validate,
3644 3645
};

3646
static const struct mv88e6xxx_ops mv88e6240_ops = {
3647
	/* MV88E6XXX_FAMILY_6352 */
3648 3649
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3650
	.irl_init_all = mv88e6352_g2_irl_init_all,
3651 3652
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3653
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3654 3655
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3656
	.port_set_link = mv88e6xxx_port_set_link,
3657
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3658
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3659
	.port_set_speed = mv88e6352_port_set_speed,
3660
	.port_tag_remap = mv88e6095_port_tag_remap,
3661
	.port_set_policy = mv88e6352_port_set_policy,
3662
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3663
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3664
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3665
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3666
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3667
	.port_pause_limit = mv88e6097_port_pause_limit,
3668
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3669
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3670
	.port_link_state = mv88e6352_port_link_state,
3671
	.port_get_cmode = mv88e6352_port_get_cmode,
3672
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3673
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3674
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3675 3676
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3677
	.stats_get_stats = mv88e6095_stats_get_stats,
3678 3679
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3680
	.watchdog_ops = &mv88e6097_watchdog_ops,
3681
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3682
	.pot_clear = mv88e6xxx_g2_pot_clear,
3683
	.reset = mv88e6352_g1_reset,
3684
	.rmu_disable = mv88e6352_g1_rmu_disable,
3685
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3686
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3687
	.serdes_get_lane = mv88e6352_serdes_get_lane,
3688
	.serdes_power = mv88e6352_serdes_power,
3689
	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
3690
	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
3691
	.serdes_irq_status = mv88e6352_serdes_irq_status,
3692
	.gpio_ops = &mv88e6352_gpio_ops,
3693
	.avb_ops = &mv88e6352_avb_ops,
3694
	.ptp_ops = &mv88e6352_ptp_ops,
3695
	.phylink_validate = mv88e6352_phylink_validate,
3696 3697
};

3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732
static const struct mv88e6xxx_ops mv88e6250_ops = {
	/* MV88E6XXX_FAMILY_6250 */
	.ieee_pri_map = mv88e6250_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
	.irl_init_all = mv88e6352_g2_irl_init_all,
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed = mv88e6250_port_set_speed,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
	.port_set_ether_type = mv88e6351_port_set_ether_type,
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6250_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6250_stats_get_sset_count,
	.stats_get_strings = mv88e6250_stats_get_strings,
	.stats_get_stats = mv88e6250_stats_get_stats,
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
	.watchdog_ops = &mv88e6250_watchdog_ops,
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
	.pot_clear = mv88e6xxx_g2_pot_clear,
	.reset = mv88e6250_g1_reset,
	.vtu_getnext = mv88e6250_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
3733 3734
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6250_ptp_ops,
3735 3736 3737
	.phylink_validate = mv88e6065_phylink_validate,
};

3738
static const struct mv88e6xxx_ops mv88e6290_ops = {
3739
	/* MV88E6XXX_FAMILY_6390 */
3740
	.setup_errata = mv88e6390_setup_errata,
3741
	.irl_init_all = mv88e6390_g2_irl_init_all,
3742 3743
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3744 3745 3746 3747 3748 3749 3750
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed = mv88e6390_port_set_speed,
3751
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
3752
	.port_tag_remap = mv88e6390_port_tag_remap,
3753
	.port_set_policy = mv88e6352_port_set_policy,
3754
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3755
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3756
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3757
	.port_pause_limit = mv88e6390_port_pause_limit,
3758
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3759
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3760
	.port_link_state = mv88e6352_port_link_state,
3761
	.port_get_cmode = mv88e6352_port_get_cmode,
3762
	.port_set_cmode = mv88e6390_port_set_cmode,
3763
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3764
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3765
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3766 3767
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3768
	.stats_get_stats = mv88e6390_stats_get_stats,
3769 3770
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3771
	.watchdog_ops = &mv88e6390_watchdog_ops,
3772
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3773
	.pot_clear = mv88e6xxx_g2_pot_clear,
3774
	.reset = mv88e6352_g1_reset,
3775
	.rmu_disable = mv88e6390_g1_rmu_disable,
3776 3777
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3778
	.serdes_power = mv88e6390_serdes_power,
3779
	.serdes_get_lane = mv88e6390_serdes_get_lane,
3780
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
3781
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
3782
	.serdes_irq_status = mv88e6390_serdes_irq_status,
3783
	.gpio_ops = &mv88e6352_gpio_ops,
3784
	.avb_ops = &mv88e6390_avb_ops,
3785
	.ptp_ops = &mv88e6352_ptp_ops,
3786
	.phylink_validate = mv88e6390_phylink_validate,
3787 3788
};

3789
static const struct mv88e6xxx_ops mv88e6320_ops = {
3790
	/* MV88E6XXX_FAMILY_6320 */
3791 3792
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3793
	.irl_init_all = mv88e6352_g2_irl_init_all,
3794 3795
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3796
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3797 3798
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3799
	.port_set_link = mv88e6xxx_port_set_link,
3800
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3801
	.port_set_speed = mv88e6185_port_set_speed,
3802
	.port_tag_remap = mv88e6095_port_tag_remap,
3803
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3804
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3805
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3806
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3807
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3808
	.port_pause_limit = mv88e6097_port_pause_limit,
3809
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3810
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3811
	.port_link_state = mv88e6352_port_link_state,
3812
	.port_get_cmode = mv88e6352_port_get_cmode,
3813
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3814
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3815
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3816 3817
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3818
	.stats_get_stats = mv88e6320_stats_get_stats,
3819 3820
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3821
	.watchdog_ops = &mv88e6390_watchdog_ops,
3822
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3823
	.pot_clear = mv88e6xxx_g2_pot_clear,
3824
	.reset = mv88e6352_g1_reset,
3825
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3826
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3827
	.gpio_ops = &mv88e6352_gpio_ops,
3828
	.avb_ops = &mv88e6352_avb_ops,
3829
	.ptp_ops = &mv88e6352_ptp_ops,
3830
	.phylink_validate = mv88e6185_phylink_validate,
3831 3832 3833
};

static const struct mv88e6xxx_ops mv88e6321_ops = {
3834
	/* MV88E6XXX_FAMILY_6320 */
3835 3836
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3837
	.irl_init_all = mv88e6352_g2_irl_init_all,
3838 3839
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3840
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3841 3842
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3843
	.port_set_link = mv88e6xxx_port_set_link,
3844
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3845
	.port_set_speed = mv88e6185_port_set_speed,
3846
	.port_tag_remap = mv88e6095_port_tag_remap,
3847
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3848
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3849
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3850
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3851
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3852
	.port_pause_limit = mv88e6097_port_pause_limit,
3853
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3854
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3855
	.port_link_state = mv88e6352_port_link_state,
3856
	.port_get_cmode = mv88e6352_port_get_cmode,
3857
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3858
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3859
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3860 3861
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3862
	.stats_get_stats = mv88e6320_stats_get_stats,
3863 3864
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3865
	.watchdog_ops = &mv88e6390_watchdog_ops,
3866
	.reset = mv88e6352_g1_reset,
3867
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3868
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3869
	.gpio_ops = &mv88e6352_gpio_ops,
3870
	.avb_ops = &mv88e6352_avb_ops,
3871
	.ptp_ops = &mv88e6352_ptp_ops,
3872
	.phylink_validate = mv88e6185_phylink_validate,
3873 3874
};

3875 3876
static const struct mv88e6xxx_ops mv88e6341_ops = {
	/* MV88E6XXX_FAMILY_6341 */
3877 3878
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3879
	.irl_init_all = mv88e6352_g2_irl_init_all,
3880 3881 3882 3883 3884 3885 3886 3887
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3888
	.port_set_speed = mv88e6341_port_set_speed,
3889
	.port_max_speed_mode = mv88e6341_port_max_speed_mode,
3890 3891 3892 3893
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3894
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3895
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3896
	.port_pause_limit = mv88e6097_port_pause_limit,
3897 3898
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3899
	.port_link_state = mv88e6352_port_link_state,
3900
	.port_get_cmode = mv88e6352_port_get_cmode,
3901
	.port_set_cmode = mv88e6341_port_set_cmode,
3902
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3903
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3904
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3905 3906 3907
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
	.stats_get_stats = mv88e6390_stats_get_stats,
3908 3909
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3910 3911
	.watchdog_ops = &mv88e6390_watchdog_ops,
	.mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
3912
	.pot_clear = mv88e6xxx_g2_pot_clear,
3913
	.reset = mv88e6352_g1_reset,
3914
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3915
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3916 3917
	.serdes_power = mv88e6390_serdes_power,
	.serdes_get_lane = mv88e6341_serdes_get_lane,
3918
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
3919
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
3920
	.serdes_irq_status = mv88e6390_serdes_irq_status,
3921
	.gpio_ops = &mv88e6352_gpio_ops,
3922
	.avb_ops = &mv88e6390_avb_ops,
3923
	.ptp_ops = &mv88e6352_ptp_ops,
3924
	.phylink_validate = mv88e6341_phylink_validate,
3925 3926
};

3927
static const struct mv88e6xxx_ops mv88e6350_ops = {
3928
	/* MV88E6XXX_FAMILY_6351 */
3929 3930
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3931
	.irl_init_all = mv88e6352_g2_irl_init_all,
3932
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3933 3934
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3935
	.port_set_link = mv88e6xxx_port_set_link,
3936
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3937
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3938
	.port_set_speed = mv88e6185_port_set_speed,
3939
	.port_tag_remap = mv88e6095_port_tag_remap,
3940
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3941
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3942
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3943
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3944
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3945
	.port_pause_limit = mv88e6097_port_pause_limit,
3946
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3947
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3948
	.port_link_state = mv88e6352_port_link_state,
3949
	.port_get_cmode = mv88e6352_port_get_cmode,
3950
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3951
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3952
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3953 3954
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3955
	.stats_get_stats = mv88e6095_stats_get_stats,
3956 3957
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3958
	.watchdog_ops = &mv88e6097_watchdog_ops,
3959
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3960
	.pot_clear = mv88e6xxx_g2_pot_clear,
3961
	.reset = mv88e6352_g1_reset,
3962
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3963
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3964
	.phylink_validate = mv88e6185_phylink_validate,
3965 3966 3967
};

static const struct mv88e6xxx_ops mv88e6351_ops = {
3968
	/* MV88E6XXX_FAMILY_6351 */
3969 3970
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3971
	.irl_init_all = mv88e6352_g2_irl_init_all,
3972
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3973 3974
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3975
	.port_set_link = mv88e6xxx_port_set_link,
3976
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3977
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3978
	.port_set_speed = mv88e6185_port_set_speed,
3979
	.port_tag_remap = mv88e6095_port_tag_remap,
3980
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3981
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3982
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3983
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3984
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3985
	.port_pause_limit = mv88e6097_port_pause_limit,
3986
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3987
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3988
	.port_link_state = mv88e6352_port_link_state,
3989
	.port_get_cmode = mv88e6352_port_get_cmode,
3990
	.port_setup_message_port = mv88e6xxx_setup_message_port,
3991
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3992
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3993 3994
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3995
	.stats_get_stats = mv88e6095_stats_get_stats,
3996 3997
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3998
	.watchdog_ops = &mv88e6097_watchdog_ops,
3999
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
4000
	.pot_clear = mv88e6xxx_g2_pot_clear,
4001
	.reset = mv88e6352_g1_reset,
4002
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
4003
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
4004
	.avb_ops = &mv88e6352_avb_ops,
4005
	.ptp_ops = &mv88e6352_ptp_ops,
4006
	.phylink_validate = mv88e6185_phylink_validate,
4007 4008 4009
};

static const struct mv88e6xxx_ops mv88e6352_ops = {
4010
	/* MV88E6XXX_FAMILY_6352 */
4011 4012
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
4013
	.irl_init_all = mv88e6352_g2_irl_init_all,
4014 4015
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
4016
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
4017 4018
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
4019
	.port_set_link = mv88e6xxx_port_set_link,
4020
	.port_set_duplex = mv88e6xxx_port_set_duplex,
4021
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
4022
	.port_set_speed = mv88e6352_port_set_speed,
4023
	.port_tag_remap = mv88e6095_port_tag_remap,
4024
	.port_set_policy = mv88e6352_port_set_policy,
4025
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
4026
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
4027
	.port_set_ether_type = mv88e6351_port_set_ether_type,
4028
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
4029
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
4030
	.port_pause_limit = mv88e6097_port_pause_limit,
4031
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
4032
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
4033
	.port_link_state = mv88e6352_port_link_state,
4034
	.port_get_cmode = mv88e6352_port_get_cmode,
4035
	.port_setup_message_port = mv88e6xxx_setup_message_port,
4036
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
4037
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
4038 4039
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
4040
	.stats_get_stats = mv88e6095_stats_get_stats,
4041 4042
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
4043
	.watchdog_ops = &mv88e6097_watchdog_ops,
4044
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
4045
	.pot_clear = mv88e6xxx_g2_pot_clear,
4046
	.reset = mv88e6352_g1_reset,
4047
	.rmu_disable = mv88e6352_g1_rmu_disable,
4048
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
4049
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
4050
	.serdes_get_lane = mv88e6352_serdes_get_lane,
4051
	.serdes_power = mv88e6352_serdes_power,
4052
	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
4053
	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
4054
	.serdes_irq_status = mv88e6352_serdes_irq_status,
4055
	.gpio_ops = &mv88e6352_gpio_ops,
4056
	.avb_ops = &mv88e6352_avb_ops,
4057
	.ptp_ops = &mv88e6352_ptp_ops,
4058 4059 4060
	.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
	.serdes_get_strings = mv88e6352_serdes_get_strings,
	.serdes_get_stats = mv88e6352_serdes_get_stats,
4061
	.phylink_validate = mv88e6352_phylink_validate,
4062 4063
};

4064
static const struct mv88e6xxx_ops mv88e6390_ops = {
4065
	/* MV88E6XXX_FAMILY_6390 */
4066
	.setup_errata = mv88e6390_setup_errata,
4067
	.irl_init_all = mv88e6390_g2_irl_init_all,
4068 4069
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
4070 4071 4072 4073 4074 4075 4076
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed = mv88e6390_port_set_speed,
4077
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
4078
	.port_tag_remap = mv88e6390_port_tag_remap,
4079
	.port_set_policy = mv88e6352_port_set_policy,
4080
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
4081
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
4082
	.port_set_ether_type = mv88e6351_port_set_ether_type,
4083
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
4084
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
4085
	.port_pause_limit = mv88e6390_port_pause_limit,
4086
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
4087
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
4088
	.port_link_state = mv88e6352_port_link_state,
4089
	.port_get_cmode = mv88e6352_port_get_cmode,
4090
	.port_set_cmode = mv88e6390_port_set_cmode,
4091
	.port_setup_message_port = mv88e6xxx_setup_message_port,
4092
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
4093
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
4094 4095
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
4096
	.stats_get_stats = mv88e6390_stats_get_stats,
4097 4098
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
4099
	.watchdog_ops = &mv88e6390_watchdog_ops,
4100
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
4101
	.pot_clear = mv88e6xxx_g2_pot_clear,
4102
	.reset = mv88e6352_g1_reset,
4103
	.rmu_disable = mv88e6390_g1_rmu_disable,
4104 4105
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
4106
	.serdes_power = mv88e6390_serdes_power,
4107
	.serdes_get_lane = mv88e6390_serdes_get_lane,
4108
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
4109
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
4110
	.serdes_irq_status = mv88e6390_serdes_irq_status,
4111
	.gpio_ops = &mv88e6352_gpio_ops,
4112
	.avb_ops = &mv88e6390_avb_ops,
4113
	.ptp_ops = &mv88e6352_ptp_ops,
4114
	.phylink_validate = mv88e6390_phylink_validate,
4115 4116 4117
};

static const struct mv88e6xxx_ops mv88e6390x_ops = {
4118
	/* MV88E6XXX_FAMILY_6390 */
4119
	.setup_errata = mv88e6390_setup_errata,
4120
	.irl_init_all = mv88e6390_g2_irl_init_all,
4121 4122
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
4123 4124 4125 4126 4127 4128 4129
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_set_duplex = mv88e6xxx_port_set_duplex,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed = mv88e6390x_port_set_speed,
4130
	.port_max_speed_mode = mv88e6390x_port_max_speed_mode,
4131
	.port_tag_remap = mv88e6390_port_tag_remap,
4132
	.port_set_policy = mv88e6352_port_set_policy,
4133
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
4134
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
4135
	.port_set_ether_type = mv88e6351_port_set_ether_type,
4136
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
4137
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
4138
	.port_pause_limit = mv88e6390_port_pause_limit,
4139
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
4140
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
4141
	.port_link_state = mv88e6352_port_link_state,
4142
	.port_get_cmode = mv88e6352_port_get_cmode,
4143
	.port_set_cmode = mv88e6390x_port_set_cmode,
4144
	.port_setup_message_port = mv88e6xxx_setup_message_port,
4145
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
4146
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
4147 4148
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
4149
	.stats_get_stats = mv88e6390_stats_get_stats,
4150 4151
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
4152
	.watchdog_ops = &mv88e6390_watchdog_ops,
4153
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
4154
	.pot_clear = mv88e6xxx_g2_pot_clear,
4155
	.reset = mv88e6352_g1_reset,
4156
	.rmu_disable = mv88e6390_g1_rmu_disable,
4157 4158
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
4159
	.serdes_power = mv88e6390_serdes_power,
4160
	.serdes_get_lane = mv88e6390x_serdes_get_lane,
4161
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
4162
	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
4163
	.serdes_irq_status = mv88e6390_serdes_irq_status,
4164
	.gpio_ops = &mv88e6352_gpio_ops,
4165
	.avb_ops = &mv88e6390_avb_ops,
4166
	.ptp_ops = &mv88e6352_ptp_ops,
4167
	.phylink_validate = mv88e6390x_phylink_validate,
4168 4169
};

4170 4171
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
	[MV88E6085] = {
4172
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
4173 4174 4175 4176
		.family = MV88E6XXX_FAMILY_6097,
		.name = "Marvell 88E6085",
		.num_databases = 4096,
		.num_ports = 10,
4177
		.num_internal_phys = 5,
4178
		.max_vid = 4095,
4179
		.port_base_addr = 0x10,
4180
		.phy_base_addr = 0x0,
4181
		.global1_addr = 0x1b,
4182
		.global2_addr = 0x1c,
4183
		.age_time_coeff = 15000,
4184
		.g1_irqs = 8,
4185
		.g2_irqs = 10,
4186
		.atu_move_port_mask = 0xf,
4187
		.pvt = true,
4188
		.multi_chip = true,
4189
		.tag_protocol = DSA_TAG_PROTO_DSA,
4190
		.ops = &mv88e6085_ops,
4191 4192 4193
	},

	[MV88E6095] = {
4194
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095,
4195 4196 4197 4198
		.family = MV88E6XXX_FAMILY_6095,
		.name = "Marvell 88E6095/88E6095F",
		.num_databases = 256,
		.num_ports = 11,
4199
		.num_internal_phys = 0,
4200
		.max_vid = 4095,
4201
		.port_base_addr = 0x10,
4202
		.phy_base_addr = 0x0,
4203
		.global1_addr = 0x1b,
4204
		.global2_addr = 0x1c,
4205
		.age_time_coeff = 15000,
4206
		.g1_irqs = 8,
4207
		.atu_move_port_mask = 0xf,
4208
		.multi_chip = true,
4209
		.tag_protocol = DSA_TAG_PROTO_DSA,
4210
		.ops = &mv88e6095_ops,
4211 4212
	},

4213
	[MV88E6097] = {
4214
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097,
4215 4216 4217 4218
		.family = MV88E6XXX_FAMILY_6097,
		.name = "Marvell 88E6097/88E6097F",
		.num_databases = 4096,
		.num_ports = 11,
4219
		.num_internal_phys = 8,
4220
		.max_vid = 4095,
4221
		.port_base_addr = 0x10,
4222
		.phy_base_addr = 0x0,
4223
		.global1_addr = 0x1b,
4224
		.global2_addr = 0x1c,
4225
		.age_time_coeff = 15000,
4226
		.g1_irqs = 8,
4227
		.g2_irqs = 10,
4228
		.atu_move_port_mask = 0xf,
4229
		.pvt = true,
4230
		.multi_chip = true,
4231
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4232 4233 4234
		.ops = &mv88e6097_ops,
	},

4235
	[MV88E6123] = {
4236
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123,
4237 4238 4239 4240
		.family = MV88E6XXX_FAMILY_6165,
		.name = "Marvell 88E6123",
		.num_databases = 4096,
		.num_ports = 3,
4241
		.num_internal_phys = 5,
4242
		.max_vid = 4095,
4243
		.port_base_addr = 0x10,
4244
		.phy_base_addr = 0x0,
4245
		.global1_addr = 0x1b,
4246
		.global2_addr = 0x1c,
4247
		.age_time_coeff = 15000,
4248
		.g1_irqs = 9,
4249
		.g2_irqs = 10,
4250
		.atu_move_port_mask = 0xf,
4251
		.pvt = true,
4252
		.multi_chip = true,
4253
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4254
		.ops = &mv88e6123_ops,
4255 4256 4257
	},

	[MV88E6131] = {
4258
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131,
4259 4260 4261 4262
		.family = MV88E6XXX_FAMILY_6185,
		.name = "Marvell 88E6131",
		.num_databases = 256,
		.num_ports = 8,
4263
		.num_internal_phys = 0,
4264
		.max_vid = 4095,
4265
		.port_base_addr = 0x10,
4266
		.phy_base_addr = 0x0,
4267
		.global1_addr = 0x1b,
4268
		.global2_addr = 0x1c,
4269
		.age_time_coeff = 15000,
4270
		.g1_irqs = 9,
4271
		.atu_move_port_mask = 0xf,
4272
		.multi_chip = true,
4273
		.tag_protocol = DSA_TAG_PROTO_DSA,
4274
		.ops = &mv88e6131_ops,
4275 4276
	},

4277
	[MV88E6141] = {
4278
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
4279
		.family = MV88E6XXX_FAMILY_6341,
4280
		.name = "Marvell 88E6141",
4281 4282
		.num_databases = 4096,
		.num_ports = 6,
4283
		.num_internal_phys = 5,
4284
		.num_gpio = 11,
4285
		.max_vid = 4095,
4286
		.port_base_addr = 0x10,
4287
		.phy_base_addr = 0x10,
4288
		.global1_addr = 0x1b,
4289
		.global2_addr = 0x1c,
4290 4291
		.age_time_coeff = 3750,
		.atu_move_port_mask = 0x1f,
4292
		.g1_irqs = 9,
4293
		.g2_irqs = 10,
4294
		.pvt = true,
4295
		.multi_chip = true,
4296 4297 4298 4299
		.tag_protocol = DSA_TAG_PROTO_EDSA,
		.ops = &mv88e6141_ops,
	},

4300
	[MV88E6161] = {
4301
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161,
4302 4303 4304 4305
		.family = MV88E6XXX_FAMILY_6165,
		.name = "Marvell 88E6161",
		.num_databases = 4096,
		.num_ports = 6,
4306
		.num_internal_phys = 5,
4307
		.max_vid = 4095,
4308
		.port_base_addr = 0x10,
4309
		.phy_base_addr = 0x0,
4310
		.global1_addr = 0x1b,
4311
		.global2_addr = 0x1c,
4312
		.age_time_coeff = 15000,
4313
		.g1_irqs = 9,
4314
		.g2_irqs = 10,
4315
		.atu_move_port_mask = 0xf,
4316
		.pvt = true,
4317
		.multi_chip = true,
4318
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4319
		.ptp_support = true,
4320
		.ops = &mv88e6161_ops,
4321 4322 4323
	},

	[MV88E6165] = {
4324
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165,
4325 4326 4327 4328
		.family = MV88E6XXX_FAMILY_6165,
		.name = "Marvell 88E6165",
		.num_databases = 4096,
		.num_ports = 6,
4329
		.num_internal_phys = 0,
4330
		.max_vid = 4095,
4331
		.port_base_addr = 0x10,
4332
		.phy_base_addr = 0x0,
4333
		.global1_addr = 0x1b,
4334
		.global2_addr = 0x1c,
4335
		.age_time_coeff = 15000,
4336
		.g1_irqs = 9,
4337
		.g2_irqs = 10,
4338
		.atu_move_port_mask = 0xf,
4339
		.pvt = true,
4340
		.multi_chip = true,
4341
		.tag_protocol = DSA_TAG_PROTO_DSA,
4342
		.ptp_support = true,
4343
		.ops = &mv88e6165_ops,
4344 4345 4346
	},

	[MV88E6171] = {
4347
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171,
4348 4349 4350 4351
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6171",
		.num_databases = 4096,
		.num_ports = 7,
4352
		.num_internal_phys = 5,
4353
		.max_vid = 4095,
4354
		.port_base_addr = 0x10,
4355
		.phy_base_addr = 0x0,
4356
		.global1_addr = 0x1b,
4357
		.global2_addr = 0x1c,
4358
		.age_time_coeff = 15000,
4359
		.g1_irqs = 9,
4360
		.g2_irqs = 10,
4361
		.atu_move_port_mask = 0xf,
4362
		.pvt = true,
4363
		.multi_chip = true,
4364
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4365
		.ops = &mv88e6171_ops,
4366 4367 4368
	},

	[MV88E6172] = {
4369
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172,
4370 4371 4372 4373
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6172",
		.num_databases = 4096,
		.num_ports = 7,
4374
		.num_internal_phys = 5,
4375
		.num_gpio = 15,
4376
		.max_vid = 4095,
4377
		.port_base_addr = 0x10,
4378
		.phy_base_addr = 0x0,
4379
		.global1_addr = 0x1b,
4380
		.global2_addr = 0x1c,
4381
		.age_time_coeff = 15000,
4382
		.g1_irqs = 9,
4383
		.g2_irqs = 10,
4384
		.atu_move_port_mask = 0xf,
4385
		.pvt = true,
4386
		.multi_chip = true,
4387
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4388
		.ops = &mv88e6172_ops,
4389 4390 4391
	},

	[MV88E6175] = {
4392
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175,
4393 4394 4395 4396
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6175",
		.num_databases = 4096,
		.num_ports = 7,
4397
		.num_internal_phys = 5,
4398
		.max_vid = 4095,
4399
		.port_base_addr = 0x10,
4400
		.phy_base_addr = 0x0,
4401
		.global1_addr = 0x1b,
4402
		.global2_addr = 0x1c,
4403
		.age_time_coeff = 15000,
4404
		.g1_irqs = 9,
4405
		.g2_irqs = 10,
4406
		.atu_move_port_mask = 0xf,
4407
		.pvt = true,
4408
		.multi_chip = true,
4409
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4410
		.ops = &mv88e6175_ops,
4411 4412 4413
	},

	[MV88E6176] = {
4414
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176,
4415 4416 4417 4418
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6176",
		.num_databases = 4096,
		.num_ports = 7,
4419
		.num_internal_phys = 5,
4420
		.num_gpio = 15,
4421
		.max_vid = 4095,
4422
		.port_base_addr = 0x10,
4423
		.phy_base_addr = 0x0,
4424
		.global1_addr = 0x1b,
4425
		.global2_addr = 0x1c,
4426
		.age_time_coeff = 15000,
4427
		.g1_irqs = 9,
4428
		.g2_irqs = 10,
4429
		.atu_move_port_mask = 0xf,
4430
		.pvt = true,
4431
		.multi_chip = true,
4432
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4433
		.ops = &mv88e6176_ops,
4434 4435 4436
	},

	[MV88E6185] = {
4437
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185,
4438 4439 4440 4441
		.family = MV88E6XXX_FAMILY_6185,
		.name = "Marvell 88E6185",
		.num_databases = 256,
		.num_ports = 10,
4442
		.num_internal_phys = 0,
4443
		.max_vid = 4095,
4444
		.port_base_addr = 0x10,
4445
		.phy_base_addr = 0x0,
4446
		.global1_addr = 0x1b,
4447
		.global2_addr = 0x1c,
4448
		.age_time_coeff = 15000,
4449
		.g1_irqs = 8,
4450
		.atu_move_port_mask = 0xf,
4451
		.multi_chip = true,
4452
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4453
		.ops = &mv88e6185_ops,
4454 4455
	},

4456
	[MV88E6190] = {
4457
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190,
4458 4459 4460 4461
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6190",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4462
		.num_internal_phys = 9,
4463
		.num_gpio = 16,
4464
		.max_vid = 8191,
4465
		.port_base_addr = 0x0,
4466
		.phy_base_addr = 0x0,
4467
		.global1_addr = 0x1b,
4468
		.global2_addr = 0x1c,
4469
		.tag_protocol = DSA_TAG_PROTO_DSA,
4470
		.age_time_coeff = 3750,
4471
		.g1_irqs = 9,
4472
		.g2_irqs = 14,
4473
		.pvt = true,
4474
		.multi_chip = true,
4475
		.atu_move_port_mask = 0x1f,
4476 4477 4478 4479
		.ops = &mv88e6190_ops,
	},

	[MV88E6190X] = {
4480
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X,
4481 4482 4483 4484
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6190X",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4485
		.num_internal_phys = 9,
4486
		.num_gpio = 16,
4487
		.max_vid = 8191,
4488
		.port_base_addr = 0x0,
4489
		.phy_base_addr = 0x0,
4490
		.global1_addr = 0x1b,
4491
		.global2_addr = 0x1c,
4492
		.age_time_coeff = 3750,
4493
		.g1_irqs = 9,
4494
		.g2_irqs = 14,
4495
		.atu_move_port_mask = 0x1f,
4496
		.pvt = true,
4497
		.multi_chip = true,
4498
		.tag_protocol = DSA_TAG_PROTO_DSA,
4499 4500 4501 4502
		.ops = &mv88e6190x_ops,
	},

	[MV88E6191] = {
4503
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191,
4504 4505 4506 4507
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6191",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4508
		.num_internal_phys = 9,
4509
		.max_vid = 8191,
4510
		.port_base_addr = 0x0,
4511
		.phy_base_addr = 0x0,
4512
		.global1_addr = 0x1b,
4513
		.global2_addr = 0x1c,
4514
		.age_time_coeff = 3750,
4515
		.g1_irqs = 9,
4516
		.g2_irqs = 14,
4517
		.atu_move_port_mask = 0x1f,
4518
		.pvt = true,
4519
		.multi_chip = true,
4520
		.tag_protocol = DSA_TAG_PROTO_DSA,
4521
		.ptp_support = true,
4522
		.ops = &mv88e6191_ops,
4523 4524
	},

4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535
	[MV88E6220] = {
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6220,
		.family = MV88E6XXX_FAMILY_6250,
		.name = "Marvell 88E6220",
		.num_databases = 64,

		/* Ports 2-4 are not routed to pins
		 * => usable ports 0, 1, 5, 6
		 */
		.num_ports = 7,
		.num_internal_phys = 2,
4536
		.invalid_port_mask = BIT(2) | BIT(3) | BIT(4),
4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547
		.max_vid = 4095,
		.port_base_addr = 0x08,
		.phy_base_addr = 0x00,
		.global1_addr = 0x0f,
		.global2_addr = 0x07,
		.age_time_coeff = 15000,
		.g1_irqs = 9,
		.g2_irqs = 10,
		.atu_move_port_mask = 0xf,
		.dual_chip = true,
		.tag_protocol = DSA_TAG_PROTO_DSA,
4548
		.ptp_support = true,
4549 4550 4551
		.ops = &mv88e6250_ops,
	},

4552
	[MV88E6240] = {
4553
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240,
4554 4555 4556 4557
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6240",
		.num_databases = 4096,
		.num_ports = 7,
4558
		.num_internal_phys = 5,
4559
		.num_gpio = 15,
4560
		.max_vid = 4095,
4561
		.port_base_addr = 0x10,
4562
		.phy_base_addr = 0x0,
4563
		.global1_addr = 0x1b,
4564
		.global2_addr = 0x1c,
4565
		.age_time_coeff = 15000,
4566
		.g1_irqs = 9,
4567
		.g2_irqs = 10,
4568
		.atu_move_port_mask = 0xf,
4569
		.pvt = true,
4570
		.multi_chip = true,
4571
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4572
		.ptp_support = true,
4573
		.ops = &mv88e6240_ops,
4574 4575
	},

4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593
	[MV88E6250] = {
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
		.family = MV88E6XXX_FAMILY_6250,
		.name = "Marvell 88E6250",
		.num_databases = 64,
		.num_ports = 7,
		.num_internal_phys = 5,
		.max_vid = 4095,
		.port_base_addr = 0x08,
		.phy_base_addr = 0x00,
		.global1_addr = 0x0f,
		.global2_addr = 0x07,
		.age_time_coeff = 15000,
		.g1_irqs = 9,
		.g2_irqs = 10,
		.atu_move_port_mask = 0xf,
		.dual_chip = true,
		.tag_protocol = DSA_TAG_PROTO_DSA,
4594
		.ptp_support = true,
4595 4596 4597
		.ops = &mv88e6250_ops,
	},

4598
	[MV88E6290] = {
4599
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
4600 4601 4602 4603
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6290",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4604
		.num_internal_phys = 9,
4605
		.num_gpio = 16,
4606
		.max_vid = 8191,
4607
		.port_base_addr = 0x0,
4608
		.phy_base_addr = 0x0,
4609
		.global1_addr = 0x1b,
4610
		.global2_addr = 0x1c,
4611
		.age_time_coeff = 3750,
4612
		.g1_irqs = 9,
4613
		.g2_irqs = 14,
4614
		.atu_move_port_mask = 0x1f,
4615
		.pvt = true,
4616
		.multi_chip = true,
4617
		.tag_protocol = DSA_TAG_PROTO_DSA,
4618
		.ptp_support = true,
4619 4620 4621
		.ops = &mv88e6290_ops,
	},

4622
	[MV88E6320] = {
4623
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320,
4624 4625 4626 4627
		.family = MV88E6XXX_FAMILY_6320,
		.name = "Marvell 88E6320",
		.num_databases = 4096,
		.num_ports = 7,
4628
		.num_internal_phys = 5,
4629
		.num_gpio = 15,
4630
		.max_vid = 4095,
4631
		.port_base_addr = 0x10,
4632
		.phy_base_addr = 0x0,
4633
		.global1_addr = 0x1b,
4634
		.global2_addr = 0x1c,
4635
		.age_time_coeff = 15000,
4636
		.g1_irqs = 8,
4637
		.g2_irqs = 10,
4638
		.atu_move_port_mask = 0xf,
4639
		.pvt = true,
4640
		.multi_chip = true,
4641
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4642
		.ptp_support = true,
4643
		.ops = &mv88e6320_ops,
4644 4645 4646
	},

	[MV88E6321] = {
4647
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321,
4648 4649 4650 4651
		.family = MV88E6XXX_FAMILY_6320,
		.name = "Marvell 88E6321",
		.num_databases = 4096,
		.num_ports = 7,
4652
		.num_internal_phys = 5,
4653
		.num_gpio = 15,
4654
		.max_vid = 4095,
4655
		.port_base_addr = 0x10,
4656
		.phy_base_addr = 0x0,
4657
		.global1_addr = 0x1b,
4658
		.global2_addr = 0x1c,
4659
		.age_time_coeff = 15000,
4660
		.g1_irqs = 8,
4661
		.g2_irqs = 10,
4662
		.atu_move_port_mask = 0xf,
4663
		.multi_chip = true,
4664
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4665
		.ptp_support = true,
4666
		.ops = &mv88e6321_ops,
4667 4668
	},

4669
	[MV88E6341] = {
4670
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
4671 4672 4673
		.family = MV88E6XXX_FAMILY_6341,
		.name = "Marvell 88E6341",
		.num_databases = 4096,
4674
		.num_internal_phys = 5,
4675
		.num_ports = 6,
4676
		.num_gpio = 11,
4677
		.max_vid = 4095,
4678
		.port_base_addr = 0x10,
4679
		.phy_base_addr = 0x10,
4680
		.global1_addr = 0x1b,
4681
		.global2_addr = 0x1c,
4682
		.age_time_coeff = 3750,
4683
		.atu_move_port_mask = 0x1f,
4684
		.g1_irqs = 9,
4685
		.g2_irqs = 10,
4686
		.pvt = true,
4687
		.multi_chip = true,
4688
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4689
		.ptp_support = true,
4690 4691 4692
		.ops = &mv88e6341_ops,
	},

4693
	[MV88E6350] = {
4694
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350,
4695 4696 4697 4698
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6350",
		.num_databases = 4096,
		.num_ports = 7,
4699
		.num_internal_phys = 5,
4700
		.max_vid = 4095,
4701
		.port_base_addr = 0x10,
4702
		.phy_base_addr = 0x0,
4703
		.global1_addr = 0x1b,
4704
		.global2_addr = 0x1c,
4705
		.age_time_coeff = 15000,
4706
		.g1_irqs = 9,
4707
		.g2_irqs = 10,
4708
		.atu_move_port_mask = 0xf,
4709
		.pvt = true,
4710
		.multi_chip = true,
4711
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4712
		.ops = &mv88e6350_ops,
4713 4714 4715
	},

	[MV88E6351] = {
4716
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6351,
4717 4718 4719 4720
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6351",
		.num_databases = 4096,
		.num_ports = 7,
4721
		.num_internal_phys = 5,
4722
		.max_vid = 4095,
4723
		.port_base_addr = 0x10,
4724
		.phy_base_addr = 0x0,
4725
		.global1_addr = 0x1b,
4726
		.global2_addr = 0x1c,
4727
		.age_time_coeff = 15000,
4728
		.g1_irqs = 9,
4729
		.g2_irqs = 10,
4730
		.atu_move_port_mask = 0xf,
4731
		.pvt = true,
4732
		.multi_chip = true,
4733
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4734
		.ops = &mv88e6351_ops,
4735 4736 4737
	},

	[MV88E6352] = {
4738
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352,
4739 4740 4741 4742
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6352",
		.num_databases = 4096,
		.num_ports = 7,
4743
		.num_internal_phys = 5,
4744
		.num_gpio = 15,
4745
		.max_vid = 4095,
4746
		.port_base_addr = 0x10,
4747
		.phy_base_addr = 0x0,
4748
		.global1_addr = 0x1b,
4749
		.global2_addr = 0x1c,
4750
		.age_time_coeff = 15000,
4751
		.g1_irqs = 9,
4752
		.g2_irqs = 10,
4753
		.atu_move_port_mask = 0xf,
4754
		.pvt = true,
4755
		.multi_chip = true,
4756
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4757
		.ptp_support = true,
4758
		.ops = &mv88e6352_ops,
4759
	},
4760
	[MV88E6390] = {
4761
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
4762 4763 4764 4765
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6390",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4766
		.num_internal_phys = 9,
4767
		.num_gpio = 16,
4768
		.max_vid = 8191,
4769
		.port_base_addr = 0x0,
4770
		.phy_base_addr = 0x0,
4771
		.global1_addr = 0x1b,
4772
		.global2_addr = 0x1c,
4773
		.age_time_coeff = 3750,
4774
		.g1_irqs = 9,
4775
		.g2_irqs = 14,
4776
		.atu_move_port_mask = 0x1f,
4777
		.pvt = true,
4778
		.multi_chip = true,
4779
		.tag_protocol = DSA_TAG_PROTO_DSA,
4780
		.ptp_support = true,
4781 4782 4783
		.ops = &mv88e6390_ops,
	},
	[MV88E6390X] = {
4784
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X,
4785 4786 4787 4788
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6390X",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4789
		.num_internal_phys = 9,
4790
		.num_gpio = 16,
4791
		.max_vid = 8191,
4792
		.port_base_addr = 0x0,
4793
		.phy_base_addr = 0x0,
4794
		.global1_addr = 0x1b,
4795
		.global2_addr = 0x1c,
4796
		.age_time_coeff = 3750,
4797
		.g1_irqs = 9,
4798
		.g2_irqs = 14,
4799
		.atu_move_port_mask = 0x1f,
4800
		.pvt = true,
4801
		.multi_chip = true,
4802
		.tag_protocol = DSA_TAG_PROTO_DSA,
4803
		.ptp_support = true,
4804 4805
		.ops = &mv88e6390x_ops,
	},
4806 4807
};

4808
static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
4809
{
4810
	int i;
4811

4812 4813 4814
	for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
		if (mv88e6xxx_table[i].prod_num == prod_num)
			return &mv88e6xxx_table[i];
4815 4816 4817 4818

	return NULL;
}

4819
static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
4820 4821
{
	const struct mv88e6xxx_info *info;
4822 4823 4824
	unsigned int prod_num, rev;
	u16 id;
	int err;
4825

4826
	mv88e6xxx_reg_lock(chip);
4827
	err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id);
4828
	mv88e6xxx_reg_unlock(chip);
4829 4830
	if (err)
		return err;
4831

4832 4833
	prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK;
	rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK;
4834 4835 4836 4837 4838

	info = mv88e6xxx_lookup_info(prod_num);
	if (!info)
		return -ENODEV;

4839
	/* Update the compatible info with the probed one */
4840
	chip->info = info;
4841

4842 4843 4844 4845
	err = mv88e6xxx_g2_require(chip);
	if (err)
		return err;

4846 4847
	dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n",
		 chip->info->prod_num, chip->info->name, rev);
4848 4849 4850 4851

	return 0;
}

4852
static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
4853
{
4854
	struct mv88e6xxx_chip *chip;
4855

4856 4857
	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
	if (!chip)
4858 4859
		return NULL;

4860
	chip->dev = dev;
4861

4862
	mutex_init(&chip->reg_lock);
4863
	INIT_LIST_HEAD(&chip->mdios);
4864
	idr_init(&chip->policies);
4865

4866
	return chip;
4867 4868
}

4869 4870
static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
							int port)
4871
{
V
Vivien Didelot 已提交
4872
	struct mv88e6xxx_chip *chip = ds->priv;
4873

4874
	return chip->info->tag_protocol;
4875 4876
}

4877
static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port,
4878
				      const struct switchdev_obj_port_mdb *mdb)
4879 4880 4881 4882 4883 4884 4885 4886 4887
{
	/* We don't need any dynamic resource from the kernel (yet),
	 * so skip the prepare phase.
	 */

	return 0;
}

static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
4888
				   const struct switchdev_obj_port_mdb *mdb)
4889
{
V
Vivien Didelot 已提交
4890
	struct mv88e6xxx_chip *chip = ds->priv;
4891

4892
	mv88e6xxx_reg_lock(chip);
4893
	if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4894
					 MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC))
4895 4896
		dev_err(ds->dev, "p%d: failed to load multicast MAC address\n",
			port);
4897
	mv88e6xxx_reg_unlock(chip);
4898 4899 4900 4901 4902
}

static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
				  const struct switchdev_obj_port_mdb *mdb)
{
V
Vivien Didelot 已提交
4903
	struct mv88e6xxx_chip *chip = ds->priv;
4904 4905
	int err;

4906
	mv88e6xxx_reg_lock(chip);
4907
	err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, 0);
4908
	mv88e6xxx_reg_unlock(chip);
4909 4910 4911 4912

	return err;
}

4913 4914 4915 4916 4917 4918
static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
					 bool unicast, bool multicast)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err = -EOPNOTSUPP;

4919
	mv88e6xxx_reg_lock(chip);
4920 4921 4922 4923
	if (chip->info->ops->port_set_egress_floods)
		err = chip->info->ops->port_set_egress_floods(chip, port,
							      unicast,
							      multicast);
4924
	mv88e6xxx_reg_unlock(chip);
4925 4926 4927 4928

	return err;
}

4929
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
4930
	.get_tag_protocol	= mv88e6xxx_get_tag_protocol,
4931
	.setup			= mv88e6xxx_setup,
4932 4933 4934 4935 4936
	.phylink_validate	= mv88e6xxx_validate,
	.phylink_mac_link_state	= mv88e6xxx_link_state,
	.phylink_mac_config	= mv88e6xxx_mac_config,
	.phylink_mac_link_down	= mv88e6xxx_mac_link_down,
	.phylink_mac_link_up	= mv88e6xxx_mac_link_up,
4937 4938 4939
	.get_strings		= mv88e6xxx_get_strings,
	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
	.get_sset_count		= mv88e6xxx_get_sset_count,
4940 4941
	.port_enable		= mv88e6xxx_port_enable,
	.port_disable		= mv88e6xxx_port_disable,
V
Vivien Didelot 已提交
4942 4943
	.get_mac_eee		= mv88e6xxx_get_mac_eee,
	.set_mac_eee		= mv88e6xxx_set_mac_eee,
4944
	.get_eeprom_len		= mv88e6xxx_get_eeprom_len,
4945 4946 4947 4948
	.get_eeprom		= mv88e6xxx_get_eeprom,
	.set_eeprom		= mv88e6xxx_set_eeprom,
	.get_regs_len		= mv88e6xxx_get_regs_len,
	.get_regs		= mv88e6xxx_get_regs,
4949 4950
	.get_rxnfc		= mv88e6xxx_get_rxnfc,
	.set_rxnfc		= mv88e6xxx_set_rxnfc,
4951
	.set_ageing_time	= mv88e6xxx_set_ageing_time,
4952 4953
	.port_bridge_join	= mv88e6xxx_port_bridge_join,
	.port_bridge_leave	= mv88e6xxx_port_bridge_leave,
4954
	.port_egress_floods	= mv88e6xxx_port_egress_floods,
4955
	.port_stp_state_set	= mv88e6xxx_port_stp_state_set,
4956
	.port_fast_age		= mv88e6xxx_port_fast_age,
4957 4958 4959 4960 4961 4962 4963
	.port_vlan_filtering	= mv88e6xxx_port_vlan_filtering,
	.port_vlan_prepare	= mv88e6xxx_port_vlan_prepare,
	.port_vlan_add		= mv88e6xxx_port_vlan_add,
	.port_vlan_del		= mv88e6xxx_port_vlan_del,
	.port_fdb_add           = mv88e6xxx_port_fdb_add,
	.port_fdb_del           = mv88e6xxx_port_fdb_del,
	.port_fdb_dump          = mv88e6xxx_port_fdb_dump,
4964 4965 4966
	.port_mdb_prepare       = mv88e6xxx_port_mdb_prepare,
	.port_mdb_add           = mv88e6xxx_port_mdb_add,
	.port_mdb_del           = mv88e6xxx_port_mdb_del,
4967 4968
	.crosschip_bridge_join	= mv88e6xxx_crosschip_bridge_join,
	.crosschip_bridge_leave	= mv88e6xxx_crosschip_bridge_leave,
4969 4970 4971 4972 4973
	.port_hwtstamp_set	= mv88e6xxx_port_hwtstamp_set,
	.port_hwtstamp_get	= mv88e6xxx_port_hwtstamp_get,
	.port_txtstamp		= mv88e6xxx_port_txtstamp,
	.port_rxtstamp		= mv88e6xxx_port_rxtstamp,
	.get_ts_info		= mv88e6xxx_get_ts_info,
4974 4975
};

4976
static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
4977
{
4978
	struct device *dev = chip->dev;
4979 4980
	struct dsa_switch *ds;

4981
	ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
4982 4983 4984
	if (!ds)
		return -ENOMEM;

4985 4986
	ds->dev = dev;
	ds->num_ports = mv88e6xxx_num_ports(chip);
4987
	ds->priv = chip;
4988
	ds->dev = dev;
4989
	ds->ops = &mv88e6xxx_switch_ops;
4990 4991
	ds->ageing_time_min = chip->info->age_time_coeff;
	ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
4992 4993 4994

	dev_set_drvdata(dev, ds);

4995
	return dsa_register_switch(ds);
4996 4997
}

4998
static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip)
4999
{
5000
	dsa_unregister_switch(chip->ds);
5001 5002
}

5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015
static const void *pdata_device_get_match_data(struct device *dev)
{
	const struct of_device_id *matches = dev->driver->of_match_table;
	const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data;

	for (; matches->name[0] || matches->type[0] || matches->compatible[0];
	     matches++) {
		if (!strcmp(pdata->compatible, matches->compatible))
			return matches->data;
	}
	return NULL;
}

5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030
/* There is no suspend to RAM support at DSA level yet, the switch configuration
 * would be lost after a power cycle so prevent it to be suspended.
 */
static int __maybe_unused mv88e6xxx_suspend(struct device *dev)
{
	return -EOPNOTSUPP;
}

static int __maybe_unused mv88e6xxx_resume(struct device *dev)
{
	return 0;
}

static SIMPLE_DEV_PM_OPS(mv88e6xxx_pm_ops, mv88e6xxx_suspend, mv88e6xxx_resume);

5031
static int mv88e6xxx_probe(struct mdio_device *mdiodev)
5032
{
5033
	struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
5034
	const struct mv88e6xxx_info *compat_info = NULL;
5035
	struct device *dev = &mdiodev->dev;
5036
	struct device_node *np = dev->of_node;
5037
	struct mv88e6xxx_chip *chip;
5038
	int port;
5039
	int err;
5040

5041 5042 5043
	if (!np && !pdata)
		return -EINVAL;

5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062
	if (np)
		compat_info = of_device_get_match_data(dev);

	if (pdata) {
		compat_info = pdata_device_get_match_data(dev);

		if (!pdata->netdev)
			return -EINVAL;

		for (port = 0; port < DSA_MAX_PORTS; port++) {
			if (!(pdata->enabled_ports & (1 << port)))
				continue;
			if (strcmp(pdata->cd.port_names[port], "cpu"))
				continue;
			pdata->cd.netdev[port] = &pdata->netdev->dev;
			break;
		}
	}

5063 5064 5065
	if (!compat_info)
		return -EINVAL;

5066
	chip = mv88e6xxx_alloc_chip(dev);
5067 5068 5069 5070
	if (!chip) {
		err = -ENOMEM;
		goto out;
	}
5071

5072
	chip->info = compat_info;
5073

5074
	err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
5075
	if (err)
5076
		goto out;
5077

5078
	chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
5079 5080 5081 5082
	if (IS_ERR(chip->reset)) {
		err = PTR_ERR(chip->reset);
		goto out;
	}
5083 5084
	if (chip->reset)
		usleep_range(1000, 2000);
5085

5086
	err = mv88e6xxx_detect(chip);
5087
	if (err)
5088
		goto out;
5089

5090 5091
	mv88e6xxx_phy_init(chip);

5092 5093 5094 5095 5096 5097 5098
	if (chip->info->ops->get_eeprom) {
		if (np)
			of_property_read_u32(np, "eeprom-length",
					     &chip->eeprom_len);
		else
			chip->eeprom_len = pdata->eeprom_len;
	}
5099

5100
	mv88e6xxx_reg_lock(chip);
5101
	err = mv88e6xxx_switch_reset(chip);
5102
	mv88e6xxx_reg_unlock(chip);
5103 5104 5105
	if (err)
		goto out;

5106 5107 5108 5109 5110 5111
	if (np) {
		chip->irq = of_irq_get(np, 0);
		if (chip->irq == -EPROBE_DEFER) {
			err = chip->irq;
			goto out;
		}
5112 5113
	}

5114 5115 5116
	if (pdata)
		chip->irq = pdata->irq;

5117
	/* Has to be performed before the MDIO bus is created, because
5118
	 * the PHYs will link their interrupts to these interrupt
5119 5120
	 * controllers
	 */
5121
	mv88e6xxx_reg_lock(chip);
5122
	if (chip->irq > 0)
5123
		err = mv88e6xxx_g1_irq_setup(chip);
5124 5125
	else
		err = mv88e6xxx_irq_poll_setup(chip);
5126
	mv88e6xxx_reg_unlock(chip);
5127

5128 5129
	if (err)
		goto out;
5130

5131 5132
	if (chip->info->g2_irqs > 0) {
		err = mv88e6xxx_g2_irq_setup(chip);
5133
		if (err)
5134
			goto out_g1_irq;
5135 5136
	}

5137 5138 5139 5140 5141 5142 5143 5144
	err = mv88e6xxx_g1_atu_prob_irq_setup(chip);
	if (err)
		goto out_g2_irq;

	err = mv88e6xxx_g1_vtu_prob_irq_setup(chip);
	if (err)
		goto out_g1_atu_prob_irq;

5145
	err = mv88e6xxx_mdios_register(chip, np);
5146
	if (err)
5147
		goto out_g1_vtu_prob_irq;
5148

5149
	err = mv88e6xxx_register_switch(chip);
5150 5151
	if (err)
		goto out_mdio;
5152

5153
	return 0;
5154 5155

out_mdio:
5156
	mv88e6xxx_mdios_unregister(chip);
5157
out_g1_vtu_prob_irq:
5158
	mv88e6xxx_g1_vtu_prob_irq_free(chip);
5159
out_g1_atu_prob_irq:
5160
	mv88e6xxx_g1_atu_prob_irq_free(chip);
5161
out_g2_irq:
5162
	if (chip->info->g2_irqs > 0)
5163 5164
		mv88e6xxx_g2_irq_free(chip);
out_g1_irq:
5165
	if (chip->irq > 0)
5166
		mv88e6xxx_g1_irq_free(chip);
5167 5168
	else
		mv88e6xxx_irq_poll_free(chip);
5169
out:
5170 5171 5172
	if (pdata)
		dev_put(pdata->netdev);

5173
	return err;
5174
}
5175 5176 5177 5178

static void mv88e6xxx_remove(struct mdio_device *mdiodev)
{
	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
V
Vivien Didelot 已提交
5179
	struct mv88e6xxx_chip *chip = ds->priv;
5180

5181 5182
	if (chip->info->ptp_support) {
		mv88e6xxx_hwtstamp_free(chip);
5183
		mv88e6xxx_ptp_free(chip);
5184
	}
5185

5186
	mv88e6xxx_phy_destroy(chip);
5187
	mv88e6xxx_unregister_switch(chip);
5188
	mv88e6xxx_mdios_unregister(chip);
5189

5190 5191 5192 5193 5194 5195 5196
	mv88e6xxx_g1_vtu_prob_irq_free(chip);
	mv88e6xxx_g1_atu_prob_irq_free(chip);

	if (chip->info->g2_irqs > 0)
		mv88e6xxx_g2_irq_free(chip);

	if (chip->irq > 0)
5197
		mv88e6xxx_g1_irq_free(chip);
5198 5199
	else
		mv88e6xxx_irq_poll_free(chip);
5200 5201 5202
}

static const struct of_device_id mv88e6xxx_of_match[] = {
5203 5204 5205 5206
	{
		.compatible = "marvell,mv88e6085",
		.data = &mv88e6xxx_table[MV88E6085],
	},
5207 5208 5209 5210
	{
		.compatible = "marvell,mv88e6190",
		.data = &mv88e6xxx_table[MV88E6190],
	},
5211 5212 5213 5214
	{
		.compatible = "marvell,mv88e6250",
		.data = &mv88e6xxx_table[MV88E6250],
	},
5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225
	{ /* sentinel */ },
};

MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);

static struct mdio_driver mv88e6xxx_driver = {
	.probe	= mv88e6xxx_probe,
	.remove = mv88e6xxx_remove,
	.mdiodrv.driver = {
		.name = "mv88e6085",
		.of_match_table = mv88e6xxx_of_match,
5226
		.pm = &mv88e6xxx_pm_ops,
5227 5228 5229
	},
};

5230
mdio_module_driver(mv88e6xxx_driver);
5231 5232 5233 5234

MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
MODULE_LICENSE("GPL");