brintos

brintos / linux-shallow public Read only

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