chip.c 138.3 KB
Newer Older
1
/*
2 3
 * Marvell 88e6xxx Ethernet switch single-chip support
 *
4 5
 * Copyright (c) 2008 Marvell Semiconductor
 *
6 7
 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
 *
V
Vivien Didelot 已提交
8 9 10
 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 *
11 12 13 14 15 16
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

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

38
#include "chip.h"
39
#include "global1.h"
40
#include "global2.h"
41
#include "hwtstamp.h"
42
#include "phy.h"
43
#include "port.h"
44
#include "ptp.h"
45
#include "serdes.h"
46

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

55 56 57 58 59 60 61 62 63 64
/* The switch ADDR[4:1] configuration pins define the chip SMI device address
 * (ADDR[0] is always zero, thus only even SMI addresses can be strapped).
 *
 * When ADDR is all zero, the chip uses Single-chip Addressing Mode, assuming it
 * is the only device connected to the SMI master. In this mode it responds to
 * all 32 possible SMI addresses, and thus maps directly the internal devices.
 *
 * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing
 * multiple devices to share the SMI interface. In this mode it responds to only
 * 2 registers, used to indirectly access the internal SMI devices.
65
 */
66

67
static int mv88e6xxx_smi_read(struct mv88e6xxx_chip *chip,
68 69
			      int addr, int reg, u16 *val)
{
70
	if (!chip->smi_ops)
71 72
		return -EOPNOTSUPP;

73
	return chip->smi_ops->read(chip, addr, reg, val);
74 75
}

76
static int mv88e6xxx_smi_write(struct mv88e6xxx_chip *chip,
77 78
			       int addr, int reg, u16 val)
{
79
	if (!chip->smi_ops)
80 81
		return -EOPNOTSUPP;

82
	return chip->smi_ops->write(chip, addr, reg, val);
83 84
}

85
static int mv88e6xxx_smi_single_chip_read(struct mv88e6xxx_chip *chip,
86 87 88 89
					  int addr, int reg, u16 *val)
{
	int ret;

90
	ret = mdiobus_read_nested(chip->bus, addr, reg);
91 92 93 94 95 96 97 98
	if (ret < 0)
		return ret;

	*val = ret & 0xffff;

	return 0;
}

99
static int mv88e6xxx_smi_single_chip_write(struct mv88e6xxx_chip *chip,
100 101 102 103
					   int addr, int reg, u16 val)
{
	int ret;

104
	ret = mdiobus_write_nested(chip->bus, addr, reg, val);
105 106 107 108 109 110
	if (ret < 0)
		return ret;

	return 0;
}

111
static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_single_chip_ops = {
112 113 114 115
	.read = mv88e6xxx_smi_single_chip_read,
	.write = mv88e6xxx_smi_single_chip_write,
};

116
static int mv88e6xxx_smi_multi_chip_wait(struct mv88e6xxx_chip *chip)
117 118 119 120 121
{
	int ret;
	int i;

	for (i = 0; i < 16; i++) {
122
		ret = mdiobus_read_nested(chip->bus, chip->sw_addr, SMI_CMD);
123 124 125
		if (ret < 0)
			return ret;

126
		if ((ret & SMI_CMD_BUSY) == 0)
127 128 129 130 131 132
			return 0;
	}

	return -ETIMEDOUT;
}

133
static int mv88e6xxx_smi_multi_chip_read(struct mv88e6xxx_chip *chip,
134
					 int addr, int reg, u16 *val)
135 136 137
{
	int ret;

138
	/* Wait for the bus to become free. */
139
	ret = mv88e6xxx_smi_multi_chip_wait(chip);
140 141 142
	if (ret < 0)
		return ret;

143
	/* Transmit the read command. */
144
	ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_CMD,
145
				   SMI_CMD_OP_22_READ | (addr << 5) | reg);
146 147 148
	if (ret < 0)
		return ret;

149
	/* Wait for the read command to complete. */
150
	ret = mv88e6xxx_smi_multi_chip_wait(chip);
151 152 153
	if (ret < 0)
		return ret;

154
	/* Read the data. */
155
	ret = mdiobus_read_nested(chip->bus, chip->sw_addr, SMI_DATA);
156 157 158
	if (ret < 0)
		return ret;

159
	*val = ret & 0xffff;
160

161
	return 0;
162 163
}

164
static int mv88e6xxx_smi_multi_chip_write(struct mv88e6xxx_chip *chip,
165
					  int addr, int reg, u16 val)
166 167 168
{
	int ret;

169
	/* Wait for the bus to become free. */
170
	ret = mv88e6xxx_smi_multi_chip_wait(chip);
171 172 173
	if (ret < 0)
		return ret;

174
	/* Transmit the data to write. */
175
	ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_DATA, val);
176 177 178
	if (ret < 0)
		return ret;

179
	/* Transmit the write command. */
180
	ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_CMD,
181
				   SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
182 183 184
	if (ret < 0)
		return ret;

185
	/* Wait for the write command to complete. */
186
	ret = mv88e6xxx_smi_multi_chip_wait(chip);
187 188 189 190 191 192
	if (ret < 0)
		return ret;

	return 0;
}

193
static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_multi_chip_ops = {
194 195 196 197
	.read = mv88e6xxx_smi_multi_chip_read,
	.write = mv88e6xxx_smi_multi_chip_write,
};

198
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)
199 200 201
{
	int err;

202
	assert_reg_lock(chip);
203

204
	err = mv88e6xxx_smi_read(chip, addr, reg, val);
205 206 207
	if (err)
		return err;

208
	dev_dbg(chip->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
209 210 211 212 213
		addr, reg, *val);

	return 0;
}

214
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
215
{
216 217
	int err;

218
	assert_reg_lock(chip);
219

220
	err = mv88e6xxx_smi_write(chip, addr, reg, val);
221 222 223
	if (err)
		return err;

224
	dev_dbg(chip->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
225 226
		addr, reg, val);

227 228 229
	return 0;
}

230
struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
231 232 233 234 235 236 237 238 239 240 241
{
	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;
}

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
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);
}

258
static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
259 260 261 262 263
{
	unsigned int nhandled = 0;
	unsigned int sub_irq;
	unsigned int n;
	u16 reg;
264
	u16 ctl1;
265 266 267
	int err;

	mutex_lock(&chip->reg_lock);
268
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
269 270 271 272 273
	mutex_unlock(&chip->reg_lock);

	if (err)
		goto out;

274 275 276 277 278 279 280 281
	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;
			}
282
		}
283 284 285 286 287 288 289 290 291 292 293 294 295

		mutex_lock(&chip->reg_lock);
		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
		if (err)
			goto unlock;
		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
unlock:
		mutex_unlock(&chip->reg_lock);
		if (err)
			goto out;
		ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
	} while (reg & ctl1);

296 297 298 299
out:
	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
}

300 301 302 303 304 305 306
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);
}

307 308 309 310 311 312 313 314 315 316 317 318 319 320
static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
{
	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);

	mutex_lock(&chip->reg_lock);
}

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;

321
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &reg);
322 323 324 325 326 327
	if (err)
		goto out;

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

328
	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);
329 330 331 332 333 334 335
	if (err)
		goto out;

out:
	mutex_unlock(&chip->reg_lock);
}

336
static const struct irq_chip mv88e6xxx_g1_irq_chip = {
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
	.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,
};

362
/* To be called with reg_lock held */
363
static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)
364 365
{
	int irq, virq;
366 367
	u16 mask;

368
	mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
369
	mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
370
	mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
371

372
	for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
373
		virq = irq_find_mapping(chip->g1_irq.domain, irq);
374 375 376
		irq_dispose_mapping(virq);
	}

377
	irq_domain_remove(chip->g1_irq.domain);
378 379
}

380 381
static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
{
382 383 384 385
	/*
	 * free_irq must be called without reg_lock taken because the irq
	 * handler takes this lock, too.
	 */
386
	free_irq(chip->irq, chip);
387 388 389 390

	mutex_lock(&chip->reg_lock);
	mv88e6xxx_g1_irq_free_common(chip);
	mutex_unlock(&chip->reg_lock);
391 392 393
}

static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)
394
{
395 396
	int err, irq, virq;
	u16 reg, mask;
397 398 399 400 401 402 403 404 405 406 407 408 409 410

	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;

411
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
412
	if (err)
413
		goto out_mapping;
414

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

417
	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
418
	if (err)
419
		goto out_disable;
420 421

	/* Reading the interrupt status clears (most of) them */
422
	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
423
	if (err)
424
		goto out_disable;
425 426 427

	return 0;

428
out_disable:
429
	mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
430
	mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
431 432 433 434 435 436 437 438

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);
439 440 441 442

	return err;
}

443 444 445 446 447 448 449 450 451 452
static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
{
	int err;

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

	err = request_threaded_irq(chip->irq, NULL,
				   mv88e6xxx_g1_irq_thread_fn,
453
				   IRQF_ONESHOT,
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
				   dev_name(chip->dev), chip);
	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);

	chip->kworker = kthread_create_worker(0, dev_name(chip->dev));
	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);
497 498 499 500

	mutex_lock(&chip->reg_lock);
	mv88e6xxx_g1_irq_free_common(chip);
	mutex_unlock(&chip->reg_lock);
501 502
}

503
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
504
{
505
	int i;
506

507
	for (i = 0; i < 16; i++) {
508 509 510 511 512 513 514 515 516 517 518 519 520
		u16 val;
		int err;

		err = mv88e6xxx_read(chip, addr, reg, &val);
		if (err)
			return err;

		if (!(val & mask))
			return 0;

		usleep_range(1000, 2000);
	}

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

525
/* Indirect write to single pointer-data register with an Update bit */
526
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
527 528
{
	u16 val;
529
	int err;
530 531

	/* Wait until the previous operation is completed */
532 533 534
	err = mv88e6xxx_wait(chip, addr, reg, BIT(15));
	if (err)
		return err;
535 536 537 538 539 540 541

	/* Set the Update bit to trigger a write operation */
	val = BIT(15) | update;

	return mv88e6xxx_write(chip, addr, reg, val);
}

542
static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
543
				    int link, int speed, int duplex, int pause,
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
				    phy_interface_t mode)
{
	int err;

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

	/* Port's MAC control must not be changed unless the link is down */
	err = chip->info->ops->port_set_link(chip, port, 0);
	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;
	}

562 563 564 565 566 567
	if (chip->info->ops->port_set_pause) {
		err = chip->info->ops->port_set_pause(chip, port, pause);
		if (err)
			goto restore_link;
	}

568 569 570 571 572 573 574 575 576 577 578 579
	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;
	}

580 581 582 583 584 585
	if (chip->info->ops->port_set_cmode) {
		err = chip->info->ops->port_set_cmode(chip, port, mode);
		if (err && err != -EOPNOTSUPP)
			goto restore_link;
	}

586 587 588
	err = 0;
restore_link:
	if (chip->info->ops->port_set_link(chip, port, link))
589
		dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port);
590 591 592 593

	return err;
}

594 595 596 597
/* We expect the switch to perform auto negotiation if there is a real
 * phy. However, in the case of a fixed link phy, we force the port
 * settings from the fixed link settings.
 */
598 599
static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
				  struct phy_device *phydev)
600
{
V
Vivien Didelot 已提交
601
	struct mv88e6xxx_chip *chip = ds->priv;
602
	int err;
603 604 605 606

	if (!phy_is_pseudo_fixed_link(phydev))
		return;

607
	mutex_lock(&chip->reg_lock);
608
	err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
609 610
				       phydev->duplex, phydev->pause,
				       phydev->interface);
611
	mutex_unlock(&chip->reg_lock);
612 613

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

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
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);
}

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)
{
	if (port >= 9)
		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);
}

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);
}

680 681 682 683
static void mv88e6xxx_validate(struct dsa_switch *ds, int port,
			       unsigned long *supported,
			       struct phylink_link_state *state)
{
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
	__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);
703 704 705 706 707 708 709 710 711
}

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

	mutex_lock(&chip->reg_lock);
712 713 714 715
	if (chip->info->ops->port_link_state)
		err = chip->info->ops->port_link_state(chip, port, state);
	else
		err = -EOPNOTSUPP;
716 717 718 719 720 721 722 723 724 725
	mutex_unlock(&chip->reg_lock);

	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;
726
	int speed, duplex, link, pause, err;
727 728 729 730 731 732 733 734 735 736 737 738 739

	if (mode == MLO_AN_PHY)
		return;

	if (mode == MLO_AN_FIXED) {
		link = LINK_FORCED_UP;
		speed = state->speed;
		duplex = state->duplex;
	} else {
		speed = SPEED_UNFORCED;
		duplex = DUPLEX_UNFORCED;
		link = LINK_UNFORCED;
	}
740
	pause = !!phylink_test(state->advertising, Pause);
741 742

	mutex_lock(&chip->reg_lock);
743
	err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, pause,
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
				       state->interface);
	mutex_unlock(&chip->reg_lock);

	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;

	mutex_lock(&chip->reg_lock);
	err = chip->info->ops->port_set_link(chip, port, link);
	mutex_unlock(&chip->reg_lock);

	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);
}

780
static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
781
{
782 783
	if (!chip->info->ops->stats_snapshot)
		return -EOPNOTSUPP;
784

785
	return chip->info->ops->stats_snapshot(chip, port);
786 787
}

788
static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
	{ "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, },
848 849
};

850
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
851
					    struct mv88e6xxx_hw_stat *s,
852 853
					    int port, u16 bank1_select,
					    u16 histogram)
854 855 856
{
	u32 low;
	u32 high = 0;
857
	u16 reg = 0;
858
	int err;
859 860
	u64 value;

861
	switch (s->type) {
862
	case STATS_TYPE_PORT:
863 864
		err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
		if (err)
865
			return U64_MAX;
866

867
		low = reg;
868
		if (s->size == 4) {
869 870
			err = mv88e6xxx_port_read(chip, port, s->reg + 1, &reg);
			if (err)
871
				return U64_MAX;
872
			high = reg;
873
		}
874
		break;
875
	case STATS_TYPE_BANK1:
876
		reg = bank1_select;
877 878
		/* fall through */
	case STATS_TYPE_BANK0:
879
		reg |= s->reg | histogram;
880
		mv88e6xxx_g1_stats_read(chip, reg, &low);
881
		if (s->size == 8)
882
			mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
883 884
		break;
	default:
885
		return U64_MAX;
886 887 888 889 890
	}
	value = (((u64)high) << 16) | low;
	return value;
}

891 892
static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data, int types)
893
{
894 895
	struct mv88e6xxx_hw_stat *stat;
	int i, j;
896

897 898
	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
		stat = &mv88e6xxx_hw_stats[i];
899
		if (stat->type & types) {
900 901 902 903
			memcpy(data + j * ETH_GSTRING_LEN, stat->string,
			       ETH_GSTRING_LEN);
			j++;
		}
904
	}
905 906

	return j;
907 908
}

909 910
static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data)
911
{
912 913
	return mv88e6xxx_stats_get_strings(chip, data,
					   STATS_TYPE_BANK0 | STATS_TYPE_PORT);
914 915
}

916 917
static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
				       uint8_t *data)
918
{
919 920
	return mv88e6xxx_stats_get_strings(chip, data,
					   STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
921 922
}

923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
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);
}

941
static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
942
				  u32 stringset, uint8_t *data)
943
{
V
Vivien Didelot 已提交
944
	struct mv88e6xxx_chip *chip = ds->priv;
945
	int count = 0;
946

947 948 949
	if (stringset != ETH_SS_STATS)
		return;

950 951
	mutex_lock(&chip->reg_lock);

952
	if (chip->info->ops->stats_get_strings)
953 954 955 956
		count = chip->info->ops->stats_get_strings(chip, data);

	if (chip->info->ops->serdes_get_strings) {
		data += count * ETH_GSTRING_LEN;
957
		count = chip->info->ops->serdes_get_strings(chip, port, data);
958
	}
959

960 961 962
	data += count * ETH_GSTRING_LEN;
	mv88e6xxx_atu_vtu_get_strings(data);

963
	mutex_unlock(&chip->reg_lock);
964 965 966 967 968
}

static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
					  int types)
{
969 970 971 972 973
	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];
974
		if (stat->type & types)
975 976 977
			j++;
	}
	return j;
978 979
}

980 981 982 983 984 985 986 987 988 989 990 991
static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
					      STATS_TYPE_PORT);
}

static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
					      STATS_TYPE_BANK1);
}

992
static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
993 994
{
	struct mv88e6xxx_chip *chip = ds->priv;
995 996
	int serdes_count = 0;
	int count = 0;
997

998 999 1000
	if (sset != ETH_SS_STATS)
		return 0;

1001
	mutex_lock(&chip->reg_lock);
1002
	if (chip->info->ops->stats_get_sset_count)
1003 1004 1005 1006 1007 1008 1009
		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);
1010
	if (serdes_count < 0) {
1011
		count = serdes_count;
1012 1013 1014 1015 1016
		goto out;
	}
	count += serdes_count;
	count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);

1017
out:
1018
	mutex_unlock(&chip->reg_lock);
1019

1020
	return count;
1021 1022
}

1023 1024 1025
static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data, int types,
				     u16 bank1_select, u16 histogram)
1026 1027 1028 1029 1030 1031 1032
{
	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) {
1033
			mutex_lock(&chip->reg_lock);
1034 1035 1036
			data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
							      bank1_select,
							      histogram);
1037 1038
			mutex_unlock(&chip->reg_lock);

1039 1040 1041
			j++;
		}
	}
1042
	return j;
1043 1044
}

1045 1046
static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
1047 1048
{
	return mv88e6xxx_stats_get_stats(chip, port, data,
1049
					 STATS_TYPE_BANK0 | STATS_TYPE_PORT,
1050
					 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
1051 1052
}

1053 1054
static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
1055 1056
{
	return mv88e6xxx_stats_get_stats(chip, port, data,
1057
					 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
1058 1059
					 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
					 MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
1060 1061
}

1062 1063
static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
				     uint64_t *data)
1064 1065 1066
{
	return mv88e6xxx_stats_get_stats(chip, port, data,
					 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
1067 1068
					 MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
					 0);
1069 1070
}

1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
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;
}

1081 1082 1083
static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
				uint64_t *data)
{
1084 1085
	int count = 0;

1086
	if (chip->info->ops->stats_get_stats)
1087 1088
		count = chip->info->ops->stats_get_stats(chip, port, data);

1089
	mutex_lock(&chip->reg_lock);
1090 1091
	if (chip->info->ops->serdes_get_stats) {
		data += count;
1092
		count = chip->info->ops->serdes_get_stats(chip, port, data);
1093
	}
1094 1095 1096
	data += count;
	mv88e6xxx_atu_vtu_get_stats(chip, port, data);
	mutex_unlock(&chip->reg_lock);
1097 1098
}

1099 1100
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
					uint64_t *data)
1101
{
V
Vivien Didelot 已提交
1102
	struct mv88e6xxx_chip *chip = ds->priv;
1103 1104
	int ret;

1105
	mutex_lock(&chip->reg_lock);
1106

1107
	ret = mv88e6xxx_stats_snapshot(chip, port);
1108 1109 1110
	mutex_unlock(&chip->reg_lock);

	if (ret < 0)
1111
		return;
1112 1113

	mv88e6xxx_get_stats(chip, port, data);
1114

1115 1116
}

1117
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
1118 1119 1120 1121
{
	return 32 * sizeof(u16);
}

1122 1123
static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
			       struct ethtool_regs *regs, void *_p)
1124
{
V
Vivien Didelot 已提交
1125
	struct mv88e6xxx_chip *chip = ds->priv;
1126 1127
	int err;
	u16 reg;
1128 1129 1130 1131 1132 1133 1134
	u16 *p = _p;
	int i;

	regs->version = 0;

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

1135
	mutex_lock(&chip->reg_lock);
1136

1137 1138
	for (i = 0; i < 32; i++) {

1139 1140 1141
		err = mv88e6xxx_port_read(chip, port, i, &reg);
		if (!err)
			p[i] = reg;
1142
	}
1143

1144
	mutex_unlock(&chip->reg_lock);
1145 1146
}

V
Vivien Didelot 已提交
1147 1148
static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
				 struct ethtool_eee *e)
1149
{
1150 1151
	/* Nothing to do on the port's MAC */
	return 0;
1152 1153
}

V
Vivien Didelot 已提交
1154 1155
static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
				 struct ethtool_eee *e)
1156
{
1157 1158
	/* Nothing to do on the port's MAC */
	return 0;
1159 1160
}

1161
static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
1162
{
1163 1164 1165
	struct dsa_switch *ds = NULL;
	struct net_device *br;
	u16 pvlan;
1166 1167
	int i;

1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
	if (dev < DSA_MAX_SWITCHES)
		ds = chip->ds->dst->ds[dev];

	/* Prevent frames from unknown switch or port */
	if (!ds || port >= ds->num_ports)
		return 0;

	/* Frames from DSA links and CPU ports can egress any local port */
	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
		return mv88e6xxx_port_mask(chip);

	br = ds->ports[port].bridge_dev;
	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.
	 */
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
		if (dsa_is_cpu_port(chip->ds, i) ||
		    dsa_is_dsa_port(chip->ds, i) ||
V
Vivien Didelot 已提交
1188
		    (br && dsa_to_port(chip->ds, i)->bridge_dev == br))
1189 1190 1191 1192 1193
			pvlan |= BIT(i);

	return pvlan;
}

1194
static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
1195 1196
{
	u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
1197 1198 1199

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

1201
	return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
1202 1203
}

1204 1205
static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
					 u8 state)
1206
{
V
Vivien Didelot 已提交
1207
	struct mv88e6xxx_chip *chip = ds->priv;
1208
	int err;
1209

1210
	mutex_lock(&chip->reg_lock);
1211
	err = mv88e6xxx_port_set_state(chip, port, state);
1212
	mutex_unlock(&chip->reg_lock);
1213 1214

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

1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
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;
}

1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
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;
	}

1257 1258 1259 1260 1261 1262 1263
	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;
	}

1264 1265 1266 1267
	err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index);
	if (err)
		return err;

1268 1269 1270
	return 0;
}

1271 1272 1273 1274 1275 1276 1277 1278 1279
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;
}

1280 1281 1282 1283 1284 1285 1286 1287
static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->rmu_disable)
		return chip->info->ops->rmu_disable(chip);

	return 0;
}

1288 1289 1290 1291 1292 1293 1294 1295
static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->pot_clear)
		return chip->info->ops->pot_clear(chip);

	return 0;
}

1296 1297 1298 1299 1300 1301 1302 1303
static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->mgmt_rsvd2cpu)
		return chip->info->ops->mgmt_rsvd2cpu(chip);

	return 0;
}

1304 1305
static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
{
1306 1307
	int err;

1308 1309 1310 1311
	err = mv88e6xxx_g1_atu_flush(chip, 0, true);
	if (err)
		return err;

1312 1313 1314 1315
	err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
	if (err)
		return err;

1316 1317 1318
	return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
}

1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
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;
}

1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
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;
}

1352 1353 1354 1355 1356 1357 1358 1359 1360
static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
{
	u16 pvlan = 0;

	if (!mv88e6xxx_has_pvt(chip))
		return -EOPNOTSUPP;

	/* Skip the local source device, which uses in-chip port VLAN */
	if (dev != chip->ds->index)
1361
		pvlan = mv88e6xxx_port_vlan(chip, dev, port);
1362 1363 1364 1365

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

1366 1367
static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
{
1368 1369 1370
	int dev, port;
	int err;

1371 1372 1373 1374 1375 1376
	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.
	 */
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
	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;
1390 1391
}

1392 1393 1394 1395 1396 1397
static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

	mutex_lock(&chip->reg_lock);
1398
	err = mv88e6xxx_g1_atu_remove(chip, 0, port, false);
1399 1400 1401
	mutex_unlock(&chip->reg_lock);

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

1405 1406 1407 1408 1409 1410 1411 1412
static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
{
	if (!chip->info->max_vid)
		return 0;

	return mv88e6xxx_g1_vtu_flush(chip);
}

1413 1414 1415 1416 1417 1418 1419 1420 1421
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);
}

1422 1423 1424 1425 1426 1427 1428 1429 1430
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);
}

1431
static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
1432 1433
{
	DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
1434 1435 1436
	struct mv88e6xxx_vtu_entry vlan = {
		.vid = chip->info->max_vid,
	};
1437
	int i, err;
1438 1439 1440

	bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);

1441
	/* Set every FID bit used by the (un)bridged ports */
1442
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1443
		err = mv88e6xxx_port_get_fid(chip, i, fid);
1444 1445 1446 1447 1448 1449
		if (err)
			return err;

		set_bit(*fid, fid_bitmap);
	}

1450 1451
	/* Set every FID bit used by the VLAN entries */
	do {
1452
		err = mv88e6xxx_vtu_getnext(chip, &vlan);
1453 1454 1455 1456 1457 1458 1459
		if (err)
			return err;

		if (!vlan.valid)
			break;

		set_bit(vlan.fid, fid_bitmap);
1460
	} while (vlan.vid < chip->info->max_vid);
1461 1462 1463 1464 1465

	/* 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);
1466
	if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
1467 1468 1469
		return -ENOSPC;

	/* Clear the database */
1470
	return mv88e6xxx_g1_atu_flush(chip, *fid, true);
1471 1472
}

1473 1474
static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
			     struct mv88e6xxx_vtu_entry *entry, bool new)
1475 1476 1477 1478 1479 1480
{
	int err;

	if (!vid)
		return -EINVAL;

1481 1482
	entry->vid = vid - 1;
	entry->valid = false;
1483

1484
	err = mv88e6xxx_vtu_getnext(chip, entry);
1485 1486 1487
	if (err)
		return err;

1488 1489
	if (entry->vid == vid && entry->valid)
		return 0;
1490

1491 1492 1493 1494 1495 1496 1497 1498
	if (new) {
		int i;

		/* Initialize a fresh VLAN entry */
		memset(entry, 0, sizeof(*entry));
		entry->valid = true;
		entry->vid = vid;

1499
		/* Exclude all ports */
1500
		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
1501
			entry->member[i] =
1502
				MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1503 1504

		return mv88e6xxx_atu_new(chip, &entry->fid);
1505 1506
	}

1507 1508
	/* switchdev expects -EOPNOTSUPP to honor software VLANs */
	return -EOPNOTSUPP;
1509 1510
}

1511 1512 1513
static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
					u16 vid_begin, u16 vid_end)
{
V
Vivien Didelot 已提交
1514
	struct mv88e6xxx_chip *chip = ds->priv;
1515 1516 1517
	struct mv88e6xxx_vtu_entry vlan = {
		.vid = vid_begin - 1,
	};
1518 1519
	int i, err;

1520 1521 1522 1523
	/* 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;

1524 1525 1526
	if (!vid_begin)
		return -EOPNOTSUPP;

1527
	mutex_lock(&chip->reg_lock);
1528 1529

	do {
1530
		err = mv88e6xxx_vtu_getnext(chip, &vlan);
1531 1532 1533 1534 1535 1536 1537 1538 1539
		if (err)
			goto unlock;

		if (!vlan.valid)
			break;

		if (vlan.vid > vid_end)
			break;

1540
		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1541 1542 1543
			if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
				continue;

1544
			if (!ds->ports[i].slave)
1545 1546
				continue;

1547
			if (vlan.member[i] ==
1548
			    MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1549 1550
				continue;

V
Vivien Didelot 已提交
1551
			if (dsa_to_port(ds, i)->bridge_dev ==
1552
			    ds->ports[port].bridge_dev)
1553 1554
				break; /* same bridge, check next VLAN */

V
Vivien Didelot 已提交
1555
			if (!dsa_to_port(ds, i)->bridge_dev)
1556 1557
				continue;

1558 1559
			dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n",
				port, vlan.vid, i,
V
Vivien Didelot 已提交
1560
				netdev_name(dsa_to_port(ds, i)->bridge_dev));
1561 1562 1563 1564 1565 1566
			err = -EOPNOTSUPP;
			goto unlock;
		}
	} while (vlan.vid < vid_end);

unlock:
1567
	mutex_unlock(&chip->reg_lock);
1568 1569 1570 1571

	return err;
}

1572 1573
static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
					 bool vlan_filtering)
1574
{
V
Vivien Didelot 已提交
1575
	struct mv88e6xxx_chip *chip = ds->priv;
1576 1577
	u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
		MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
1578
	int err;
1579

1580
	if (!chip->info->max_vid)
1581 1582
		return -EOPNOTSUPP;

1583
	mutex_lock(&chip->reg_lock);
1584
	err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
1585
	mutex_unlock(&chip->reg_lock);
1586

1587
	return err;
1588 1589
}

1590 1591
static int
mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
1592
			    const struct switchdev_obj_port_vlan *vlan)
1593
{
V
Vivien Didelot 已提交
1594
	struct mv88e6xxx_chip *chip = ds->priv;
1595 1596
	int err;

1597
	if (!chip->info->max_vid)
1598 1599
		return -EOPNOTSUPP;

1600 1601 1602 1603 1604 1605 1606 1607
	/* 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.
	 */
	err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin,
					   vlan->vid_end);
	if (err)
		return err;

1608 1609 1610 1611 1612 1613
	/* We don't need any dynamic resource from the kernel (yet),
	 * so skip the prepare phase.
	 */
	return 0;
}

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
static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
					const unsigned char *addr, u16 vid,
					u8 state)
{
	struct mv88e6xxx_vtu_entry vlan;
	struct mv88e6xxx_atu_entry entry;
	int err;

	/* Null VLAN ID corresponds to the port private database */
	if (vid == 0)
		err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
	else
		err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
	if (err)
		return err;

	entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
	ether_addr_copy(entry.mac, addr);
	eth_addr_dec(entry.mac);

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

	/* Initialize a fresh ATU entry if it isn't found */
	if (entry.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ||
	    !ether_addr_equal(entry.mac, addr)) {
		memset(&entry, 0, sizeof(entry));
		ether_addr_copy(entry.mac, addr);
	}

	/* Purge the ATU entry only if no port is using it anymore */
	if (state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED) {
		entry.portvec &= ~BIT(port);
		if (!entry.portvec)
			entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
	} else {
		entry.portvec |= BIT(port);
		entry.state = state;
	}

	return mv88e6xxx_g1_atu_loadpurge(chip, vlan.fid, &entry);
}

1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
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;
}

1681
static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
1682
				    u16 vid, u8 member)
1683
{
1684
	struct mv88e6xxx_vtu_entry vlan;
1685 1686
	int err;

1687
	err = mv88e6xxx_vtu_get(chip, vid, &vlan, true);
1688
	if (err)
1689
		return err;
1690

1691
	vlan.member[port] = member;
1692

1693 1694 1695 1696 1697
	err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
	if (err)
		return err;

	return mv88e6xxx_broadcast_setup(chip, vid);
1698 1699
}

1700
static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
1701
				    const struct switchdev_obj_port_vlan *vlan)
1702
{
V
Vivien Didelot 已提交
1703
	struct mv88e6xxx_chip *chip = ds->priv;
1704 1705
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1706
	u8 member;
1707 1708
	u16 vid;

1709
	if (!chip->info->max_vid)
1710 1711
		return;

1712
	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
1713
		member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED;
1714
	else if (untagged)
1715
		member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED;
1716
	else
1717
		member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED;
1718

1719
	mutex_lock(&chip->reg_lock);
1720

1721
	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
1722
		if (_mv88e6xxx_port_vlan_add(chip, port, vid, member))
1723 1724
			dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
				vid, untagged ? 'u' : 't');
1725

1726
	if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
1727 1728
		dev_err(ds->dev, "p%d: failed to set PVID %d\n", port,
			vlan->vid_end);
1729

1730
	mutex_unlock(&chip->reg_lock);
1731 1732
}

1733
static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
1734
				    int port, u16 vid)
1735
{
1736
	struct mv88e6xxx_vtu_entry vlan;
1737 1738
	int i, err;

1739
	err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
1740
	if (err)
1741
		return err;
1742

1743
	/* Tell switchdev if this VLAN is handled in software */
1744
	if (vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1745
		return -EOPNOTSUPP;
1746

1747
	vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1748 1749

	/* keep the VLAN unless all ports are excluded */
1750
	vlan.valid = false;
1751
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1752 1753
		if (vlan.member[i] !=
		    MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
1754
			vlan.valid = true;
1755 1756 1757 1758
			break;
		}
	}

1759
	err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
1760 1761 1762
	if (err)
		return err;

1763
	return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
1764 1765
}

1766 1767
static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
				   const struct switchdev_obj_port_vlan *vlan)
1768
{
V
Vivien Didelot 已提交
1769
	struct mv88e6xxx_chip *chip = ds->priv;
1770 1771 1772
	u16 pvid, vid;
	int err = 0;

1773
	if (!chip->info->max_vid)
1774 1775
		return -EOPNOTSUPP;

1776
	mutex_lock(&chip->reg_lock);
1777

1778
	err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
1779 1780 1781
	if (err)
		goto unlock;

1782
	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
1783
		err = _mv88e6xxx_port_vlan_del(chip, port, vid);
1784 1785 1786 1787
		if (err)
			goto unlock;

		if (vid == pvid) {
1788
			err = mv88e6xxx_port_set_pvid(chip, port, 0);
1789 1790 1791 1792 1793
			if (err)
				goto unlock;
		}
	}

1794
unlock:
1795
	mutex_unlock(&chip->reg_lock);
1796 1797 1798 1799

	return err;
}

1800 1801
static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
				  const unsigned char *addr, u16 vid)
1802
{
V
Vivien Didelot 已提交
1803
	struct mv88e6xxx_chip *chip = ds->priv;
1804
	int err;
1805

1806
	mutex_lock(&chip->reg_lock);
1807 1808
	err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
					   MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
1809
	mutex_unlock(&chip->reg_lock);
1810 1811

	return err;
1812 1813
}

1814
static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1815
				  const unsigned char *addr, u16 vid)
1816
{
V
Vivien Didelot 已提交
1817
	struct mv88e6xxx_chip *chip = ds->priv;
1818
	int err;
1819

1820
	mutex_lock(&chip->reg_lock);
1821
	err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
1822
					   MV88E6XXX_G1_ATU_DATA_STATE_UNUSED);
1823
	mutex_unlock(&chip->reg_lock);
1824

1825
	return err;
1826 1827
}

1828 1829
static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
				      u16 fid, u16 vid, int port,
1830
				      dsa_fdb_dump_cb_t *cb, void *data)
1831
{
1832
	struct mv88e6xxx_atu_entry addr;
1833
	bool is_static;
1834 1835
	int err;

1836
	addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
1837
	eth_broadcast_addr(addr.mac);
1838 1839

	do {
1840
		mutex_lock(&chip->reg_lock);
1841
		err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
1842
		mutex_unlock(&chip->reg_lock);
1843
		if (err)
1844
			return err;
1845

1846
		if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED)
1847 1848
			break;

1849
		if (addr.trunk || (addr.portvec & BIT(port)) == 0)
1850 1851
			continue;

1852 1853
		if (!is_unicast_ether_addr(addr.mac))
			continue;
1854

1855 1856 1857
		is_static = (addr.state ==
			     MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
		err = cb(addr.mac, vid, is_static, data);
1858 1859
		if (err)
			return err;
1860 1861 1862 1863 1864
	} while (!is_broadcast_ether_addr(addr.mac));

	return err;
}

1865
static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1866
				  dsa_fdb_dump_cb_t *cb, void *data)
1867
{
1868
	struct mv88e6xxx_vtu_entry vlan = {
1869
		.vid = chip->info->max_vid,
1870
	};
1871
	u16 fid;
1872 1873
	int err;

1874
	/* Dump port's default Filtering Information Database (VLAN ID 0) */
1875
	mutex_lock(&chip->reg_lock);
1876
	err = mv88e6xxx_port_get_fid(chip, port, &fid);
1877 1878
	mutex_unlock(&chip->reg_lock);

1879
	if (err)
1880
		return err;
1881

1882
	err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data);
1883
	if (err)
1884
		return err;
1885

1886
	/* Dump VLANs' Filtering Information Databases */
1887
	do {
1888
		mutex_lock(&chip->reg_lock);
1889
		err = mv88e6xxx_vtu_getnext(chip, &vlan);
1890
		mutex_unlock(&chip->reg_lock);
1891
		if (err)
1892
			return err;
1893 1894 1895 1896

		if (!vlan.valid)
			break;

1897
		err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
1898
						 cb, data);
1899
		if (err)
1900
			return err;
1901
	} while (vlan.vid < chip->info->max_vid);
1902

1903 1904 1905 1906
	return err;
}

static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
1907
				   dsa_fdb_dump_cb_t *cb, void *data)
1908
{
V
Vivien Didelot 已提交
1909
	struct mv88e6xxx_chip *chip = ds->priv;
1910

1911
	return mv88e6xxx_port_db_dump(chip, port, cb, data);
1912 1913
}

1914 1915
static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
				struct net_device *br)
1916
{
1917
	struct dsa_switch *ds;
1918
	int port;
1919
	int dev;
1920
	int err;
1921

1922 1923 1924 1925
	/* Remap the Port VLAN of each local bridge group member */
	for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
		if (chip->ds->ports[port].bridge_dev == br) {
			err = mv88e6xxx_port_vlan_map(chip, port);
1926
			if (err)
1927
				return err;
1928 1929 1930
		}
	}

1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948
	if (!mv88e6xxx_has_pvt(chip))
		return 0;

	/* Remap the Port VLAN of each cross-chip bridge group member */
	for (dev = 0; dev < DSA_MAX_SWITCHES; ++dev) {
		ds = chip->ds->dst->ds[dev];
		if (!ds)
			break;

		for (port = 0; port < ds->num_ports; ++port) {
			if (ds->ports[port].bridge_dev == br) {
				err = mv88e6xxx_pvt_map(chip, dev, port);
				if (err)
					return err;
			}
		}
	}

1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959
	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;

	mutex_lock(&chip->reg_lock);
	err = mv88e6xxx_bridge_map(chip, br);
1960
	mutex_unlock(&chip->reg_lock);
1961

1962
	return err;
1963 1964
}

1965 1966
static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
					struct net_device *br)
1967
{
V
Vivien Didelot 已提交
1968
	struct mv88e6xxx_chip *chip = ds->priv;
1969

1970
	mutex_lock(&chip->reg_lock);
1971 1972 1973
	if (mv88e6xxx_bridge_map(chip, br) ||
	    mv88e6xxx_port_vlan_map(chip, port))
		dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
1974
	mutex_unlock(&chip->reg_lock);
1975 1976
}

1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
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;

	if (!mv88e6xxx_has_pvt(chip))
		return 0;

	mutex_lock(&chip->reg_lock);
	err = mv88e6xxx_pvt_map(chip, dev, port);
	mutex_unlock(&chip->reg_lock);

	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;

	if (!mv88e6xxx_has_pvt(chip))
		return;

	mutex_lock(&chip->reg_lock);
	if (mv88e6xxx_pvt_map(chip, dev, port))
		dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
	mutex_unlock(&chip->reg_lock);
}

2007 2008 2009 2010 2011 2012 2013 2014
static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
{
	if (chip->info->ops->reset)
		return chip->info->ops->reset(chip);

	return 0;
}

2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
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);
	}
}

2028
static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
2029
{
2030
	int i, err;
2031

2032
	/* Set all ports to the Disabled state */
2033
	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
2034
		err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED);
2035 2036
		if (err)
			return err;
2037 2038
	}

2039 2040 2041
	/* Wait for transmit queues to drain,
	 * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
	 */
2042 2043
	usleep_range(2000, 4000);

2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
	return 0;
}

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

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

2055
	mv88e6xxx_hardware_reset(chip);
2056

2057
	return mv88e6xxx_software_reset(chip);
2058 2059
}

2060
static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
2061 2062
				   enum mv88e6xxx_frame_mode frame,
				   enum mv88e6xxx_egress_mode egress, u16 etype)
2063 2064 2065
{
	int err;

2066 2067 2068 2069
	if (!chip->info->ops->port_set_frame_mode)
		return -EOPNOTSUPP;

	err = mv88e6xxx_port_set_egress_mode(chip, port, egress);
2070 2071 2072
	if (err)
		return err;

2073 2074 2075 2076 2077 2078 2079 2080
	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;
2081 2082
}

2083
static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port)
2084
{
2085
	return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
2086
				       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
2087
				       MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
2088
}
2089

2090 2091 2092
static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
2093
				       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
2094
				       MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
2095
}
2096

2097 2098 2099 2100
static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6xxx_set_port_mode(chip, port,
				       MV88E6XXX_FRAME_MODE_ETHERTYPE,
2101 2102
				       MV88E6XXX_EGRESS_MODE_ETHERTYPE,
				       ETH_P_EDSA);
2103
}
2104

2105 2106 2107 2108
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);
2109

2110
	if (dsa_is_user_port(chip->ds, port))
2111
		return mv88e6xxx_set_port_mode_normal(chip, port);
2112

2113 2114 2115
	/* 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);
2116

2117 2118
	if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA)
		return mv88e6xxx_set_port_mode_edsa(chip, port);
2119

2120
	return -EINVAL;
2121 2122
}

2123
static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
2124
{
2125
	bool message = dsa_is_dsa_port(chip->ds, port);
2126

2127
	return mv88e6xxx_port_set_message_port(chip, port, message);
2128
}
2129

2130
static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
2131
{
2132 2133
	struct dsa_switch *ds = chip->ds;
	bool flood;
2134

2135
	/* Upstream ports flood frames with unknown unicast or multicast DA */
2136
	flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port);
2137 2138 2139
	if (chip->info->ops->port_set_egress_floods)
		return chip->info->ops->port_set_egress_floods(chip, port,
							       flood, flood);
2140

2141
	return 0;
2142 2143
}

2144 2145 2146
static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
				  bool on)
{
2147 2148
	if (chip->info->ops->serdes_power)
		return chip->info->ops->serdes_power(chip, port, on);
2149

2150
	return 0;
2151 2152
}

2153 2154 2155 2156 2157 2158
static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
{
	struct dsa_switch *ds = chip->ds;
	int upstream_port;
	int err;

2159
	upstream_port = dsa_upstream_port(ds, port);
2160 2161 2162 2163 2164 2165 2166
	if (chip->info->ops->port_set_upstream_port) {
		err = chip->info->ops->port_set_upstream_port(chip, port,
							      upstream_port);
		if (err)
			return err;
	}

2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182
	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;
		}
	}

2183 2184 2185
	return 0;
}

2186
static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
2187
{
2188
	struct dsa_switch *ds = chip->ds;
2189
	int err;
2190
	u16 reg;
2191

2192 2193 2194
	chip->ports[port].chip = chip;
	chip->ports[port].port = port;

2195 2196 2197 2198 2199 2200 2201
	/* 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,
2202
					       PAUSE_OFF,
2203 2204 2205 2206
					       PHY_INTERFACE_MODE_NA);
	else
		err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
					       SPEED_UNFORCED, DUPLEX_UNFORCED,
2207
					       PAUSE_ON,
2208 2209 2210
					       PHY_INTERFACE_MODE_NA);
	if (err)
		return err;
2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225

	/* 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.
	 */
2226 2227 2228 2229
	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);
2230 2231
	if (err)
		return err;
2232

2233
	err = mv88e6xxx_setup_port_mode(chip, port);
2234 2235
	if (err)
		return err;
2236

2237
	err = mv88e6xxx_setup_egress_floods(chip, port);
2238 2239 2240
	if (err)
		return err;

2241 2242 2243
	/* Enable the SERDES interface for DSA and CPU ports. Normal
	 * ports SERDES are enabled when the port is enabled, thus
	 * saving a bit of power.
2244
	 */
2245 2246 2247 2248 2249
	if ((dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))) {
		err = mv88e6xxx_serdes_power(chip, port, true);
		if (err)
			return err;
	}
2250

2251
	/* Port Control 2: don't force a good FCS, set the maximum frame size to
2252
	 * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
2253 2254 2255
	 * 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.
2256
	 */
2257 2258 2259
	err = mv88e6xxx_port_set_map_da(chip, port);
	if (err)
		return err;
2260

2261 2262 2263
	err = mv88e6xxx_setup_upstream_port(chip, port);
	if (err)
		return err;
2264

2265
	err = mv88e6xxx_port_set_8021q_mode(chip, port,
2266
				MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED);
2267 2268 2269
	if (err)
		return err;

2270 2271
	if (chip->info->ops->port_set_jumbo_size) {
		err = chip->info->ops->port_set_jumbo_size(chip, port, 10240);
2272 2273 2274 2275
		if (err)
			return err;
	}

2276 2277 2278 2279 2280
	/* 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.
	 */
2281
	reg = 1 << port;
2282 2283
	/* Disable learning for CPU port */
	if (dsa_is_cpu_port(ds, port))
2284
		reg = 0;
2285

2286 2287
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
				   reg);
2288 2289
	if (err)
		return err;
2290 2291

	/* Egress rate control 2: disable egress rate control. */
2292 2293
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2,
				   0x0000);
2294 2295
	if (err)
		return err;
2296

2297 2298
	if (chip->info->ops->port_pause_limit) {
		err = chip->info->ops->port_pause_limit(chip, port, 0, 0);
2299 2300
		if (err)
			return err;
2301
	}
2302

2303 2304 2305 2306 2307 2308
	if (chip->info->ops->port_disable_learn_limit) {
		err = chip->info->ops->port_disable_learn_limit(chip, port);
		if (err)
			return err;
	}

2309 2310
	if (chip->info->ops->port_disable_pri_override) {
		err = chip->info->ops->port_disable_pri_override(chip, port);
2311 2312
		if (err)
			return err;
2313
	}
2314

2315 2316
	if (chip->info->ops->port_tag_remap) {
		err = chip->info->ops->port_tag_remap(chip, port);
2317 2318
		if (err)
			return err;
2319 2320
	}

2321 2322
	if (chip->info->ops->port_egress_rate_limiting) {
		err = chip->info->ops->port_egress_rate_limiting(chip, port);
2323 2324
		if (err)
			return err;
2325 2326
	}

2327
	err = mv88e6xxx_setup_message_port(chip, port);
2328 2329
	if (err)
		return err;
2330

2331
	/* Port based VLAN map: give each port the same default address
2332 2333
	 * database, and allow bidirectional communication between the
	 * CPU and DSA port(s), and the other ports.
2334
	 */
2335
	err = mv88e6xxx_port_set_fid(chip, port, 0);
2336 2337
	if (err)
		return err;
2338

2339
	err = mv88e6xxx_port_vlan_map(chip, port);
2340 2341
	if (err)
		return err;
2342 2343 2344 2345

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

2349 2350 2351 2352
static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
				 struct phy_device *phydev)
{
	struct mv88e6xxx_chip *chip = ds->priv;
2353
	int err;
2354 2355

	mutex_lock(&chip->reg_lock);
2356

2357
	err = mv88e6xxx_serdes_power(chip, port, true);
2358 2359 2360 2361

	if (!err && chip->info->ops->serdes_irq_setup)
		err = chip->info->ops->serdes_irq_setup(chip, port);

2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
	mutex_unlock(&chip->reg_lock);

	return err;
}

static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port,
				   struct phy_device *phydev)
{
	struct mv88e6xxx_chip *chip = ds->priv;

	mutex_lock(&chip->reg_lock);
2373 2374 2375 2376

	if (chip->info->ops->serdes_irq_free)
		chip->info->ops->serdes_irq_free(chip, port);

2377 2378
	if (mv88e6xxx_serdes_power(chip, port, false))
		dev_err(chip->dev, "failed to power off SERDES\n");
2379

2380 2381 2382
	mutex_unlock(&chip->reg_lock);
}

2383 2384 2385
static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds,
				     unsigned int ageing_time)
{
V
Vivien Didelot 已提交
2386
	struct mv88e6xxx_chip *chip = ds->priv;
2387 2388 2389
	int err;

	mutex_lock(&chip->reg_lock);
2390
	err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time);
2391 2392 2393 2394 2395
	mutex_unlock(&chip->reg_lock);

	return err;
}

2396
static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
2397
{
2398
	int err;
2399

2400
	/* Initialize the statistics unit */
2401 2402 2403 2404 2405
	if (chip->info->ops->stats_set_histogram) {
		err = chip->info->ops->stats_set_histogram(chip);
		if (err)
			return err;
	}
2406

2407
	return mv88e6xxx_g1_stats_clear(chip);
2408 2409
}

2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
/* The mv88e6390 has some hidden registers used for debug and
 * development. The errata also makes use of them.
 */
static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
				  int reg, u16 val)
{
	u16 ctrl;
	int err;

	err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
				   PORT_RESERVED_1A, val);
	if (err)
		return err;

	ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
	       PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
	       reg;

	return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
				    PORT_RESERVED_1A, ctrl);
}

static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
			      PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
}


static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
				  int reg, u16 *val)
{
	u16 ctrl;
	int err;

	ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
	       PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
	       reg;

	err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
				   PORT_RESERVED_1A, ctrl);
	if (err)
		return err;

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

	return 	mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
				    PORT_RESERVED_1A, val);
}

/* 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++) {
		err = mv88e6390_hidden_read(chip, port, 0, &val);
		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++) {
		err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
		if (err)
			return err;
	}

	return mv88e6xxx_software_reset(chip);
}

2511
static int mv88e6xxx_setup(struct dsa_switch *ds)
2512
{
V
Vivien Didelot 已提交
2513
	struct mv88e6xxx_chip *chip = ds->priv;
2514
	u8 cmode;
2515
	int err;
2516 2517
	int i;

2518
	chip->ds = ds;
2519
	ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
2520

2521
	mutex_lock(&chip->reg_lock);
2522

2523 2524 2525 2526 2527 2528
	if (chip->info->ops->setup_errata) {
		err = chip->info->ops->setup_errata(chip);
		if (err)
			goto unlock;
	}

2529 2530 2531 2532 2533
	/* 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)
2534
				goto unlock;
2535 2536 2537 2538 2539

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

2540
	/* Setup Switch Port Registers */
2541
	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
2542 2543 2544
		if (dsa_is_unused_port(ds, i))
			continue;

2545 2546 2547 2548 2549
		err = mv88e6xxx_setup_port(chip, i);
		if (err)
			goto unlock;
	}

2550 2551 2552 2553
	err = mv88e6xxx_irl_setup(chip);
	if (err)
		goto unlock;

2554 2555 2556 2557
	err = mv88e6xxx_mac_setup(chip);
	if (err)
		goto unlock;

2558 2559 2560 2561
	err = mv88e6xxx_phy_setup(chip);
	if (err)
		goto unlock;

2562 2563 2564 2565
	err = mv88e6xxx_vtu_setup(chip);
	if (err)
		goto unlock;

2566 2567 2568 2569
	err = mv88e6xxx_pvt_setup(chip);
	if (err)
		goto unlock;

2570 2571 2572 2573
	err = mv88e6xxx_atu_setup(chip);
	if (err)
		goto unlock;

2574 2575 2576 2577
	err = mv88e6xxx_broadcast_setup(chip, 0);
	if (err)
		goto unlock;

2578 2579 2580 2581
	err = mv88e6xxx_pot_setup(chip);
	if (err)
		goto unlock;

2582 2583 2584 2585
	err = mv88e6xxx_rmu_setup(chip);
	if (err)
		goto unlock;

2586 2587 2588
	err = mv88e6xxx_rsvd2cpu_setup(chip);
	if (err)
		goto unlock;
2589

2590 2591 2592 2593
	err = mv88e6xxx_trunk_setup(chip);
	if (err)
		goto unlock;

2594 2595 2596 2597
	err = mv88e6xxx_devmap_setup(chip);
	if (err)
		goto unlock;

2598 2599 2600 2601
	err = mv88e6xxx_pri_setup(chip);
	if (err)
		goto unlock;

2602
	/* Setup PTP Hardware Clock and timestamping */
2603 2604 2605 2606
	if (chip->info->ptp_support) {
		err = mv88e6xxx_ptp_setup(chip);
		if (err)
			goto unlock;
2607 2608 2609 2610

		err = mv88e6xxx_hwtstamp_setup(chip);
		if (err)
			goto unlock;
2611 2612
	}

2613 2614 2615 2616
	err = mv88e6xxx_stats_setup(chip);
	if (err)
		goto unlock;

2617
unlock:
2618
	mutex_unlock(&chip->reg_lock);
2619

2620
	return err;
2621 2622
}

2623
static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
2624
{
2625 2626
	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
	struct mv88e6xxx_chip *chip = mdio_bus->chip;
2627 2628
	u16 val;
	int err;
2629

2630 2631 2632
	if (!chip->info->ops->phy_read)
		return -EOPNOTSUPP;

2633
	mutex_lock(&chip->reg_lock);
2634
	err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
2635
	mutex_unlock(&chip->reg_lock);
2636

2637 2638 2639 2640 2641
	if (reg == MII_PHYSID2) {
		/* Some internal PHYS don't have a model number.  Use
		 * the mv88e6390 family model number instead.
		 */
		if (!(val & 0x3f0))
2642
			val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
2643 2644
	}

2645
	return err ? err : val;
2646 2647
}

2648
static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
2649
{
2650 2651
	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
	struct mv88e6xxx_chip *chip = mdio_bus->chip;
2652
	int err;
2653

2654 2655 2656
	if (!chip->info->ops->phy_write)
		return -EOPNOTSUPP;

2657
	mutex_lock(&chip->reg_lock);
2658
	err = chip->info->ops->phy_write(chip, bus, phy, reg, val);
2659
	mutex_unlock(&chip->reg_lock);
2660 2661

	return err;
2662 2663
}

2664
static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
2665 2666
				   struct device_node *np,
				   bool external)
2667 2668
{
	static int index;
2669
	struct mv88e6xxx_mdio_bus *mdio_bus;
2670 2671 2672
	struct mii_bus *bus;
	int err;

2673 2674 2675 2676 2677 2678 2679 2680 2681
	if (external) {
		mutex_lock(&chip->reg_lock);
		err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true);
		mutex_unlock(&chip->reg_lock);

		if (err)
			return err;
	}

2682
	bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus));
2683 2684 2685
	if (!bus)
		return -ENOMEM;

2686
	mdio_bus = bus->priv;
2687
	mdio_bus->bus = bus;
2688
	mdio_bus->chip = chip;
2689 2690
	INIT_LIST_HEAD(&mdio_bus->list);
	mdio_bus->external = external;
2691

2692 2693
	if (np) {
		bus->name = np->full_name;
2694
		snprintf(bus->id, MII_BUS_ID_SIZE, "%pOF", np);
2695 2696 2697 2698 2699 2700 2701
	} 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;
2702
	bus->parent = chip->dev;
2703

2704 2705 2706 2707 2708 2709
	if (!external) {
		err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
		if (err)
			return err;
	}

2710
	err = of_mdiobus_register(bus, np);
2711
	if (err) {
2712
		dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
2713
		mv88e6xxx_g2_irq_mdio_free(chip, bus);
2714
		return err;
2715
	}
2716 2717 2718 2719 2720

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

	return 0;
2723
}
2724

2725 2726 2727 2728 2729
static const struct of_device_id mv88e6xxx_mdio_external_match[] = {
	{ .compatible = "marvell,mv88e6xxx-mdio-external",
	  .data = (void *)true },
	{ },
};
2730

2731 2732 2733 2734 2735 2736 2737 2738 2739
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;

2740 2741 2742
		if (!mdio_bus->external)
			mv88e6xxx_g2_irq_mdio_free(chip, bus);

2743 2744 2745 2746
		mdiobus_unregister(bus);
	}
}

2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770
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);
2771 2772
			if (err) {
				mv88e6xxx_mdios_unregister(chip);
2773
				return err;
2774
			}
2775 2776 2777 2778
		}
	}

	return 0;
2779 2780
}

2781 2782
static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
{
V
Vivien Didelot 已提交
2783
	struct mv88e6xxx_chip *chip = ds->priv;
2784 2785 2786 2787 2788 2789 2790

	return chip->eeprom_len;
}

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

2794 2795
	if (!chip->info->ops->get_eeprom)
		return -EOPNOTSUPP;
2796

2797 2798
	mutex_lock(&chip->reg_lock);
	err = chip->info->ops->get_eeprom(chip, eeprom, data);
2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811
	mutex_unlock(&chip->reg_lock);

	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 已提交
2812
	struct mv88e6xxx_chip *chip = ds->priv;
2813 2814
	int err;

2815 2816 2817
	if (!chip->info->ops->set_eeprom)
		return -EOPNOTSUPP;

2818 2819 2820 2821
	if (eeprom->magic != 0xc3ec4951)
		return -EINVAL;

	mutex_lock(&chip->reg_lock);
2822
	err = chip->info->ops->set_eeprom(chip, eeprom, data);
2823 2824 2825 2826 2827
	mutex_unlock(&chip->reg_lock);

	return err;
}

2828
static const struct mv88e6xxx_ops mv88e6085_ops = {
2829
	/* MV88E6XXX_FAMILY_6097 */
2830 2831
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
2832
	.irl_init_all = mv88e6352_g2_irl_init_all,
2833
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2834 2835
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
2836
	.port_set_link = mv88e6xxx_port_set_link,
2837
	.port_set_duplex = mv88e6xxx_port_set_duplex,
2838
	.port_set_speed = mv88e6185_port_set_speed,
2839
	.port_tag_remap = mv88e6095_port_tag_remap,
2840
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
2841
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
2842
	.port_set_ether_type = mv88e6351_port_set_ether_type,
2843
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2844
	.port_pause_limit = mv88e6097_port_pause_limit,
2845
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2846
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2847
	.port_link_state = mv88e6352_port_link_state,
2848
	.port_get_cmode = mv88e6185_port_get_cmode,
2849
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2850
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2851 2852
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
2853
	.stats_get_stats = mv88e6095_stats_get_stats,
2854 2855
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
2856
	.watchdog_ops = &mv88e6097_watchdog_ops,
2857
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2858
	.pot_clear = mv88e6xxx_g2_pot_clear,
2859 2860
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
2861
	.reset = mv88e6185_g1_reset,
2862
	.rmu_disable = mv88e6085_g1_rmu_disable,
2863
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
2864
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2865
	.phylink_validate = mv88e6185_phylink_validate,
2866 2867 2868
};

static const struct mv88e6xxx_ops mv88e6095_ops = {
2869
	/* MV88E6XXX_FAMILY_6095 */
2870 2871
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
2872
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2873 2874
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
2875
	.port_set_link = mv88e6xxx_port_set_link,
2876
	.port_set_duplex = mv88e6xxx_port_set_duplex,
2877
	.port_set_speed = mv88e6185_port_set_speed,
2878
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
2879
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
2880
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
2881
	.port_link_state = mv88e6185_port_link_state,
2882
	.port_get_cmode = mv88e6185_port_get_cmode,
2883
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2884
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2885 2886
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
2887
	.stats_get_stats = mv88e6095_stats_get_stats,
2888
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
2889 2890
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
2891
	.reset = mv88e6185_g1_reset,
2892
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
2893
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
2894
	.phylink_validate = mv88e6185_phylink_validate,
2895 2896
};

2897
static const struct mv88e6xxx_ops mv88e6097_ops = {
2898
	/* MV88E6XXX_FAMILY_6097 */
2899 2900
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
2901
	.irl_init_all = mv88e6352_g2_irl_init_all,
2902 2903 2904 2905 2906 2907
	.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,
2908
	.port_tag_remap = mv88e6095_port_tag_remap,
2909
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
2910
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
2911
	.port_set_ether_type = mv88e6351_port_set_ether_type,
2912
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2913
	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
2914
	.port_pause_limit = mv88e6097_port_pause_limit,
2915
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2916
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2917
	.port_link_state = mv88e6352_port_link_state,
2918
	.port_get_cmode = mv88e6185_port_get_cmode,
2919
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2920
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2921 2922 2923
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
	.stats_get_stats = mv88e6095_stats_get_stats,
2924 2925
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
2926
	.watchdog_ops = &mv88e6097_watchdog_ops,
2927
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2928
	.pot_clear = mv88e6xxx_g2_pot_clear,
2929
	.reset = mv88e6352_g1_reset,
2930
	.rmu_disable = mv88e6085_g1_rmu_disable,
2931
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
2932
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2933
	.phylink_validate = mv88e6185_phylink_validate,
2934 2935
};

2936
static const struct mv88e6xxx_ops mv88e6123_ops = {
2937
	/* MV88E6XXX_FAMILY_6165 */
2938 2939
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
2940
	.irl_init_all = mv88e6352_g2_irl_init_all,
2941
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2942 2943
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
2944
	.port_set_link = mv88e6xxx_port_set_link,
2945
	.port_set_duplex = mv88e6xxx_port_set_duplex,
2946
	.port_set_speed = mv88e6185_port_set_speed,
2947
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
2948
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
2949
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2950
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2951
	.port_link_state = mv88e6352_port_link_state,
2952
	.port_get_cmode = mv88e6185_port_get_cmode,
2953
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
2954
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2955 2956
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
2957
	.stats_get_stats = mv88e6095_stats_get_stats,
2958 2959
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
2960
	.watchdog_ops = &mv88e6097_watchdog_ops,
2961
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2962
	.pot_clear = mv88e6xxx_g2_pot_clear,
2963
	.reset = mv88e6352_g1_reset,
2964
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
2965
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2966
	.phylink_validate = mv88e6185_phylink_validate,
2967 2968 2969
};

static const struct mv88e6xxx_ops mv88e6131_ops = {
2970
	/* MV88E6XXX_FAMILY_6185 */
2971 2972
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
2973
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2974 2975
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
2976
	.port_set_link = mv88e6xxx_port_set_link,
2977
	.port_set_duplex = mv88e6xxx_port_set_duplex,
2978
	.port_set_speed = mv88e6185_port_set_speed,
2979
	.port_tag_remap = mv88e6095_port_tag_remap,
2980
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
2981
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
2982
	.port_set_ether_type = mv88e6351_port_set_ether_type,
2983
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
2984
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2985
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2986
	.port_pause_limit = mv88e6097_port_pause_limit,
2987
	.port_set_pause = mv88e6185_port_set_pause,
2988
	.port_link_state = mv88e6352_port_link_state,
2989
	.port_get_cmode = mv88e6185_port_get_cmode,
2990
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2991
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2992 2993
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
2994
	.stats_get_stats = mv88e6095_stats_get_stats,
2995 2996
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
2997
	.watchdog_ops = &mv88e6097_watchdog_ops,
2998
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
2999
	.ppu_enable = mv88e6185_g1_ppu_enable,
3000
	.set_cascade_port = mv88e6185_g1_set_cascade_port,
3001
	.ppu_disable = mv88e6185_g1_ppu_disable,
3002
	.reset = mv88e6185_g1_reset,
3003
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3004
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3005
	.phylink_validate = mv88e6185_phylink_validate,
3006 3007
};

3008 3009
static const struct mv88e6xxx_ops mv88e6141_ops = {
	/* MV88E6XXX_FAMILY_6341 */
3010 3011
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3012
	.irl_init_all = mv88e6352_g2_irl_init_all,
3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
	.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,
	.port_set_speed = mv88e6390_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,
3026
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3027
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3028
	.port_pause_limit = mv88e6097_port_pause_limit,
3029 3030
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3031
	.port_link_state = mv88e6352_port_link_state,
3032
	.port_get_cmode = mv88e6352_port_get_cmode,
3033
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3034
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3035 3036 3037
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
	.stats_get_stats = mv88e6390_stats_get_stats,
3038 3039
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3040 3041
	.watchdog_ops = &mv88e6390_watchdog_ops,
	.mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
3042
	.pot_clear = mv88e6xxx_g2_pot_clear,
3043
	.reset = mv88e6352_g1_reset,
3044
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3045
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3046
	.serdes_power = mv88e6341_serdes_power,
3047
	.gpio_ops = &mv88e6352_gpio_ops,
3048
	.phylink_validate = mv88e6390_phylink_validate,
3049 3050
};

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

static const struct mv88e6xxx_ops mv88e6165_ops = {
3092
	/* MV88E6XXX_FAMILY_6165 */
3093 3094
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3095
	.irl_init_all = mv88e6352_g2_irl_init_all,
3096
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3097 3098
	.phy_read = mv88e6165_phy_read,
	.phy_write = mv88e6165_phy_write,
3099
	.port_set_link = mv88e6xxx_port_set_link,
3100
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3101
	.port_set_speed = mv88e6185_port_set_speed,
3102
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3103
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3104
	.port_link_state = mv88e6352_port_link_state,
3105
	.port_get_cmode = mv88e6185_port_get_cmode,
3106
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3107
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3108 3109
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3110
	.stats_get_stats = mv88e6095_stats_get_stats,
3111 3112
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3113
	.watchdog_ops = &mv88e6097_watchdog_ops,
3114
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3115
	.pot_clear = mv88e6xxx_g2_pot_clear,
3116
	.reset = mv88e6352_g1_reset,
3117
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3118
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3119
	.avb_ops = &mv88e6165_avb_ops,
3120
	.ptp_ops = &mv88e6165_ptp_ops,
3121
	.phylink_validate = mv88e6185_phylink_validate,
3122 3123 3124
};

static const struct mv88e6xxx_ops mv88e6171_ops = {
3125
	/* MV88E6XXX_FAMILY_6351 */
3126 3127
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3128
	.irl_init_all = mv88e6352_g2_irl_init_all,
3129
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3130 3131
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3132
	.port_set_link = mv88e6xxx_port_set_link,
3133
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3134
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3135
	.port_set_speed = mv88e6185_port_set_speed,
3136
	.port_tag_remap = mv88e6095_port_tag_remap,
3137
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3138
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3139
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3140
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3141
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3142
	.port_pause_limit = mv88e6097_port_pause_limit,
3143
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3144
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3145
	.port_link_state = mv88e6352_port_link_state,
3146
	.port_get_cmode = mv88e6352_port_get_cmode,
3147
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3148
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3149 3150
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3151
	.stats_get_stats = mv88e6095_stats_get_stats,
3152 3153
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3154
	.watchdog_ops = &mv88e6097_watchdog_ops,
3155
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3156
	.pot_clear = mv88e6xxx_g2_pot_clear,
3157
	.reset = mv88e6352_g1_reset,
3158
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3159
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3160
	.phylink_validate = mv88e6185_phylink_validate,
3161 3162 3163
};

static const struct mv88e6xxx_ops mv88e6172_ops = {
3164
	/* MV88E6XXX_FAMILY_6352 */
3165 3166
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3167
	.irl_init_all = mv88e6352_g2_irl_init_all,
3168 3169
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3170
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3171 3172
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3173
	.port_set_link = mv88e6xxx_port_set_link,
3174
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3175
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3176
	.port_set_speed = mv88e6352_port_set_speed,
3177
	.port_tag_remap = mv88e6095_port_tag_remap,
3178
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3179
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3180
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3181
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3182
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3183
	.port_pause_limit = mv88e6097_port_pause_limit,
3184
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3185
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3186
	.port_link_state = mv88e6352_port_link_state,
3187
	.port_get_cmode = mv88e6352_port_get_cmode,
3188
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3189
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3190 3191
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3192
	.stats_get_stats = mv88e6095_stats_get_stats,
3193 3194
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3195
	.watchdog_ops = &mv88e6097_watchdog_ops,
3196
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3197
	.pot_clear = mv88e6xxx_g2_pot_clear,
3198
	.reset = mv88e6352_g1_reset,
3199
	.rmu_disable = mv88e6352_g1_rmu_disable,
3200
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3201
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3202
	.serdes_power = mv88e6352_serdes_power,
3203
	.gpio_ops = &mv88e6352_gpio_ops,
3204
	.phylink_validate = mv88e6352_phylink_validate,
3205 3206 3207
};

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

static const struct mv88e6xxx_ops mv88e6176_ops = {
3247
	/* MV88E6XXX_FAMILY_6352 */
3248 3249
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3250
	.irl_init_all = mv88e6352_g2_irl_init_all,
3251 3252
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3253
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3254 3255
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3256
	.port_set_link = mv88e6xxx_port_set_link,
3257
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3258
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3259
	.port_set_speed = mv88e6352_port_set_speed,
3260
	.port_tag_remap = mv88e6095_port_tag_remap,
3261
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3262
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3263
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3264
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3265
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3266
	.port_pause_limit = mv88e6097_port_pause_limit,
3267
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3268
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3269
	.port_link_state = mv88e6352_port_link_state,
3270
	.port_get_cmode = mv88e6352_port_get_cmode,
3271
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3272
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3273 3274
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3275
	.stats_get_stats = mv88e6095_stats_get_stats,
3276 3277
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3278
	.watchdog_ops = &mv88e6097_watchdog_ops,
3279
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3280
	.pot_clear = mv88e6xxx_g2_pot_clear,
3281
	.reset = mv88e6352_g1_reset,
3282
	.rmu_disable = mv88e6352_g1_rmu_disable,
3283
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3284
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3285
	.serdes_power = mv88e6352_serdes_power,
3286
	.gpio_ops = &mv88e6352_gpio_ops,
3287
	.phylink_validate = mv88e6352_phylink_validate,
3288 3289 3290
};

static const struct mv88e6xxx_ops mv88e6185_ops = {
3291
	/* MV88E6XXX_FAMILY_6185 */
3292 3293
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3294
	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3295 3296
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
3297
	.port_set_link = mv88e6xxx_port_set_link,
3298
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3299
	.port_set_speed = mv88e6185_port_set_speed,
3300
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
3301
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
3302
	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
3303
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
3304
	.port_set_pause = mv88e6185_port_set_pause,
3305
	.port_link_state = mv88e6185_port_link_state,
3306
	.port_get_cmode = mv88e6185_port_get_cmode,
3307
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3308
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3309 3310
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3311
	.stats_get_stats = mv88e6095_stats_get_stats,
3312 3313
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3314
	.watchdog_ops = &mv88e6097_watchdog_ops,
3315
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
3316
	.set_cascade_port = mv88e6185_g1_set_cascade_port,
3317 3318
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
3319
	.reset = mv88e6185_g1_reset,
3320
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3321
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3322
	.phylink_validate = mv88e6185_phylink_validate,
3323 3324
};

3325
static const struct mv88e6xxx_ops mv88e6190_ops = {
3326
	/* MV88E6XXX_FAMILY_6390 */
3327
	.setup_errata = mv88e6390_setup_errata,
3328
	.irl_init_all = mv88e6390_g2_irl_init_all,
3329 3330
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3331 3332 3333 3334 3335 3336 3337
	.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,
3338
	.port_tag_remap = mv88e6390_port_tag_remap,
3339
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3340
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3341
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3342
	.port_pause_limit = mv88e6390_port_pause_limit,
3343
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3344
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3345
	.port_link_state = mv88e6352_port_link_state,
3346
	.port_get_cmode = mv88e6352_port_get_cmode,
3347
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3348
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3349 3350
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3351
	.stats_get_stats = mv88e6390_stats_get_stats,
3352 3353
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3354
	.watchdog_ops = &mv88e6390_watchdog_ops,
3355
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3356
	.pot_clear = mv88e6xxx_g2_pot_clear,
3357
	.reset = mv88e6352_g1_reset,
3358
	.rmu_disable = mv88e6390_g1_rmu_disable,
3359 3360
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3361
	.serdes_power = mv88e6390_serdes_power,
3362 3363
	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
	.serdes_irq_free = mv88e6390_serdes_irq_free,
3364
	.gpio_ops = &mv88e6352_gpio_ops,
3365
	.phylink_validate = mv88e6390_phylink_validate,
3366 3367 3368
};

static const struct mv88e6xxx_ops mv88e6190x_ops = {
3369
	/* MV88E6XXX_FAMILY_6390 */
3370
	.setup_errata = mv88e6390_setup_errata,
3371
	.irl_init_all = mv88e6390_g2_irl_init_all,
3372 3373
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3374 3375 3376 3377 3378 3379 3380
	.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,
3381
	.port_tag_remap = mv88e6390_port_tag_remap,
3382
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3383
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3384
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3385
	.port_pause_limit = mv88e6390_port_pause_limit,
3386
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3387
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3388
	.port_link_state = mv88e6352_port_link_state,
3389
	.port_get_cmode = mv88e6352_port_get_cmode,
3390
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3391
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3392 3393
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3394
	.stats_get_stats = mv88e6390_stats_get_stats,
3395 3396
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3397
	.watchdog_ops = &mv88e6390_watchdog_ops,
3398
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3399
	.pot_clear = mv88e6xxx_g2_pot_clear,
3400
	.reset = mv88e6352_g1_reset,
3401
	.rmu_disable = mv88e6390_g1_rmu_disable,
3402 3403
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3404
	.serdes_power = mv88e6390x_serdes_power,
3405 3406
	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
	.serdes_irq_free = mv88e6390_serdes_irq_free,
3407
	.gpio_ops = &mv88e6352_gpio_ops,
3408
	.phylink_validate = mv88e6390x_phylink_validate,
3409 3410 3411
};

static const struct mv88e6xxx_ops mv88e6191_ops = {
3412
	/* MV88E6XXX_FAMILY_6390 */
3413
	.setup_errata = mv88e6390_setup_errata,
3414
	.irl_init_all = mv88e6390_g2_irl_init_all,
3415 3416
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3417 3418 3419 3420 3421 3422 3423
	.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,
3424
	.port_tag_remap = mv88e6390_port_tag_remap,
3425
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3426
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3427
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3428
	.port_pause_limit = mv88e6390_port_pause_limit,
3429
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3430
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3431
	.port_link_state = mv88e6352_port_link_state,
3432
	.port_get_cmode = mv88e6352_port_get_cmode,
3433
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3434
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3435 3436
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3437
	.stats_get_stats = mv88e6390_stats_get_stats,
3438 3439
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3440
	.watchdog_ops = &mv88e6390_watchdog_ops,
3441
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3442
	.pot_clear = mv88e6xxx_g2_pot_clear,
3443
	.reset = mv88e6352_g1_reset,
3444
	.rmu_disable = mv88e6390_g1_rmu_disable,
3445 3446
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3447
	.serdes_power = mv88e6390_serdes_power,
3448 3449
	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
	.serdes_irq_free = mv88e6390_serdes_irq_free,
3450 3451
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
3452
	.phylink_validate = mv88e6390_phylink_validate,
3453 3454
};

3455
static const struct mv88e6xxx_ops mv88e6240_ops = {
3456
	/* MV88E6XXX_FAMILY_6352 */
3457 3458
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3459
	.irl_init_all = mv88e6352_g2_irl_init_all,
3460 3461
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3462
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3463 3464
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3465
	.port_set_link = mv88e6xxx_port_set_link,
3466
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3467
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3468
	.port_set_speed = mv88e6352_port_set_speed,
3469
	.port_tag_remap = mv88e6095_port_tag_remap,
3470
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3471
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3472
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3473
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3474
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3475
	.port_pause_limit = mv88e6097_port_pause_limit,
3476
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3477
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3478
	.port_link_state = mv88e6352_port_link_state,
3479
	.port_get_cmode = mv88e6352_port_get_cmode,
3480
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3481
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3482 3483
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3484
	.stats_get_stats = mv88e6095_stats_get_stats,
3485 3486
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3487
	.watchdog_ops = &mv88e6097_watchdog_ops,
3488
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3489
	.pot_clear = mv88e6xxx_g2_pot_clear,
3490
	.reset = mv88e6352_g1_reset,
3491
	.rmu_disable = mv88e6352_g1_rmu_disable,
3492
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3493
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3494
	.serdes_power = mv88e6352_serdes_power,
3495
	.gpio_ops = &mv88e6352_gpio_ops,
3496
	.avb_ops = &mv88e6352_avb_ops,
3497
	.ptp_ops = &mv88e6352_ptp_ops,
3498
	.phylink_validate = mv88e6352_phylink_validate,
3499 3500
};

3501
static const struct mv88e6xxx_ops mv88e6290_ops = {
3502
	/* MV88E6XXX_FAMILY_6390 */
3503
	.setup_errata = mv88e6390_setup_errata,
3504
	.irl_init_all = mv88e6390_g2_irl_init_all,
3505 3506
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3507 3508 3509 3510 3511 3512 3513
	.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,
3514
	.port_tag_remap = mv88e6390_port_tag_remap,
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_set_cmode = mv88e6390x_port_set_cmode,
3520
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3521
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3522
	.port_link_state = mv88e6352_port_link_state,
3523
	.port_get_cmode = mv88e6352_port_get_cmode,
3524
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3525
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3526 3527
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3528
	.stats_get_stats = mv88e6390_stats_get_stats,
3529 3530
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3531
	.watchdog_ops = &mv88e6390_watchdog_ops,
3532
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3533
	.pot_clear = mv88e6xxx_g2_pot_clear,
3534
	.reset = mv88e6352_g1_reset,
3535
	.rmu_disable = mv88e6390_g1_rmu_disable,
3536 3537
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3538
	.serdes_power = mv88e6390_serdes_power,
3539 3540
	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
	.serdes_irq_free = mv88e6390_serdes_irq_free,
3541
	.gpio_ops = &mv88e6352_gpio_ops,
3542
	.avb_ops = &mv88e6390_avb_ops,
3543
	.ptp_ops = &mv88e6352_ptp_ops,
3544
	.phylink_validate = mv88e6390_phylink_validate,
3545 3546
};

3547
static const struct mv88e6xxx_ops mv88e6320_ops = {
3548
	/* MV88E6XXX_FAMILY_6320 */
3549 3550
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3551
	.irl_init_all = mv88e6352_g2_irl_init_all,
3552 3553
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3554
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3555 3556
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3557
	.port_set_link = mv88e6xxx_port_set_link,
3558
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3559
	.port_set_speed = mv88e6185_port_set_speed,
3560
	.port_tag_remap = mv88e6095_port_tag_remap,
3561
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3562
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3563
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3564
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3565
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3566
	.port_pause_limit = mv88e6097_port_pause_limit,
3567
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3568
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3569
	.port_link_state = mv88e6352_port_link_state,
3570
	.port_get_cmode = mv88e6352_port_get_cmode,
3571
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3572
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3573 3574
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3575
	.stats_get_stats = mv88e6320_stats_get_stats,
3576 3577
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3578
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3579
	.pot_clear = mv88e6xxx_g2_pot_clear,
3580
	.reset = mv88e6352_g1_reset,
3581
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3582
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3583
	.gpio_ops = &mv88e6352_gpio_ops,
3584
	.avb_ops = &mv88e6352_avb_ops,
3585
	.ptp_ops = &mv88e6352_ptp_ops,
3586
	.phylink_validate = mv88e6185_phylink_validate,
3587 3588 3589
};

static const struct mv88e6xxx_ops mv88e6321_ops = {
3590
	/* MV88E6XXX_FAMILY_6320 */
3591 3592
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3593
	.irl_init_all = mv88e6352_g2_irl_init_all,
3594 3595
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3596
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3597 3598
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3599
	.port_set_link = mv88e6xxx_port_set_link,
3600
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3601
	.port_set_speed = mv88e6185_port_set_speed,
3602
	.port_tag_remap = mv88e6095_port_tag_remap,
3603
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3604
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3605
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3606
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3607
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3608
	.port_pause_limit = mv88e6097_port_pause_limit,
3609
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3610
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3611
	.port_link_state = mv88e6352_port_link_state,
3612
	.port_get_cmode = mv88e6352_port_get_cmode,
3613
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3614
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3615 3616
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3617
	.stats_get_stats = mv88e6320_stats_get_stats,
3618 3619
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3620
	.reset = mv88e6352_g1_reset,
3621
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
3622
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3623
	.gpio_ops = &mv88e6352_gpio_ops,
3624
	.avb_ops = &mv88e6352_avb_ops,
3625
	.ptp_ops = &mv88e6352_ptp_ops,
3626
	.phylink_validate = mv88e6185_phylink_validate,
3627 3628
};

3629 3630
static const struct mv88e6xxx_ops mv88e6341_ops = {
	/* MV88E6XXX_FAMILY_6341 */
3631 3632
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3633
	.irl_init_all = mv88e6352_g2_irl_init_all,
3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646
	.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,
	.port_set_speed = mv88e6390_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,
3647
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3648
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3649
	.port_pause_limit = mv88e6097_port_pause_limit,
3650 3651
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3652
	.port_link_state = mv88e6352_port_link_state,
3653
	.port_get_cmode = mv88e6352_port_get_cmode,
3654
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3655
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3656 3657 3658
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
	.stats_get_stats = mv88e6390_stats_get_stats,
3659 3660
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3661 3662
	.watchdog_ops = &mv88e6390_watchdog_ops,
	.mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
3663
	.pot_clear = mv88e6xxx_g2_pot_clear,
3664
	.reset = mv88e6352_g1_reset,
3665
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3666
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3667
	.serdes_power = mv88e6341_serdes_power,
3668
	.gpio_ops = &mv88e6352_gpio_ops,
3669
	.avb_ops = &mv88e6390_avb_ops,
3670
	.ptp_ops = &mv88e6352_ptp_ops,
3671
	.phylink_validate = mv88e6390_phylink_validate,
3672 3673
};

3674
static const struct mv88e6xxx_ops mv88e6350_ops = {
3675
	/* MV88E6XXX_FAMILY_6351 */
3676 3677
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3678
	.irl_init_all = mv88e6352_g2_irl_init_all,
3679
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3680 3681
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3682
	.port_set_link = mv88e6xxx_port_set_link,
3683
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3684
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3685
	.port_set_speed = mv88e6185_port_set_speed,
3686
	.port_tag_remap = mv88e6095_port_tag_remap,
3687
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3688
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3689
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3690
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3691
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3692
	.port_pause_limit = mv88e6097_port_pause_limit,
3693
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3694
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3695
	.port_link_state = mv88e6352_port_link_state,
3696
	.port_get_cmode = mv88e6352_port_get_cmode,
3697
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3698
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3699 3700
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3701
	.stats_get_stats = mv88e6095_stats_get_stats,
3702 3703
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3704
	.watchdog_ops = &mv88e6097_watchdog_ops,
3705
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3706
	.pot_clear = mv88e6xxx_g2_pot_clear,
3707
	.reset = mv88e6352_g1_reset,
3708
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3709
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3710
	.phylink_validate = mv88e6185_phylink_validate,
3711 3712 3713
};

static const struct mv88e6xxx_ops mv88e6351_ops = {
3714
	/* MV88E6XXX_FAMILY_6351 */
3715 3716
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3717
	.irl_init_all = mv88e6352_g2_irl_init_all,
3718
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3719 3720
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3721
	.port_set_link = mv88e6xxx_port_set_link,
3722
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3723
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3724
	.port_set_speed = mv88e6185_port_set_speed,
3725
	.port_tag_remap = mv88e6095_port_tag_remap,
3726
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3727
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3728
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3729
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3730
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3731
	.port_pause_limit = mv88e6097_port_pause_limit,
3732
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3733
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3734
	.port_link_state = mv88e6352_port_link_state,
3735
	.port_get_cmode = mv88e6352_port_get_cmode,
3736
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3737
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3738 3739
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3740
	.stats_get_stats = mv88e6095_stats_get_stats,
3741 3742
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3743
	.watchdog_ops = &mv88e6097_watchdog_ops,
3744
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3745
	.pot_clear = mv88e6xxx_g2_pot_clear,
3746
	.reset = mv88e6352_g1_reset,
3747
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3748
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3749
	.avb_ops = &mv88e6352_avb_ops,
3750
	.ptp_ops = &mv88e6352_ptp_ops,
3751
	.phylink_validate = mv88e6185_phylink_validate,
3752 3753 3754
};

static const struct mv88e6xxx_ops mv88e6352_ops = {
3755
	/* MV88E6XXX_FAMILY_6352 */
3756 3757
	.ieee_pri_map = mv88e6085_g1_ieee_pri_map,
	.ip_pri_map = mv88e6085_g1_ip_pri_map,
3758
	.irl_init_all = mv88e6352_g2_irl_init_all,
3759 3760
	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
3761
	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3762 3763
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
3764
	.port_set_link = mv88e6xxx_port_set_link,
3765
	.port_set_duplex = mv88e6xxx_port_set_duplex,
3766
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3767
	.port_set_speed = mv88e6352_port_set_speed,
3768
	.port_tag_remap = mv88e6095_port_tag_remap,
3769
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3770
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3771
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3772
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3773
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3774
	.port_pause_limit = mv88e6097_port_pause_limit,
3775
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3776
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3777
	.port_link_state = mv88e6352_port_link_state,
3778
	.port_get_cmode = mv88e6352_port_get_cmode,
3779
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
3780
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3781 3782
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
	.stats_get_strings = mv88e6095_stats_get_strings,
3783
	.stats_get_stats = mv88e6095_stats_get_stats,
3784 3785
	.set_cpu_port = mv88e6095_g1_set_cpu_port,
	.set_egress_port = mv88e6095_g1_set_egress_port,
3786
	.watchdog_ops = &mv88e6097_watchdog_ops,
3787
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3788
	.pot_clear = mv88e6xxx_g2_pot_clear,
3789
	.reset = mv88e6352_g1_reset,
3790
	.rmu_disable = mv88e6352_g1_rmu_disable,
3791
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
3792
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3793
	.serdes_power = mv88e6352_serdes_power,
3794
	.gpio_ops = &mv88e6352_gpio_ops,
3795
	.avb_ops = &mv88e6352_avb_ops,
3796
	.ptp_ops = &mv88e6352_ptp_ops,
3797 3798 3799
	.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
	.serdes_get_strings = mv88e6352_serdes_get_strings,
	.serdes_get_stats = mv88e6352_serdes_get_stats,
3800
	.phylink_validate = mv88e6352_phylink_validate,
3801 3802
};

3803
static const struct mv88e6xxx_ops mv88e6390_ops = {
3804
	/* MV88E6XXX_FAMILY_6390 */
3805
	.setup_errata = mv88e6390_setup_errata,
3806
	.irl_init_all = mv88e6390_g2_irl_init_all,
3807 3808
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3809 3810 3811 3812 3813 3814 3815
	.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,
3816
	.port_tag_remap = mv88e6390_port_tag_remap,
3817
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3818
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3819
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3820
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3821
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3822
	.port_pause_limit = mv88e6390_port_pause_limit,
3823
	.port_set_cmode = mv88e6390x_port_set_cmode,
3824
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3825
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3826
	.port_link_state = mv88e6352_port_link_state,
3827
	.port_get_cmode = mv88e6352_port_get_cmode,
3828
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3829
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3830 3831
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3832
	.stats_get_stats = mv88e6390_stats_get_stats,
3833 3834
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3835
	.watchdog_ops = &mv88e6390_watchdog_ops,
3836
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3837
	.pot_clear = mv88e6xxx_g2_pot_clear,
3838
	.reset = mv88e6352_g1_reset,
3839
	.rmu_disable = mv88e6390_g1_rmu_disable,
3840 3841
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3842
	.serdes_power = mv88e6390_serdes_power,
3843 3844
	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
	.serdes_irq_free = mv88e6390_serdes_irq_free,
3845
	.gpio_ops = &mv88e6352_gpio_ops,
3846
	.avb_ops = &mv88e6390_avb_ops,
3847
	.ptp_ops = &mv88e6352_ptp_ops,
3848
	.phylink_validate = mv88e6390_phylink_validate,
3849 3850 3851
};

static const struct mv88e6xxx_ops mv88e6390x_ops = {
3852
	/* MV88E6XXX_FAMILY_6390 */
3853
	.setup_errata = mv88e6390_setup_errata,
3854
	.irl_init_all = mv88e6390_g2_irl_init_all,
3855 3856
	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
3857 3858 3859 3860 3861 3862 3863
	.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,
3864
	.port_tag_remap = mv88e6390_port_tag_remap,
3865
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
3866
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
3867
	.port_set_ether_type = mv88e6351_port_set_ether_type,
3868
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3869
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3870
	.port_pause_limit = mv88e6390_port_pause_limit,
3871
	.port_set_cmode = mv88e6390x_port_set_cmode,
3872
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3873
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3874
	.port_link_state = mv88e6352_port_link_state,
3875
	.port_get_cmode = mv88e6352_port_get_cmode,
3876
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
3877
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3878 3879
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
	.stats_get_strings = mv88e6320_stats_get_strings,
3880
	.stats_get_stats = mv88e6390_stats_get_stats,
3881 3882
	.set_cpu_port = mv88e6390_g1_set_cpu_port,
	.set_egress_port = mv88e6390_g1_set_egress_port,
3883
	.watchdog_ops = &mv88e6390_watchdog_ops,
3884
	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3885
	.pot_clear = mv88e6xxx_g2_pot_clear,
3886
	.reset = mv88e6352_g1_reset,
3887
	.rmu_disable = mv88e6390_g1_rmu_disable,
3888 3889
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3890
	.serdes_power = mv88e6390x_serdes_power,
3891 3892
	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
	.serdes_irq_free = mv88e6390_serdes_irq_free,
3893
	.gpio_ops = &mv88e6352_gpio_ops,
3894
	.avb_ops = &mv88e6390_avb_ops,
3895
	.ptp_ops = &mv88e6352_ptp_ops,
3896
	.phylink_validate = mv88e6390x_phylink_validate,
3897 3898
};

3899 3900
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
	[MV88E6085] = {
3901
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
3902 3903 3904 3905
		.family = MV88E6XXX_FAMILY_6097,
		.name = "Marvell 88E6085",
		.num_databases = 4096,
		.num_ports = 10,
3906
		.num_internal_phys = 5,
3907
		.max_vid = 4095,
3908
		.port_base_addr = 0x10,
3909
		.phy_base_addr = 0x0,
3910
		.global1_addr = 0x1b,
3911
		.global2_addr = 0x1c,
3912
		.age_time_coeff = 15000,
3913
		.g1_irqs = 8,
3914
		.g2_irqs = 10,
3915
		.atu_move_port_mask = 0xf,
3916
		.pvt = true,
3917
		.multi_chip = true,
3918
		.tag_protocol = DSA_TAG_PROTO_DSA,
3919
		.ops = &mv88e6085_ops,
3920 3921 3922
	},

	[MV88E6095] = {
3923
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095,
3924 3925 3926 3927
		.family = MV88E6XXX_FAMILY_6095,
		.name = "Marvell 88E6095/88E6095F",
		.num_databases = 256,
		.num_ports = 11,
3928
		.num_internal_phys = 0,
3929
		.max_vid = 4095,
3930
		.port_base_addr = 0x10,
3931
		.phy_base_addr = 0x0,
3932
		.global1_addr = 0x1b,
3933
		.global2_addr = 0x1c,
3934
		.age_time_coeff = 15000,
3935
		.g1_irqs = 8,
3936
		.atu_move_port_mask = 0xf,
3937
		.multi_chip = true,
3938
		.tag_protocol = DSA_TAG_PROTO_DSA,
3939
		.ops = &mv88e6095_ops,
3940 3941
	},

3942
	[MV88E6097] = {
3943
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097,
3944 3945 3946 3947
		.family = MV88E6XXX_FAMILY_6097,
		.name = "Marvell 88E6097/88E6097F",
		.num_databases = 4096,
		.num_ports = 11,
3948
		.num_internal_phys = 8,
3949
		.max_vid = 4095,
3950
		.port_base_addr = 0x10,
3951
		.phy_base_addr = 0x0,
3952
		.global1_addr = 0x1b,
3953
		.global2_addr = 0x1c,
3954
		.age_time_coeff = 15000,
3955
		.g1_irqs = 8,
3956
		.g2_irqs = 10,
3957
		.atu_move_port_mask = 0xf,
3958
		.pvt = true,
3959
		.multi_chip = true,
3960
		.tag_protocol = DSA_TAG_PROTO_EDSA,
3961 3962 3963
		.ops = &mv88e6097_ops,
	},

3964
	[MV88E6123] = {
3965
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123,
3966 3967 3968 3969
		.family = MV88E6XXX_FAMILY_6165,
		.name = "Marvell 88E6123",
		.num_databases = 4096,
		.num_ports = 3,
3970
		.num_internal_phys = 5,
3971
		.max_vid = 4095,
3972
		.port_base_addr = 0x10,
3973
		.phy_base_addr = 0x0,
3974
		.global1_addr = 0x1b,
3975
		.global2_addr = 0x1c,
3976
		.age_time_coeff = 15000,
3977
		.g1_irqs = 9,
3978
		.g2_irqs = 10,
3979
		.atu_move_port_mask = 0xf,
3980
		.pvt = true,
3981
		.multi_chip = true,
3982
		.tag_protocol = DSA_TAG_PROTO_EDSA,
3983
		.ops = &mv88e6123_ops,
3984 3985 3986
	},

	[MV88E6131] = {
3987
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131,
3988 3989 3990 3991
		.family = MV88E6XXX_FAMILY_6185,
		.name = "Marvell 88E6131",
		.num_databases = 256,
		.num_ports = 8,
3992
		.num_internal_phys = 0,
3993
		.max_vid = 4095,
3994
		.port_base_addr = 0x10,
3995
		.phy_base_addr = 0x0,
3996
		.global1_addr = 0x1b,
3997
		.global2_addr = 0x1c,
3998
		.age_time_coeff = 15000,
3999
		.g1_irqs = 9,
4000
		.atu_move_port_mask = 0xf,
4001
		.multi_chip = true,
4002
		.tag_protocol = DSA_TAG_PROTO_DSA,
4003
		.ops = &mv88e6131_ops,
4004 4005
	},

4006
	[MV88E6141] = {
4007
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
4008
		.family = MV88E6XXX_FAMILY_6341,
4009
		.name = "Marvell 88E6141",
4010 4011
		.num_databases = 4096,
		.num_ports = 6,
4012
		.num_internal_phys = 5,
4013
		.num_gpio = 11,
4014
		.max_vid = 4095,
4015
		.port_base_addr = 0x10,
4016
		.phy_base_addr = 0x10,
4017
		.global1_addr = 0x1b,
4018
		.global2_addr = 0x1c,
4019 4020
		.age_time_coeff = 3750,
		.atu_move_port_mask = 0x1f,
4021
		.g1_irqs = 9,
4022
		.g2_irqs = 10,
4023
		.pvt = true,
4024
		.multi_chip = true,
4025 4026 4027 4028
		.tag_protocol = DSA_TAG_PROTO_EDSA,
		.ops = &mv88e6141_ops,
	},

4029
	[MV88E6161] = {
4030
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161,
4031 4032 4033 4034
		.family = MV88E6XXX_FAMILY_6165,
		.name = "Marvell 88E6161",
		.num_databases = 4096,
		.num_ports = 6,
4035
		.num_internal_phys = 5,
4036
		.max_vid = 4095,
4037
		.port_base_addr = 0x10,
4038
		.phy_base_addr = 0x0,
4039
		.global1_addr = 0x1b,
4040
		.global2_addr = 0x1c,
4041
		.age_time_coeff = 15000,
4042
		.g1_irqs = 9,
4043
		.g2_irqs = 10,
4044
		.atu_move_port_mask = 0xf,
4045
		.pvt = true,
4046
		.multi_chip = true,
4047
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4048
		.ptp_support = true,
4049
		.ops = &mv88e6161_ops,
4050 4051 4052
	},

	[MV88E6165] = {
4053
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165,
4054 4055 4056 4057
		.family = MV88E6XXX_FAMILY_6165,
		.name = "Marvell 88E6165",
		.num_databases = 4096,
		.num_ports = 6,
4058
		.num_internal_phys = 0,
4059
		.max_vid = 4095,
4060
		.port_base_addr = 0x10,
4061
		.phy_base_addr = 0x0,
4062
		.global1_addr = 0x1b,
4063
		.global2_addr = 0x1c,
4064
		.age_time_coeff = 15000,
4065
		.g1_irqs = 9,
4066
		.g2_irqs = 10,
4067
		.atu_move_port_mask = 0xf,
4068
		.pvt = true,
4069
		.multi_chip = true,
4070
		.tag_protocol = DSA_TAG_PROTO_DSA,
4071
		.ptp_support = true,
4072
		.ops = &mv88e6165_ops,
4073 4074 4075
	},

	[MV88E6171] = {
4076
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171,
4077 4078 4079 4080
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6171",
		.num_databases = 4096,
		.num_ports = 7,
4081
		.num_internal_phys = 5,
4082
		.max_vid = 4095,
4083
		.port_base_addr = 0x10,
4084
		.phy_base_addr = 0x0,
4085
		.global1_addr = 0x1b,
4086
		.global2_addr = 0x1c,
4087
		.age_time_coeff = 15000,
4088
		.g1_irqs = 9,
4089
		.g2_irqs = 10,
4090
		.atu_move_port_mask = 0xf,
4091
		.pvt = true,
4092
		.multi_chip = true,
4093
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4094
		.ops = &mv88e6171_ops,
4095 4096 4097
	},

	[MV88E6172] = {
4098
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172,
4099 4100 4101 4102
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6172",
		.num_databases = 4096,
		.num_ports = 7,
4103
		.num_internal_phys = 5,
4104
		.num_gpio = 15,
4105
		.max_vid = 4095,
4106
		.port_base_addr = 0x10,
4107
		.phy_base_addr = 0x0,
4108
		.global1_addr = 0x1b,
4109
		.global2_addr = 0x1c,
4110
		.age_time_coeff = 15000,
4111
		.g1_irqs = 9,
4112
		.g2_irqs = 10,
4113
		.atu_move_port_mask = 0xf,
4114
		.pvt = true,
4115
		.multi_chip = true,
4116
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4117
		.ops = &mv88e6172_ops,
4118 4119 4120
	},

	[MV88E6175] = {
4121
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175,
4122 4123 4124 4125
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6175",
		.num_databases = 4096,
		.num_ports = 7,
4126
		.num_internal_phys = 5,
4127
		.max_vid = 4095,
4128
		.port_base_addr = 0x10,
4129
		.phy_base_addr = 0x0,
4130
		.global1_addr = 0x1b,
4131
		.global2_addr = 0x1c,
4132
		.age_time_coeff = 15000,
4133
		.g1_irqs = 9,
4134
		.g2_irqs = 10,
4135
		.atu_move_port_mask = 0xf,
4136
		.pvt = true,
4137
		.multi_chip = true,
4138
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4139
		.ops = &mv88e6175_ops,
4140 4141 4142
	},

	[MV88E6176] = {
4143
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176,
4144 4145 4146 4147
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6176",
		.num_databases = 4096,
		.num_ports = 7,
4148
		.num_internal_phys = 5,
4149
		.num_gpio = 15,
4150
		.max_vid = 4095,
4151
		.port_base_addr = 0x10,
4152
		.phy_base_addr = 0x0,
4153
		.global1_addr = 0x1b,
4154
		.global2_addr = 0x1c,
4155
		.age_time_coeff = 15000,
4156
		.g1_irqs = 9,
4157
		.g2_irqs = 10,
4158
		.atu_move_port_mask = 0xf,
4159
		.pvt = true,
4160
		.multi_chip = true,
4161
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4162
		.ops = &mv88e6176_ops,
4163 4164 4165
	},

	[MV88E6185] = {
4166
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185,
4167 4168 4169 4170
		.family = MV88E6XXX_FAMILY_6185,
		.name = "Marvell 88E6185",
		.num_databases = 256,
		.num_ports = 10,
4171
		.num_internal_phys = 0,
4172
		.max_vid = 4095,
4173
		.port_base_addr = 0x10,
4174
		.phy_base_addr = 0x0,
4175
		.global1_addr = 0x1b,
4176
		.global2_addr = 0x1c,
4177
		.age_time_coeff = 15000,
4178
		.g1_irqs = 8,
4179
		.atu_move_port_mask = 0xf,
4180
		.multi_chip = true,
4181
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4182
		.ops = &mv88e6185_ops,
4183 4184
	},

4185
	[MV88E6190] = {
4186
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190,
4187 4188 4189 4190
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6190",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4191
		.num_internal_phys = 9,
4192
		.num_gpio = 16,
4193
		.max_vid = 8191,
4194
		.port_base_addr = 0x0,
4195
		.phy_base_addr = 0x0,
4196
		.global1_addr = 0x1b,
4197
		.global2_addr = 0x1c,
4198
		.tag_protocol = DSA_TAG_PROTO_DSA,
4199
		.age_time_coeff = 3750,
4200
		.g1_irqs = 9,
4201
		.g2_irqs = 14,
4202
		.pvt = true,
4203
		.multi_chip = true,
4204
		.atu_move_port_mask = 0x1f,
4205 4206 4207 4208
		.ops = &mv88e6190_ops,
	},

	[MV88E6190X] = {
4209
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X,
4210 4211 4212 4213
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6190X",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4214
		.num_internal_phys = 9,
4215
		.num_gpio = 16,
4216
		.max_vid = 8191,
4217
		.port_base_addr = 0x0,
4218
		.phy_base_addr = 0x0,
4219
		.global1_addr = 0x1b,
4220
		.global2_addr = 0x1c,
4221
		.age_time_coeff = 3750,
4222
		.g1_irqs = 9,
4223
		.g2_irqs = 14,
4224
		.atu_move_port_mask = 0x1f,
4225
		.pvt = true,
4226
		.multi_chip = true,
4227
		.tag_protocol = DSA_TAG_PROTO_DSA,
4228 4229 4230 4231
		.ops = &mv88e6190x_ops,
	},

	[MV88E6191] = {
4232
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191,
4233 4234 4235 4236
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6191",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4237
		.num_internal_phys = 9,
4238
		.max_vid = 8191,
4239
		.port_base_addr = 0x0,
4240
		.phy_base_addr = 0x0,
4241
		.global1_addr = 0x1b,
4242
		.global2_addr = 0x1c,
4243
		.age_time_coeff = 3750,
4244
		.g1_irqs = 9,
4245
		.g2_irqs = 14,
4246
		.atu_move_port_mask = 0x1f,
4247
		.pvt = true,
4248
		.multi_chip = true,
4249
		.tag_protocol = DSA_TAG_PROTO_DSA,
4250
		.ptp_support = true,
4251
		.ops = &mv88e6191_ops,
4252 4253
	},

4254
	[MV88E6240] = {
4255
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240,
4256 4257 4258 4259
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6240",
		.num_databases = 4096,
		.num_ports = 7,
4260
		.num_internal_phys = 5,
4261
		.num_gpio = 15,
4262
		.max_vid = 4095,
4263
		.port_base_addr = 0x10,
4264
		.phy_base_addr = 0x0,
4265
		.global1_addr = 0x1b,
4266
		.global2_addr = 0x1c,
4267
		.age_time_coeff = 15000,
4268
		.g1_irqs = 9,
4269
		.g2_irqs = 10,
4270
		.atu_move_port_mask = 0xf,
4271
		.pvt = true,
4272
		.multi_chip = true,
4273
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4274
		.ptp_support = true,
4275
		.ops = &mv88e6240_ops,
4276 4277
	},

4278
	[MV88E6290] = {
4279
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
4280 4281 4282 4283
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6290",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4284
		.num_internal_phys = 9,
4285
		.num_gpio = 16,
4286
		.max_vid = 8191,
4287
		.port_base_addr = 0x0,
4288
		.phy_base_addr = 0x0,
4289
		.global1_addr = 0x1b,
4290
		.global2_addr = 0x1c,
4291
		.age_time_coeff = 3750,
4292
		.g1_irqs = 9,
4293
		.g2_irqs = 14,
4294
		.atu_move_port_mask = 0x1f,
4295
		.pvt = true,
4296
		.multi_chip = true,
4297
		.tag_protocol = DSA_TAG_PROTO_DSA,
4298
		.ptp_support = true,
4299 4300 4301
		.ops = &mv88e6290_ops,
	},

4302
	[MV88E6320] = {
4303
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320,
4304 4305 4306 4307
		.family = MV88E6XXX_FAMILY_6320,
		.name = "Marvell 88E6320",
		.num_databases = 4096,
		.num_ports = 7,
4308
		.num_internal_phys = 5,
4309
		.num_gpio = 15,
4310
		.max_vid = 4095,
4311
		.port_base_addr = 0x10,
4312
		.phy_base_addr = 0x0,
4313
		.global1_addr = 0x1b,
4314
		.global2_addr = 0x1c,
4315
		.age_time_coeff = 15000,
4316
		.g1_irqs = 8,
4317
		.g2_irqs = 10,
4318
		.atu_move_port_mask = 0xf,
4319
		.pvt = true,
4320
		.multi_chip = true,
4321
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4322
		.ptp_support = true,
4323
		.ops = &mv88e6320_ops,
4324 4325 4326
	},

	[MV88E6321] = {
4327
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321,
4328 4329 4330 4331
		.family = MV88E6XXX_FAMILY_6320,
		.name = "Marvell 88E6321",
		.num_databases = 4096,
		.num_ports = 7,
4332
		.num_internal_phys = 5,
4333
		.num_gpio = 15,
4334
		.max_vid = 4095,
4335
		.port_base_addr = 0x10,
4336
		.phy_base_addr = 0x0,
4337
		.global1_addr = 0x1b,
4338
		.global2_addr = 0x1c,
4339
		.age_time_coeff = 15000,
4340
		.g1_irqs = 8,
4341
		.g2_irqs = 10,
4342
		.atu_move_port_mask = 0xf,
4343
		.multi_chip = true,
4344
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4345
		.ptp_support = true,
4346
		.ops = &mv88e6321_ops,
4347 4348
	},

4349
	[MV88E6341] = {
4350
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
4351 4352 4353
		.family = MV88E6XXX_FAMILY_6341,
		.name = "Marvell 88E6341",
		.num_databases = 4096,
4354
		.num_internal_phys = 5,
4355
		.num_ports = 6,
4356
		.num_gpio = 11,
4357
		.max_vid = 4095,
4358
		.port_base_addr = 0x10,
4359
		.phy_base_addr = 0x10,
4360
		.global1_addr = 0x1b,
4361
		.global2_addr = 0x1c,
4362
		.age_time_coeff = 3750,
4363
		.atu_move_port_mask = 0x1f,
4364
		.g1_irqs = 9,
4365
		.g2_irqs = 10,
4366
		.pvt = true,
4367
		.multi_chip = true,
4368
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4369
		.ptp_support = true,
4370 4371 4372
		.ops = &mv88e6341_ops,
	},

4373
	[MV88E6350] = {
4374
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350,
4375 4376 4377 4378
		.family = MV88E6XXX_FAMILY_6351,
		.name = "Marvell 88E6350",
		.num_databases = 4096,
		.num_ports = 7,
4379
		.num_internal_phys = 5,
4380
		.max_vid = 4095,
4381
		.port_base_addr = 0x10,
4382
		.phy_base_addr = 0x0,
4383
		.global1_addr = 0x1b,
4384
		.global2_addr = 0x1c,
4385
		.age_time_coeff = 15000,
4386
		.g1_irqs = 9,
4387
		.g2_irqs = 10,
4388
		.atu_move_port_mask = 0xf,
4389
		.pvt = true,
4390
		.multi_chip = true,
4391
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4392
		.ops = &mv88e6350_ops,
4393 4394 4395
	},

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

	[MV88E6352] = {
4418
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352,
4419 4420 4421 4422
		.family = MV88E6XXX_FAMILY_6352,
		.name = "Marvell 88E6352",
		.num_databases = 4096,
		.num_ports = 7,
4423
		.num_internal_phys = 5,
4424
		.num_gpio = 15,
4425
		.max_vid = 4095,
4426
		.port_base_addr = 0x10,
4427
		.phy_base_addr = 0x0,
4428
		.global1_addr = 0x1b,
4429
		.global2_addr = 0x1c,
4430
		.age_time_coeff = 15000,
4431
		.g1_irqs = 9,
4432
		.g2_irqs = 10,
4433
		.atu_move_port_mask = 0xf,
4434
		.pvt = true,
4435
		.multi_chip = true,
4436
		.tag_protocol = DSA_TAG_PROTO_EDSA,
4437
		.ptp_support = true,
4438
		.ops = &mv88e6352_ops,
4439
	},
4440
	[MV88E6390] = {
4441
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
4442 4443 4444 4445
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6390",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4446
		.num_internal_phys = 9,
4447
		.num_gpio = 16,
4448
		.max_vid = 8191,
4449
		.port_base_addr = 0x0,
4450
		.phy_base_addr = 0x0,
4451
		.global1_addr = 0x1b,
4452
		.global2_addr = 0x1c,
4453
		.age_time_coeff = 3750,
4454
		.g1_irqs = 9,
4455
		.g2_irqs = 14,
4456
		.atu_move_port_mask = 0x1f,
4457
		.pvt = true,
4458
		.multi_chip = true,
4459
		.tag_protocol = DSA_TAG_PROTO_DSA,
4460
		.ptp_support = true,
4461 4462 4463
		.ops = &mv88e6390_ops,
	},
	[MV88E6390X] = {
4464
		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X,
4465 4466 4467 4468
		.family = MV88E6XXX_FAMILY_6390,
		.name = "Marvell 88E6390X",
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
4469
		.num_internal_phys = 9,
4470
		.num_gpio = 16,
4471
		.max_vid = 8191,
4472
		.port_base_addr = 0x0,
4473
		.phy_base_addr = 0x0,
4474
		.global1_addr = 0x1b,
4475
		.global2_addr = 0x1c,
4476
		.age_time_coeff = 3750,
4477
		.g1_irqs = 9,
4478
		.g2_irqs = 14,
4479
		.atu_move_port_mask = 0x1f,
4480
		.pvt = true,
4481
		.multi_chip = true,
4482
		.tag_protocol = DSA_TAG_PROTO_DSA,
4483
		.ptp_support = true,
4484 4485
		.ops = &mv88e6390x_ops,
	},
4486 4487
};

4488
static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
4489
{
4490
	int i;
4491

4492 4493 4494
	for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
		if (mv88e6xxx_table[i].prod_num == prod_num)
			return &mv88e6xxx_table[i];
4495 4496 4497 4498

	return NULL;
}

4499
static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
4500 4501
{
	const struct mv88e6xxx_info *info;
4502 4503 4504
	unsigned int prod_num, rev;
	u16 id;
	int err;
4505

4506
	mutex_lock(&chip->reg_lock);
4507
	err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id);
4508 4509 4510
	mutex_unlock(&chip->reg_lock);
	if (err)
		return err;
4511

4512 4513
	prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK;
	rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK;
4514 4515 4516 4517 4518

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

4519
	/* Update the compatible info with the probed one */
4520
	chip->info = info;
4521

4522 4523 4524 4525
	err = mv88e6xxx_g2_require(chip);
	if (err)
		return err;

4526 4527
	dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n",
		 chip->info->prod_num, chip->info->name, rev);
4528 4529 4530 4531

	return 0;
}

4532
static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
4533
{
4534
	struct mv88e6xxx_chip *chip;
4535

4536 4537
	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
	if (!chip)
4538 4539
		return NULL;

4540
	chip->dev = dev;
4541

4542
	mutex_init(&chip->reg_lock);
4543
	INIT_LIST_HEAD(&chip->mdios);
4544

4545
	return chip;
4546 4547
}

4548
static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
4549 4550
			      struct mii_bus *bus, int sw_addr)
{
4551
	if (sw_addr == 0)
4552
		chip->smi_ops = &mv88e6xxx_smi_single_chip_ops;
4553
	else if (chip->info->multi_chip)
4554
		chip->smi_ops = &mv88e6xxx_smi_multi_chip_ops;
4555 4556 4557
	else
		return -EINVAL;

4558 4559
	chip->bus = bus;
	chip->sw_addr = sw_addr;
4560 4561 4562 4563

	return 0;
}

4564 4565
static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
							int port)
4566
{
V
Vivien Didelot 已提交
4567
	struct mv88e6xxx_chip *chip = ds->priv;
4568

4569
	return chip->info->tag_protocol;
4570 4571
}

4572
#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
4573 4574 4575
static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
				       struct device *host_dev, int sw_addr,
				       void **priv)
4576
{
4577
	struct mv88e6xxx_chip *chip;
4578
	struct mii_bus *bus;
4579
	int err;
4580

4581
	bus = dsa_host_dev_to_mii_bus(host_dev);
4582 4583 4584
	if (!bus)
		return NULL;

4585 4586
	chip = mv88e6xxx_alloc_chip(dsa_dev);
	if (!chip)
4587 4588
		return NULL;

4589
	/* Legacy SMI probing will only support chips similar to 88E6085 */
4590
	chip->info = &mv88e6xxx_table[MV88E6085];
4591

4592
	err = mv88e6xxx_smi_init(chip, bus, sw_addr);
4593 4594 4595
	if (err)
		goto free;

4596
	err = mv88e6xxx_detect(chip);
4597
	if (err)
4598
		goto free;
4599

4600 4601 4602 4603 4604 4605
	mutex_lock(&chip->reg_lock);
	err = mv88e6xxx_switch_reset(chip);
	mutex_unlock(&chip->reg_lock);
	if (err)
		goto free;

4606 4607
	mv88e6xxx_phy_init(chip);

4608
	err = mv88e6xxx_mdios_register(chip, NULL);
4609
	if (err)
4610
		goto free;
4611

4612
	*priv = chip;
4613

4614
	return chip->info->name;
4615
free:
4616
	devm_kfree(dsa_dev, chip);
4617 4618

	return NULL;
4619
}
4620
#endif
4621

4622
static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port,
4623
				      const struct switchdev_obj_port_mdb *mdb)
4624 4625 4626 4627 4628 4629 4630 4631 4632
{
	/* 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,
4633
				   const struct switchdev_obj_port_mdb *mdb)
4634
{
V
Vivien Didelot 已提交
4635
	struct mv88e6xxx_chip *chip = ds->priv;
4636 4637 4638

	mutex_lock(&chip->reg_lock);
	if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4639
					 MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC))
4640 4641
		dev_err(ds->dev, "p%d: failed to load multicast MAC address\n",
			port);
4642 4643 4644 4645 4646 4647
	mutex_unlock(&chip->reg_lock);
}

static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
				  const struct switchdev_obj_port_mdb *mdb)
{
V
Vivien Didelot 已提交
4648
	struct mv88e6xxx_chip *chip = ds->priv;
4649 4650 4651 4652
	int err;

	mutex_lock(&chip->reg_lock);
	err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4653
					   MV88E6XXX_G1_ATU_DATA_STATE_UNUSED);
4654 4655 4656 4657 4658
	mutex_unlock(&chip->reg_lock);

	return err;
}

4659
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
4660
#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
4661
	.probe			= mv88e6xxx_drv_probe,
4662
#endif
4663
	.get_tag_protocol	= mv88e6xxx_get_tag_protocol,
4664 4665
	.setup			= mv88e6xxx_setup,
	.adjust_link		= mv88e6xxx_adjust_link,
4666 4667 4668 4669 4670
	.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,
4671 4672 4673
	.get_strings		= mv88e6xxx_get_strings,
	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
	.get_sset_count		= mv88e6xxx_get_sset_count,
4674 4675
	.port_enable		= mv88e6xxx_port_enable,
	.port_disable		= mv88e6xxx_port_disable,
V
Vivien Didelot 已提交
4676 4677
	.get_mac_eee		= mv88e6xxx_get_mac_eee,
	.set_mac_eee		= mv88e6xxx_set_mac_eee,
4678
	.get_eeprom_len		= mv88e6xxx_get_eeprom_len,
4679 4680 4681 4682
	.get_eeprom		= mv88e6xxx_get_eeprom,
	.set_eeprom		= mv88e6xxx_set_eeprom,
	.get_regs_len		= mv88e6xxx_get_regs_len,
	.get_regs		= mv88e6xxx_get_regs,
4683
	.set_ageing_time	= mv88e6xxx_set_ageing_time,
4684 4685 4686
	.port_bridge_join	= mv88e6xxx_port_bridge_join,
	.port_bridge_leave	= mv88e6xxx_port_bridge_leave,
	.port_stp_state_set	= mv88e6xxx_port_stp_state_set,
4687
	.port_fast_age		= mv88e6xxx_port_fast_age,
4688 4689 4690 4691 4692 4693 4694
	.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,
4695 4696 4697
	.port_mdb_prepare       = mv88e6xxx_port_mdb_prepare,
	.port_mdb_add           = mv88e6xxx_port_mdb_add,
	.port_mdb_del           = mv88e6xxx_port_mdb_del,
4698 4699
	.crosschip_bridge_join	= mv88e6xxx_crosschip_bridge_join,
	.crosschip_bridge_leave	= mv88e6xxx_crosschip_bridge_leave,
4700 4701 4702 4703 4704
	.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,
4705 4706
};

4707 4708 4709 4710
static struct dsa_switch_driver mv88e6xxx_switch_drv = {
	.ops			= &mv88e6xxx_switch_ops,
};

4711
static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
4712
{
4713
	struct device *dev = chip->dev;
4714 4715
	struct dsa_switch *ds;

4716
	ds = dsa_switch_alloc(dev, mv88e6xxx_num_ports(chip));
4717 4718 4719
	if (!ds)
		return -ENOMEM;

4720
	ds->priv = chip;
4721
	ds->dev = dev;
4722
	ds->ops = &mv88e6xxx_switch_ops;
4723 4724
	ds->ageing_time_min = chip->info->age_time_coeff;
	ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
4725 4726 4727

	dev_set_drvdata(dev, ds);

4728
	return dsa_register_switch(ds);
4729 4730
}

4731
static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip)
4732
{
4733
	dsa_unregister_switch(chip->ds);
4734 4735
}

4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748
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;
}

4749
static int mv88e6xxx_probe(struct mdio_device *mdiodev)
4750
{
4751
	struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
4752
	const struct mv88e6xxx_info *compat_info = NULL;
4753
	struct device *dev = &mdiodev->dev;
4754
	struct device_node *np = dev->of_node;
4755
	struct mv88e6xxx_chip *chip;
4756
	int port;
4757
	int err;
4758

4759 4760 4761
	if (!np && !pdata)
		return -EINVAL;

4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780
	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;
		}
	}

4781 4782 4783
	if (!compat_info)
		return -EINVAL;

4784
	chip = mv88e6xxx_alloc_chip(dev);
4785 4786 4787 4788
	if (!chip) {
		err = -ENOMEM;
		goto out;
	}
4789

4790
	chip->info = compat_info;
4791

4792
	err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
4793
	if (err)
4794
		goto out;
4795

4796
	chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
4797 4798 4799 4800
	if (IS_ERR(chip->reset)) {
		err = PTR_ERR(chip->reset);
		goto out;
	}
4801

4802
	err = mv88e6xxx_detect(chip);
4803
	if (err)
4804
		goto out;
4805

4806 4807
	mv88e6xxx_phy_init(chip);

4808 4809 4810 4811 4812 4813 4814
	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;
	}
4815

4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827
	mutex_lock(&chip->reg_lock);
	err = mv88e6xxx_switch_reset(chip);
	mutex_unlock(&chip->reg_lock);
	if (err)
		goto out;

	chip->irq = of_irq_get(np, 0);
	if (chip->irq == -EPROBE_DEFER) {
		err = chip->irq;
		goto out;
	}

4828
	/* Has to be performed before the MDIO bus is created, because
4829
	 * the PHYs will link their interrupts to these interrupt
4830 4831 4832 4833
	 * controllers
	 */
	mutex_lock(&chip->reg_lock);
	if (chip->irq > 0)
4834
		err = mv88e6xxx_g1_irq_setup(chip);
4835 4836 4837
	else
		err = mv88e6xxx_irq_poll_setup(chip);
	mutex_unlock(&chip->reg_lock);
4838

4839 4840
	if (err)
		goto out;
4841

4842 4843
	if (chip->info->g2_irqs > 0) {
		err = mv88e6xxx_g2_irq_setup(chip);
4844
		if (err)
4845
			goto out_g1_irq;
4846 4847
	}

4848 4849 4850 4851 4852 4853 4854 4855
	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;

4856
	err = mv88e6xxx_mdios_register(chip, np);
4857
	if (err)
4858
		goto out_g1_vtu_prob_irq;
4859

4860
	err = mv88e6xxx_register_switch(chip);
4861 4862
	if (err)
		goto out_mdio;
4863

4864
	return 0;
4865 4866

out_mdio:
4867
	mv88e6xxx_mdios_unregister(chip);
4868
out_g1_vtu_prob_irq:
4869
	mv88e6xxx_g1_vtu_prob_irq_free(chip);
4870
out_g1_atu_prob_irq:
4871
	mv88e6xxx_g1_atu_prob_irq_free(chip);
4872
out_g2_irq:
4873
	if (chip->info->g2_irqs > 0)
4874 4875
		mv88e6xxx_g2_irq_free(chip);
out_g1_irq:
4876
	if (chip->irq > 0)
4877
		mv88e6xxx_g1_irq_free(chip);
4878 4879
	else
		mv88e6xxx_irq_poll_free(chip);
4880
out:
4881 4882 4883
	if (pdata)
		dev_put(pdata->netdev);

4884
	return err;
4885
}
4886 4887 4888 4889

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

4892 4893
	if (chip->info->ptp_support) {
		mv88e6xxx_hwtstamp_free(chip);
4894
		mv88e6xxx_ptp_free(chip);
4895
	}
4896

4897
	mv88e6xxx_phy_destroy(chip);
4898
	mv88e6xxx_unregister_switch(chip);
4899
	mv88e6xxx_mdios_unregister(chip);
4900

4901 4902 4903 4904 4905 4906 4907
	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)
4908
		mv88e6xxx_g1_irq_free(chip);
4909 4910
	else
		mv88e6xxx_irq_poll_free(chip);
4911 4912 4913
}

static const struct of_device_id mv88e6xxx_of_match[] = {
4914 4915 4916 4917
	{
		.compatible = "marvell,mv88e6085",
		.data = &mv88e6xxx_table[MV88E6085],
	},
4918 4919 4920 4921
	{
		.compatible = "marvell,mv88e6190",
		.data = &mv88e6xxx_table[MV88E6190],
	},
4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937
	{ /* 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,
	},
};

static int __init mv88e6xxx_init(void)
{
4938
	register_switch_driver(&mv88e6xxx_switch_drv);
4939 4940
	return mdio_driver_register(&mv88e6xxx_driver);
}
4941 4942 4943 4944
module_init(mv88e6xxx_init);

static void __exit mv88e6xxx_cleanup(void)
{
4945
	mdio_driver_unregister(&mv88e6xxx_driver);
4946
	unregister_switch_driver(&mv88e6xxx_switch_drv);
4947 4948
}
module_exit(mv88e6xxx_cleanup);
4949 4950 4951 4952

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