12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2fad09c73SVivien Didelot /* 3fad09c73SVivien Didelot * Marvell 88e6xxx Ethernet switch single-chip support 4fad09c73SVivien Didelot * 5fad09c73SVivien Didelot * Copyright (c) 2008 Marvell Semiconductor 6fad09c73SVivien Didelot * 7fad09c73SVivien Didelot * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch> 8fad09c73SVivien Didelot * 94333d619SVivien Didelot * Copyright (c) 2016-2017 Savoir-faire Linux Inc. 104333d619SVivien Didelot * Vivien Didelot <vivien.didelot@savoirfairelinux.com> 11fad09c73SVivien Didelot */ 12fad09c73SVivien Didelot 1319fb7f69SVivien Didelot #include <linux/bitfield.h> 14fad09c73SVivien Didelot #include <linux/delay.h> 15fad09c73SVivien Didelot #include <linux/etherdevice.h> 16fad09c73SVivien Didelot #include <linux/ethtool.h> 17fad09c73SVivien Didelot #include <linux/if_bridge.h> 18dc30c35bSAndrew Lunn #include <linux/interrupt.h> 19dc30c35bSAndrew Lunn #include <linux/irq.h> 20dc30c35bSAndrew Lunn #include <linux/irqdomain.h> 21fad09c73SVivien Didelot #include <linux/jiffies.h> 22fad09c73SVivien Didelot #include <linux/list.h> 23fad09c73SVivien Didelot #include <linux/mdio.h> 24fad09c73SVivien Didelot #include <linux/module.h> 25fad09c73SVivien Didelot #include <linux/of_device.h> 26dc30c35bSAndrew Lunn #include <linux/of_irq.h> 27fad09c73SVivien Didelot #include <linux/of_mdio.h> 28877b7cb0SAndrew Lunn #include <linux/platform_data/mv88e6xxx.h> 29fad09c73SVivien Didelot #include <linux/netdevice.h> 30fad09c73SVivien Didelot #include <linux/gpio/consumer.h> 31c9a2356fSRussell King #include <linux/phylink.h> 32fad09c73SVivien Didelot #include <net/dsa.h> 33ec561276SVivien Didelot 344d5f2ba7SVivien Didelot #include "chip.h" 35a935c052SVivien Didelot #include "global1.h" 36ec561276SVivien Didelot #include "global2.h" 37c6fe0ad2SBrandon Streiff #include "hwtstamp.h" 3810fa5bfcSAndrew Lunn #include "phy.h" 3918abed21SVivien Didelot #include "port.h" 402fa8d3afSBrandon Streiff #include "ptp.h" 416d91782fSAndrew Lunn #include "serdes.h" 42e7ba0fadSVivien Didelot #include "smi.h" 43fad09c73SVivien Didelot 44fad09c73SVivien Didelot static void assert_reg_lock(struct mv88e6xxx_chip *chip) 45fad09c73SVivien Didelot { 46fad09c73SVivien Didelot if (unlikely(!mutex_is_locked(&chip->reg_lock))) { 47fad09c73SVivien Didelot dev_err(chip->dev, "Switch registers lock not held!\n"); 48fad09c73SVivien Didelot dump_stack(); 49fad09c73SVivien Didelot } 50fad09c73SVivien Didelot } 51fad09c73SVivien Didelot 52ec561276SVivien Didelot int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val) 53fad09c73SVivien Didelot { 54fad09c73SVivien Didelot int err; 55fad09c73SVivien Didelot 56fad09c73SVivien Didelot assert_reg_lock(chip); 57fad09c73SVivien Didelot 58fad09c73SVivien Didelot err = mv88e6xxx_smi_read(chip, addr, reg, val); 59fad09c73SVivien Didelot if (err) 60fad09c73SVivien Didelot return err; 61fad09c73SVivien Didelot 62fad09c73SVivien Didelot dev_dbg(chip->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", 63fad09c73SVivien Didelot addr, reg, *val); 64fad09c73SVivien Didelot 65fad09c73SVivien Didelot return 0; 66fad09c73SVivien Didelot } 67fad09c73SVivien Didelot 68ec561276SVivien Didelot int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val) 69fad09c73SVivien Didelot { 70fad09c73SVivien Didelot int err; 71fad09c73SVivien Didelot 72fad09c73SVivien Didelot assert_reg_lock(chip); 73fad09c73SVivien Didelot 74fad09c73SVivien Didelot err = mv88e6xxx_smi_write(chip, addr, reg, val); 75fad09c73SVivien Didelot if (err) 76fad09c73SVivien Didelot return err; 77fad09c73SVivien Didelot 78fad09c73SVivien Didelot dev_dbg(chip->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", 79fad09c73SVivien Didelot addr, reg, val); 80fad09c73SVivien Didelot 81fad09c73SVivien Didelot return 0; 82fad09c73SVivien Didelot } 83fad09c73SVivien Didelot 84683f2244SVivien Didelot int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, 85683f2244SVivien Didelot u16 mask, u16 val) 86683f2244SVivien Didelot { 87683f2244SVivien Didelot u16 data; 88683f2244SVivien Didelot int err; 89683f2244SVivien Didelot int i; 90683f2244SVivien Didelot 91683f2244SVivien Didelot /* There's no bus specific operation to wait for a mask */ 92683f2244SVivien Didelot for (i = 0; i < 16; i++) { 93683f2244SVivien Didelot err = mv88e6xxx_read(chip, addr, reg, &data); 94683f2244SVivien Didelot if (err) 95683f2244SVivien Didelot return err; 96683f2244SVivien Didelot 97683f2244SVivien Didelot if ((data & mask) == val) 98683f2244SVivien Didelot return 0; 99683f2244SVivien Didelot 100683f2244SVivien Didelot usleep_range(1000, 2000); 101683f2244SVivien Didelot } 102683f2244SVivien Didelot 103683f2244SVivien Didelot dev_err(chip->dev, "Timeout while waiting for switch\n"); 104683f2244SVivien Didelot return -ETIMEDOUT; 105683f2244SVivien Didelot } 106683f2244SVivien Didelot 10719fb7f69SVivien Didelot int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg, 10819fb7f69SVivien Didelot int bit, int val) 10919fb7f69SVivien Didelot { 11019fb7f69SVivien Didelot return mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit), 11119fb7f69SVivien Didelot val ? BIT(bit) : 0x0000); 11219fb7f69SVivien Didelot } 11319fb7f69SVivien Didelot 11410fa5bfcSAndrew Lunn struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip) 115a3c53be5SAndrew Lunn { 116a3c53be5SAndrew Lunn struct mv88e6xxx_mdio_bus *mdio_bus; 117a3c53be5SAndrew Lunn 118a3c53be5SAndrew Lunn mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus, 119a3c53be5SAndrew Lunn list); 120a3c53be5SAndrew Lunn if (!mdio_bus) 121a3c53be5SAndrew Lunn return NULL; 122a3c53be5SAndrew Lunn 123a3c53be5SAndrew Lunn return mdio_bus->bus; 124a3c53be5SAndrew Lunn } 125a3c53be5SAndrew Lunn 126dc30c35bSAndrew Lunn static void mv88e6xxx_g1_irq_mask(struct irq_data *d) 127dc30c35bSAndrew Lunn { 128dc30c35bSAndrew Lunn struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); 129dc30c35bSAndrew Lunn unsigned int n = d->hwirq; 130dc30c35bSAndrew Lunn 131dc30c35bSAndrew Lunn chip->g1_irq.masked |= (1 << n); 132dc30c35bSAndrew Lunn } 133dc30c35bSAndrew Lunn 134dc30c35bSAndrew Lunn static void mv88e6xxx_g1_irq_unmask(struct irq_data *d) 135dc30c35bSAndrew Lunn { 136dc30c35bSAndrew Lunn struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); 137dc30c35bSAndrew Lunn unsigned int n = d->hwirq; 138dc30c35bSAndrew Lunn 139dc30c35bSAndrew Lunn chip->g1_irq.masked &= ~(1 << n); 140dc30c35bSAndrew Lunn } 141dc30c35bSAndrew Lunn 142294d711eSAndrew Lunn static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip) 143dc30c35bSAndrew Lunn { 144dc30c35bSAndrew Lunn unsigned int nhandled = 0; 145dc30c35bSAndrew Lunn unsigned int sub_irq; 146dc30c35bSAndrew Lunn unsigned int n; 147dc30c35bSAndrew Lunn u16 reg; 1487c0db24cSJohn David Anglin u16 ctl1; 149dc30c35bSAndrew Lunn int err; 150dc30c35bSAndrew Lunn 151c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 15282466921SVivien Didelot err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, ®); 153c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 154dc30c35bSAndrew Lunn 155dc30c35bSAndrew Lunn if (err) 156dc30c35bSAndrew Lunn goto out; 157dc30c35bSAndrew Lunn 1587c0db24cSJohn David Anglin do { 159dc30c35bSAndrew Lunn for (n = 0; n < chip->g1_irq.nirqs; ++n) { 160dc30c35bSAndrew Lunn if (reg & (1 << n)) { 1617c0db24cSJohn David Anglin sub_irq = irq_find_mapping(chip->g1_irq.domain, 1627c0db24cSJohn David Anglin n); 163dc30c35bSAndrew Lunn handle_nested_irq(sub_irq); 164dc30c35bSAndrew Lunn ++nhandled; 165dc30c35bSAndrew Lunn } 166dc30c35bSAndrew Lunn } 1677c0db24cSJohn David Anglin 168c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1697c0db24cSJohn David Anglin err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1); 1707c0db24cSJohn David Anglin if (err) 1717c0db24cSJohn David Anglin goto unlock; 1727c0db24cSJohn David Anglin err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, ®); 1737c0db24cSJohn David Anglin unlock: 174c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1757c0db24cSJohn David Anglin if (err) 1767c0db24cSJohn David Anglin goto out; 1777c0db24cSJohn David Anglin ctl1 &= GENMASK(chip->g1_irq.nirqs, 0); 1787c0db24cSJohn David Anglin } while (reg & ctl1); 1797c0db24cSJohn David Anglin 180dc30c35bSAndrew Lunn out: 181dc30c35bSAndrew Lunn return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 182dc30c35bSAndrew Lunn } 183dc30c35bSAndrew Lunn 184294d711eSAndrew Lunn static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id) 185294d711eSAndrew Lunn { 186294d711eSAndrew Lunn struct mv88e6xxx_chip *chip = dev_id; 187294d711eSAndrew Lunn 188294d711eSAndrew Lunn return mv88e6xxx_g1_irq_thread_work(chip); 189294d711eSAndrew Lunn } 190294d711eSAndrew Lunn 191dc30c35bSAndrew Lunn static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d) 192dc30c35bSAndrew Lunn { 193dc30c35bSAndrew Lunn struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); 194dc30c35bSAndrew Lunn 195c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 196dc30c35bSAndrew Lunn } 197dc30c35bSAndrew Lunn 198dc30c35bSAndrew Lunn static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d) 199dc30c35bSAndrew Lunn { 200dc30c35bSAndrew Lunn struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); 201dc30c35bSAndrew Lunn u16 mask = GENMASK(chip->g1_irq.nirqs, 0); 202dc30c35bSAndrew Lunn u16 reg; 203dc30c35bSAndrew Lunn int err; 204dc30c35bSAndrew Lunn 205d77f4321SVivien Didelot err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, ®); 206dc30c35bSAndrew Lunn if (err) 207dc30c35bSAndrew Lunn goto out; 208dc30c35bSAndrew Lunn 209dc30c35bSAndrew Lunn reg &= ~mask; 210dc30c35bSAndrew Lunn reg |= (~chip->g1_irq.masked & mask); 211dc30c35bSAndrew Lunn 212d77f4321SVivien Didelot err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg); 213dc30c35bSAndrew Lunn if (err) 214dc30c35bSAndrew Lunn goto out; 215dc30c35bSAndrew Lunn 216dc30c35bSAndrew Lunn out: 217c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 218dc30c35bSAndrew Lunn } 219dc30c35bSAndrew Lunn 2206eb15e21SBhumika Goyal static const struct irq_chip mv88e6xxx_g1_irq_chip = { 221dc30c35bSAndrew Lunn .name = "mv88e6xxx-g1", 222dc30c35bSAndrew Lunn .irq_mask = mv88e6xxx_g1_irq_mask, 223dc30c35bSAndrew Lunn .irq_unmask = mv88e6xxx_g1_irq_unmask, 224dc30c35bSAndrew Lunn .irq_bus_lock = mv88e6xxx_g1_irq_bus_lock, 225dc30c35bSAndrew Lunn .irq_bus_sync_unlock = mv88e6xxx_g1_irq_bus_sync_unlock, 226dc30c35bSAndrew Lunn }; 227dc30c35bSAndrew Lunn 228dc30c35bSAndrew Lunn static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d, 229dc30c35bSAndrew Lunn unsigned int irq, 230dc30c35bSAndrew Lunn irq_hw_number_t hwirq) 231dc30c35bSAndrew Lunn { 232dc30c35bSAndrew Lunn struct mv88e6xxx_chip *chip = d->host_data; 233dc30c35bSAndrew Lunn 234dc30c35bSAndrew Lunn irq_set_chip_data(irq, d->host_data); 235dc30c35bSAndrew Lunn irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq); 236dc30c35bSAndrew Lunn irq_set_noprobe(irq); 237dc30c35bSAndrew Lunn 238dc30c35bSAndrew Lunn return 0; 239dc30c35bSAndrew Lunn } 240dc30c35bSAndrew Lunn 241dc30c35bSAndrew Lunn static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = { 242dc30c35bSAndrew Lunn .map = mv88e6xxx_g1_irq_domain_map, 243dc30c35bSAndrew Lunn .xlate = irq_domain_xlate_twocell, 244dc30c35bSAndrew Lunn }; 245dc30c35bSAndrew Lunn 2463d82475aSUwe Kleine-König /* To be called with reg_lock held */ 247294d711eSAndrew Lunn static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip) 248dc30c35bSAndrew Lunn { 249dc30c35bSAndrew Lunn int irq, virq; 2503460a577SAndrew Lunn u16 mask; 2513460a577SAndrew Lunn 252d77f4321SVivien Didelot mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask); 2533d5fdba1SAndrew Lunn mask &= ~GENMASK(chip->g1_irq.nirqs, 0); 254d77f4321SVivien Didelot mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); 2553460a577SAndrew Lunn 2565edef2f2SAndreas Färber for (irq = 0; irq < chip->g1_irq.nirqs; irq++) { 257a3db3d3aSAndrew Lunn virq = irq_find_mapping(chip->g1_irq.domain, irq); 258dc30c35bSAndrew Lunn irq_dispose_mapping(virq); 259dc30c35bSAndrew Lunn } 260dc30c35bSAndrew Lunn 261a3db3d3aSAndrew Lunn irq_domain_remove(chip->g1_irq.domain); 262dc30c35bSAndrew Lunn } 263dc30c35bSAndrew Lunn 264294d711eSAndrew Lunn static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip) 265294d711eSAndrew Lunn { 2663d82475aSUwe Kleine-König /* 2673d82475aSUwe Kleine-König * free_irq must be called without reg_lock taken because the irq 2683d82475aSUwe Kleine-König * handler takes this lock, too. 2693d82475aSUwe Kleine-König */ 270294d711eSAndrew Lunn free_irq(chip->irq, chip); 2713d82475aSUwe Kleine-König 272c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2733d82475aSUwe Kleine-König mv88e6xxx_g1_irq_free_common(chip); 274c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 275294d711eSAndrew Lunn } 276294d711eSAndrew Lunn 277294d711eSAndrew Lunn static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip) 278dc30c35bSAndrew Lunn { 2793dd0ef05SAndrew Lunn int err, irq, virq; 2803dd0ef05SAndrew Lunn u16 reg, mask; 281dc30c35bSAndrew Lunn 282dc30c35bSAndrew Lunn chip->g1_irq.nirqs = chip->info->g1_irqs; 283dc30c35bSAndrew Lunn chip->g1_irq.domain = irq_domain_add_simple( 284dc30c35bSAndrew Lunn NULL, chip->g1_irq.nirqs, 0, 285dc30c35bSAndrew Lunn &mv88e6xxx_g1_irq_domain_ops, chip); 286dc30c35bSAndrew Lunn if (!chip->g1_irq.domain) 287dc30c35bSAndrew Lunn return -ENOMEM; 288dc30c35bSAndrew Lunn 289dc30c35bSAndrew Lunn for (irq = 0; irq < chip->g1_irq.nirqs; irq++) 290dc30c35bSAndrew Lunn irq_create_mapping(chip->g1_irq.domain, irq); 291dc30c35bSAndrew Lunn 292dc30c35bSAndrew Lunn chip->g1_irq.chip = mv88e6xxx_g1_irq_chip; 293dc30c35bSAndrew Lunn chip->g1_irq.masked = ~0; 294dc30c35bSAndrew Lunn 295d77f4321SVivien Didelot err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask); 296dc30c35bSAndrew Lunn if (err) 2973dd0ef05SAndrew Lunn goto out_mapping; 298dc30c35bSAndrew Lunn 2993dd0ef05SAndrew Lunn mask &= ~GENMASK(chip->g1_irq.nirqs, 0); 300dc30c35bSAndrew Lunn 301d77f4321SVivien Didelot err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); 302dc30c35bSAndrew Lunn if (err) 3033dd0ef05SAndrew Lunn goto out_disable; 304dc30c35bSAndrew Lunn 305dc30c35bSAndrew Lunn /* Reading the interrupt status clears (most of) them */ 30682466921SVivien Didelot err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, ®); 307dc30c35bSAndrew Lunn if (err) 3083dd0ef05SAndrew Lunn goto out_disable; 309dc30c35bSAndrew Lunn 310dc30c35bSAndrew Lunn return 0; 311dc30c35bSAndrew Lunn 3123dd0ef05SAndrew Lunn out_disable: 3133d5fdba1SAndrew Lunn mask &= ~GENMASK(chip->g1_irq.nirqs, 0); 314d77f4321SVivien Didelot mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); 3153dd0ef05SAndrew Lunn 3163dd0ef05SAndrew Lunn out_mapping: 3173dd0ef05SAndrew Lunn for (irq = 0; irq < 16; irq++) { 3183dd0ef05SAndrew Lunn virq = irq_find_mapping(chip->g1_irq.domain, irq); 3193dd0ef05SAndrew Lunn irq_dispose_mapping(virq); 3203dd0ef05SAndrew Lunn } 3213dd0ef05SAndrew Lunn 3223dd0ef05SAndrew Lunn irq_domain_remove(chip->g1_irq.domain); 323dc30c35bSAndrew Lunn 324dc30c35bSAndrew Lunn return err; 325dc30c35bSAndrew Lunn } 326dc30c35bSAndrew Lunn 327294d711eSAndrew Lunn static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) 328294d711eSAndrew Lunn { 329f6d9758bSAndrew Lunn static struct lock_class_key lock_key; 330f6d9758bSAndrew Lunn static struct lock_class_key request_key; 331294d711eSAndrew Lunn int err; 332294d711eSAndrew Lunn 333294d711eSAndrew Lunn err = mv88e6xxx_g1_irq_setup_common(chip); 334294d711eSAndrew Lunn if (err) 335294d711eSAndrew Lunn return err; 336294d711eSAndrew Lunn 337f6d9758bSAndrew Lunn /* These lock classes tells lockdep that global 1 irqs are in 338f6d9758bSAndrew Lunn * a different category than their parent GPIO, so it won't 339f6d9758bSAndrew Lunn * report false recursion. 340f6d9758bSAndrew Lunn */ 341f6d9758bSAndrew Lunn irq_set_lockdep_class(chip->irq, &lock_key, &request_key); 342f6d9758bSAndrew Lunn 3433095383aSAndrew Lunn snprintf(chip->irq_name, sizeof(chip->irq_name), 3443095383aSAndrew Lunn "mv88e6xxx-%s", dev_name(chip->dev)); 3453095383aSAndrew Lunn 346c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 347294d711eSAndrew Lunn err = request_threaded_irq(chip->irq, NULL, 348294d711eSAndrew Lunn mv88e6xxx_g1_irq_thread_fn, 3490340376eSMarek Behún IRQF_ONESHOT | IRQF_SHARED, 3503095383aSAndrew Lunn chip->irq_name, chip); 351c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 352294d711eSAndrew Lunn if (err) 353294d711eSAndrew Lunn mv88e6xxx_g1_irq_free_common(chip); 354294d711eSAndrew Lunn 355294d711eSAndrew Lunn return err; 356294d711eSAndrew Lunn } 357294d711eSAndrew Lunn 358294d711eSAndrew Lunn static void mv88e6xxx_irq_poll(struct kthread_work *work) 359294d711eSAndrew Lunn { 360294d711eSAndrew Lunn struct mv88e6xxx_chip *chip = container_of(work, 361294d711eSAndrew Lunn struct mv88e6xxx_chip, 362294d711eSAndrew Lunn irq_poll_work.work); 363294d711eSAndrew Lunn mv88e6xxx_g1_irq_thread_work(chip); 364294d711eSAndrew Lunn 365294d711eSAndrew Lunn kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work, 366294d711eSAndrew Lunn msecs_to_jiffies(100)); 367294d711eSAndrew Lunn } 368294d711eSAndrew Lunn 369294d711eSAndrew Lunn static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip) 370294d711eSAndrew Lunn { 371294d711eSAndrew Lunn int err; 372294d711eSAndrew Lunn 373294d711eSAndrew Lunn err = mv88e6xxx_g1_irq_setup_common(chip); 374294d711eSAndrew Lunn if (err) 375294d711eSAndrew Lunn return err; 376294d711eSAndrew Lunn 377294d711eSAndrew Lunn kthread_init_delayed_work(&chip->irq_poll_work, 378294d711eSAndrew Lunn mv88e6xxx_irq_poll); 379294d711eSAndrew Lunn 3803f8b8696SFlorian Fainelli chip->kworker = kthread_create_worker(0, "%s", dev_name(chip->dev)); 381294d711eSAndrew Lunn if (IS_ERR(chip->kworker)) 382294d711eSAndrew Lunn return PTR_ERR(chip->kworker); 383294d711eSAndrew Lunn 384294d711eSAndrew Lunn kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work, 385294d711eSAndrew Lunn msecs_to_jiffies(100)); 386294d711eSAndrew Lunn 387294d711eSAndrew Lunn return 0; 388294d711eSAndrew Lunn } 389294d711eSAndrew Lunn 390294d711eSAndrew Lunn static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip) 391294d711eSAndrew Lunn { 392294d711eSAndrew Lunn kthread_cancel_delayed_work_sync(&chip->irq_poll_work); 393294d711eSAndrew Lunn kthread_destroy_worker(chip->kworker); 3943d82475aSUwe Kleine-König 395c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 3963d82475aSUwe Kleine-König mv88e6xxx_g1_irq_free_common(chip); 397c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 398294d711eSAndrew Lunn } 399294d711eSAndrew Lunn 40072d8b4fdSHeiner Kallweit int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, 40172d8b4fdSHeiner Kallweit int speed, int duplex, int pause, 402d78343d2SVivien Didelot phy_interface_t mode) 403d78343d2SVivien Didelot { 404a26deec6SAndrew Lunn struct phylink_link_state state; 405d78343d2SVivien Didelot int err; 406d78343d2SVivien Didelot 407d78343d2SVivien Didelot if (!chip->info->ops->port_set_link) 408d78343d2SVivien Didelot return 0; 409d78343d2SVivien Didelot 410a26deec6SAndrew Lunn if (!chip->info->ops->port_link_state) 411a26deec6SAndrew Lunn return 0; 412a26deec6SAndrew Lunn 413a26deec6SAndrew Lunn err = chip->info->ops->port_link_state(chip, port, &state); 414a26deec6SAndrew Lunn if (err) 415a26deec6SAndrew Lunn return err; 416a26deec6SAndrew Lunn 417a26deec6SAndrew Lunn /* Has anything actually changed? We don't expect the 418a26deec6SAndrew Lunn * interface mode to change without one of the other 419a26deec6SAndrew Lunn * parameters also changing 420a26deec6SAndrew Lunn */ 421a26deec6SAndrew Lunn if (state.link == link && 422a26deec6SAndrew Lunn state.speed == speed && 423927441adSMarek Behún state.duplex == duplex && 424927441adSMarek Behún (state.interface == mode || 425927441adSMarek Behún state.interface == PHY_INTERFACE_MODE_NA)) 426a26deec6SAndrew Lunn return 0; 427a26deec6SAndrew Lunn 428d78343d2SVivien Didelot /* Port's MAC control must not be changed unless the link is down */ 42943c8e0aeSHubert Feurstein err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN); 430d78343d2SVivien Didelot if (err) 431d78343d2SVivien Didelot return err; 432d78343d2SVivien Didelot 433d78343d2SVivien Didelot if (chip->info->ops->port_set_speed) { 434d78343d2SVivien Didelot err = chip->info->ops->port_set_speed(chip, port, speed); 435d78343d2SVivien Didelot if (err && err != -EOPNOTSUPP) 436d78343d2SVivien Didelot goto restore_link; 437d78343d2SVivien Didelot } 438d78343d2SVivien Didelot 4397cbbee05SAndrew Lunn if (speed == SPEED_MAX && chip->info->ops->port_max_speed_mode) 4407cbbee05SAndrew Lunn mode = chip->info->ops->port_max_speed_mode(port); 4417cbbee05SAndrew Lunn 44254186b91SAndrew Lunn if (chip->info->ops->port_set_pause) { 44354186b91SAndrew Lunn err = chip->info->ops->port_set_pause(chip, port, pause); 44454186b91SAndrew Lunn if (err) 44554186b91SAndrew Lunn goto restore_link; 44654186b91SAndrew Lunn } 44754186b91SAndrew Lunn 448d78343d2SVivien Didelot if (chip->info->ops->port_set_duplex) { 449d78343d2SVivien Didelot err = chip->info->ops->port_set_duplex(chip, port, duplex); 450d78343d2SVivien Didelot if (err && err != -EOPNOTSUPP) 451d78343d2SVivien Didelot goto restore_link; 452d78343d2SVivien Didelot } 453d78343d2SVivien Didelot 454d78343d2SVivien Didelot if (chip->info->ops->port_set_rgmii_delay) { 455d78343d2SVivien Didelot err = chip->info->ops->port_set_rgmii_delay(chip, port, mode); 456d78343d2SVivien Didelot if (err && err != -EOPNOTSUPP) 457d78343d2SVivien Didelot goto restore_link; 458d78343d2SVivien Didelot } 459d78343d2SVivien Didelot 460f39908d3SAndrew Lunn if (chip->info->ops->port_set_cmode) { 461f39908d3SAndrew Lunn err = chip->info->ops->port_set_cmode(chip, port, mode); 462f39908d3SAndrew Lunn if (err && err != -EOPNOTSUPP) 463f39908d3SAndrew Lunn goto restore_link; 464f39908d3SAndrew Lunn } 465f39908d3SAndrew Lunn 466d78343d2SVivien Didelot err = 0; 467d78343d2SVivien Didelot restore_link: 468d78343d2SVivien Didelot if (chip->info->ops->port_set_link(chip, port, link)) 469774439e5SVivien Didelot dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port); 470d78343d2SVivien Didelot 471d78343d2SVivien Didelot return err; 472d78343d2SVivien Didelot } 473d78343d2SVivien Didelot 474d700ec41SMarek Vasut static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) 475d700ec41SMarek Vasut { 476d700ec41SMarek Vasut struct mv88e6xxx_chip *chip = ds->priv; 477d700ec41SMarek Vasut 478d700ec41SMarek Vasut return port < chip->info->num_internal_phys; 479d700ec41SMarek Vasut } 480d700ec41SMarek Vasut 4816c422e34SRussell King static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port, 4826c422e34SRussell King unsigned long *mask, 4836c422e34SRussell King struct phylink_link_state *state) 4846c422e34SRussell King { 4856c422e34SRussell King if (!phy_interface_mode_is_8023z(state->interface)) { 4866c422e34SRussell King /* 10M and 100M are only supported in non-802.3z mode */ 4876c422e34SRussell King phylink_set(mask, 10baseT_Half); 4886c422e34SRussell King phylink_set(mask, 10baseT_Full); 4896c422e34SRussell King phylink_set(mask, 100baseT_Half); 4906c422e34SRussell King phylink_set(mask, 100baseT_Full); 4916c422e34SRussell King } 4926c422e34SRussell King } 4936c422e34SRussell King 4946c422e34SRussell King static void mv88e6185_phylink_validate(struct mv88e6xxx_chip *chip, int port, 4956c422e34SRussell King unsigned long *mask, 4966c422e34SRussell King struct phylink_link_state *state) 4976c422e34SRussell King { 4986c422e34SRussell King /* FIXME: if the port is in 1000Base-X mode, then it only supports 4996c422e34SRussell King * 1000M FD speeds. In this case, CMODE will indicate 5. 5006c422e34SRussell King */ 5016c422e34SRussell King phylink_set(mask, 1000baseT_Full); 5026c422e34SRussell King phylink_set(mask, 1000baseX_Full); 5036c422e34SRussell King 5046c422e34SRussell King mv88e6065_phylink_validate(chip, port, mask, state); 5056c422e34SRussell King } 5066c422e34SRussell King 507e3af71a3SMarek Behún static void mv88e6341_phylink_validate(struct mv88e6xxx_chip *chip, int port, 508e3af71a3SMarek Behún unsigned long *mask, 509e3af71a3SMarek Behún struct phylink_link_state *state) 510e3af71a3SMarek Behún { 511e3af71a3SMarek Behún if (port >= 5) 512e3af71a3SMarek Behún phylink_set(mask, 2500baseX_Full); 513e3af71a3SMarek Behún 514e3af71a3SMarek Behún /* No ethtool bits for 200Mbps */ 515e3af71a3SMarek Behún phylink_set(mask, 1000baseT_Full); 516e3af71a3SMarek Behún phylink_set(mask, 1000baseX_Full); 517e3af71a3SMarek Behún 518e3af71a3SMarek Behún mv88e6065_phylink_validate(chip, port, mask, state); 519e3af71a3SMarek Behún } 520e3af71a3SMarek Behún 5216c422e34SRussell King static void mv88e6352_phylink_validate(struct mv88e6xxx_chip *chip, int port, 5226c422e34SRussell King unsigned long *mask, 5236c422e34SRussell King struct phylink_link_state *state) 5246c422e34SRussell King { 5256c422e34SRussell King /* No ethtool bits for 200Mbps */ 5266c422e34SRussell King phylink_set(mask, 1000baseT_Full); 5276c422e34SRussell King phylink_set(mask, 1000baseX_Full); 5286c422e34SRussell King 5296c422e34SRussell King mv88e6065_phylink_validate(chip, port, mask, state); 5306c422e34SRussell King } 5316c422e34SRussell King 5326c422e34SRussell King static void mv88e6390_phylink_validate(struct mv88e6xxx_chip *chip, int port, 5336c422e34SRussell King unsigned long *mask, 5346c422e34SRussell King struct phylink_link_state *state) 5356c422e34SRussell King { 536ec26016bSAndrew Lunn if (port >= 9) { 5376c422e34SRussell King phylink_set(mask, 2500baseX_Full); 538ec26016bSAndrew Lunn phylink_set(mask, 2500baseT_Full); 539ec26016bSAndrew Lunn } 5406c422e34SRussell King 5416c422e34SRussell King /* No ethtool bits for 200Mbps */ 5426c422e34SRussell King phylink_set(mask, 1000baseT_Full); 5436c422e34SRussell King phylink_set(mask, 1000baseX_Full); 5446c422e34SRussell King 5456c422e34SRussell King mv88e6065_phylink_validate(chip, port, mask, state); 5466c422e34SRussell King } 5476c422e34SRussell King 5486c422e34SRussell King static void mv88e6390x_phylink_validate(struct mv88e6xxx_chip *chip, int port, 5496c422e34SRussell King unsigned long *mask, 5506c422e34SRussell King struct phylink_link_state *state) 5516c422e34SRussell King { 5526c422e34SRussell King if (port >= 9) { 5536c422e34SRussell King phylink_set(mask, 10000baseT_Full); 5546c422e34SRussell King phylink_set(mask, 10000baseKR_Full); 5556c422e34SRussell King } 5566c422e34SRussell King 5576c422e34SRussell King mv88e6390_phylink_validate(chip, port, mask, state); 5586c422e34SRussell King } 5596c422e34SRussell King 560c9a2356fSRussell King static void mv88e6xxx_validate(struct dsa_switch *ds, int port, 561c9a2356fSRussell King unsigned long *supported, 562c9a2356fSRussell King struct phylink_link_state *state) 563c9a2356fSRussell King { 5646c422e34SRussell King __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; 5656c422e34SRussell King struct mv88e6xxx_chip *chip = ds->priv; 5666c422e34SRussell King 5676c422e34SRussell King /* Allow all the expected bits */ 5686c422e34SRussell King phylink_set(mask, Autoneg); 5696c422e34SRussell King phylink_set(mask, Pause); 5706c422e34SRussell King phylink_set_port_modes(mask); 5716c422e34SRussell King 5726c422e34SRussell King if (chip->info->ops->phylink_validate) 5736c422e34SRussell King chip->info->ops->phylink_validate(chip, port, mask, state); 5746c422e34SRussell King 5756c422e34SRussell King bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); 5766c422e34SRussell King bitmap_and(state->advertising, state->advertising, mask, 5776c422e34SRussell King __ETHTOOL_LINK_MODE_MASK_NBITS); 5786c422e34SRussell King 5796c422e34SRussell King /* We can only operate at 2500BaseX or 1000BaseX. If requested 5806c422e34SRussell King * to advertise both, only report advertising at 2500BaseX. 5816c422e34SRussell King */ 5826c422e34SRussell King phylink_helper_basex_speed(state); 583c9a2356fSRussell King } 584c9a2356fSRussell King 585c9a2356fSRussell King static int mv88e6xxx_link_state(struct dsa_switch *ds, int port, 586c9a2356fSRussell King struct phylink_link_state *state) 587c9a2356fSRussell King { 588c9a2356fSRussell King struct mv88e6xxx_chip *chip = ds->priv; 589c9a2356fSRussell King int err; 590c9a2356fSRussell King 591c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 5926c422e34SRussell King if (chip->info->ops->port_link_state) 5936c422e34SRussell King err = chip->info->ops->port_link_state(chip, port, state); 5946c422e34SRussell King else 5956c422e34SRussell King err = -EOPNOTSUPP; 596c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 597c9a2356fSRussell King 598c9a2356fSRussell King return err; 599c9a2356fSRussell King } 600c9a2356fSRussell King 601c9a2356fSRussell King static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, 602c9a2356fSRussell King unsigned int mode, 603c9a2356fSRussell King const struct phylink_link_state *state) 604c9a2356fSRussell King { 605c9a2356fSRussell King struct mv88e6xxx_chip *chip = ds->priv; 60654186b91SAndrew Lunn int speed, duplex, link, pause, err; 607c9a2356fSRussell King 608d700ec41SMarek Vasut if ((mode == MLO_AN_PHY) && mv88e6xxx_phy_is_internal(ds, port)) 609c9a2356fSRussell King return; 610c9a2356fSRussell King 611c9a2356fSRussell King if (mode == MLO_AN_FIXED) { 612c9a2356fSRussell King link = LINK_FORCED_UP; 613c9a2356fSRussell King speed = state->speed; 614c9a2356fSRussell King duplex = state->duplex; 615d700ec41SMarek Vasut } else if (!mv88e6xxx_phy_is_internal(ds, port)) { 616d700ec41SMarek Vasut link = state->link; 617d700ec41SMarek Vasut speed = state->speed; 618d700ec41SMarek Vasut duplex = state->duplex; 619c9a2356fSRussell King } else { 620c9a2356fSRussell King speed = SPEED_UNFORCED; 621c9a2356fSRussell King duplex = DUPLEX_UNFORCED; 622c9a2356fSRussell King link = LINK_UNFORCED; 623c9a2356fSRussell King } 62454186b91SAndrew Lunn pause = !!phylink_test(state->advertising, Pause); 625c9a2356fSRussell King 626c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 62754186b91SAndrew Lunn err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, pause, 628c9a2356fSRussell King state->interface); 629c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 630c9a2356fSRussell King 631c9a2356fSRussell King if (err && err != -EOPNOTSUPP) 632c9a2356fSRussell King dev_err(ds->dev, "p%d: failed to configure MAC\n", port); 633c9a2356fSRussell King } 634c9a2356fSRussell King 635c9a2356fSRussell King static void mv88e6xxx_mac_link_force(struct dsa_switch *ds, int port, int link) 636c9a2356fSRussell King { 637c9a2356fSRussell King struct mv88e6xxx_chip *chip = ds->priv; 638c9a2356fSRussell King int err; 639c9a2356fSRussell King 640c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 641c9a2356fSRussell King err = chip->info->ops->port_set_link(chip, port, link); 642c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 643c9a2356fSRussell King 644c9a2356fSRussell King if (err) 645c9a2356fSRussell King dev_err(chip->dev, "p%d: failed to force MAC link\n", port); 646c9a2356fSRussell King } 647c9a2356fSRussell King 648c9a2356fSRussell King static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, 649c9a2356fSRussell King unsigned int mode, 650c9a2356fSRussell King phy_interface_t interface) 651c9a2356fSRussell King { 652c9a2356fSRussell King if (mode == MLO_AN_FIXED) 653c9a2356fSRussell King mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_DOWN); 654c9a2356fSRussell King } 655c9a2356fSRussell King 656c9a2356fSRussell King static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, 657c9a2356fSRussell King unsigned int mode, phy_interface_t interface, 658c9a2356fSRussell King struct phy_device *phydev) 659c9a2356fSRussell King { 660c9a2356fSRussell King if (mode == MLO_AN_FIXED) 661c9a2356fSRussell King mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP); 662c9a2356fSRussell King } 663c9a2356fSRussell King 664a605a0feSAndrew Lunn static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 665fad09c73SVivien Didelot { 666a605a0feSAndrew Lunn if (!chip->info->ops->stats_snapshot) 667a605a0feSAndrew Lunn return -EOPNOTSUPP; 668fad09c73SVivien Didelot 669a605a0feSAndrew Lunn return chip->info->ops->stats_snapshot(chip, port); 670fad09c73SVivien Didelot } 671fad09c73SVivien Didelot 672fad09c73SVivien Didelot static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = { 673dfafe449SAndrew Lunn { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, }, 674dfafe449SAndrew Lunn { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, }, 675dfafe449SAndrew Lunn { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, }, 676dfafe449SAndrew Lunn { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, }, 677dfafe449SAndrew Lunn { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, }, 678dfafe449SAndrew Lunn { "in_pause", 4, 0x16, STATS_TYPE_BANK0, }, 679dfafe449SAndrew Lunn { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, }, 680dfafe449SAndrew Lunn { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, }, 681dfafe449SAndrew Lunn { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, }, 682dfafe449SAndrew Lunn { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, }, 683dfafe449SAndrew Lunn { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, }, 684dfafe449SAndrew Lunn { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, }, 685dfafe449SAndrew Lunn { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, }, 686dfafe449SAndrew Lunn { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, }, 687dfafe449SAndrew Lunn { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, }, 688dfafe449SAndrew Lunn { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, }, 689dfafe449SAndrew Lunn { "out_pause", 4, 0x15, STATS_TYPE_BANK0, }, 690dfafe449SAndrew Lunn { "excessive", 4, 0x11, STATS_TYPE_BANK0, }, 691dfafe449SAndrew Lunn { "collisions", 4, 0x1e, STATS_TYPE_BANK0, }, 692dfafe449SAndrew Lunn { "deferred", 4, 0x05, STATS_TYPE_BANK0, }, 693dfafe449SAndrew Lunn { "single", 4, 0x14, STATS_TYPE_BANK0, }, 694dfafe449SAndrew Lunn { "multiple", 4, 0x17, STATS_TYPE_BANK0, }, 695dfafe449SAndrew Lunn { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, }, 696dfafe449SAndrew Lunn { "late", 4, 0x1f, STATS_TYPE_BANK0, }, 697dfafe449SAndrew Lunn { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, }, 698dfafe449SAndrew Lunn { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, }, 699dfafe449SAndrew Lunn { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, }, 700dfafe449SAndrew Lunn { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, }, 701dfafe449SAndrew Lunn { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, }, 702dfafe449SAndrew Lunn { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, }, 703dfafe449SAndrew Lunn { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, }, 704dfafe449SAndrew Lunn { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, }, 705dfafe449SAndrew Lunn { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, }, 706dfafe449SAndrew Lunn { "in_discards", 4, 0x00, STATS_TYPE_BANK1, }, 707dfafe449SAndrew Lunn { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, }, 708dfafe449SAndrew Lunn { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, }, 709dfafe449SAndrew Lunn { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, }, 710dfafe449SAndrew Lunn { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, }, 711dfafe449SAndrew Lunn { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, }, 712dfafe449SAndrew Lunn { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, }, 713dfafe449SAndrew Lunn { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, }, 714dfafe449SAndrew Lunn { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, }, 715dfafe449SAndrew Lunn { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, }, 716dfafe449SAndrew Lunn { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, }, 717dfafe449SAndrew Lunn { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, }, 718dfafe449SAndrew Lunn { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, }, 719dfafe449SAndrew Lunn { "in_management", 4, 0x0f, STATS_TYPE_BANK1, }, 720dfafe449SAndrew Lunn { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, }, 721dfafe449SAndrew Lunn { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, }, 722dfafe449SAndrew Lunn { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, }, 723dfafe449SAndrew Lunn { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, }, 724dfafe449SAndrew Lunn { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, }, 725dfafe449SAndrew Lunn { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, }, 726dfafe449SAndrew Lunn { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, }, 727dfafe449SAndrew Lunn { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, }, 728dfafe449SAndrew Lunn { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, }, 729dfafe449SAndrew Lunn { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, }, 730dfafe449SAndrew Lunn { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, }, 731dfafe449SAndrew Lunn { "out_management", 4, 0x1f, STATS_TYPE_BANK1, }, 732fad09c73SVivien Didelot }; 733fad09c73SVivien Didelot 734fad09c73SVivien Didelot static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, 735fad09c73SVivien Didelot struct mv88e6xxx_hw_stat *s, 736e0d8b615SAndrew Lunn int port, u16 bank1_select, 737e0d8b615SAndrew Lunn u16 histogram) 738fad09c73SVivien Didelot { 739fad09c73SVivien Didelot u32 low; 740fad09c73SVivien Didelot u32 high = 0; 741dfafe449SAndrew Lunn u16 reg = 0; 7420e7b9925SAndrew Lunn int err; 743fad09c73SVivien Didelot u64 value; 744fad09c73SVivien Didelot 745fad09c73SVivien Didelot switch (s->type) { 746dfafe449SAndrew Lunn case STATS_TYPE_PORT: 7470e7b9925SAndrew Lunn err = mv88e6xxx_port_read(chip, port, s->reg, ®); 7480e7b9925SAndrew Lunn if (err) 7496c3442f5SJisheng Zhang return U64_MAX; 750fad09c73SVivien Didelot 7510e7b9925SAndrew Lunn low = reg; 752cda9f4aaSAndrew Lunn if (s->size == 4) { 7530e7b9925SAndrew Lunn err = mv88e6xxx_port_read(chip, port, s->reg + 1, ®); 7540e7b9925SAndrew Lunn if (err) 7556c3442f5SJisheng Zhang return U64_MAX; 75684b3fd1fSRasmus Villemoes low |= ((u32)reg) << 16; 757fad09c73SVivien Didelot } 758fad09c73SVivien Didelot break; 759dfafe449SAndrew Lunn case STATS_TYPE_BANK1: 760e0d8b615SAndrew Lunn reg = bank1_select; 761dfafe449SAndrew Lunn /* fall through */ 762dfafe449SAndrew Lunn case STATS_TYPE_BANK0: 763e0d8b615SAndrew Lunn reg |= s->reg | histogram; 7647f9ef3afSAndrew Lunn mv88e6xxx_g1_stats_read(chip, reg, &low); 765cda9f4aaSAndrew Lunn if (s->size == 8) 7667f9ef3afSAndrew Lunn mv88e6xxx_g1_stats_read(chip, reg + 1, &high); 7679fc3e4dcSGustavo A. R. Silva break; 7689fc3e4dcSGustavo A. R. Silva default: 7696c3442f5SJisheng Zhang return U64_MAX; 770fad09c73SVivien Didelot } 7716e46e2d8SAndrew Lunn value = (((u64)high) << 32) | low; 772fad09c73SVivien Didelot return value; 773fad09c73SVivien Didelot } 774fad09c73SVivien Didelot 775436fe17dSAndrew Lunn static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip, 776dfafe449SAndrew Lunn uint8_t *data, int types) 777fad09c73SVivien Didelot { 778fad09c73SVivien Didelot struct mv88e6xxx_hw_stat *stat; 779fad09c73SVivien Didelot int i, j; 780fad09c73SVivien Didelot 781fad09c73SVivien Didelot for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { 782fad09c73SVivien Didelot stat = &mv88e6xxx_hw_stats[i]; 783dfafe449SAndrew Lunn if (stat->type & types) { 784fad09c73SVivien Didelot memcpy(data + j * ETH_GSTRING_LEN, stat->string, 785fad09c73SVivien Didelot ETH_GSTRING_LEN); 786fad09c73SVivien Didelot j++; 787fad09c73SVivien Didelot } 788fad09c73SVivien Didelot } 789436fe17dSAndrew Lunn 790436fe17dSAndrew Lunn return j; 791fad09c73SVivien Didelot } 792fad09c73SVivien Didelot 793436fe17dSAndrew Lunn static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip, 794dfafe449SAndrew Lunn uint8_t *data) 795dfafe449SAndrew Lunn { 796436fe17dSAndrew Lunn return mv88e6xxx_stats_get_strings(chip, data, 797dfafe449SAndrew Lunn STATS_TYPE_BANK0 | STATS_TYPE_PORT); 798dfafe449SAndrew Lunn } 799dfafe449SAndrew Lunn 8001f71836fSRasmus Villemoes static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip, 8011f71836fSRasmus Villemoes uint8_t *data) 8021f71836fSRasmus Villemoes { 8031f71836fSRasmus Villemoes return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0); 8041f71836fSRasmus Villemoes } 8051f71836fSRasmus Villemoes 806436fe17dSAndrew Lunn static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, 807dfafe449SAndrew Lunn uint8_t *data) 808dfafe449SAndrew Lunn { 809436fe17dSAndrew Lunn return mv88e6xxx_stats_get_strings(chip, data, 810dfafe449SAndrew Lunn STATS_TYPE_BANK0 | STATS_TYPE_BANK1); 811dfafe449SAndrew Lunn } 812dfafe449SAndrew Lunn 81365f60e45SAndrew Lunn static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = { 81465f60e45SAndrew Lunn "atu_member_violation", 81565f60e45SAndrew Lunn "atu_miss_violation", 81665f60e45SAndrew Lunn "atu_full_violation", 81765f60e45SAndrew Lunn "vtu_member_violation", 81865f60e45SAndrew Lunn "vtu_miss_violation", 81965f60e45SAndrew Lunn }; 82065f60e45SAndrew Lunn 82165f60e45SAndrew Lunn static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data) 82265f60e45SAndrew Lunn { 82365f60e45SAndrew Lunn unsigned int i; 82465f60e45SAndrew Lunn 82565f60e45SAndrew Lunn for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++) 82665f60e45SAndrew Lunn strlcpy(data + i * ETH_GSTRING_LEN, 82765f60e45SAndrew Lunn mv88e6xxx_atu_vtu_stats_strings[i], 82865f60e45SAndrew Lunn ETH_GSTRING_LEN); 82965f60e45SAndrew Lunn } 83065f60e45SAndrew Lunn 831dfafe449SAndrew Lunn static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, 83289f09048SFlorian Fainelli u32 stringset, uint8_t *data) 833fad09c73SVivien Didelot { 83404bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 835436fe17dSAndrew Lunn int count = 0; 836dfafe449SAndrew Lunn 83789f09048SFlorian Fainelli if (stringset != ETH_SS_STATS) 83889f09048SFlorian Fainelli return; 83989f09048SFlorian Fainelli 840c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 841c6c8cd5eSAndrew Lunn 842dfafe449SAndrew Lunn if (chip->info->ops->stats_get_strings) 843436fe17dSAndrew Lunn count = chip->info->ops->stats_get_strings(chip, data); 844436fe17dSAndrew Lunn 845436fe17dSAndrew Lunn if (chip->info->ops->serdes_get_strings) { 846436fe17dSAndrew Lunn data += count * ETH_GSTRING_LEN; 84765f60e45SAndrew Lunn count = chip->info->ops->serdes_get_strings(chip, port, data); 848436fe17dSAndrew Lunn } 849c6c8cd5eSAndrew Lunn 85065f60e45SAndrew Lunn data += count * ETH_GSTRING_LEN; 85165f60e45SAndrew Lunn mv88e6xxx_atu_vtu_get_strings(data); 85265f60e45SAndrew Lunn 853c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 854dfafe449SAndrew Lunn } 855dfafe449SAndrew Lunn 856dfafe449SAndrew Lunn static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip, 857dfafe449SAndrew Lunn int types) 858dfafe449SAndrew Lunn { 859fad09c73SVivien Didelot struct mv88e6xxx_hw_stat *stat; 860fad09c73SVivien Didelot int i, j; 861fad09c73SVivien Didelot 862fad09c73SVivien Didelot for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { 863fad09c73SVivien Didelot stat = &mv88e6xxx_hw_stats[i]; 864dfafe449SAndrew Lunn if (stat->type & types) 865fad09c73SVivien Didelot j++; 866fad09c73SVivien Didelot } 867fad09c73SVivien Didelot return j; 868fad09c73SVivien Didelot } 869fad09c73SVivien Didelot 870dfafe449SAndrew Lunn static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip) 871dfafe449SAndrew Lunn { 872dfafe449SAndrew Lunn return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 | 873dfafe449SAndrew Lunn STATS_TYPE_PORT); 874dfafe449SAndrew Lunn } 875dfafe449SAndrew Lunn 8761f71836fSRasmus Villemoes static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip) 8771f71836fSRasmus Villemoes { 8781f71836fSRasmus Villemoes return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0); 8791f71836fSRasmus Villemoes } 8801f71836fSRasmus Villemoes 881dfafe449SAndrew Lunn static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) 882dfafe449SAndrew Lunn { 883dfafe449SAndrew Lunn return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 | 884dfafe449SAndrew Lunn STATS_TYPE_BANK1); 885dfafe449SAndrew Lunn } 886dfafe449SAndrew Lunn 88789f09048SFlorian Fainelli static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset) 888dfafe449SAndrew Lunn { 889dfafe449SAndrew Lunn struct mv88e6xxx_chip *chip = ds->priv; 890436fe17dSAndrew Lunn int serdes_count = 0; 891436fe17dSAndrew Lunn int count = 0; 892dfafe449SAndrew Lunn 89389f09048SFlorian Fainelli if (sset != ETH_SS_STATS) 89489f09048SFlorian Fainelli return 0; 89589f09048SFlorian Fainelli 896c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 897dfafe449SAndrew Lunn if (chip->info->ops->stats_get_sset_count) 898436fe17dSAndrew Lunn count = chip->info->ops->stats_get_sset_count(chip); 899436fe17dSAndrew Lunn if (count < 0) 900436fe17dSAndrew Lunn goto out; 901436fe17dSAndrew Lunn 902436fe17dSAndrew Lunn if (chip->info->ops->serdes_get_sset_count) 903436fe17dSAndrew Lunn serdes_count = chip->info->ops->serdes_get_sset_count(chip, 904436fe17dSAndrew Lunn port); 90565f60e45SAndrew Lunn if (serdes_count < 0) { 906436fe17dSAndrew Lunn count = serdes_count; 90765f60e45SAndrew Lunn goto out; 90865f60e45SAndrew Lunn } 909436fe17dSAndrew Lunn count += serdes_count; 91065f60e45SAndrew Lunn count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); 91165f60e45SAndrew Lunn 912436fe17dSAndrew Lunn out: 913c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 914dfafe449SAndrew Lunn 915436fe17dSAndrew Lunn return count; 916dfafe449SAndrew Lunn } 917dfafe449SAndrew Lunn 918436fe17dSAndrew Lunn static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port, 919e0d8b615SAndrew Lunn uint64_t *data, int types, 920e0d8b615SAndrew Lunn u16 bank1_select, u16 histogram) 921052f947fSAndrew Lunn { 922052f947fSAndrew Lunn struct mv88e6xxx_hw_stat *stat; 923052f947fSAndrew Lunn int i, j; 924052f947fSAndrew Lunn 925052f947fSAndrew Lunn for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { 926052f947fSAndrew Lunn stat = &mv88e6xxx_hw_stats[i]; 927052f947fSAndrew Lunn if (stat->type & types) { 928c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 929e0d8b615SAndrew Lunn data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 930e0d8b615SAndrew Lunn bank1_select, 931e0d8b615SAndrew Lunn histogram); 932c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 933377cda13SAndrew Lunn 934052f947fSAndrew Lunn j++; 935052f947fSAndrew Lunn } 936052f947fSAndrew Lunn } 937436fe17dSAndrew Lunn return j; 938052f947fSAndrew Lunn } 939052f947fSAndrew Lunn 940436fe17dSAndrew Lunn static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port, 941052f947fSAndrew Lunn uint64_t *data) 942052f947fSAndrew Lunn { 943052f947fSAndrew Lunn return mv88e6xxx_stats_get_stats(chip, port, data, 944e0d8b615SAndrew Lunn STATS_TYPE_BANK0 | STATS_TYPE_PORT, 94557d1ef38SVivien Didelot 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); 946052f947fSAndrew Lunn } 947052f947fSAndrew Lunn 9481f71836fSRasmus Villemoes static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port, 9491f71836fSRasmus Villemoes uint64_t *data) 9501f71836fSRasmus Villemoes { 9511f71836fSRasmus Villemoes return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0, 9521f71836fSRasmus Villemoes 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); 9531f71836fSRasmus Villemoes } 9541f71836fSRasmus Villemoes 955436fe17dSAndrew Lunn static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, 956052f947fSAndrew Lunn uint64_t *data) 957052f947fSAndrew Lunn { 958052f947fSAndrew Lunn return mv88e6xxx_stats_get_stats(chip, port, data, 959e0d8b615SAndrew Lunn STATS_TYPE_BANK0 | STATS_TYPE_BANK1, 96057d1ef38SVivien Didelot MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9, 96157d1ef38SVivien Didelot MV88E6XXX_G1_STATS_OP_HIST_RX_TX); 962e0d8b615SAndrew Lunn } 963e0d8b615SAndrew Lunn 964436fe17dSAndrew Lunn static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port, 965e0d8b615SAndrew Lunn uint64_t *data) 966e0d8b615SAndrew Lunn { 967e0d8b615SAndrew Lunn return mv88e6xxx_stats_get_stats(chip, port, data, 968e0d8b615SAndrew Lunn STATS_TYPE_BANK0 | STATS_TYPE_BANK1, 96957d1ef38SVivien Didelot MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10, 97057d1ef38SVivien Didelot 0); 971052f947fSAndrew Lunn } 972052f947fSAndrew Lunn 97365f60e45SAndrew Lunn static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port, 97465f60e45SAndrew Lunn uint64_t *data) 97565f60e45SAndrew Lunn { 97665f60e45SAndrew Lunn *data++ = chip->ports[port].atu_member_violation; 97765f60e45SAndrew Lunn *data++ = chip->ports[port].atu_miss_violation; 97865f60e45SAndrew Lunn *data++ = chip->ports[port].atu_full_violation; 97965f60e45SAndrew Lunn *data++ = chip->ports[port].vtu_member_violation; 98065f60e45SAndrew Lunn *data++ = chip->ports[port].vtu_miss_violation; 98165f60e45SAndrew Lunn } 98265f60e45SAndrew Lunn 983052f947fSAndrew Lunn static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, 984052f947fSAndrew Lunn uint64_t *data) 985052f947fSAndrew Lunn { 986436fe17dSAndrew Lunn int count = 0; 987436fe17dSAndrew Lunn 988052f947fSAndrew Lunn if (chip->info->ops->stats_get_stats) 989436fe17dSAndrew Lunn count = chip->info->ops->stats_get_stats(chip, port, data); 990436fe17dSAndrew Lunn 991c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 992436fe17dSAndrew Lunn if (chip->info->ops->serdes_get_stats) { 993436fe17dSAndrew Lunn data += count; 99465f60e45SAndrew Lunn count = chip->info->ops->serdes_get_stats(chip, port, data); 995436fe17dSAndrew Lunn } 99665f60e45SAndrew Lunn data += count; 99765f60e45SAndrew Lunn mv88e6xxx_atu_vtu_get_stats(chip, port, data); 998c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 999052f947fSAndrew Lunn } 1000052f947fSAndrew Lunn 1001fad09c73SVivien Didelot static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, 1002fad09c73SVivien Didelot uint64_t *data) 1003fad09c73SVivien Didelot { 100404bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1005fad09c73SVivien Didelot int ret; 1006fad09c73SVivien Didelot 1007c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1008fad09c73SVivien Didelot 1009a605a0feSAndrew Lunn ret = mv88e6xxx_stats_snapshot(chip, port); 1010c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1011377cda13SAndrew Lunn 1012377cda13SAndrew Lunn if (ret < 0) 1013fad09c73SVivien Didelot return; 1014052f947fSAndrew Lunn 1015052f947fSAndrew Lunn mv88e6xxx_get_stats(chip, port, data); 1016fad09c73SVivien Didelot 1017fad09c73SVivien Didelot } 1018fad09c73SVivien Didelot 1019fad09c73SVivien Didelot static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port) 1020fad09c73SVivien Didelot { 1021fad09c73SVivien Didelot return 32 * sizeof(u16); 1022fad09c73SVivien Didelot } 1023fad09c73SVivien Didelot 1024fad09c73SVivien Didelot static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, 1025fad09c73SVivien Didelot struct ethtool_regs *regs, void *_p) 1026fad09c73SVivien Didelot { 102704bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 10280e7b9925SAndrew Lunn int err; 10290e7b9925SAndrew Lunn u16 reg; 1030fad09c73SVivien Didelot u16 *p = _p; 1031fad09c73SVivien Didelot int i; 1032fad09c73SVivien Didelot 1033a5f39326SVivien Didelot regs->version = chip->info->prod_num; 1034fad09c73SVivien Didelot 1035fad09c73SVivien Didelot memset(p, 0xff, 32 * sizeof(u16)); 1036fad09c73SVivien Didelot 1037c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1038fad09c73SVivien Didelot 1039fad09c73SVivien Didelot for (i = 0; i < 32; i++) { 1040fad09c73SVivien Didelot 10410e7b9925SAndrew Lunn err = mv88e6xxx_port_read(chip, port, i, ®); 10420e7b9925SAndrew Lunn if (!err) 10430e7b9925SAndrew Lunn p[i] = reg; 1044fad09c73SVivien Didelot } 1045fad09c73SVivien Didelot 1046c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1047fad09c73SVivien Didelot } 1048fad09c73SVivien Didelot 104908f50061SVivien Didelot static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port, 1050fad09c73SVivien Didelot struct ethtool_eee *e) 1051fad09c73SVivien Didelot { 10525480db69SVivien Didelot /* Nothing to do on the port's MAC */ 10535480db69SVivien Didelot return 0; 1054fad09c73SVivien Didelot } 1055fad09c73SVivien Didelot 105608f50061SVivien Didelot static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port, 105746587e4aSVivien Didelot struct ethtool_eee *e) 1058fad09c73SVivien Didelot { 10595480db69SVivien Didelot /* Nothing to do on the port's MAC */ 10605480db69SVivien Didelot return 0; 1061fad09c73SVivien Didelot } 1062fad09c73SVivien Didelot 10639dc8b13eSVivien Didelot /* Mask of the local ports allowed to receive frames from a given fabric port */ 1064e5887a2aSVivien Didelot static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port) 1065fad09c73SVivien Didelot { 10669dc8b13eSVivien Didelot struct dsa_switch *ds = chip->ds; 10679dc8b13eSVivien Didelot struct dsa_switch_tree *dst = ds->dst; 1068e5887a2aSVivien Didelot struct net_device *br; 10699dc8b13eSVivien Didelot struct dsa_port *dp; 10709dc8b13eSVivien Didelot bool found = false; 1071e5887a2aSVivien Didelot u16 pvlan; 1072fad09c73SVivien Didelot 10739dc8b13eSVivien Didelot list_for_each_entry(dp, &dst->ports, list) { 10749dc8b13eSVivien Didelot if (dp->ds->index == dev && dp->index == port) { 10759dc8b13eSVivien Didelot found = true; 10769dc8b13eSVivien Didelot break; 10779dc8b13eSVivien Didelot } 10789dc8b13eSVivien Didelot } 1079fad09c73SVivien Didelot 1080e5887a2aSVivien Didelot /* Prevent frames from unknown switch or port */ 10819dc8b13eSVivien Didelot if (!found) 1082e5887a2aSVivien Didelot return 0; 1083e5887a2aSVivien Didelot 1084e5887a2aSVivien Didelot /* Frames from DSA links and CPU ports can egress any local port */ 10859dc8b13eSVivien Didelot if (dp->type == DSA_PORT_TYPE_CPU || dp->type == DSA_PORT_TYPE_DSA) 1086e5887a2aSVivien Didelot return mv88e6xxx_port_mask(chip); 1087e5887a2aSVivien Didelot 10889dc8b13eSVivien Didelot br = dp->bridge_dev; 1089e5887a2aSVivien Didelot pvlan = 0; 1090e5887a2aSVivien Didelot 1091e5887a2aSVivien Didelot /* Frames from user ports can egress any local DSA links and CPU ports, 1092e5887a2aSVivien Didelot * as well as any local member of their bridge group. 1093e5887a2aSVivien Didelot */ 10949dc8b13eSVivien Didelot list_for_each_entry(dp, &dst->ports, list) 10959dc8b13eSVivien Didelot if (dp->ds == ds && 10969dc8b13eSVivien Didelot (dp->type == DSA_PORT_TYPE_CPU || 10979dc8b13eSVivien Didelot dp->type == DSA_PORT_TYPE_DSA || 10989dc8b13eSVivien Didelot (br && dp->bridge_dev == br))) 10999dc8b13eSVivien Didelot pvlan |= BIT(dp->index); 1100e5887a2aSVivien Didelot 1101e5887a2aSVivien Didelot return pvlan; 1102fad09c73SVivien Didelot } 1103e5887a2aSVivien Didelot 1104240ea3efSVivien Didelot static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port) 1105e5887a2aSVivien Didelot { 1106e5887a2aSVivien Didelot u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port); 1107fad09c73SVivien Didelot 1108fad09c73SVivien Didelot /* prevent frames from going back out of the port they came in on */ 1109fad09c73SVivien Didelot output_ports &= ~BIT(port); 1110fad09c73SVivien Didelot 11115a7921f4SVivien Didelot return mv88e6xxx_port_set_vlan_map(chip, port, output_ports); 1112fad09c73SVivien Didelot } 1113fad09c73SVivien Didelot 1114fad09c73SVivien Didelot static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, 1115fad09c73SVivien Didelot u8 state) 1116fad09c73SVivien Didelot { 111704bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1118fad09c73SVivien Didelot int err; 1119fad09c73SVivien Didelot 1120c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1121f894c29cSVivien Didelot err = mv88e6xxx_port_set_state(chip, port, state); 1122c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1123fad09c73SVivien Didelot 1124fad09c73SVivien Didelot if (err) 1125774439e5SVivien Didelot dev_err(ds->dev, "p%d: failed to update state\n", port); 1126fad09c73SVivien Didelot } 1127fad09c73SVivien Didelot 112893e18d61SVivien Didelot static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip) 112993e18d61SVivien Didelot { 113093e18d61SVivien Didelot int err; 113193e18d61SVivien Didelot 113293e18d61SVivien Didelot if (chip->info->ops->ieee_pri_map) { 113393e18d61SVivien Didelot err = chip->info->ops->ieee_pri_map(chip); 113493e18d61SVivien Didelot if (err) 113593e18d61SVivien Didelot return err; 113693e18d61SVivien Didelot } 113793e18d61SVivien Didelot 113893e18d61SVivien Didelot if (chip->info->ops->ip_pri_map) { 113993e18d61SVivien Didelot err = chip->info->ops->ip_pri_map(chip); 114093e18d61SVivien Didelot if (err) 114193e18d61SVivien Didelot return err; 114293e18d61SVivien Didelot } 114393e18d61SVivien Didelot 114493e18d61SVivien Didelot return 0; 114593e18d61SVivien Didelot } 114693e18d61SVivien Didelot 1147c7f047b6SVivien Didelot static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip) 1148c7f047b6SVivien Didelot { 1149c5f51765SVivien Didelot struct dsa_switch *ds = chip->ds; 1150c7f047b6SVivien Didelot int target, port; 1151c7f047b6SVivien Didelot int err; 1152c7f047b6SVivien Didelot 1153c7f047b6SVivien Didelot if (!chip->info->global2_addr) 1154c7f047b6SVivien Didelot return 0; 1155c7f047b6SVivien Didelot 1156c7f047b6SVivien Didelot /* Initialize the routing port to the 32 possible target devices */ 1157c7f047b6SVivien Didelot for (target = 0; target < 32; target++) { 1158c5f51765SVivien Didelot port = dsa_routing_port(ds, target); 1159c5f51765SVivien Didelot if (port == ds->num_ports) 1160c7f047b6SVivien Didelot port = 0x1f; 1161c7f047b6SVivien Didelot 1162c7f047b6SVivien Didelot err = mv88e6xxx_g2_device_mapping_write(chip, target, port); 1163c7f047b6SVivien Didelot if (err) 1164c7f047b6SVivien Didelot return err; 1165c7f047b6SVivien Didelot } 1166c7f047b6SVivien Didelot 116702317e68SVivien Didelot if (chip->info->ops->set_cascade_port) { 116802317e68SVivien Didelot port = MV88E6XXX_CASCADE_PORT_MULTIPLE; 116902317e68SVivien Didelot err = chip->info->ops->set_cascade_port(chip, port); 117002317e68SVivien Didelot if (err) 117102317e68SVivien Didelot return err; 117202317e68SVivien Didelot } 117302317e68SVivien Didelot 117423c98919SVivien Didelot err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index); 117523c98919SVivien Didelot if (err) 117623c98919SVivien Didelot return err; 117723c98919SVivien Didelot 1178c7f047b6SVivien Didelot return 0; 1179c7f047b6SVivien Didelot } 1180c7f047b6SVivien Didelot 1181b28f872dSVivien Didelot static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip) 1182b28f872dSVivien Didelot { 1183b28f872dSVivien Didelot /* Clear all trunk masks and mapping */ 1184b28f872dSVivien Didelot if (chip->info->global2_addr) 1185b28f872dSVivien Didelot return mv88e6xxx_g2_trunk_clear(chip); 1186b28f872dSVivien Didelot 1187b28f872dSVivien Didelot return 0; 1188b28f872dSVivien Didelot } 1189b28f872dSVivien Didelot 11909e5baf9bSVivien Didelot static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip) 11919e5baf9bSVivien Didelot { 11929e5baf9bSVivien Didelot if (chip->info->ops->rmu_disable) 11939e5baf9bSVivien Didelot return chip->info->ops->rmu_disable(chip); 11949e5baf9bSVivien Didelot 11959e5baf9bSVivien Didelot return 0; 11969e5baf9bSVivien Didelot } 11979e5baf9bSVivien Didelot 11989e907d73SVivien Didelot static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip) 11999e907d73SVivien Didelot { 12009e907d73SVivien Didelot if (chip->info->ops->pot_clear) 12019e907d73SVivien Didelot return chip->info->ops->pot_clear(chip); 12029e907d73SVivien Didelot 12039e907d73SVivien Didelot return 0; 12049e907d73SVivien Didelot } 12059e907d73SVivien Didelot 120651c901a7SVivien Didelot static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip) 120751c901a7SVivien Didelot { 120851c901a7SVivien Didelot if (chip->info->ops->mgmt_rsvd2cpu) 120951c901a7SVivien Didelot return chip->info->ops->mgmt_rsvd2cpu(chip); 121051c901a7SVivien Didelot 121151c901a7SVivien Didelot return 0; 121251c901a7SVivien Didelot } 121351c901a7SVivien Didelot 1214a2ac29d2SVivien Didelot static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip) 1215a2ac29d2SVivien Didelot { 1216c3a7d4adSVivien Didelot int err; 1217c3a7d4adSVivien Didelot 1218daefc943SVivien Didelot err = mv88e6xxx_g1_atu_flush(chip, 0, true); 1219daefc943SVivien Didelot if (err) 1220daefc943SVivien Didelot return err; 1221daefc943SVivien Didelot 1222c3a7d4adSVivien Didelot err = mv88e6xxx_g1_atu_set_learn2all(chip, true); 1223c3a7d4adSVivien Didelot if (err) 1224c3a7d4adSVivien Didelot return err; 1225c3a7d4adSVivien Didelot 1226a2ac29d2SVivien Didelot return mv88e6xxx_g1_atu_set_age_time(chip, 300000); 1227a2ac29d2SVivien Didelot } 1228a2ac29d2SVivien Didelot 1229cd8da8bbSVivien Didelot static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip) 1230cd8da8bbSVivien Didelot { 1231cd8da8bbSVivien Didelot int port; 1232cd8da8bbSVivien Didelot int err; 1233cd8da8bbSVivien Didelot 1234cd8da8bbSVivien Didelot if (!chip->info->ops->irl_init_all) 1235cd8da8bbSVivien Didelot return 0; 1236cd8da8bbSVivien Didelot 1237cd8da8bbSVivien Didelot for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { 1238cd8da8bbSVivien Didelot /* Disable ingress rate limiting by resetting all per port 1239cd8da8bbSVivien Didelot * ingress rate limit resources to their initial state. 1240cd8da8bbSVivien Didelot */ 1241cd8da8bbSVivien Didelot err = chip->info->ops->irl_init_all(chip, port); 1242cd8da8bbSVivien Didelot if (err) 1243cd8da8bbSVivien Didelot return err; 1244cd8da8bbSVivien Didelot } 1245cd8da8bbSVivien Didelot 1246cd8da8bbSVivien Didelot return 0; 1247cd8da8bbSVivien Didelot } 1248cd8da8bbSVivien Didelot 124904a69a17SVivien Didelot static int mv88e6xxx_mac_setup(struct mv88e6xxx_chip *chip) 125004a69a17SVivien Didelot { 125104a69a17SVivien Didelot if (chip->info->ops->set_switch_mac) { 125204a69a17SVivien Didelot u8 addr[ETH_ALEN]; 125304a69a17SVivien Didelot 125404a69a17SVivien Didelot eth_random_addr(addr); 125504a69a17SVivien Didelot 125604a69a17SVivien Didelot return chip->info->ops->set_switch_mac(chip, addr); 125704a69a17SVivien Didelot } 125804a69a17SVivien Didelot 125904a69a17SVivien Didelot return 0; 126004a69a17SVivien Didelot } 126104a69a17SVivien Didelot 126217a1594eSVivien Didelot static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port) 126317a1594eSVivien Didelot { 126417a1594eSVivien Didelot u16 pvlan = 0; 126517a1594eSVivien Didelot 126617a1594eSVivien Didelot if (!mv88e6xxx_has_pvt(chip)) 1267d14939beSVivien Didelot return 0; 126817a1594eSVivien Didelot 126917a1594eSVivien Didelot /* Skip the local source device, which uses in-chip port VLAN */ 127017a1594eSVivien Didelot if (dev != chip->ds->index) 1271aec5ac88SVivien Didelot pvlan = mv88e6xxx_port_vlan(chip, dev, port); 127217a1594eSVivien Didelot 127317a1594eSVivien Didelot return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan); 127417a1594eSVivien Didelot } 127517a1594eSVivien Didelot 127681228996SVivien Didelot static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip) 127781228996SVivien Didelot { 127817a1594eSVivien Didelot int dev, port; 127917a1594eSVivien Didelot int err; 128017a1594eSVivien Didelot 128181228996SVivien Didelot if (!mv88e6xxx_has_pvt(chip)) 128281228996SVivien Didelot return 0; 128381228996SVivien Didelot 128481228996SVivien Didelot /* Clear 5 Bit Port for usage with Marvell Link Street devices: 128581228996SVivien Didelot * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev. 128681228996SVivien Didelot */ 128717a1594eSVivien Didelot err = mv88e6xxx_g2_misc_4_bit_port(chip); 128817a1594eSVivien Didelot if (err) 128917a1594eSVivien Didelot return err; 129017a1594eSVivien Didelot 129117a1594eSVivien Didelot for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; ++dev) { 129217a1594eSVivien Didelot for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; ++port) { 129317a1594eSVivien Didelot err = mv88e6xxx_pvt_map(chip, dev, port); 129417a1594eSVivien Didelot if (err) 129517a1594eSVivien Didelot return err; 129617a1594eSVivien Didelot } 129717a1594eSVivien Didelot } 129817a1594eSVivien Didelot 129917a1594eSVivien Didelot return 0; 130081228996SVivien Didelot } 130181228996SVivien Didelot 1302749efcb8SVivien Didelot static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) 1303749efcb8SVivien Didelot { 1304749efcb8SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1305749efcb8SVivien Didelot int err; 1306749efcb8SVivien Didelot 1307c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1308e606ca36SVivien Didelot err = mv88e6xxx_g1_atu_remove(chip, 0, port, false); 1309c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1310749efcb8SVivien Didelot 1311749efcb8SVivien Didelot if (err) 1312774439e5SVivien Didelot dev_err(ds->dev, "p%d: failed to flush ATU\n", port); 1313749efcb8SVivien Didelot } 1314749efcb8SVivien Didelot 1315b486d7c9SVivien Didelot static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip) 1316b486d7c9SVivien Didelot { 1317b486d7c9SVivien Didelot if (!chip->info->max_vid) 1318b486d7c9SVivien Didelot return 0; 1319b486d7c9SVivien Didelot 1320b486d7c9SVivien Didelot return mv88e6xxx_g1_vtu_flush(chip); 1321b486d7c9SVivien Didelot } 1322b486d7c9SVivien Didelot 1323f1394b78SVivien Didelot static int mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip, 1324f1394b78SVivien Didelot struct mv88e6xxx_vtu_entry *entry) 1325f1394b78SVivien Didelot { 1326f1394b78SVivien Didelot if (!chip->info->ops->vtu_getnext) 1327f1394b78SVivien Didelot return -EOPNOTSUPP; 1328f1394b78SVivien Didelot 1329f1394b78SVivien Didelot return chip->info->ops->vtu_getnext(chip, entry); 1330f1394b78SVivien Didelot } 1331f1394b78SVivien Didelot 13320ad5daf6SVivien Didelot static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip, 13330ad5daf6SVivien Didelot struct mv88e6xxx_vtu_entry *entry) 13340ad5daf6SVivien Didelot { 13350ad5daf6SVivien Didelot if (!chip->info->ops->vtu_loadpurge) 13360ad5daf6SVivien Didelot return -EOPNOTSUPP; 13370ad5daf6SVivien Didelot 13380ad5daf6SVivien Didelot return chip->info->ops->vtu_loadpurge(chip, entry); 13390ad5daf6SVivien Didelot } 13400ad5daf6SVivien Didelot 1341d7f435f9SVivien Didelot static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid) 1342fad09c73SVivien Didelot { 1343fad09c73SVivien Didelot DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); 1344425d2d37SVivien Didelot struct mv88e6xxx_vtu_entry vlan; 1345fad09c73SVivien Didelot int i, err; 1346fad09c73SVivien Didelot 1347fad09c73SVivien Didelot bitmap_zero(fid_bitmap, MV88E6XXX_N_FID); 1348fad09c73SVivien Didelot 1349fad09c73SVivien Didelot /* Set every FID bit used by the (un)bridged ports */ 1350370b4ffbSVivien Didelot for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 1351b4e48c50SVivien Didelot err = mv88e6xxx_port_get_fid(chip, i, fid); 1352fad09c73SVivien Didelot if (err) 1353fad09c73SVivien Didelot return err; 1354fad09c73SVivien Didelot 1355fad09c73SVivien Didelot set_bit(*fid, fid_bitmap); 1356fad09c73SVivien Didelot } 1357fad09c73SVivien Didelot 1358fad09c73SVivien Didelot /* Set every FID bit used by the VLAN entries */ 1359425d2d37SVivien Didelot vlan.vid = chip->info->max_vid; 1360425d2d37SVivien Didelot vlan.valid = false; 1361425d2d37SVivien Didelot 1362fad09c73SVivien Didelot do { 1363f1394b78SVivien Didelot err = mv88e6xxx_vtu_getnext(chip, &vlan); 1364fad09c73SVivien Didelot if (err) 1365fad09c73SVivien Didelot return err; 1366fad09c73SVivien Didelot 1367fad09c73SVivien Didelot if (!vlan.valid) 1368fad09c73SVivien Didelot break; 1369fad09c73SVivien Didelot 1370fad09c73SVivien Didelot set_bit(vlan.fid, fid_bitmap); 13713cf3c846SVivien Didelot } while (vlan.vid < chip->info->max_vid); 1372fad09c73SVivien Didelot 1373fad09c73SVivien Didelot /* The reset value 0x000 is used to indicate that multiple address 1374fad09c73SVivien Didelot * databases are not needed. Return the next positive available. 1375fad09c73SVivien Didelot */ 1376fad09c73SVivien Didelot *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1); 1377fad09c73SVivien Didelot if (unlikely(*fid >= mv88e6xxx_num_databases(chip))) 1378fad09c73SVivien Didelot return -ENOSPC; 1379fad09c73SVivien Didelot 1380fad09c73SVivien Didelot /* Clear the database */ 1381daefc943SVivien Didelot return mv88e6xxx_g1_atu_flush(chip, *fid, true); 1382fad09c73SVivien Didelot } 1383fad09c73SVivien Didelot 138423e8b470SAndrew Lunn static int mv88e6xxx_atu_get_hash(struct mv88e6xxx_chip *chip, u8 *hash) 138523e8b470SAndrew Lunn { 138623e8b470SAndrew Lunn if (chip->info->ops->atu_get_hash) 138723e8b470SAndrew Lunn return chip->info->ops->atu_get_hash(chip, hash); 138823e8b470SAndrew Lunn 138923e8b470SAndrew Lunn return -EOPNOTSUPP; 139023e8b470SAndrew Lunn } 139123e8b470SAndrew Lunn 139223e8b470SAndrew Lunn static int mv88e6xxx_atu_set_hash(struct mv88e6xxx_chip *chip, u8 hash) 139323e8b470SAndrew Lunn { 139423e8b470SAndrew Lunn if (chip->info->ops->atu_set_hash) 139523e8b470SAndrew Lunn return chip->info->ops->atu_set_hash(chip, hash); 139623e8b470SAndrew Lunn 139723e8b470SAndrew Lunn return -EOPNOTSUPP; 139823e8b470SAndrew Lunn } 139923e8b470SAndrew Lunn 1400fad09c73SVivien Didelot static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, 1401fad09c73SVivien Didelot u16 vid_begin, u16 vid_end) 1402fad09c73SVivien Didelot { 140304bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1404425d2d37SVivien Didelot struct mv88e6xxx_vtu_entry vlan; 1405fad09c73SVivien Didelot int i, err; 1406fad09c73SVivien Didelot 1407db06ae41SAndrew Lunn /* DSA and CPU ports have to be members of multiple vlans */ 1408db06ae41SAndrew Lunn if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) 1409db06ae41SAndrew Lunn return 0; 1410db06ae41SAndrew Lunn 1411fad09c73SVivien Didelot if (!vid_begin) 1412fad09c73SVivien Didelot return -EOPNOTSUPP; 1413fad09c73SVivien Didelot 1414425d2d37SVivien Didelot vlan.vid = vid_begin - 1; 1415425d2d37SVivien Didelot vlan.valid = false; 1416425d2d37SVivien Didelot 1417fad09c73SVivien Didelot do { 1418f1394b78SVivien Didelot err = mv88e6xxx_vtu_getnext(chip, &vlan); 1419fad09c73SVivien Didelot if (err) 14207095a4c4SVivien Didelot return err; 1421fad09c73SVivien Didelot 1422fad09c73SVivien Didelot if (!vlan.valid) 1423fad09c73SVivien Didelot break; 1424fad09c73SVivien Didelot 1425fad09c73SVivien Didelot if (vlan.vid > vid_end) 1426fad09c73SVivien Didelot break; 1427fad09c73SVivien Didelot 1428370b4ffbSVivien Didelot for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 1429fad09c73SVivien Didelot if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i)) 1430fad09c73SVivien Didelot continue; 1431fad09c73SVivien Didelot 143268bb8ea8SVivien Didelot if (!dsa_to_port(ds, i)->slave) 143366e2809dSAndrew Lunn continue; 143466e2809dSAndrew Lunn 1435bd00e053SVivien Didelot if (vlan.member[i] == 14367ec60d6eSVivien Didelot MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) 1437fad09c73SVivien Didelot continue; 1438fad09c73SVivien Didelot 1439c8652c83SVivien Didelot if (dsa_to_port(ds, i)->bridge_dev == 144068bb8ea8SVivien Didelot dsa_to_port(ds, port)->bridge_dev) 1441fad09c73SVivien Didelot break; /* same bridge, check next VLAN */ 1442fad09c73SVivien Didelot 1443c8652c83SVivien Didelot if (!dsa_to_port(ds, i)->bridge_dev) 144466e2809dSAndrew Lunn continue; 144566e2809dSAndrew Lunn 1446743fcc28SAndrew Lunn dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n", 1447743fcc28SAndrew Lunn port, vlan.vid, i, 1448c8652c83SVivien Didelot netdev_name(dsa_to_port(ds, i)->bridge_dev)); 14497095a4c4SVivien Didelot return -EOPNOTSUPP; 1450fad09c73SVivien Didelot } 1451fad09c73SVivien Didelot } while (vlan.vid < vid_end); 1452fad09c73SVivien Didelot 14537095a4c4SVivien Didelot return 0; 1454fad09c73SVivien Didelot } 1455fad09c73SVivien Didelot 1456fad09c73SVivien Didelot static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, 1457fad09c73SVivien Didelot bool vlan_filtering) 1458fad09c73SVivien Didelot { 145904bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 146081c6edb2SVivien Didelot u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE : 146181c6edb2SVivien Didelot MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED; 14620e7b9925SAndrew Lunn int err; 1463fad09c73SVivien Didelot 14643cf3c846SVivien Didelot if (!chip->info->max_vid) 1465fad09c73SVivien Didelot return -EOPNOTSUPP; 1466fad09c73SVivien Didelot 1467c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1468385a0995SVivien Didelot err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); 1469c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1470fad09c73SVivien Didelot 14710e7b9925SAndrew Lunn return err; 1472fad09c73SVivien Didelot } 1473fad09c73SVivien Didelot 1474fad09c73SVivien Didelot static int 1475fad09c73SVivien Didelot mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, 147680e02360SVivien Didelot const struct switchdev_obj_port_vlan *vlan) 1477fad09c73SVivien Didelot { 147804bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1479fad09c73SVivien Didelot int err; 1480fad09c73SVivien Didelot 14813cf3c846SVivien Didelot if (!chip->info->max_vid) 1482fad09c73SVivien Didelot return -EOPNOTSUPP; 1483fad09c73SVivien Didelot 1484fad09c73SVivien Didelot /* If the requested port doesn't belong to the same bridge as the VLAN 1485fad09c73SVivien Didelot * members, do not support it (yet) and fallback to software VLAN. 1486fad09c73SVivien Didelot */ 14877095a4c4SVivien Didelot mv88e6xxx_reg_lock(chip); 1488fad09c73SVivien Didelot err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin, 1489fad09c73SVivien Didelot vlan->vid_end); 14907095a4c4SVivien Didelot mv88e6xxx_reg_unlock(chip); 1491fad09c73SVivien Didelot 1492fad09c73SVivien Didelot /* We don't need any dynamic resource from the kernel (yet), 1493fad09c73SVivien Didelot * so skip the prepare phase. 1494fad09c73SVivien Didelot */ 14957095a4c4SVivien Didelot return err; 1496fad09c73SVivien Didelot } 1497fad09c73SVivien Didelot 1498a4c93ae1SAndrew Lunn static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, 1499a4c93ae1SAndrew Lunn const unsigned char *addr, u16 vid, 1500a4c93ae1SAndrew Lunn u8 state) 1501a4c93ae1SAndrew Lunn { 1502a4c93ae1SAndrew Lunn struct mv88e6xxx_atu_entry entry; 15035ef8d249SVivien Didelot struct mv88e6xxx_vtu_entry vlan; 15045ef8d249SVivien Didelot u16 fid; 1505a4c93ae1SAndrew Lunn int err; 1506a4c93ae1SAndrew Lunn 1507a4c93ae1SAndrew Lunn /* Null VLAN ID corresponds to the port private database */ 15085ef8d249SVivien Didelot if (vid == 0) { 15095ef8d249SVivien Didelot err = mv88e6xxx_port_get_fid(chip, port, &fid); 1510a4c93ae1SAndrew Lunn if (err) 1511a4c93ae1SAndrew Lunn return err; 15125ef8d249SVivien Didelot } else { 15135ef8d249SVivien Didelot vlan.vid = vid - 1; 15145ef8d249SVivien Didelot vlan.valid = false; 15155ef8d249SVivien Didelot 15165ef8d249SVivien Didelot err = mv88e6xxx_vtu_getnext(chip, &vlan); 15175ef8d249SVivien Didelot if (err) 15185ef8d249SVivien Didelot return err; 15195ef8d249SVivien Didelot 15205ef8d249SVivien Didelot /* switchdev expects -EOPNOTSUPP to honor software VLANs */ 15215ef8d249SVivien Didelot if (vlan.vid != vid || !vlan.valid) 15225ef8d249SVivien Didelot return -EOPNOTSUPP; 15235ef8d249SVivien Didelot 15245ef8d249SVivien Didelot fid = vlan.fid; 15255ef8d249SVivien Didelot } 1526a4c93ae1SAndrew Lunn 1527d8291a95SVivien Didelot entry.state = 0; 1528a4c93ae1SAndrew Lunn ether_addr_copy(entry.mac, addr); 1529a4c93ae1SAndrew Lunn eth_addr_dec(entry.mac); 1530a4c93ae1SAndrew Lunn 15315ef8d249SVivien Didelot err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry); 1532a4c93ae1SAndrew Lunn if (err) 1533a4c93ae1SAndrew Lunn return err; 1534a4c93ae1SAndrew Lunn 1535a4c93ae1SAndrew Lunn /* Initialize a fresh ATU entry if it isn't found */ 1536d8291a95SVivien Didelot if (!entry.state || !ether_addr_equal(entry.mac, addr)) { 1537a4c93ae1SAndrew Lunn memset(&entry, 0, sizeof(entry)); 1538a4c93ae1SAndrew Lunn ether_addr_copy(entry.mac, addr); 1539a4c93ae1SAndrew Lunn } 1540a4c93ae1SAndrew Lunn 1541a4c93ae1SAndrew Lunn /* Purge the ATU entry only if no port is using it anymore */ 1542d8291a95SVivien Didelot if (!state) { 1543a4c93ae1SAndrew Lunn entry.portvec &= ~BIT(port); 1544a4c93ae1SAndrew Lunn if (!entry.portvec) 1545d8291a95SVivien Didelot entry.state = 0; 1546a4c93ae1SAndrew Lunn } else { 1547a4c93ae1SAndrew Lunn entry.portvec |= BIT(port); 1548a4c93ae1SAndrew Lunn entry.state = state; 1549a4c93ae1SAndrew Lunn } 1550a4c93ae1SAndrew Lunn 15515ef8d249SVivien Didelot return mv88e6xxx_g1_atu_loadpurge(chip, fid, &entry); 1552a4c93ae1SAndrew Lunn } 1553a4c93ae1SAndrew Lunn 1554da7dc875SVivien Didelot static int mv88e6xxx_policy_apply(struct mv88e6xxx_chip *chip, int port, 1555da7dc875SVivien Didelot const struct mv88e6xxx_policy *policy) 1556da7dc875SVivien Didelot { 1557da7dc875SVivien Didelot enum mv88e6xxx_policy_mapping mapping = policy->mapping; 1558da7dc875SVivien Didelot enum mv88e6xxx_policy_action action = policy->action; 1559da7dc875SVivien Didelot const u8 *addr = policy->addr; 1560da7dc875SVivien Didelot u16 vid = policy->vid; 1561da7dc875SVivien Didelot u8 state; 1562da7dc875SVivien Didelot int err; 1563da7dc875SVivien Didelot int id; 1564da7dc875SVivien Didelot 1565da7dc875SVivien Didelot if (!chip->info->ops->port_set_policy) 1566da7dc875SVivien Didelot return -EOPNOTSUPP; 1567da7dc875SVivien Didelot 1568da7dc875SVivien Didelot switch (mapping) { 1569da7dc875SVivien Didelot case MV88E6XXX_POLICY_MAPPING_DA: 1570da7dc875SVivien Didelot case MV88E6XXX_POLICY_MAPPING_SA: 1571da7dc875SVivien Didelot if (action == MV88E6XXX_POLICY_ACTION_NORMAL) 1572da7dc875SVivien Didelot state = 0; /* Dissociate the port and address */ 1573da7dc875SVivien Didelot else if (action == MV88E6XXX_POLICY_ACTION_DISCARD && 1574da7dc875SVivien Didelot is_multicast_ether_addr(addr)) 1575da7dc875SVivien Didelot state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC_POLICY; 1576da7dc875SVivien Didelot else if (action == MV88E6XXX_POLICY_ACTION_DISCARD && 1577da7dc875SVivien Didelot is_unicast_ether_addr(addr)) 1578da7dc875SVivien Didelot state = MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC_POLICY; 1579da7dc875SVivien Didelot else 1580da7dc875SVivien Didelot return -EOPNOTSUPP; 1581da7dc875SVivien Didelot 1582da7dc875SVivien Didelot err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 1583da7dc875SVivien Didelot state); 1584da7dc875SVivien Didelot if (err) 1585da7dc875SVivien Didelot return err; 1586da7dc875SVivien Didelot break; 1587da7dc875SVivien Didelot default: 1588da7dc875SVivien Didelot return -EOPNOTSUPP; 1589da7dc875SVivien Didelot } 1590da7dc875SVivien Didelot 1591da7dc875SVivien Didelot /* Skip the port's policy clearing if the mapping is still in use */ 1592da7dc875SVivien Didelot if (action == MV88E6XXX_POLICY_ACTION_NORMAL) 1593da7dc875SVivien Didelot idr_for_each_entry(&chip->policies, policy, id) 1594da7dc875SVivien Didelot if (policy->port == port && 1595da7dc875SVivien Didelot policy->mapping == mapping && 1596da7dc875SVivien Didelot policy->action != action) 1597da7dc875SVivien Didelot return 0; 1598da7dc875SVivien Didelot 1599da7dc875SVivien Didelot return chip->info->ops->port_set_policy(chip, port, mapping, action); 1600da7dc875SVivien Didelot } 1601da7dc875SVivien Didelot 1602da7dc875SVivien Didelot static int mv88e6xxx_policy_insert(struct mv88e6xxx_chip *chip, int port, 1603da7dc875SVivien Didelot struct ethtool_rx_flow_spec *fs) 1604da7dc875SVivien Didelot { 1605da7dc875SVivien Didelot struct ethhdr *mac_entry = &fs->h_u.ether_spec; 1606da7dc875SVivien Didelot struct ethhdr *mac_mask = &fs->m_u.ether_spec; 1607da7dc875SVivien Didelot enum mv88e6xxx_policy_mapping mapping; 1608da7dc875SVivien Didelot enum mv88e6xxx_policy_action action; 1609da7dc875SVivien Didelot struct mv88e6xxx_policy *policy; 1610da7dc875SVivien Didelot u16 vid = 0; 1611da7dc875SVivien Didelot u8 *addr; 1612da7dc875SVivien Didelot int err; 1613da7dc875SVivien Didelot int id; 1614da7dc875SVivien Didelot 1615da7dc875SVivien Didelot if (fs->location != RX_CLS_LOC_ANY) 1616da7dc875SVivien Didelot return -EINVAL; 1617da7dc875SVivien Didelot 1618da7dc875SVivien Didelot if (fs->ring_cookie == RX_CLS_FLOW_DISC) 1619da7dc875SVivien Didelot action = MV88E6XXX_POLICY_ACTION_DISCARD; 1620da7dc875SVivien Didelot else 1621da7dc875SVivien Didelot return -EOPNOTSUPP; 1622da7dc875SVivien Didelot 1623da7dc875SVivien Didelot switch (fs->flow_type & ~FLOW_EXT) { 1624da7dc875SVivien Didelot case ETHER_FLOW: 1625da7dc875SVivien Didelot if (!is_zero_ether_addr(mac_mask->h_dest) && 1626da7dc875SVivien Didelot is_zero_ether_addr(mac_mask->h_source)) { 1627da7dc875SVivien Didelot mapping = MV88E6XXX_POLICY_MAPPING_DA; 1628da7dc875SVivien Didelot addr = mac_entry->h_dest; 1629da7dc875SVivien Didelot } else if (is_zero_ether_addr(mac_mask->h_dest) && 1630da7dc875SVivien Didelot !is_zero_ether_addr(mac_mask->h_source)) { 1631da7dc875SVivien Didelot mapping = MV88E6XXX_POLICY_MAPPING_SA; 1632da7dc875SVivien Didelot addr = mac_entry->h_source; 1633da7dc875SVivien Didelot } else { 1634da7dc875SVivien Didelot /* Cannot support DA and SA mapping in the same rule */ 1635da7dc875SVivien Didelot return -EOPNOTSUPP; 1636da7dc875SVivien Didelot } 1637da7dc875SVivien Didelot break; 1638da7dc875SVivien Didelot default: 1639da7dc875SVivien Didelot return -EOPNOTSUPP; 1640da7dc875SVivien Didelot } 1641da7dc875SVivien Didelot 1642da7dc875SVivien Didelot if ((fs->flow_type & FLOW_EXT) && fs->m_ext.vlan_tci) { 1643da7dc875SVivien Didelot if (fs->m_ext.vlan_tci != 0xffff) 1644da7dc875SVivien Didelot return -EOPNOTSUPP; 1645da7dc875SVivien Didelot vid = be16_to_cpu(fs->h_ext.vlan_tci) & VLAN_VID_MASK; 1646da7dc875SVivien Didelot } 1647da7dc875SVivien Didelot 1648da7dc875SVivien Didelot idr_for_each_entry(&chip->policies, policy, id) { 1649da7dc875SVivien Didelot if (policy->port == port && policy->mapping == mapping && 1650da7dc875SVivien Didelot policy->action == action && policy->vid == vid && 1651da7dc875SVivien Didelot ether_addr_equal(policy->addr, addr)) 1652da7dc875SVivien Didelot return -EEXIST; 1653da7dc875SVivien Didelot } 1654da7dc875SVivien Didelot 1655da7dc875SVivien Didelot policy = devm_kzalloc(chip->dev, sizeof(*policy), GFP_KERNEL); 1656da7dc875SVivien Didelot if (!policy) 1657da7dc875SVivien Didelot return -ENOMEM; 1658da7dc875SVivien Didelot 1659da7dc875SVivien Didelot fs->location = 0; 1660da7dc875SVivien Didelot err = idr_alloc_u32(&chip->policies, policy, &fs->location, 0xffffffff, 1661da7dc875SVivien Didelot GFP_KERNEL); 1662da7dc875SVivien Didelot if (err) { 1663da7dc875SVivien Didelot devm_kfree(chip->dev, policy); 1664da7dc875SVivien Didelot return err; 1665da7dc875SVivien Didelot } 1666da7dc875SVivien Didelot 1667da7dc875SVivien Didelot memcpy(&policy->fs, fs, sizeof(*fs)); 1668da7dc875SVivien Didelot ether_addr_copy(policy->addr, addr); 1669da7dc875SVivien Didelot policy->mapping = mapping; 1670da7dc875SVivien Didelot policy->action = action; 1671da7dc875SVivien Didelot policy->port = port; 1672da7dc875SVivien Didelot policy->vid = vid; 1673da7dc875SVivien Didelot 1674da7dc875SVivien Didelot err = mv88e6xxx_policy_apply(chip, port, policy); 1675da7dc875SVivien Didelot if (err) { 1676da7dc875SVivien Didelot idr_remove(&chip->policies, fs->location); 1677da7dc875SVivien Didelot devm_kfree(chip->dev, policy); 1678da7dc875SVivien Didelot return err; 1679da7dc875SVivien Didelot } 1680da7dc875SVivien Didelot 1681da7dc875SVivien Didelot return 0; 1682da7dc875SVivien Didelot } 1683da7dc875SVivien Didelot 1684da7dc875SVivien Didelot static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port, 1685da7dc875SVivien Didelot struct ethtool_rxnfc *rxnfc, u32 *rule_locs) 1686da7dc875SVivien Didelot { 1687da7dc875SVivien Didelot struct ethtool_rx_flow_spec *fs = &rxnfc->fs; 1688da7dc875SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1689da7dc875SVivien Didelot struct mv88e6xxx_policy *policy; 1690da7dc875SVivien Didelot int err; 1691da7dc875SVivien Didelot int id; 1692da7dc875SVivien Didelot 1693da7dc875SVivien Didelot mv88e6xxx_reg_lock(chip); 1694da7dc875SVivien Didelot 1695da7dc875SVivien Didelot switch (rxnfc->cmd) { 1696da7dc875SVivien Didelot case ETHTOOL_GRXCLSRLCNT: 1697da7dc875SVivien Didelot rxnfc->data = 0; 1698da7dc875SVivien Didelot rxnfc->data |= RX_CLS_LOC_SPECIAL; 1699da7dc875SVivien Didelot rxnfc->rule_cnt = 0; 1700da7dc875SVivien Didelot idr_for_each_entry(&chip->policies, policy, id) 1701da7dc875SVivien Didelot if (policy->port == port) 1702da7dc875SVivien Didelot rxnfc->rule_cnt++; 1703da7dc875SVivien Didelot err = 0; 1704da7dc875SVivien Didelot break; 1705da7dc875SVivien Didelot case ETHTOOL_GRXCLSRULE: 1706da7dc875SVivien Didelot err = -ENOENT; 1707da7dc875SVivien Didelot policy = idr_find(&chip->policies, fs->location); 1708da7dc875SVivien Didelot if (policy) { 1709da7dc875SVivien Didelot memcpy(fs, &policy->fs, sizeof(*fs)); 1710da7dc875SVivien Didelot err = 0; 1711da7dc875SVivien Didelot } 1712da7dc875SVivien Didelot break; 1713da7dc875SVivien Didelot case ETHTOOL_GRXCLSRLALL: 1714da7dc875SVivien Didelot rxnfc->data = 0; 1715da7dc875SVivien Didelot rxnfc->rule_cnt = 0; 1716da7dc875SVivien Didelot idr_for_each_entry(&chip->policies, policy, id) 1717da7dc875SVivien Didelot if (policy->port == port) 1718da7dc875SVivien Didelot rule_locs[rxnfc->rule_cnt++] = id; 1719da7dc875SVivien Didelot err = 0; 1720da7dc875SVivien Didelot break; 1721da7dc875SVivien Didelot default: 1722da7dc875SVivien Didelot err = -EOPNOTSUPP; 1723da7dc875SVivien Didelot break; 1724da7dc875SVivien Didelot } 1725da7dc875SVivien Didelot 1726da7dc875SVivien Didelot mv88e6xxx_reg_unlock(chip); 1727da7dc875SVivien Didelot 1728da7dc875SVivien Didelot return err; 1729da7dc875SVivien Didelot } 1730da7dc875SVivien Didelot 1731da7dc875SVivien Didelot static int mv88e6xxx_set_rxnfc(struct dsa_switch *ds, int port, 1732da7dc875SVivien Didelot struct ethtool_rxnfc *rxnfc) 1733da7dc875SVivien Didelot { 1734da7dc875SVivien Didelot struct ethtool_rx_flow_spec *fs = &rxnfc->fs; 1735da7dc875SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1736da7dc875SVivien Didelot struct mv88e6xxx_policy *policy; 1737da7dc875SVivien Didelot int err; 1738da7dc875SVivien Didelot 1739da7dc875SVivien Didelot mv88e6xxx_reg_lock(chip); 1740da7dc875SVivien Didelot 1741da7dc875SVivien Didelot switch (rxnfc->cmd) { 1742da7dc875SVivien Didelot case ETHTOOL_SRXCLSRLINS: 1743da7dc875SVivien Didelot err = mv88e6xxx_policy_insert(chip, port, fs); 1744da7dc875SVivien Didelot break; 1745da7dc875SVivien Didelot case ETHTOOL_SRXCLSRLDEL: 1746da7dc875SVivien Didelot err = -ENOENT; 1747da7dc875SVivien Didelot policy = idr_remove(&chip->policies, fs->location); 1748da7dc875SVivien Didelot if (policy) { 1749da7dc875SVivien Didelot policy->action = MV88E6XXX_POLICY_ACTION_NORMAL; 1750da7dc875SVivien Didelot err = mv88e6xxx_policy_apply(chip, port, policy); 1751da7dc875SVivien Didelot devm_kfree(chip->dev, policy); 1752da7dc875SVivien Didelot } 1753da7dc875SVivien Didelot break; 1754da7dc875SVivien Didelot default: 1755da7dc875SVivien Didelot err = -EOPNOTSUPP; 1756da7dc875SVivien Didelot break; 1757da7dc875SVivien Didelot } 1758da7dc875SVivien Didelot 1759da7dc875SVivien Didelot mv88e6xxx_reg_unlock(chip); 1760da7dc875SVivien Didelot 1761da7dc875SVivien Didelot return err; 1762da7dc875SVivien Didelot } 1763da7dc875SVivien Didelot 176487fa886eSAndrew Lunn static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port, 176587fa886eSAndrew Lunn u16 vid) 176687fa886eSAndrew Lunn { 176787fa886eSAndrew Lunn const char broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 176887fa886eSAndrew Lunn u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC; 176987fa886eSAndrew Lunn 177087fa886eSAndrew Lunn return mv88e6xxx_port_db_load_purge(chip, port, broadcast, vid, state); 177187fa886eSAndrew Lunn } 177287fa886eSAndrew Lunn 177387fa886eSAndrew Lunn static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid) 177487fa886eSAndrew Lunn { 177587fa886eSAndrew Lunn int port; 177687fa886eSAndrew Lunn int err; 177787fa886eSAndrew Lunn 177887fa886eSAndrew Lunn for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { 177987fa886eSAndrew Lunn err = mv88e6xxx_port_add_broadcast(chip, port, vid); 178087fa886eSAndrew Lunn if (err) 178187fa886eSAndrew Lunn return err; 178287fa886eSAndrew Lunn } 178387fa886eSAndrew Lunn 178487fa886eSAndrew Lunn return 0; 178587fa886eSAndrew Lunn } 178687fa886eSAndrew Lunn 1787b1ac6fb4SVivien Didelot static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, 1788c91498e1SVivien Didelot u16 vid, u8 member) 1789fad09c73SVivien Didelot { 1790b1ac6fb4SVivien Didelot const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; 1791b4e47c0fSVivien Didelot struct mv88e6xxx_vtu_entry vlan; 1792b1ac6fb4SVivien Didelot int i, err; 1793fad09c73SVivien Didelot 1794b1ac6fb4SVivien Didelot if (!vid) 1795b1ac6fb4SVivien Didelot return -EOPNOTSUPP; 1796b1ac6fb4SVivien Didelot 1797b1ac6fb4SVivien Didelot vlan.vid = vid - 1; 1798b1ac6fb4SVivien Didelot vlan.valid = false; 1799b1ac6fb4SVivien Didelot 1800b1ac6fb4SVivien Didelot err = mv88e6xxx_vtu_getnext(chip, &vlan); 1801fad09c73SVivien Didelot if (err) 1802fad09c73SVivien Didelot return err; 1803fad09c73SVivien Didelot 1804b1ac6fb4SVivien Didelot if (vlan.vid != vid || !vlan.valid) { 1805b1ac6fb4SVivien Didelot memset(&vlan, 0, sizeof(vlan)); 1806b1ac6fb4SVivien Didelot 1807b1ac6fb4SVivien Didelot err = mv88e6xxx_atu_new(chip, &vlan.fid); 1808b1ac6fb4SVivien Didelot if (err) 1809b1ac6fb4SVivien Didelot return err; 1810b1ac6fb4SVivien Didelot 1811b1ac6fb4SVivien Didelot for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) 1812b1ac6fb4SVivien Didelot if (i == port) 1813b1ac6fb4SVivien Didelot vlan.member[i] = member; 1814b1ac6fb4SVivien Didelot else 1815b1ac6fb4SVivien Didelot vlan.member[i] = non_member; 1816b1ac6fb4SVivien Didelot 1817b1ac6fb4SVivien Didelot vlan.vid = vid; 18181cb9dfcaSRasmus Villemoes vlan.valid = true; 1819fad09c73SVivien Didelot 182087fa886eSAndrew Lunn err = mv88e6xxx_vtu_loadpurge(chip, &vlan); 182187fa886eSAndrew Lunn if (err) 182287fa886eSAndrew Lunn return err; 182387fa886eSAndrew Lunn 1824b1ac6fb4SVivien Didelot err = mv88e6xxx_broadcast_setup(chip, vlan.vid); 1825b1ac6fb4SVivien Didelot if (err) 1826b1ac6fb4SVivien Didelot return err; 1827b1ac6fb4SVivien Didelot } else if (vlan.member[port] != member) { 1828b1ac6fb4SVivien Didelot vlan.member[port] = member; 1829b1ac6fb4SVivien Didelot 1830b1ac6fb4SVivien Didelot err = mv88e6xxx_vtu_loadpurge(chip, &vlan); 1831b1ac6fb4SVivien Didelot if (err) 1832b1ac6fb4SVivien Didelot return err; 1833b1ac6fb4SVivien Didelot } else { 1834b1ac6fb4SVivien Didelot dev_info(chip->dev, "p%d: already a member of VLAN %d\n", 1835b1ac6fb4SVivien Didelot port, vid); 1836b1ac6fb4SVivien Didelot } 1837b1ac6fb4SVivien Didelot 1838b1ac6fb4SVivien Didelot return 0; 1839fad09c73SVivien Didelot } 1840fad09c73SVivien Didelot 1841fad09c73SVivien Didelot static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, 184280e02360SVivien Didelot const struct switchdev_obj_port_vlan *vlan) 1843fad09c73SVivien Didelot { 184404bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1845fad09c73SVivien Didelot bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 1846fad09c73SVivien Didelot bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 1847c91498e1SVivien Didelot u8 member; 1848fad09c73SVivien Didelot u16 vid; 1849fad09c73SVivien Didelot 18503cf3c846SVivien Didelot if (!chip->info->max_vid) 1851fad09c73SVivien Didelot return; 1852fad09c73SVivien Didelot 1853c91498e1SVivien Didelot if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) 18547ec60d6eSVivien Didelot member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED; 1855c91498e1SVivien Didelot else if (untagged) 18567ec60d6eSVivien Didelot member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED; 1857c91498e1SVivien Didelot else 18587ec60d6eSVivien Didelot member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED; 1859c91498e1SVivien Didelot 1860c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1861fad09c73SVivien Didelot 1862fad09c73SVivien Didelot for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) 1863b1ac6fb4SVivien Didelot if (mv88e6xxx_port_vlan_join(chip, port, vid, member)) 1864774439e5SVivien Didelot dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port, 1865fad09c73SVivien Didelot vid, untagged ? 'u' : 't'); 1866fad09c73SVivien Didelot 186777064f37SVivien Didelot if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end)) 1868774439e5SVivien Didelot dev_err(ds->dev, "p%d: failed to set PVID %d\n", port, 1869fad09c73SVivien Didelot vlan->vid_end); 1870fad09c73SVivien Didelot 1871c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1872fad09c73SVivien Didelot } 1873fad09c73SVivien Didelot 187452109892SVivien Didelot static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip, 1875fad09c73SVivien Didelot int port, u16 vid) 1876fad09c73SVivien Didelot { 1877b4e47c0fSVivien Didelot struct mv88e6xxx_vtu_entry vlan; 1878fad09c73SVivien Didelot int i, err; 1879fad09c73SVivien Didelot 188052109892SVivien Didelot if (!vid) 188152109892SVivien Didelot return -EOPNOTSUPP; 188252109892SVivien Didelot 188352109892SVivien Didelot vlan.vid = vid - 1; 188452109892SVivien Didelot vlan.valid = false; 188552109892SVivien Didelot 188652109892SVivien Didelot err = mv88e6xxx_vtu_getnext(chip, &vlan); 1887fad09c73SVivien Didelot if (err) 1888fad09c73SVivien Didelot return err; 1889fad09c73SVivien Didelot 189052109892SVivien Didelot /* If the VLAN doesn't exist in hardware or the port isn't a member, 189152109892SVivien Didelot * tell switchdev that this VLAN is likely handled in software. 189252109892SVivien Didelot */ 189352109892SVivien Didelot if (vlan.vid != vid || !vlan.valid || 189452109892SVivien Didelot vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) 1895fad09c73SVivien Didelot return -EOPNOTSUPP; 1896fad09c73SVivien Didelot 18977ec60d6eSVivien Didelot vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; 1898fad09c73SVivien Didelot 1899fad09c73SVivien Didelot /* keep the VLAN unless all ports are excluded */ 1900fad09c73SVivien Didelot vlan.valid = false; 1901370b4ffbSVivien Didelot for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 19027ec60d6eSVivien Didelot if (vlan.member[i] != 19037ec60d6eSVivien Didelot MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) { 1904fad09c73SVivien Didelot vlan.valid = true; 1905fad09c73SVivien Didelot break; 1906fad09c73SVivien Didelot } 1907fad09c73SVivien Didelot } 1908fad09c73SVivien Didelot 19090ad5daf6SVivien Didelot err = mv88e6xxx_vtu_loadpurge(chip, &vlan); 1910fad09c73SVivien Didelot if (err) 1911fad09c73SVivien Didelot return err; 1912fad09c73SVivien Didelot 1913e606ca36SVivien Didelot return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false); 1914fad09c73SVivien Didelot } 1915fad09c73SVivien Didelot 1916fad09c73SVivien Didelot static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, 1917fad09c73SVivien Didelot const struct switchdev_obj_port_vlan *vlan) 1918fad09c73SVivien Didelot { 191904bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 1920fad09c73SVivien Didelot u16 pvid, vid; 1921fad09c73SVivien Didelot int err = 0; 1922fad09c73SVivien Didelot 19233cf3c846SVivien Didelot if (!chip->info->max_vid) 1924fad09c73SVivien Didelot return -EOPNOTSUPP; 1925fad09c73SVivien Didelot 1926c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1927fad09c73SVivien Didelot 192877064f37SVivien Didelot err = mv88e6xxx_port_get_pvid(chip, port, &pvid); 1929fad09c73SVivien Didelot if (err) 1930fad09c73SVivien Didelot goto unlock; 1931fad09c73SVivien Didelot 1932fad09c73SVivien Didelot for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { 193352109892SVivien Didelot err = mv88e6xxx_port_vlan_leave(chip, port, vid); 1934fad09c73SVivien Didelot if (err) 1935fad09c73SVivien Didelot goto unlock; 1936fad09c73SVivien Didelot 1937fad09c73SVivien Didelot if (vid == pvid) { 193877064f37SVivien Didelot err = mv88e6xxx_port_set_pvid(chip, port, 0); 1939fad09c73SVivien Didelot if (err) 1940fad09c73SVivien Didelot goto unlock; 1941fad09c73SVivien Didelot } 1942fad09c73SVivien Didelot } 1943fad09c73SVivien Didelot 1944fad09c73SVivien Didelot unlock: 1945c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1946fad09c73SVivien Didelot 1947fad09c73SVivien Didelot return err; 1948fad09c73SVivien Didelot } 1949fad09c73SVivien Didelot 19501b6dd556SArkadi Sharshevsky static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, 19516c2c1dcbSArkadi Sharshevsky const unsigned char *addr, u16 vid) 1952fad09c73SVivien Didelot { 195304bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 19541b6dd556SArkadi Sharshevsky int err; 1955fad09c73SVivien Didelot 1956c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 19571b6dd556SArkadi Sharshevsky err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 19581b6dd556SArkadi Sharshevsky MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); 1959c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 19601b6dd556SArkadi Sharshevsky 19611b6dd556SArkadi Sharshevsky return err; 1962fad09c73SVivien Didelot } 1963fad09c73SVivien Didelot 1964fad09c73SVivien Didelot static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, 19656c2c1dcbSArkadi Sharshevsky const unsigned char *addr, u16 vid) 1966fad09c73SVivien Didelot { 196704bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 196883dabd1fSVivien Didelot int err; 1969fad09c73SVivien Didelot 1970c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 1971d8291a95SVivien Didelot err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 0); 1972c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 1973fad09c73SVivien Didelot 197483dabd1fSVivien Didelot return err; 1975fad09c73SVivien Didelot } 1976fad09c73SVivien Didelot 197783dabd1fSVivien Didelot static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, 1978fad09c73SVivien Didelot u16 fid, u16 vid, int port, 19792bedde1aSArkadi Sharshevsky dsa_fdb_dump_cb_t *cb, void *data) 1980fad09c73SVivien Didelot { 1981dabc1a96SVivien Didelot struct mv88e6xxx_atu_entry addr; 19822bedde1aSArkadi Sharshevsky bool is_static; 1983fad09c73SVivien Didelot int err; 1984fad09c73SVivien Didelot 1985d8291a95SVivien Didelot addr.state = 0; 1986dabc1a96SVivien Didelot eth_broadcast_addr(addr.mac); 1987fad09c73SVivien Didelot 1988fad09c73SVivien Didelot do { 1989dabc1a96SVivien Didelot err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr); 1990fad09c73SVivien Didelot if (err) 199183dabd1fSVivien Didelot return err; 1992fad09c73SVivien Didelot 1993d8291a95SVivien Didelot if (!addr.state) 1994fad09c73SVivien Didelot break; 1995fad09c73SVivien Didelot 199601bd96c8SVivien Didelot if (addr.trunk || (addr.portvec & BIT(port)) == 0) 199783dabd1fSVivien Didelot continue; 1998fad09c73SVivien Didelot 199983dabd1fSVivien Didelot if (!is_unicast_ether_addr(addr.mac)) 200083dabd1fSVivien Didelot continue; 200183dabd1fSVivien Didelot 20022bedde1aSArkadi Sharshevsky is_static = (addr.state == 20032bedde1aSArkadi Sharshevsky MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); 20042bedde1aSArkadi Sharshevsky err = cb(addr.mac, vid, is_static, data); 200583dabd1fSVivien Didelot if (err) 200683dabd1fSVivien Didelot return err; 2007fad09c73SVivien Didelot } while (!is_broadcast_ether_addr(addr.mac)); 2008fad09c73SVivien Didelot 2009fad09c73SVivien Didelot return err; 2010fad09c73SVivien Didelot } 2011fad09c73SVivien Didelot 201283dabd1fSVivien Didelot static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, 20132bedde1aSArkadi Sharshevsky dsa_fdb_dump_cb_t *cb, void *data) 201483dabd1fSVivien Didelot { 2015425d2d37SVivien Didelot struct mv88e6xxx_vtu_entry vlan; 201683dabd1fSVivien Didelot u16 fid; 201783dabd1fSVivien Didelot int err; 201883dabd1fSVivien Didelot 201983dabd1fSVivien Didelot /* Dump port's default Filtering Information Database (VLAN ID 0) */ 2020b4e48c50SVivien Didelot err = mv88e6xxx_port_get_fid(chip, port, &fid); 202183dabd1fSVivien Didelot if (err) 202283dabd1fSVivien Didelot return err; 202383dabd1fSVivien Didelot 20242bedde1aSArkadi Sharshevsky err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data); 202583dabd1fSVivien Didelot if (err) 202683dabd1fSVivien Didelot return err; 202783dabd1fSVivien Didelot 202883dabd1fSVivien Didelot /* Dump VLANs' Filtering Information Databases */ 2029425d2d37SVivien Didelot vlan.vid = chip->info->max_vid; 2030425d2d37SVivien Didelot vlan.valid = false; 2031425d2d37SVivien Didelot 203283dabd1fSVivien Didelot do { 2033f1394b78SVivien Didelot err = mv88e6xxx_vtu_getnext(chip, &vlan); 203483dabd1fSVivien Didelot if (err) 203583dabd1fSVivien Didelot return err; 203683dabd1fSVivien Didelot 203783dabd1fSVivien Didelot if (!vlan.valid) 203883dabd1fSVivien Didelot break; 203983dabd1fSVivien Didelot 204083dabd1fSVivien Didelot err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port, 20412bedde1aSArkadi Sharshevsky cb, data); 204283dabd1fSVivien Didelot if (err) 204383dabd1fSVivien Didelot return err; 20443cf3c846SVivien Didelot } while (vlan.vid < chip->info->max_vid); 204583dabd1fSVivien Didelot 204683dabd1fSVivien Didelot return err; 204783dabd1fSVivien Didelot } 204883dabd1fSVivien Didelot 2049fad09c73SVivien Didelot static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, 20502bedde1aSArkadi Sharshevsky dsa_fdb_dump_cb_t *cb, void *data) 2051fad09c73SVivien Didelot { 205204bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 2053fcf15367SVivien Didelot int err; 2054fad09c73SVivien Didelot 2055c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2056fcf15367SVivien Didelot err = mv88e6xxx_port_db_dump(chip, port, cb, data); 2057c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 2058fcf15367SVivien Didelot 2059fcf15367SVivien Didelot return err; 2060fad09c73SVivien Didelot } 2061fad09c73SVivien Didelot 2062240ea3efSVivien Didelot static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip, 2063240ea3efSVivien Didelot struct net_device *br) 2064240ea3efSVivien Didelot { 2065ef2025ecSVivien Didelot struct dsa_switch *ds = chip->ds; 2066ef2025ecSVivien Didelot struct dsa_switch_tree *dst = ds->dst; 2067ef2025ecSVivien Didelot struct dsa_port *dp; 2068240ea3efSVivien Didelot int err; 2069240ea3efSVivien Didelot 2070ef2025ecSVivien Didelot list_for_each_entry(dp, &dst->ports, list) { 2071ef2025ecSVivien Didelot if (dp->bridge_dev == br) { 2072ef2025ecSVivien Didelot if (dp->ds == ds) { 2073ef2025ecSVivien Didelot /* This is a local bridge group member, 2074ef2025ecSVivien Didelot * remap its Port VLAN Map. 2075ef2025ecSVivien Didelot */ 2076ef2025ecSVivien Didelot err = mv88e6xxx_port_vlan_map(chip, dp->index); 2077240ea3efSVivien Didelot if (err) 2078240ea3efSVivien Didelot return err; 2079ef2025ecSVivien Didelot } else { 2080ef2025ecSVivien Didelot /* This is an external bridge group member, 2081ef2025ecSVivien Didelot * remap its cross-chip Port VLAN Table entry. 2082ef2025ecSVivien Didelot */ 2083ef2025ecSVivien Didelot err = mv88e6xxx_pvt_map(chip, dp->ds->index, 2084ef2025ecSVivien Didelot dp->index); 2085e96a6e02SVivien Didelot if (err) 2086e96a6e02SVivien Didelot return err; 2087e96a6e02SVivien Didelot } 2088e96a6e02SVivien Didelot } 2089e96a6e02SVivien Didelot } 2090e96a6e02SVivien Didelot 2091240ea3efSVivien Didelot return 0; 2092240ea3efSVivien Didelot } 2093240ea3efSVivien Didelot 2094fad09c73SVivien Didelot static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, 2095fae8a25eSVivien Didelot struct net_device *br) 2096fad09c73SVivien Didelot { 209704bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 2098240ea3efSVivien Didelot int err; 2099fad09c73SVivien Didelot 2100c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2101240ea3efSVivien Didelot err = mv88e6xxx_bridge_map(chip, br); 2102c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 2103fad09c73SVivien Didelot 2104fad09c73SVivien Didelot return err; 2105fad09c73SVivien Didelot } 2106fad09c73SVivien Didelot 2107f123f2fbSVivien Didelot static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, 2108f123f2fbSVivien Didelot struct net_device *br) 2109fad09c73SVivien Didelot { 211004bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 2111fad09c73SVivien Didelot 2112c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2113240ea3efSVivien Didelot if (mv88e6xxx_bridge_map(chip, br) || 2114240ea3efSVivien Didelot mv88e6xxx_port_vlan_map(chip, port)) 2115240ea3efSVivien Didelot dev_err(ds->dev, "failed to remap in-chip Port VLAN\n"); 2116c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 2117fad09c73SVivien Didelot } 2118fad09c73SVivien Didelot 2119aec5ac88SVivien Didelot static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev, 2120aec5ac88SVivien Didelot int port, struct net_device *br) 2121aec5ac88SVivien Didelot { 2122aec5ac88SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 2123aec5ac88SVivien Didelot int err; 2124aec5ac88SVivien Didelot 2125c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2126aec5ac88SVivien Didelot err = mv88e6xxx_pvt_map(chip, dev, port); 2127c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 2128aec5ac88SVivien Didelot 2129aec5ac88SVivien Didelot return err; 2130aec5ac88SVivien Didelot } 2131aec5ac88SVivien Didelot 2132aec5ac88SVivien Didelot static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev, 2133aec5ac88SVivien Didelot int port, struct net_device *br) 2134aec5ac88SVivien Didelot { 2135aec5ac88SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 2136aec5ac88SVivien Didelot 2137c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2138aec5ac88SVivien Didelot if (mv88e6xxx_pvt_map(chip, dev, port)) 2139aec5ac88SVivien Didelot dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n"); 2140c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 2141aec5ac88SVivien Didelot } 2142aec5ac88SVivien Didelot 214317e708baSVivien Didelot static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip) 214417e708baSVivien Didelot { 214517e708baSVivien Didelot if (chip->info->ops->reset) 214617e708baSVivien Didelot return chip->info->ops->reset(chip); 214717e708baSVivien Didelot 214817e708baSVivien Didelot return 0; 214917e708baSVivien Didelot } 215017e708baSVivien Didelot 2151309eca6dSVivien Didelot static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) 2152309eca6dSVivien Didelot { 2153309eca6dSVivien Didelot struct gpio_desc *gpiod = chip->reset; 2154309eca6dSVivien Didelot 2155309eca6dSVivien Didelot /* If there is a GPIO connected to the reset pin, toggle it */ 2156309eca6dSVivien Didelot if (gpiod) { 2157309eca6dSVivien Didelot gpiod_set_value_cansleep(gpiod, 1); 2158309eca6dSVivien Didelot usleep_range(10000, 20000); 2159309eca6dSVivien Didelot gpiod_set_value_cansleep(gpiod, 0); 2160309eca6dSVivien Didelot usleep_range(10000, 20000); 2161309eca6dSVivien Didelot } 2162309eca6dSVivien Didelot } 2163309eca6dSVivien Didelot 21644ac4b5a6SVivien Didelot static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip) 21654ac4b5a6SVivien Didelot { 21664ac4b5a6SVivien Didelot int i, err; 21674ac4b5a6SVivien Didelot 21684ac4b5a6SVivien Didelot /* Set all ports to the Disabled state */ 21694ac4b5a6SVivien Didelot for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { 2170f894c29cSVivien Didelot err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED); 21714ac4b5a6SVivien Didelot if (err) 21724ac4b5a6SVivien Didelot return err; 21734ac4b5a6SVivien Didelot } 21744ac4b5a6SVivien Didelot 21754ac4b5a6SVivien Didelot /* Wait for transmit queues to drain, 21764ac4b5a6SVivien Didelot * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps. 21774ac4b5a6SVivien Didelot */ 21784ac4b5a6SVivien Didelot usleep_range(2000, 4000); 21794ac4b5a6SVivien Didelot 21804ac4b5a6SVivien Didelot return 0; 21814ac4b5a6SVivien Didelot } 21824ac4b5a6SVivien Didelot 2183fad09c73SVivien Didelot static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip) 2184fad09c73SVivien Didelot { 2185a935c052SVivien Didelot int err; 2186fad09c73SVivien Didelot 21874ac4b5a6SVivien Didelot err = mv88e6xxx_disable_ports(chip); 21880e7b9925SAndrew Lunn if (err) 21890e7b9925SAndrew Lunn return err; 2190fad09c73SVivien Didelot 2191309eca6dSVivien Didelot mv88e6xxx_hardware_reset(chip); 2192fad09c73SVivien Didelot 219317e708baSVivien Didelot return mv88e6xxx_software_reset(chip); 2194fad09c73SVivien Didelot } 2195fad09c73SVivien Didelot 21964314557cSVivien Didelot static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port, 219731bef4e9SVivien Didelot enum mv88e6xxx_frame_mode frame, 219831bef4e9SVivien Didelot enum mv88e6xxx_egress_mode egress, u16 etype) 219956995cbcSAndrew Lunn { 220056995cbcSAndrew Lunn int err; 220156995cbcSAndrew Lunn 22024314557cSVivien Didelot if (!chip->info->ops->port_set_frame_mode) 22034314557cSVivien Didelot return -EOPNOTSUPP; 22044314557cSVivien Didelot 22054314557cSVivien Didelot err = mv88e6xxx_port_set_egress_mode(chip, port, egress); 220656995cbcSAndrew Lunn if (err) 220756995cbcSAndrew Lunn return err; 220856995cbcSAndrew Lunn 22094314557cSVivien Didelot err = chip->info->ops->port_set_frame_mode(chip, port, frame); 22104314557cSVivien Didelot if (err) 22114314557cSVivien Didelot return err; 22124314557cSVivien Didelot 22134314557cSVivien Didelot if (chip->info->ops->port_set_ether_type) 22144314557cSVivien Didelot return chip->info->ops->port_set_ether_type(chip, port, etype); 22154314557cSVivien Didelot 22164314557cSVivien Didelot return 0; 22174314557cSVivien Didelot } 22184314557cSVivien Didelot 22194314557cSVivien Didelot static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port) 22204314557cSVivien Didelot { 22214314557cSVivien Didelot return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL, 222231bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_UNMODIFIED, 2223b8109594SVivien Didelot MV88E6XXX_PORT_ETH_TYPE_DEFAULT); 22244314557cSVivien Didelot } 22254314557cSVivien Didelot 22264314557cSVivien Didelot static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port) 22274314557cSVivien Didelot { 22284314557cSVivien Didelot return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA, 222931bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_UNMODIFIED, 2230b8109594SVivien Didelot MV88E6XXX_PORT_ETH_TYPE_DEFAULT); 22314314557cSVivien Didelot } 22324314557cSVivien Didelot 22334314557cSVivien Didelot static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port) 22344314557cSVivien Didelot { 22354314557cSVivien Didelot return mv88e6xxx_set_port_mode(chip, port, 22364314557cSVivien Didelot MV88E6XXX_FRAME_MODE_ETHERTYPE, 223731bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_ETHERTYPE, 223831bef4e9SVivien Didelot ETH_P_EDSA); 22394314557cSVivien Didelot } 22404314557cSVivien Didelot 22414314557cSVivien Didelot static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port) 22424314557cSVivien Didelot { 22434314557cSVivien Didelot if (dsa_is_dsa_port(chip->ds, port)) 22444314557cSVivien Didelot return mv88e6xxx_set_port_mode_dsa(chip, port); 22454314557cSVivien Didelot 22462b3e9891SVivien Didelot if (dsa_is_user_port(chip->ds, port)) 22474314557cSVivien Didelot return mv88e6xxx_set_port_mode_normal(chip, port); 22484314557cSVivien Didelot 22494314557cSVivien Didelot /* Setup CPU port mode depending on its supported tag format */ 22504314557cSVivien Didelot if (chip->info->tag_protocol == DSA_TAG_PROTO_DSA) 22514314557cSVivien Didelot return mv88e6xxx_set_port_mode_dsa(chip, port); 22524314557cSVivien Didelot 22534314557cSVivien Didelot if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA) 22544314557cSVivien Didelot return mv88e6xxx_set_port_mode_edsa(chip, port); 22554314557cSVivien Didelot 22564314557cSVivien Didelot return -EINVAL; 22574314557cSVivien Didelot } 22584314557cSVivien Didelot 2259ea698f4fSVivien Didelot static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port) 2260ea698f4fSVivien Didelot { 2261ea698f4fSVivien Didelot bool message = dsa_is_dsa_port(chip->ds, port); 2262ea698f4fSVivien Didelot 2263ea698f4fSVivien Didelot return mv88e6xxx_port_set_message_port(chip, port, message); 2264ea698f4fSVivien Didelot } 2265ea698f4fSVivien Didelot 2266601aeed3SVivien Didelot static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port) 2267601aeed3SVivien Didelot { 22683ee50cbfSVivien Didelot struct dsa_switch *ds = chip->ds; 2269407308f6SDavid S. Miller bool flood; 2270601aeed3SVivien Didelot 2271407308f6SDavid S. Miller /* Upstream ports flood frames with unknown unicast or multicast DA */ 2272407308f6SDavid S. Miller flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port); 2273407308f6SDavid S. Miller if (chip->info->ops->port_set_egress_floods) 2274407308f6SDavid S. Miller return chip->info->ops->port_set_egress_floods(chip, port, 2275407308f6SDavid S. Miller flood, flood); 2276407308f6SDavid S. Miller 2277601aeed3SVivien Didelot return 0; 2278601aeed3SVivien Didelot } 2279601aeed3SVivien Didelot 228045de77ffSVivien Didelot static irqreturn_t mv88e6xxx_serdes_irq_thread_fn(int irq, void *dev_id) 228145de77ffSVivien Didelot { 228245de77ffSVivien Didelot struct mv88e6xxx_port *mvp = dev_id; 228345de77ffSVivien Didelot struct mv88e6xxx_chip *chip = mvp->chip; 228445de77ffSVivien Didelot irqreturn_t ret = IRQ_NONE; 228545de77ffSVivien Didelot int port = mvp->port; 228645de77ffSVivien Didelot u8 lane; 228745de77ffSVivien Didelot 228845de77ffSVivien Didelot mv88e6xxx_reg_lock(chip); 228945de77ffSVivien Didelot lane = mv88e6xxx_serdes_get_lane(chip, port); 229045de77ffSVivien Didelot if (lane) 229145de77ffSVivien Didelot ret = mv88e6xxx_serdes_irq_status(chip, port, lane); 229245de77ffSVivien Didelot mv88e6xxx_reg_unlock(chip); 229345de77ffSVivien Didelot 229445de77ffSVivien Didelot return ret; 229545de77ffSVivien Didelot } 229645de77ffSVivien Didelot 229745de77ffSVivien Didelot static int mv88e6xxx_serdes_irq_request(struct mv88e6xxx_chip *chip, int port, 229845de77ffSVivien Didelot u8 lane) 229945de77ffSVivien Didelot { 230045de77ffSVivien Didelot struct mv88e6xxx_port *dev_id = &chip->ports[port]; 230145de77ffSVivien Didelot unsigned int irq; 230245de77ffSVivien Didelot int err; 230345de77ffSVivien Didelot 230445de77ffSVivien Didelot /* Nothing to request if this SERDES port has no IRQ */ 230545de77ffSVivien Didelot irq = mv88e6xxx_serdes_irq_mapping(chip, port); 230645de77ffSVivien Didelot if (!irq) 230745de77ffSVivien Didelot return 0; 230845de77ffSVivien Didelot 2309e6f2f6b8SAndrew Lunn snprintf(dev_id->serdes_irq_name, sizeof(dev_id->serdes_irq_name), 2310e6f2f6b8SAndrew Lunn "mv88e6xxx-%s-serdes-%d", dev_name(chip->dev), port); 2311e6f2f6b8SAndrew Lunn 231245de77ffSVivien Didelot /* Requesting the IRQ will trigger IRQ callbacks, so release the lock */ 231345de77ffSVivien Didelot mv88e6xxx_reg_unlock(chip); 231445de77ffSVivien Didelot err = request_threaded_irq(irq, NULL, mv88e6xxx_serdes_irq_thread_fn, 2315e6f2f6b8SAndrew Lunn IRQF_ONESHOT, dev_id->serdes_irq_name, 2316e6f2f6b8SAndrew Lunn dev_id); 231745de77ffSVivien Didelot mv88e6xxx_reg_lock(chip); 231845de77ffSVivien Didelot if (err) 231945de77ffSVivien Didelot return err; 232045de77ffSVivien Didelot 232145de77ffSVivien Didelot dev_id->serdes_irq = irq; 232245de77ffSVivien Didelot 232345de77ffSVivien Didelot return mv88e6xxx_serdes_irq_enable(chip, port, lane); 232445de77ffSVivien Didelot } 232545de77ffSVivien Didelot 232645de77ffSVivien Didelot static int mv88e6xxx_serdes_irq_free(struct mv88e6xxx_chip *chip, int port, 232745de77ffSVivien Didelot u8 lane) 232845de77ffSVivien Didelot { 232945de77ffSVivien Didelot struct mv88e6xxx_port *dev_id = &chip->ports[port]; 233045de77ffSVivien Didelot unsigned int irq = dev_id->serdes_irq; 233145de77ffSVivien Didelot int err; 233245de77ffSVivien Didelot 233345de77ffSVivien Didelot /* Nothing to free if no IRQ has been requested */ 233445de77ffSVivien Didelot if (!irq) 233545de77ffSVivien Didelot return 0; 233645de77ffSVivien Didelot 233745de77ffSVivien Didelot err = mv88e6xxx_serdes_irq_disable(chip, port, lane); 233845de77ffSVivien Didelot 233945de77ffSVivien Didelot /* Freeing the IRQ will trigger IRQ callbacks, so release the lock */ 234045de77ffSVivien Didelot mv88e6xxx_reg_unlock(chip); 234145de77ffSVivien Didelot free_irq(irq, dev_id); 234245de77ffSVivien Didelot mv88e6xxx_reg_lock(chip); 234345de77ffSVivien Didelot 234445de77ffSVivien Didelot dev_id->serdes_irq = 0; 234545de77ffSVivien Didelot 234645de77ffSVivien Didelot return err; 234745de77ffSVivien Didelot } 234845de77ffSVivien Didelot 23496d91782fSAndrew Lunn static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port, 23506d91782fSAndrew Lunn bool on) 23516d91782fSAndrew Lunn { 2352dc272f60SVivien Didelot u8 lane; 2353fc0bc019SVivien Didelot int err; 23546d91782fSAndrew Lunn 2355dc272f60SVivien Didelot lane = mv88e6xxx_serdes_get_lane(chip, port); 2356dc272f60SVivien Didelot if (!lane) 2357523a8904SVivien Didelot return 0; 2358fc0bc019SVivien Didelot 2359fc0bc019SVivien Didelot if (on) { 2360dc272f60SVivien Didelot err = mv88e6xxx_serdes_power_up(chip, port, lane); 2361fc0bc019SVivien Didelot if (err) 2362fc0bc019SVivien Didelot return err; 2363fc0bc019SVivien Didelot 236445de77ffSVivien Didelot err = mv88e6xxx_serdes_irq_request(chip, port, lane); 2365fc0bc019SVivien Didelot } else { 236645de77ffSVivien Didelot err = mv88e6xxx_serdes_irq_free(chip, port, lane); 236745de77ffSVivien Didelot if (err) 236845de77ffSVivien Didelot return err; 2369fc0bc019SVivien Didelot 2370dc272f60SVivien Didelot err = mv88e6xxx_serdes_power_down(chip, port, lane); 2371fc0bc019SVivien Didelot } 2372fc0bc019SVivien Didelot 2373fc0bc019SVivien Didelot return err; 23746d91782fSAndrew Lunn } 23756d91782fSAndrew Lunn 2376fa371c80SVivien Didelot static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port) 2377fa371c80SVivien Didelot { 2378fa371c80SVivien Didelot struct dsa_switch *ds = chip->ds; 2379fa371c80SVivien Didelot int upstream_port; 2380fa371c80SVivien Didelot int err; 2381fa371c80SVivien Didelot 238207073c79SVivien Didelot upstream_port = dsa_upstream_port(ds, port); 2383fa371c80SVivien Didelot if (chip->info->ops->port_set_upstream_port) { 2384fa371c80SVivien Didelot err = chip->info->ops->port_set_upstream_port(chip, port, 2385fa371c80SVivien Didelot upstream_port); 2386fa371c80SVivien Didelot if (err) 2387fa371c80SVivien Didelot return err; 2388fa371c80SVivien Didelot } 2389fa371c80SVivien Didelot 23900ea54ddaSVivien Didelot if (port == upstream_port) { 23910ea54ddaSVivien Didelot if (chip->info->ops->set_cpu_port) { 23920ea54ddaSVivien Didelot err = chip->info->ops->set_cpu_port(chip, 23930ea54ddaSVivien Didelot upstream_port); 23940ea54ddaSVivien Didelot if (err) 23950ea54ddaSVivien Didelot return err; 23960ea54ddaSVivien Didelot } 23970ea54ddaSVivien Didelot 23980ea54ddaSVivien Didelot if (chip->info->ops->set_egress_port) { 23990ea54ddaSVivien Didelot err = chip->info->ops->set_egress_port(chip, 24005c74c54cSIwan R Timmer MV88E6XXX_EGRESS_DIR_INGRESS, 24015c74c54cSIwan R Timmer upstream_port); 24025c74c54cSIwan R Timmer if (err) 24035c74c54cSIwan R Timmer return err; 24045c74c54cSIwan R Timmer 24055c74c54cSIwan R Timmer err = chip->info->ops->set_egress_port(chip, 24065c74c54cSIwan R Timmer MV88E6XXX_EGRESS_DIR_EGRESS, 24070ea54ddaSVivien Didelot upstream_port); 24080ea54ddaSVivien Didelot if (err) 24090ea54ddaSVivien Didelot return err; 24100ea54ddaSVivien Didelot } 24110ea54ddaSVivien Didelot } 24120ea54ddaSVivien Didelot 2413fa371c80SVivien Didelot return 0; 2414fa371c80SVivien Didelot } 2415fa371c80SVivien Didelot 2416fad09c73SVivien Didelot static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) 2417fad09c73SVivien Didelot { 2418fad09c73SVivien Didelot struct dsa_switch *ds = chip->ds; 24190e7b9925SAndrew Lunn int err; 2420fad09c73SVivien Didelot u16 reg; 2421fad09c73SVivien Didelot 24227b898469SAndrew Lunn chip->ports[port].chip = chip; 24237b898469SAndrew Lunn chip->ports[port].port = port; 24247b898469SAndrew Lunn 2425d78343d2SVivien Didelot /* MAC Forcing register: don't force link, speed, duplex or flow control 2426d78343d2SVivien Didelot * state to any particular values on physical ports, but force the CPU 2427d78343d2SVivien Didelot * port and all DSA ports to their maximum bandwidth and full duplex. 2428fad09c73SVivien Didelot */ 2429d78343d2SVivien Didelot if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) 2430d78343d2SVivien Didelot err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP, 2431d78343d2SVivien Didelot SPEED_MAX, DUPLEX_FULL, 243254186b91SAndrew Lunn PAUSE_OFF, 2433d78343d2SVivien Didelot PHY_INTERFACE_MODE_NA); 2434fad09c73SVivien Didelot else 2435d78343d2SVivien Didelot err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, 2436d78343d2SVivien Didelot SPEED_UNFORCED, DUPLEX_UNFORCED, 243754186b91SAndrew Lunn PAUSE_ON, 2438d78343d2SVivien Didelot PHY_INTERFACE_MODE_NA); 24390e7b9925SAndrew Lunn if (err) 24400e7b9925SAndrew Lunn return err; 2441fad09c73SVivien Didelot 2442fad09c73SVivien Didelot /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, 2443fad09c73SVivien Didelot * disable Header mode, enable IGMP/MLD snooping, disable VLAN 2444fad09c73SVivien Didelot * tunneling, determine priority by looking at 802.1p and IP 2445fad09c73SVivien Didelot * priority fields (IP prio has precedence), and set STP state 2446fad09c73SVivien Didelot * to Forwarding. 2447fad09c73SVivien Didelot * 2448fad09c73SVivien Didelot * If this is the CPU link, use DSA or EDSA tagging depending 2449fad09c73SVivien Didelot * on which tagging mode was configured. 2450fad09c73SVivien Didelot * 2451fad09c73SVivien Didelot * If this is a link to another switch, use DSA tagging mode. 2452fad09c73SVivien Didelot * 2453fad09c73SVivien Didelot * If this is the upstream port for this switch, enable 2454fad09c73SVivien Didelot * forwarding of unknown unicasts and multicasts. 2455fad09c73SVivien Didelot */ 2456a89b433bSVivien Didelot reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP | 2457a89b433bSVivien Didelot MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP | 2458a89b433bSVivien Didelot MV88E6XXX_PORT_CTL0_STATE_FORWARDING; 2459a89b433bSVivien Didelot err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg); 24600e7b9925SAndrew Lunn if (err) 24610e7b9925SAndrew Lunn return err; 246256995cbcSAndrew Lunn 2463601aeed3SVivien Didelot err = mv88e6xxx_setup_port_mode(chip, port); 246456995cbcSAndrew Lunn if (err) 246556995cbcSAndrew Lunn return err; 2466fad09c73SVivien Didelot 2467601aeed3SVivien Didelot err = mv88e6xxx_setup_egress_floods(chip, port); 24684314557cSVivien Didelot if (err) 24694314557cSVivien Didelot return err; 24704314557cSVivien Didelot 2471fad09c73SVivien Didelot /* Port Control 2: don't force a good FCS, set the maximum frame size to 2472fad09c73SVivien Didelot * 10240 bytes, disable 802.1q tags checking, don't discard tagged or 2473fad09c73SVivien Didelot * untagged frames on this port, do a destination address lookup on all 2474fad09c73SVivien Didelot * received packets as usual, disable ARP mirroring and don't send a 2475fad09c73SVivien Didelot * copy of all transmitted/received frames on this port to the CPU. 2476fad09c73SVivien Didelot */ 2477a23b2961SAndrew Lunn err = mv88e6xxx_port_set_map_da(chip, port); 2478a23b2961SAndrew Lunn if (err) 2479a23b2961SAndrew Lunn return err; 2480a23b2961SAndrew Lunn 2481fa371c80SVivien Didelot err = mv88e6xxx_setup_upstream_port(chip, port); 24820e7b9925SAndrew Lunn if (err) 24830e7b9925SAndrew Lunn return err; 2484fad09c73SVivien Didelot 2485a23b2961SAndrew Lunn err = mv88e6xxx_port_set_8021q_mode(chip, port, 248681c6edb2SVivien Didelot MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED); 2487a23b2961SAndrew Lunn if (err) 2488a23b2961SAndrew Lunn return err; 2489a23b2961SAndrew Lunn 2490cd782656SVivien Didelot if (chip->info->ops->port_set_jumbo_size) { 2491cd782656SVivien Didelot err = chip->info->ops->port_set_jumbo_size(chip, port, 10240); 24925f436666SAndrew Lunn if (err) 24935f436666SAndrew Lunn return err; 24945f436666SAndrew Lunn } 24955f436666SAndrew Lunn 2496fad09c73SVivien Didelot /* Port Association Vector: when learning source addresses 2497fad09c73SVivien Didelot * of packets, add the address to the address database using 2498fad09c73SVivien Didelot * a port bitmap that has only the bit for this port set and 2499fad09c73SVivien Didelot * the other bits clear. 2500fad09c73SVivien Didelot */ 2501fad09c73SVivien Didelot reg = 1 << port; 2502fad09c73SVivien Didelot /* Disable learning for CPU port */ 2503fad09c73SVivien Didelot if (dsa_is_cpu_port(ds, port)) 2504fad09c73SVivien Didelot reg = 0; 2505fad09c73SVivien Didelot 25062a4614e4SVivien Didelot err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, 25072a4614e4SVivien Didelot reg); 25080e7b9925SAndrew Lunn if (err) 25090e7b9925SAndrew Lunn return err; 2510fad09c73SVivien Didelot 2511fad09c73SVivien Didelot /* Egress rate control 2: disable egress rate control. */ 25122cb8cb14SVivien Didelot err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2, 25132cb8cb14SVivien Didelot 0x0000); 25140e7b9925SAndrew Lunn if (err) 25150e7b9925SAndrew Lunn return err; 2516fad09c73SVivien Didelot 25170898432cSVivien Didelot if (chip->info->ops->port_pause_limit) { 25180898432cSVivien Didelot err = chip->info->ops->port_pause_limit(chip, port, 0, 0); 2519b35d322aSAndrew Lunn if (err) 2520b35d322aSAndrew Lunn return err; 2521b35d322aSAndrew Lunn } 2522b35d322aSAndrew Lunn 2523c8c94891SVivien Didelot if (chip->info->ops->port_disable_learn_limit) { 2524c8c94891SVivien Didelot err = chip->info->ops->port_disable_learn_limit(chip, port); 2525c8c94891SVivien Didelot if (err) 2526c8c94891SVivien Didelot return err; 2527c8c94891SVivien Didelot } 2528c8c94891SVivien Didelot 25299dbfb4e1SVivien Didelot if (chip->info->ops->port_disable_pri_override) { 25309dbfb4e1SVivien Didelot err = chip->info->ops->port_disable_pri_override(chip, port); 25310e7b9925SAndrew Lunn if (err) 25320e7b9925SAndrew Lunn return err; 2533ef0a7318SAndrew Lunn } 25342bbb33beSAndrew Lunn 2535ef0a7318SAndrew Lunn if (chip->info->ops->port_tag_remap) { 2536ef0a7318SAndrew Lunn err = chip->info->ops->port_tag_remap(chip, port); 25370e7b9925SAndrew Lunn if (err) 25380e7b9925SAndrew Lunn return err; 2539fad09c73SVivien Didelot } 2540fad09c73SVivien Didelot 2541ef70b111SAndrew Lunn if (chip->info->ops->port_egress_rate_limiting) { 2542ef70b111SAndrew Lunn err = chip->info->ops->port_egress_rate_limiting(chip, port); 25430e7b9925SAndrew Lunn if (err) 25440e7b9925SAndrew Lunn return err; 2545fad09c73SVivien Didelot } 2546fad09c73SVivien Didelot 2547121b8fe2SHubert Feurstein if (chip->info->ops->port_setup_message_port) { 2548121b8fe2SHubert Feurstein err = chip->info->ops->port_setup_message_port(chip, port); 25490e7b9925SAndrew Lunn if (err) 25500e7b9925SAndrew Lunn return err; 2551121b8fe2SHubert Feurstein } 2552fad09c73SVivien Didelot 2553fad09c73SVivien Didelot /* Port based VLAN map: give each port the same default address 2554fad09c73SVivien Didelot * database, and allow bidirectional communication between the 2555fad09c73SVivien Didelot * CPU and DSA port(s), and the other ports. 2556fad09c73SVivien Didelot */ 2557b4e48c50SVivien Didelot err = mv88e6xxx_port_set_fid(chip, port, 0); 25580e7b9925SAndrew Lunn if (err) 25590e7b9925SAndrew Lunn return err; 2560fad09c73SVivien Didelot 2561240ea3efSVivien Didelot err = mv88e6xxx_port_vlan_map(chip, port); 25620e7b9925SAndrew Lunn if (err) 25630e7b9925SAndrew Lunn return err; 2564fad09c73SVivien Didelot 2565fad09c73SVivien Didelot /* Default VLAN ID and priority: don't set a default VLAN 2566fad09c73SVivien Didelot * ID, and set the default packet priority to zero. 2567fad09c73SVivien Didelot */ 2568b7929fb3SVivien Didelot return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0); 2569fad09c73SVivien Didelot } 2570fad09c73SVivien Didelot 257104aca993SAndrew Lunn static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port, 257204aca993SAndrew Lunn struct phy_device *phydev) 257304aca993SAndrew Lunn { 257404aca993SAndrew Lunn struct mv88e6xxx_chip *chip = ds->priv; 2575523a8904SVivien Didelot int err; 257604aca993SAndrew Lunn 2577c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2578523a8904SVivien Didelot err = mv88e6xxx_serdes_power(chip, port, true); 2579c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 258004aca993SAndrew Lunn 258104aca993SAndrew Lunn return err; 258204aca993SAndrew Lunn } 258304aca993SAndrew Lunn 258475104db0SAndrew Lunn static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port) 258504aca993SAndrew Lunn { 258604aca993SAndrew Lunn struct mv88e6xxx_chip *chip = ds->priv; 258704aca993SAndrew Lunn 2588c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2589523a8904SVivien Didelot if (mv88e6xxx_serdes_power(chip, port, false)) 2590523a8904SVivien Didelot dev_err(chip->dev, "failed to power off SERDES\n"); 2591c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 259204aca993SAndrew Lunn } 259304aca993SAndrew Lunn 25942cfcd964SVivien Didelot static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds, 25952cfcd964SVivien Didelot unsigned int ageing_time) 25962cfcd964SVivien Didelot { 259704bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 25982cfcd964SVivien Didelot int err; 25992cfcd964SVivien Didelot 2600c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2601720c6343SVivien Didelot err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time); 2602c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 26032cfcd964SVivien Didelot 26042cfcd964SVivien Didelot return err; 26052cfcd964SVivien Didelot } 26062cfcd964SVivien Didelot 2607447b1bb8SVivien Didelot static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip) 2608fad09c73SVivien Didelot { 2609fad09c73SVivien Didelot int err; 2610fad09c73SVivien Didelot 2611de227387SAndrew Lunn /* Initialize the statistics unit */ 2612447b1bb8SVivien Didelot if (chip->info->ops->stats_set_histogram) { 2613447b1bb8SVivien Didelot err = chip->info->ops->stats_set_histogram(chip); 2614de227387SAndrew Lunn if (err) 2615de227387SAndrew Lunn return err; 2616447b1bb8SVivien Didelot } 2617de227387SAndrew Lunn 261840cff8fcSAndrew Lunn return mv88e6xxx_g1_stats_clear(chip); 26199729934cSVivien Didelot } 26209729934cSVivien Didelot 2621ea89098eSAndrew Lunn /* Check if the errata has already been applied. */ 2622ea89098eSAndrew Lunn static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip) 2623ea89098eSAndrew Lunn { 2624ea89098eSAndrew Lunn int port; 2625ea89098eSAndrew Lunn int err; 2626ea89098eSAndrew Lunn u16 val; 2627ea89098eSAndrew Lunn 2628ea89098eSAndrew Lunn for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { 262960907013SMarek Behún err = mv88e6xxx_port_hidden_read(chip, 0xf, port, 0, &val); 2630ea89098eSAndrew Lunn if (err) { 2631ea89098eSAndrew Lunn dev_err(chip->dev, 2632ea89098eSAndrew Lunn "Error reading hidden register: %d\n", err); 2633ea89098eSAndrew Lunn return false; 2634ea89098eSAndrew Lunn } 2635ea89098eSAndrew Lunn if (val != 0x01c0) 2636ea89098eSAndrew Lunn return false; 2637ea89098eSAndrew Lunn } 2638ea89098eSAndrew Lunn 2639ea89098eSAndrew Lunn return true; 2640ea89098eSAndrew Lunn } 2641ea89098eSAndrew Lunn 2642ea89098eSAndrew Lunn /* The 6390 copper ports have an errata which require poking magic 2643ea89098eSAndrew Lunn * values into undocumented hidden registers and then performing a 2644ea89098eSAndrew Lunn * software reset. 2645ea89098eSAndrew Lunn */ 2646ea89098eSAndrew Lunn static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip) 2647ea89098eSAndrew Lunn { 2648ea89098eSAndrew Lunn int port; 2649ea89098eSAndrew Lunn int err; 2650ea89098eSAndrew Lunn 2651ea89098eSAndrew Lunn if (mv88e6390_setup_errata_applied(chip)) 2652ea89098eSAndrew Lunn return 0; 2653ea89098eSAndrew Lunn 2654ea89098eSAndrew Lunn /* Set the ports into blocking mode */ 2655ea89098eSAndrew Lunn for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { 2656ea89098eSAndrew Lunn err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED); 2657ea89098eSAndrew Lunn if (err) 2658ea89098eSAndrew Lunn return err; 2659ea89098eSAndrew Lunn } 2660ea89098eSAndrew Lunn 2661ea89098eSAndrew Lunn for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { 266260907013SMarek Behún err = mv88e6xxx_port_hidden_write(chip, 0xf, port, 0, 0x01c0); 2663ea89098eSAndrew Lunn if (err) 2664ea89098eSAndrew Lunn return err; 2665ea89098eSAndrew Lunn } 2666ea89098eSAndrew Lunn 2667ea89098eSAndrew Lunn return mv88e6xxx_software_reset(chip); 2668ea89098eSAndrew Lunn } 2669ea89098eSAndrew Lunn 267023e8b470SAndrew Lunn enum mv88e6xxx_devlink_param_id { 267123e8b470SAndrew Lunn MV88E6XXX_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 267223e8b470SAndrew Lunn MV88E6XXX_DEVLINK_PARAM_ID_ATU_HASH, 267323e8b470SAndrew Lunn }; 267423e8b470SAndrew Lunn 267523e8b470SAndrew Lunn static int mv88e6xxx_devlink_param_get(struct dsa_switch *ds, u32 id, 267623e8b470SAndrew Lunn struct devlink_param_gset_ctx *ctx) 267723e8b470SAndrew Lunn { 267823e8b470SAndrew Lunn struct mv88e6xxx_chip *chip = ds->priv; 267923e8b470SAndrew Lunn int err; 268023e8b470SAndrew Lunn 268123e8b470SAndrew Lunn mv88e6xxx_reg_lock(chip); 268223e8b470SAndrew Lunn 268323e8b470SAndrew Lunn switch (id) { 268423e8b470SAndrew Lunn case MV88E6XXX_DEVLINK_PARAM_ID_ATU_HASH: 268523e8b470SAndrew Lunn err = mv88e6xxx_atu_get_hash(chip, &ctx->val.vu8); 268623e8b470SAndrew Lunn break; 268723e8b470SAndrew Lunn default: 268823e8b470SAndrew Lunn err = -EOPNOTSUPP; 268923e8b470SAndrew Lunn break; 269023e8b470SAndrew Lunn } 269123e8b470SAndrew Lunn 269223e8b470SAndrew Lunn mv88e6xxx_reg_unlock(chip); 269323e8b470SAndrew Lunn 269423e8b470SAndrew Lunn return err; 269523e8b470SAndrew Lunn } 269623e8b470SAndrew Lunn 269723e8b470SAndrew Lunn static int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id, 269823e8b470SAndrew Lunn struct devlink_param_gset_ctx *ctx) 269923e8b470SAndrew Lunn { 270023e8b470SAndrew Lunn struct mv88e6xxx_chip *chip = ds->priv; 270123e8b470SAndrew Lunn int err; 270223e8b470SAndrew Lunn 270323e8b470SAndrew Lunn mv88e6xxx_reg_lock(chip); 270423e8b470SAndrew Lunn 270523e8b470SAndrew Lunn switch (id) { 270623e8b470SAndrew Lunn case MV88E6XXX_DEVLINK_PARAM_ID_ATU_HASH: 270723e8b470SAndrew Lunn err = mv88e6xxx_atu_set_hash(chip, ctx->val.vu8); 270823e8b470SAndrew Lunn break; 270923e8b470SAndrew Lunn default: 271023e8b470SAndrew Lunn err = -EOPNOTSUPP; 271123e8b470SAndrew Lunn break; 271223e8b470SAndrew Lunn } 271323e8b470SAndrew Lunn 271423e8b470SAndrew Lunn mv88e6xxx_reg_unlock(chip); 271523e8b470SAndrew Lunn 271623e8b470SAndrew Lunn return err; 271723e8b470SAndrew Lunn } 271823e8b470SAndrew Lunn 271923e8b470SAndrew Lunn static const struct devlink_param mv88e6xxx_devlink_params[] = { 272023e8b470SAndrew Lunn DSA_DEVLINK_PARAM_DRIVER(MV88E6XXX_DEVLINK_PARAM_ID_ATU_HASH, 272123e8b470SAndrew Lunn "ATU_hash", DEVLINK_PARAM_TYPE_U8, 272223e8b470SAndrew Lunn BIT(DEVLINK_PARAM_CMODE_RUNTIME)), 272323e8b470SAndrew Lunn }; 272423e8b470SAndrew Lunn 272523e8b470SAndrew Lunn static int mv88e6xxx_setup_devlink_params(struct dsa_switch *ds) 272623e8b470SAndrew Lunn { 272723e8b470SAndrew Lunn return dsa_devlink_params_register(ds, mv88e6xxx_devlink_params, 272823e8b470SAndrew Lunn ARRAY_SIZE(mv88e6xxx_devlink_params)); 272923e8b470SAndrew Lunn } 273023e8b470SAndrew Lunn 273123e8b470SAndrew Lunn static void mv88e6xxx_teardown_devlink_params(struct dsa_switch *ds) 273223e8b470SAndrew Lunn { 273323e8b470SAndrew Lunn dsa_devlink_params_unregister(ds, mv88e6xxx_devlink_params, 273423e8b470SAndrew Lunn ARRAY_SIZE(mv88e6xxx_devlink_params)); 273523e8b470SAndrew Lunn } 273623e8b470SAndrew Lunn 2737e0c69ca7SAndrew Lunn enum mv88e6xxx_devlink_resource_id { 2738e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2739e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_0, 2740e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_1, 2741e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_2, 2742e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_3, 2743e0c69ca7SAndrew Lunn }; 2744e0c69ca7SAndrew Lunn 2745e0c69ca7SAndrew Lunn static u64 mv88e6xxx_devlink_atu_bin_get(struct mv88e6xxx_chip *chip, 2746e0c69ca7SAndrew Lunn u16 bin) 2747e0c69ca7SAndrew Lunn { 2748e0c69ca7SAndrew Lunn u16 occupancy = 0; 2749e0c69ca7SAndrew Lunn int err; 2750e0c69ca7SAndrew Lunn 2751e0c69ca7SAndrew Lunn mv88e6xxx_reg_lock(chip); 2752e0c69ca7SAndrew Lunn 2753e0c69ca7SAndrew Lunn err = mv88e6xxx_g2_atu_stats_set(chip, MV88E6XXX_G2_ATU_STATS_MODE_ALL, 2754e0c69ca7SAndrew Lunn bin); 2755e0c69ca7SAndrew Lunn if (err) { 2756e0c69ca7SAndrew Lunn dev_err(chip->dev, "failed to set ATU stats kind/bin\n"); 2757e0c69ca7SAndrew Lunn goto unlock; 2758e0c69ca7SAndrew Lunn } 2759e0c69ca7SAndrew Lunn 2760e0c69ca7SAndrew Lunn err = mv88e6xxx_g1_atu_get_next(chip, 0); 2761e0c69ca7SAndrew Lunn if (err) { 2762e0c69ca7SAndrew Lunn dev_err(chip->dev, "failed to perform ATU get next\n"); 2763e0c69ca7SAndrew Lunn goto unlock; 2764e0c69ca7SAndrew Lunn } 2765e0c69ca7SAndrew Lunn 2766e0c69ca7SAndrew Lunn err = mv88e6xxx_g2_atu_stats_get(chip, &occupancy); 2767e0c69ca7SAndrew Lunn if (err) { 2768e0c69ca7SAndrew Lunn dev_err(chip->dev, "failed to get ATU stats\n"); 2769e0c69ca7SAndrew Lunn goto unlock; 2770e0c69ca7SAndrew Lunn } 2771e0c69ca7SAndrew Lunn 2772e0c69ca7SAndrew Lunn unlock: 2773e0c69ca7SAndrew Lunn mv88e6xxx_reg_unlock(chip); 2774e0c69ca7SAndrew Lunn 2775e0c69ca7SAndrew Lunn return occupancy; 2776e0c69ca7SAndrew Lunn } 2777e0c69ca7SAndrew Lunn 2778e0c69ca7SAndrew Lunn static u64 mv88e6xxx_devlink_atu_bin_0_get(void *priv) 2779e0c69ca7SAndrew Lunn { 2780e0c69ca7SAndrew Lunn struct mv88e6xxx_chip *chip = priv; 2781e0c69ca7SAndrew Lunn 2782e0c69ca7SAndrew Lunn return mv88e6xxx_devlink_atu_bin_get(chip, 2783e0c69ca7SAndrew Lunn MV88E6XXX_G2_ATU_STATS_BIN_0); 2784e0c69ca7SAndrew Lunn } 2785e0c69ca7SAndrew Lunn 2786e0c69ca7SAndrew Lunn static u64 mv88e6xxx_devlink_atu_bin_1_get(void *priv) 2787e0c69ca7SAndrew Lunn { 2788e0c69ca7SAndrew Lunn struct mv88e6xxx_chip *chip = priv; 2789e0c69ca7SAndrew Lunn 2790e0c69ca7SAndrew Lunn return mv88e6xxx_devlink_atu_bin_get(chip, 2791e0c69ca7SAndrew Lunn MV88E6XXX_G2_ATU_STATS_BIN_1); 2792e0c69ca7SAndrew Lunn } 2793e0c69ca7SAndrew Lunn 2794e0c69ca7SAndrew Lunn static u64 mv88e6xxx_devlink_atu_bin_2_get(void *priv) 2795e0c69ca7SAndrew Lunn { 2796e0c69ca7SAndrew Lunn struct mv88e6xxx_chip *chip = priv; 2797e0c69ca7SAndrew Lunn 2798e0c69ca7SAndrew Lunn return mv88e6xxx_devlink_atu_bin_get(chip, 2799e0c69ca7SAndrew Lunn MV88E6XXX_G2_ATU_STATS_BIN_2); 2800e0c69ca7SAndrew Lunn } 2801e0c69ca7SAndrew Lunn 2802e0c69ca7SAndrew Lunn static u64 mv88e6xxx_devlink_atu_bin_3_get(void *priv) 2803e0c69ca7SAndrew Lunn { 2804e0c69ca7SAndrew Lunn struct mv88e6xxx_chip *chip = priv; 2805e0c69ca7SAndrew Lunn 2806e0c69ca7SAndrew Lunn return mv88e6xxx_devlink_atu_bin_get(chip, 2807e0c69ca7SAndrew Lunn MV88E6XXX_G2_ATU_STATS_BIN_3); 2808e0c69ca7SAndrew Lunn } 2809e0c69ca7SAndrew Lunn 2810e0c69ca7SAndrew Lunn static u64 mv88e6xxx_devlink_atu_get(void *priv) 2811e0c69ca7SAndrew Lunn { 2812e0c69ca7SAndrew Lunn return mv88e6xxx_devlink_atu_bin_0_get(priv) + 2813e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_1_get(priv) + 2814e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_2_get(priv) + 2815e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_3_get(priv); 2816e0c69ca7SAndrew Lunn } 2817e0c69ca7SAndrew Lunn 2818e0c69ca7SAndrew Lunn static int mv88e6xxx_setup_devlink_resources(struct dsa_switch *ds) 2819e0c69ca7SAndrew Lunn { 2820e0c69ca7SAndrew Lunn struct devlink_resource_size_params size_params; 2821e0c69ca7SAndrew Lunn struct mv88e6xxx_chip *chip = ds->priv; 2822e0c69ca7SAndrew Lunn int err; 2823e0c69ca7SAndrew Lunn 2824e0c69ca7SAndrew Lunn devlink_resource_size_params_init(&size_params, 2825e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip), 2826e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip), 2827e0c69ca7SAndrew Lunn 1, DEVLINK_RESOURCE_UNIT_ENTRY); 2828e0c69ca7SAndrew Lunn 2829e0c69ca7SAndrew Lunn err = dsa_devlink_resource_register(ds, "ATU", 2830e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip), 2831e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2832e0c69ca7SAndrew Lunn DEVLINK_RESOURCE_ID_PARENT_TOP, 2833e0c69ca7SAndrew Lunn &size_params); 2834e0c69ca7SAndrew Lunn if (err) 2835e0c69ca7SAndrew Lunn goto out; 2836e0c69ca7SAndrew Lunn 2837e0c69ca7SAndrew Lunn devlink_resource_size_params_init(&size_params, 2838e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip) / 4, 2839e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip) / 4, 2840e0c69ca7SAndrew Lunn 1, DEVLINK_RESOURCE_UNIT_ENTRY); 2841e0c69ca7SAndrew Lunn 2842e0c69ca7SAndrew Lunn err = dsa_devlink_resource_register(ds, "ATU_bin_0", 2843e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip) / 4, 2844e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_0, 2845e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2846e0c69ca7SAndrew Lunn &size_params); 2847e0c69ca7SAndrew Lunn if (err) 2848e0c69ca7SAndrew Lunn goto out; 2849e0c69ca7SAndrew Lunn 2850e0c69ca7SAndrew Lunn err = dsa_devlink_resource_register(ds, "ATU_bin_1", 2851e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip) / 4, 2852e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_1, 2853e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2854e0c69ca7SAndrew Lunn &size_params); 2855e0c69ca7SAndrew Lunn if (err) 2856e0c69ca7SAndrew Lunn goto out; 2857e0c69ca7SAndrew Lunn 2858e0c69ca7SAndrew Lunn err = dsa_devlink_resource_register(ds, "ATU_bin_2", 2859e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip) / 4, 2860e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_2, 2861e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2862e0c69ca7SAndrew Lunn &size_params); 2863e0c69ca7SAndrew Lunn if (err) 2864e0c69ca7SAndrew Lunn goto out; 2865e0c69ca7SAndrew Lunn 2866e0c69ca7SAndrew Lunn err = dsa_devlink_resource_register(ds, "ATU_bin_3", 2867e0c69ca7SAndrew Lunn mv88e6xxx_num_macs(chip) / 4, 2868e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_3, 2869e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2870e0c69ca7SAndrew Lunn &size_params); 2871e0c69ca7SAndrew Lunn if (err) 2872e0c69ca7SAndrew Lunn goto out; 2873e0c69ca7SAndrew Lunn 2874e0c69ca7SAndrew Lunn dsa_devlink_resource_occ_get_register(ds, 2875e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU, 2876e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_get, 2877e0c69ca7SAndrew Lunn chip); 2878e0c69ca7SAndrew Lunn 2879e0c69ca7SAndrew Lunn dsa_devlink_resource_occ_get_register(ds, 2880e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_0, 2881e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_0_get, 2882e0c69ca7SAndrew Lunn chip); 2883e0c69ca7SAndrew Lunn 2884e0c69ca7SAndrew Lunn dsa_devlink_resource_occ_get_register(ds, 2885e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_1, 2886e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_1_get, 2887e0c69ca7SAndrew Lunn chip); 2888e0c69ca7SAndrew Lunn 2889e0c69ca7SAndrew Lunn dsa_devlink_resource_occ_get_register(ds, 2890e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_2, 2891e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_2_get, 2892e0c69ca7SAndrew Lunn chip); 2893e0c69ca7SAndrew Lunn 2894e0c69ca7SAndrew Lunn dsa_devlink_resource_occ_get_register(ds, 2895e0c69ca7SAndrew Lunn MV88E6XXX_RESOURCE_ID_ATU_BIN_3, 2896e0c69ca7SAndrew Lunn mv88e6xxx_devlink_atu_bin_3_get, 2897e0c69ca7SAndrew Lunn chip); 2898e0c69ca7SAndrew Lunn 2899e0c69ca7SAndrew Lunn return 0; 2900e0c69ca7SAndrew Lunn 2901e0c69ca7SAndrew Lunn out: 2902e0c69ca7SAndrew Lunn dsa_devlink_resources_unregister(ds); 2903e0c69ca7SAndrew Lunn return err; 2904e0c69ca7SAndrew Lunn } 2905e0c69ca7SAndrew Lunn 290623e8b470SAndrew Lunn static void mv88e6xxx_teardown(struct dsa_switch *ds) 290723e8b470SAndrew Lunn { 290823e8b470SAndrew Lunn mv88e6xxx_teardown_devlink_params(ds); 2909e0c69ca7SAndrew Lunn dsa_devlink_resources_unregister(ds); 291023e8b470SAndrew Lunn } 291123e8b470SAndrew Lunn 2912fad09c73SVivien Didelot static int mv88e6xxx_setup(struct dsa_switch *ds) 2913fad09c73SVivien Didelot { 291404bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 29152d2e1dd2SAndrew Lunn u8 cmode; 2916fad09c73SVivien Didelot int err; 2917fad09c73SVivien Didelot int i; 2918fad09c73SVivien Didelot 2919fad09c73SVivien Didelot chip->ds = ds; 2920a3c53be5SAndrew Lunn ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); 2921fad09c73SVivien Didelot 2922c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 2923fad09c73SVivien Didelot 2924ea89098eSAndrew Lunn if (chip->info->ops->setup_errata) { 2925ea89098eSAndrew Lunn err = chip->info->ops->setup_errata(chip); 2926ea89098eSAndrew Lunn if (err) 2927ea89098eSAndrew Lunn goto unlock; 2928ea89098eSAndrew Lunn } 2929ea89098eSAndrew Lunn 29302d2e1dd2SAndrew Lunn /* Cache the cmode of each port. */ 29312d2e1dd2SAndrew Lunn for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { 29322d2e1dd2SAndrew Lunn if (chip->info->ops->port_get_cmode) { 29332d2e1dd2SAndrew Lunn err = chip->info->ops->port_get_cmode(chip, i, &cmode); 29342d2e1dd2SAndrew Lunn if (err) 2935e29129fcSDan Carpenter goto unlock; 29362d2e1dd2SAndrew Lunn 29372d2e1dd2SAndrew Lunn chip->ports[i].cmode = cmode; 29382d2e1dd2SAndrew Lunn } 29392d2e1dd2SAndrew Lunn } 29402d2e1dd2SAndrew Lunn 29419729934cSVivien Didelot /* Setup Switch Port Registers */ 2942370b4ffbSVivien Didelot for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { 2943b759f528SVivien Didelot if (dsa_is_unused_port(ds, i)) 2944b759f528SVivien Didelot continue; 2945b759f528SVivien Didelot 2946c857486aSHubert Feurstein /* Prevent the use of an invalid port. */ 2947b759f528SVivien Didelot if (mv88e6xxx_is_invalid_port(chip, i)) { 2948c857486aSHubert Feurstein dev_err(chip->dev, "port %d is invalid\n", i); 2949c857486aSHubert Feurstein err = -EINVAL; 2950c857486aSHubert Feurstein goto unlock; 2951c857486aSHubert Feurstein } 2952c857486aSHubert Feurstein 29539729934cSVivien Didelot err = mv88e6xxx_setup_port(chip, i); 29549729934cSVivien Didelot if (err) 29559729934cSVivien Didelot goto unlock; 29569729934cSVivien Didelot } 29579729934cSVivien Didelot 2958cd8da8bbSVivien Didelot err = mv88e6xxx_irl_setup(chip); 2959cd8da8bbSVivien Didelot if (err) 2960cd8da8bbSVivien Didelot goto unlock; 2961cd8da8bbSVivien Didelot 296204a69a17SVivien Didelot err = mv88e6xxx_mac_setup(chip); 296304a69a17SVivien Didelot if (err) 296404a69a17SVivien Didelot goto unlock; 296504a69a17SVivien Didelot 29661b17aedfSVivien Didelot err = mv88e6xxx_phy_setup(chip); 29671b17aedfSVivien Didelot if (err) 29681b17aedfSVivien Didelot goto unlock; 29691b17aedfSVivien Didelot 2970b486d7c9SVivien Didelot err = mv88e6xxx_vtu_setup(chip); 2971b486d7c9SVivien Didelot if (err) 2972b486d7c9SVivien Didelot goto unlock; 2973b486d7c9SVivien Didelot 297481228996SVivien Didelot err = mv88e6xxx_pvt_setup(chip); 297581228996SVivien Didelot if (err) 297681228996SVivien Didelot goto unlock; 297781228996SVivien Didelot 2978a2ac29d2SVivien Didelot err = mv88e6xxx_atu_setup(chip); 2979a2ac29d2SVivien Didelot if (err) 2980a2ac29d2SVivien Didelot goto unlock; 2981a2ac29d2SVivien Didelot 298287fa886eSAndrew Lunn err = mv88e6xxx_broadcast_setup(chip, 0); 298387fa886eSAndrew Lunn if (err) 298487fa886eSAndrew Lunn goto unlock; 298587fa886eSAndrew Lunn 29869e907d73SVivien Didelot err = mv88e6xxx_pot_setup(chip); 29879e907d73SVivien Didelot if (err) 29889e907d73SVivien Didelot goto unlock; 29899e907d73SVivien Didelot 29909e5baf9bSVivien Didelot err = mv88e6xxx_rmu_setup(chip); 29919e5baf9bSVivien Didelot if (err) 29929e5baf9bSVivien Didelot goto unlock; 29939e5baf9bSVivien Didelot 299451c901a7SVivien Didelot err = mv88e6xxx_rsvd2cpu_setup(chip); 29956e55f698SAndrew Lunn if (err) 29966e55f698SAndrew Lunn goto unlock; 29976e55f698SAndrew Lunn 2998b28f872dSVivien Didelot err = mv88e6xxx_trunk_setup(chip); 2999b28f872dSVivien Didelot if (err) 3000b28f872dSVivien Didelot goto unlock; 3001b28f872dSVivien Didelot 3002c7f047b6SVivien Didelot err = mv88e6xxx_devmap_setup(chip); 3003c7f047b6SVivien Didelot if (err) 3004c7f047b6SVivien Didelot goto unlock; 3005c7f047b6SVivien Didelot 300693e18d61SVivien Didelot err = mv88e6xxx_pri_setup(chip); 300793e18d61SVivien Didelot if (err) 300893e18d61SVivien Didelot goto unlock; 300993e18d61SVivien Didelot 3010c6fe0ad2SBrandon Streiff /* Setup PTP Hardware Clock and timestamping */ 30112fa8d3afSBrandon Streiff if (chip->info->ptp_support) { 30122fa8d3afSBrandon Streiff err = mv88e6xxx_ptp_setup(chip); 30132fa8d3afSBrandon Streiff if (err) 30142fa8d3afSBrandon Streiff goto unlock; 3015c6fe0ad2SBrandon Streiff 3016c6fe0ad2SBrandon Streiff err = mv88e6xxx_hwtstamp_setup(chip); 3017c6fe0ad2SBrandon Streiff if (err) 3018c6fe0ad2SBrandon Streiff goto unlock; 30192fa8d3afSBrandon Streiff } 30202fa8d3afSBrandon Streiff 3021447b1bb8SVivien Didelot err = mv88e6xxx_stats_setup(chip); 3022447b1bb8SVivien Didelot if (err) 3023447b1bb8SVivien Didelot goto unlock; 3024447b1bb8SVivien Didelot 3025fad09c73SVivien Didelot unlock: 3026c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 3027fad09c73SVivien Didelot 3028e0c69ca7SAndrew Lunn if (err) 3029e0c69ca7SAndrew Lunn return err; 3030e0c69ca7SAndrew Lunn 3031e0c69ca7SAndrew Lunn /* Have to be called without holding the register lock, since 3032e0c69ca7SAndrew Lunn * they take the devlink lock, and we later take the locks in 3033e0c69ca7SAndrew Lunn * the reverse order when getting/setting parameters or 3034e0c69ca7SAndrew Lunn * resource occupancy. 303523e8b470SAndrew Lunn */ 3036e0c69ca7SAndrew Lunn err = mv88e6xxx_setup_devlink_resources(ds); 3037e0c69ca7SAndrew Lunn if (err) 3038e0c69ca7SAndrew Lunn return err; 3039e0c69ca7SAndrew Lunn 3040e0c69ca7SAndrew Lunn err = mv88e6xxx_setup_devlink_params(ds); 3041e0c69ca7SAndrew Lunn if (err) 3042e0c69ca7SAndrew Lunn dsa_devlink_resources_unregister(ds); 3043e0c69ca7SAndrew Lunn 3044e0c69ca7SAndrew Lunn return err; 3045fad09c73SVivien Didelot } 3046fad09c73SVivien Didelot 3047e57e5e77SVivien Didelot static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg) 3048fad09c73SVivien Didelot { 30490dd12d54SAndrew Lunn struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; 30500dd12d54SAndrew Lunn struct mv88e6xxx_chip *chip = mdio_bus->chip; 3051e57e5e77SVivien Didelot u16 val; 3052e57e5e77SVivien Didelot int err; 3053fad09c73SVivien Didelot 3054ee26a228SAndrew Lunn if (!chip->info->ops->phy_read) 3055ee26a228SAndrew Lunn return -EOPNOTSUPP; 3056ee26a228SAndrew Lunn 3057c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 3058ee26a228SAndrew Lunn err = chip->info->ops->phy_read(chip, bus, phy, reg, &val); 3059c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 3060e57e5e77SVivien Didelot 3061da9f3301SAndrew Lunn if (reg == MII_PHYSID2) { 3062ddc49acbSAndrew Lunn /* Some internal PHYs don't have a model number. */ 3063ddc49acbSAndrew Lunn if (chip->info->family != MV88E6XXX_FAMILY_6165) 3064ddc49acbSAndrew Lunn /* Then there is the 6165 family. It gets is 3065ddc49acbSAndrew Lunn * PHYs correct. But it can also have two 3066ddc49acbSAndrew Lunn * SERDES interfaces in the PHY address 3067ddc49acbSAndrew Lunn * space. And these don't have a model 3068ddc49acbSAndrew Lunn * number. But they are not PHYs, so we don't 3069ddc49acbSAndrew Lunn * want to give them something a PHY driver 3070ddc49acbSAndrew Lunn * will recognise. 3071ddc49acbSAndrew Lunn * 3072ddc49acbSAndrew Lunn * Use the mv88e6390 family model number 3073ddc49acbSAndrew Lunn * instead, for anything which really could be 3074ddc49acbSAndrew Lunn * a PHY, 3075da9f3301SAndrew Lunn */ 3076da9f3301SAndrew Lunn if (!(val & 0x3f0)) 3077107fcc10SVivien Didelot val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4; 3078da9f3301SAndrew Lunn } 3079da9f3301SAndrew Lunn 3080e57e5e77SVivien Didelot return err ? err : val; 3081fad09c73SVivien Didelot } 3082fad09c73SVivien Didelot 3083e57e5e77SVivien Didelot static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val) 3084fad09c73SVivien Didelot { 30850dd12d54SAndrew Lunn struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; 30860dd12d54SAndrew Lunn struct mv88e6xxx_chip *chip = mdio_bus->chip; 3087e57e5e77SVivien Didelot int err; 3088fad09c73SVivien Didelot 3089ee26a228SAndrew Lunn if (!chip->info->ops->phy_write) 3090ee26a228SAndrew Lunn return -EOPNOTSUPP; 3091ee26a228SAndrew Lunn 3092c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 3093ee26a228SAndrew Lunn err = chip->info->ops->phy_write(chip, bus, phy, reg, val); 3094c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 3095e57e5e77SVivien Didelot 3096e57e5e77SVivien Didelot return err; 3097fad09c73SVivien Didelot } 3098fad09c73SVivien Didelot 3099fad09c73SVivien Didelot static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, 3100a3c53be5SAndrew Lunn struct device_node *np, 3101a3c53be5SAndrew Lunn bool external) 3102fad09c73SVivien Didelot { 3103fad09c73SVivien Didelot static int index; 31040dd12d54SAndrew Lunn struct mv88e6xxx_mdio_bus *mdio_bus; 3105fad09c73SVivien Didelot struct mii_bus *bus; 3106fad09c73SVivien Didelot int err; 3107fad09c73SVivien Didelot 31082510babcSAndrew Lunn if (external) { 3109c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 31102510babcSAndrew Lunn err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true); 3111c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 31122510babcSAndrew Lunn 31132510babcSAndrew Lunn if (err) 31142510babcSAndrew Lunn return err; 31152510babcSAndrew Lunn } 31162510babcSAndrew Lunn 31170dd12d54SAndrew Lunn bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus)); 3118fad09c73SVivien Didelot if (!bus) 3119fad09c73SVivien Didelot return -ENOMEM; 3120fad09c73SVivien Didelot 31210dd12d54SAndrew Lunn mdio_bus = bus->priv; 3122a3c53be5SAndrew Lunn mdio_bus->bus = bus; 31230dd12d54SAndrew Lunn mdio_bus->chip = chip; 3124a3c53be5SAndrew Lunn INIT_LIST_HEAD(&mdio_bus->list); 3125a3c53be5SAndrew Lunn mdio_bus->external = external; 31260dd12d54SAndrew Lunn 3127fad09c73SVivien Didelot if (np) { 3128fad09c73SVivien Didelot bus->name = np->full_name; 3129f7ce9103SRob Herring snprintf(bus->id, MII_BUS_ID_SIZE, "%pOF", np); 3130fad09c73SVivien Didelot } else { 3131fad09c73SVivien Didelot bus->name = "mv88e6xxx SMI"; 3132fad09c73SVivien Didelot snprintf(bus->id, MII_BUS_ID_SIZE, "mv88e6xxx-%d", index++); 3133fad09c73SVivien Didelot } 3134fad09c73SVivien Didelot 3135fad09c73SVivien Didelot bus->read = mv88e6xxx_mdio_read; 3136fad09c73SVivien Didelot bus->write = mv88e6xxx_mdio_write; 3137fad09c73SVivien Didelot bus->parent = chip->dev; 3138fad09c73SVivien Didelot 31396f88284fSAndrew Lunn if (!external) { 31406f88284fSAndrew Lunn err = mv88e6xxx_g2_irq_mdio_setup(chip, bus); 31416f88284fSAndrew Lunn if (err) 31426f88284fSAndrew Lunn return err; 31436f88284fSAndrew Lunn } 31446f88284fSAndrew Lunn 3145a3c53be5SAndrew Lunn err = of_mdiobus_register(bus, np); 3146fad09c73SVivien Didelot if (err) { 3147fad09c73SVivien Didelot dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err); 31486f88284fSAndrew Lunn mv88e6xxx_g2_irq_mdio_free(chip, bus); 3149fad09c73SVivien Didelot return err; 3150fad09c73SVivien Didelot } 3151fad09c73SVivien Didelot 3152a3c53be5SAndrew Lunn if (external) 3153a3c53be5SAndrew Lunn list_add_tail(&mdio_bus->list, &chip->mdios); 3154a3c53be5SAndrew Lunn else 3155a3c53be5SAndrew Lunn list_add(&mdio_bus->list, &chip->mdios); 3156a3c53be5SAndrew Lunn 3157a3c53be5SAndrew Lunn return 0; 3158a3c53be5SAndrew Lunn } 3159a3c53be5SAndrew Lunn 3160a3c53be5SAndrew Lunn static const struct of_device_id mv88e6xxx_mdio_external_match[] = { 3161a3c53be5SAndrew Lunn { .compatible = "marvell,mv88e6xxx-mdio-external", 3162a3c53be5SAndrew Lunn .data = (void *)true }, 3163a3c53be5SAndrew Lunn { }, 3164a3c53be5SAndrew Lunn }; 3165a3c53be5SAndrew Lunn 31663126aeecSAndrew Lunn static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) 31673126aeecSAndrew Lunn 31683126aeecSAndrew Lunn { 31693126aeecSAndrew Lunn struct mv88e6xxx_mdio_bus *mdio_bus; 31703126aeecSAndrew Lunn struct mii_bus *bus; 31713126aeecSAndrew Lunn 31723126aeecSAndrew Lunn list_for_each_entry(mdio_bus, &chip->mdios, list) { 31733126aeecSAndrew Lunn bus = mdio_bus->bus; 31743126aeecSAndrew Lunn 31756f88284fSAndrew Lunn if (!mdio_bus->external) 31766f88284fSAndrew Lunn mv88e6xxx_g2_irq_mdio_free(chip, bus); 31776f88284fSAndrew Lunn 31783126aeecSAndrew Lunn mdiobus_unregister(bus); 31793126aeecSAndrew Lunn } 31803126aeecSAndrew Lunn } 31813126aeecSAndrew Lunn 3182a3c53be5SAndrew Lunn static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip, 3183a3c53be5SAndrew Lunn struct device_node *np) 3184a3c53be5SAndrew Lunn { 3185a3c53be5SAndrew Lunn const struct of_device_id *match; 3186a3c53be5SAndrew Lunn struct device_node *child; 3187a3c53be5SAndrew Lunn int err; 3188a3c53be5SAndrew Lunn 3189a3c53be5SAndrew Lunn /* Always register one mdio bus for the internal/default mdio 3190a3c53be5SAndrew Lunn * bus. This maybe represented in the device tree, but is 3191a3c53be5SAndrew Lunn * optional. 3192a3c53be5SAndrew Lunn */ 3193a3c53be5SAndrew Lunn child = of_get_child_by_name(np, "mdio"); 3194a3c53be5SAndrew Lunn err = mv88e6xxx_mdio_register(chip, child, false); 3195a3c53be5SAndrew Lunn if (err) 3196a3c53be5SAndrew Lunn return err; 3197a3c53be5SAndrew Lunn 3198a3c53be5SAndrew Lunn /* Walk the device tree, and see if there are any other nodes 3199a3c53be5SAndrew Lunn * which say they are compatible with the external mdio 3200a3c53be5SAndrew Lunn * bus. 3201a3c53be5SAndrew Lunn */ 3202a3c53be5SAndrew Lunn for_each_available_child_of_node(np, child) { 3203a3c53be5SAndrew Lunn match = of_match_node(mv88e6xxx_mdio_external_match, child); 3204a3c53be5SAndrew Lunn if (match) { 3205a3c53be5SAndrew Lunn err = mv88e6xxx_mdio_register(chip, child, true); 32063126aeecSAndrew Lunn if (err) { 32073126aeecSAndrew Lunn mv88e6xxx_mdios_unregister(chip); 320878e42040SNishka Dasgupta of_node_put(child); 3209a3c53be5SAndrew Lunn return err; 3210a3c53be5SAndrew Lunn } 3211a3c53be5SAndrew Lunn } 32123126aeecSAndrew Lunn } 3213a3c53be5SAndrew Lunn 3214a3c53be5SAndrew Lunn return 0; 3215a3c53be5SAndrew Lunn } 3216a3c53be5SAndrew Lunn 3217855b1932SVivien Didelot static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds) 3218855b1932SVivien Didelot { 321904bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 3220855b1932SVivien Didelot 3221855b1932SVivien Didelot return chip->eeprom_len; 3222855b1932SVivien Didelot } 3223855b1932SVivien Didelot 3224855b1932SVivien Didelot static int mv88e6xxx_get_eeprom(struct dsa_switch *ds, 3225855b1932SVivien Didelot struct ethtool_eeprom *eeprom, u8 *data) 3226855b1932SVivien Didelot { 322704bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 3228855b1932SVivien Didelot int err; 3229855b1932SVivien Didelot 3230ee4dc2e7SVivien Didelot if (!chip->info->ops->get_eeprom) 3231ee4dc2e7SVivien Didelot return -EOPNOTSUPP; 3232ee4dc2e7SVivien Didelot 3233c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 3234ee4dc2e7SVivien Didelot err = chip->info->ops->get_eeprom(chip, eeprom, data); 3235c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 3236855b1932SVivien Didelot 3237855b1932SVivien Didelot if (err) 3238855b1932SVivien Didelot return err; 3239855b1932SVivien Didelot 3240855b1932SVivien Didelot eeprom->magic = 0xc3ec4951; 3241855b1932SVivien Didelot 3242855b1932SVivien Didelot return 0; 3243855b1932SVivien Didelot } 3244855b1932SVivien Didelot 3245855b1932SVivien Didelot static int mv88e6xxx_set_eeprom(struct dsa_switch *ds, 3246855b1932SVivien Didelot struct ethtool_eeprom *eeprom, u8 *data) 3247855b1932SVivien Didelot { 324804bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 3249855b1932SVivien Didelot int err; 3250855b1932SVivien Didelot 3251ee4dc2e7SVivien Didelot if (!chip->info->ops->set_eeprom) 3252ee4dc2e7SVivien Didelot return -EOPNOTSUPP; 3253ee4dc2e7SVivien Didelot 3254855b1932SVivien Didelot if (eeprom->magic != 0xc3ec4951) 3255855b1932SVivien Didelot return -EINVAL; 3256855b1932SVivien Didelot 3257c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 3258ee4dc2e7SVivien Didelot err = chip->info->ops->set_eeprom(chip, eeprom, data); 3259c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 3260855b1932SVivien Didelot 3261855b1932SVivien Didelot return err; 3262855b1932SVivien Didelot } 3263855b1932SVivien Didelot 3264b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6085_ops = { 32654b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6097 */ 326693e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 326793e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3268cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3269b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 32707e20cfb5SVivien Didelot .phy_read = mv88e6185_phy_ppu_read, 32717e20cfb5SVivien Didelot .phy_write = mv88e6185_phy_ppu_write, 327208ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 32737f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 327496a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 3275ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 327656995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3277601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 327856995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3279ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 32800898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3281c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 32829dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 32836c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 32842d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3285121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3286a605a0feSAndrew Lunn .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 328740cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3288dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3289dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3290052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3291fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3292fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3293fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 329451c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 32959e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 3296a199d8b6SVivien Didelot .ppu_enable = mv88e6185_g1_ppu_enable, 3297a199d8b6SVivien Didelot .ppu_disable = mv88e6185_g1_ppu_disable, 329817e708baSVivien Didelot .reset = mv88e6185_g1_reset, 32999e5baf9bSVivien Didelot .rmu_disable = mv88e6085_g1_rmu_disable, 3300f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 33010ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 33026c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3303b3469dd8SVivien Didelot }; 3304b3469dd8SVivien Didelot 3305b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6095_ops = { 33064b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6095 */ 330793e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 330893e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3309b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 33107e20cfb5SVivien Didelot .phy_read = mv88e6185_phy_ppu_read, 33117e20cfb5SVivien Didelot .phy_write = mv88e6185_phy_ppu_write, 331208ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 33137f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 331496a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 331556995cbcSAndrew Lunn .port_set_frame_mode = mv88e6085_port_set_frame_mode, 3316601aeed3SVivien Didelot .port_set_egress_floods = mv88e6185_port_set_egress_floods, 3317a23b2961SAndrew Lunn .port_set_upstream_port = mv88e6095_port_set_upstream_port, 33186c422e34SRussell King .port_link_state = mv88e6185_port_link_state, 33192d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3320121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3321a605a0feSAndrew Lunn .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 332240cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3323dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3324dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3325052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 332651c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, 3327a199d8b6SVivien Didelot .ppu_enable = mv88e6185_g1_ppu_enable, 3328a199d8b6SVivien Didelot .ppu_disable = mv88e6185_g1_ppu_disable, 332917e708baSVivien Didelot .reset = mv88e6185_g1_reset, 3330f1394b78SVivien Didelot .vtu_getnext = mv88e6185_g1_vtu_getnext, 33310ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, 33326c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3333b3469dd8SVivien Didelot }; 3334b3469dd8SVivien Didelot 33357d381a02SStefan Eichenberger static const struct mv88e6xxx_ops mv88e6097_ops = { 333615da3cc8SStefan Eichenberger /* MV88E6XXX_FAMILY_6097 */ 333793e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 333893e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3339cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 33407d381a02SStefan Eichenberger .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 33417d381a02SStefan Eichenberger .phy_read = mv88e6xxx_g2_smi_phy_read, 33427d381a02SStefan Eichenberger .phy_write = mv88e6xxx_g2_smi_phy_write, 33437d381a02SStefan Eichenberger .port_set_link = mv88e6xxx_port_set_link, 33447d381a02SStefan Eichenberger .port_set_duplex = mv88e6xxx_port_set_duplex, 33457d381a02SStefan Eichenberger .port_set_speed = mv88e6185_port_set_speed, 3346ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 334756995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3348601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 334956995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3350cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3351ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting, 33520898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3353c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 33549dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 33556c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 33562d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3357121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 33587d381a02SStefan Eichenberger .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 335940cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 33607d381a02SStefan Eichenberger .stats_get_sset_count = mv88e6095_stats_get_sset_count, 33617d381a02SStefan Eichenberger .stats_get_strings = mv88e6095_stats_get_strings, 33627d381a02SStefan Eichenberger .stats_get_stats = mv88e6095_stats_get_stats, 3363fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3364fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 336591eaa475SVolodymyr Bendiuga .watchdog_ops = &mv88e6097_watchdog_ops, 336651c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 33679e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 336817e708baSVivien Didelot .reset = mv88e6352_g1_reset, 33699e5baf9bSVivien Didelot .rmu_disable = mv88e6085_g1_rmu_disable, 3370f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 33710ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 33726c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 33737d381a02SStefan Eichenberger }; 33747d381a02SStefan Eichenberger 3375b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6123_ops = { 33764b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6165 */ 337793e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 337893e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3379cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3380b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3381ec8378bbSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 3382ec8378bbSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 338308ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 33847f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 338596a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 338656995cbcSAndrew Lunn .port_set_frame_mode = mv88e6085_port_set_frame_mode, 3387601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 3388c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 33899dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 33906c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 33912d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3392121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 33930ac64c39SAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 339440cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3395dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3396dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3397052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3398fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3399fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3400fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 340151c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 34029e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 340317e708baSVivien Didelot .reset = mv88e6352_g1_reset, 340423e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 340523e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3406f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 34070ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 34086c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3409b3469dd8SVivien Didelot }; 3410b3469dd8SVivien Didelot 3411b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6131_ops = { 34124b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6185 */ 341393e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 341493e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3415b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 34167e20cfb5SVivien Didelot .phy_read = mv88e6185_phy_ppu_read, 34177e20cfb5SVivien Didelot .phy_write = mv88e6185_phy_ppu_write, 341808ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 34197f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 342096a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 3421ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 342256995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3423601aeed3SVivien Didelot .port_set_egress_floods = mv88e6185_port_set_egress_floods, 342456995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3425a23b2961SAndrew Lunn .port_set_upstream_port = mv88e6095_port_set_upstream_port, 3426cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3427ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 34280898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 342954186b91SAndrew Lunn .port_set_pause = mv88e6185_port_set_pause, 34306c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 34312d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3432121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3433a605a0feSAndrew Lunn .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 343440cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3435dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3436dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3437052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3438fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3439fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3440fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 344151c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, 3442a199d8b6SVivien Didelot .ppu_enable = mv88e6185_g1_ppu_enable, 344302317e68SVivien Didelot .set_cascade_port = mv88e6185_g1_set_cascade_port, 3444a199d8b6SVivien Didelot .ppu_disable = mv88e6185_g1_ppu_disable, 344517e708baSVivien Didelot .reset = mv88e6185_g1_reset, 3446f1394b78SVivien Didelot .vtu_getnext = mv88e6185_g1_vtu_getnext, 34470ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, 34486c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3449b3469dd8SVivien Didelot }; 3450b3469dd8SVivien Didelot 3451990e27b0SVivien Didelot static const struct mv88e6xxx_ops mv88e6141_ops = { 3452990e27b0SVivien Didelot /* MV88E6XXX_FAMILY_6341 */ 345393e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 345493e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3455cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3456990e27b0SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 3457990e27b0SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 3458990e27b0SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3459990e27b0SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 3460990e27b0SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 3461990e27b0SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 3462990e27b0SVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 3463990e27b0SVivien Didelot .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 346426422340SMarek Behún .port_set_speed = mv88e6341_port_set_speed, 34657cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6341_port_max_speed_mode, 3466990e27b0SVivien Didelot .port_tag_remap = mv88e6095_port_tag_remap, 3467990e27b0SVivien Didelot .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3468990e27b0SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 3469990e27b0SVivien Didelot .port_set_ether_type = mv88e6351_port_set_ether_type, 3470cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3471990e27b0SVivien Didelot .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 34720898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3473990e27b0SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 3474990e27b0SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 34756c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 34762d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 34777a3007d2SMarek Behún .port_set_cmode = mv88e6341_port_set_cmode, 3478121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3479990e27b0SVivien Didelot .stats_snapshot = mv88e6390_g1_stats_snapshot, 348040cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3481990e27b0SVivien Didelot .stats_get_sset_count = mv88e6320_stats_get_sset_count, 3482990e27b0SVivien Didelot .stats_get_strings = mv88e6320_stats_get_strings, 3483990e27b0SVivien Didelot .stats_get_stats = mv88e6390_stats_get_stats, 3484fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 3485fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 3486990e27b0SVivien Didelot .watchdog_ops = &mv88e6390_watchdog_ops, 3487990e27b0SVivien Didelot .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 34889e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 3489990e27b0SVivien Didelot .reset = mv88e6352_g1_reset, 3490f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 34910ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 3492d3cf7d8fSMarek Behún .serdes_power = mv88e6390_serdes_power, 3493d3cf7d8fSMarek Behún .serdes_get_lane = mv88e6341_serdes_get_lane, 34944241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 349561a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 3496907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 3497a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 3498e3af71a3SMarek Behún .phylink_validate = mv88e6341_phylink_validate, 3499990e27b0SVivien Didelot }; 3500990e27b0SVivien Didelot 3501b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6161_ops = { 35024b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6165 */ 350393e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 350493e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3505cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3506b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3507ec8378bbSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 3508ec8378bbSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 350908ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 35107f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 351196a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 3512ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 351356995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3514601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 351556995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3516cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3517ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 35180898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3519c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 35209dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 35216c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 35222d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3523121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3524a6da21bbSAndrew Lunn .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 352540cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3526dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3527dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3528052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3529fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3530fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3531fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 353251c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 35339e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 353417e708baSVivien Didelot .reset = mv88e6352_g1_reset, 353523e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 353623e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3537f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 35380ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 3539a469a612SAndrew Lunn .avb_ops = &mv88e6165_avb_ops, 3540dfa54348SAndrew Lunn .ptp_ops = &mv88e6165_ptp_ops, 35416c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3542b3469dd8SVivien Didelot }; 3543b3469dd8SVivien Didelot 3544b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6165_ops = { 35454b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6165 */ 354693e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 354793e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3548cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3549b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3550efb3e74dSAndrew Lunn .phy_read = mv88e6165_phy_read, 3551efb3e74dSAndrew Lunn .phy_write = mv88e6165_phy_write, 355208ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 35537f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 355496a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 3555c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 35569dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 35576c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 35582d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3559121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3560a605a0feSAndrew Lunn .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 356140cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3562dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3563dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3564052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3565fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3566fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3567fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 356851c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 35699e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 357017e708baSVivien Didelot .reset = mv88e6352_g1_reset, 357123e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 357223e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3573f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 35740ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 3575a469a612SAndrew Lunn .avb_ops = &mv88e6165_avb_ops, 3576dfa54348SAndrew Lunn .ptp_ops = &mv88e6165_ptp_ops, 35776c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3578b3469dd8SVivien Didelot }; 3579b3469dd8SVivien Didelot 3580b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6171_ops = { 35814b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6351 */ 358293e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 358393e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3584cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3585b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3586b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 3587b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 358808ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 35897f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 359094d66ae6SAndrew Lunn .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 359196a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 3592ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 359356995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3594601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 359556995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3596cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3597ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 35980898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3599c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 36009dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 36016c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 36022d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3603121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3604a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 360540cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3606dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3607dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3608052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3609fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3610fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3611fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 361251c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 36139e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 361417e708baSVivien Didelot .reset = mv88e6352_g1_reset, 361523e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 361623e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3617f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 36180ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 36196c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3620b3469dd8SVivien Didelot }; 3621b3469dd8SVivien Didelot 3622b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6172_ops = { 36234b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6352 */ 362493e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 362593e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3626cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3627ee4dc2e7SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3628ee4dc2e7SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3629b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3630b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 3631b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 363208ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 36337f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 3634a0a0f622SVivien Didelot .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 363596a2b40cSVivien Didelot .port_set_speed = mv88e6352_port_set_speed, 3636ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 3637f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 363856995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3639601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 364056995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3641cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3642ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 36430898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3644c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 36459dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 36466c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 36472d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3648121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3649a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 365040cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3651dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3652dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3653052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3654fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3655fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3656fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 365751c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 36589e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 365917e708baSVivien Didelot .reset = mv88e6352_g1_reset, 36609e5baf9bSVivien Didelot .rmu_disable = mv88e6352_g1_rmu_disable, 366123e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 366223e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3663f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 36640ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 36659db4a725SVivien Didelot .serdes_get_lane = mv88e6352_serdes_get_lane, 36666d91782fSAndrew Lunn .serdes_power = mv88e6352_serdes_power, 3667a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 36686c422e34SRussell King .phylink_validate = mv88e6352_phylink_validate, 3669b3469dd8SVivien Didelot }; 3670b3469dd8SVivien Didelot 3671b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6175_ops = { 36724b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6351 */ 367393e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 367493e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3675cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3676b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3677b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 3678b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 367908ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 36807f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 368194d66ae6SAndrew Lunn .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 368296a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 3683ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 368456995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3685601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 368656995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3687cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3688ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 36890898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3690c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 36919dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 36926c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 36932d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3694121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3695a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 369640cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3697dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3698dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3699052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3700fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3701fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3702fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 370351c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 37049e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 370517e708baSVivien Didelot .reset = mv88e6352_g1_reset, 370623e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 370723e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3708f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 37090ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 37106c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3711b3469dd8SVivien Didelot }; 3712b3469dd8SVivien Didelot 3713b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6176_ops = { 37144b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6352 */ 371593e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 371693e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3717cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3718ee4dc2e7SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3719ee4dc2e7SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3720b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3721b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 3722b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 372308ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 37247f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 3725a0a0f622SVivien Didelot .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 372696a2b40cSVivien Didelot .port_set_speed = mv88e6352_port_set_speed, 3727ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 3728f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 372956995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3730601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 373156995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3732cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3733ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 37340898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3735c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 37369dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 37376c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 37382d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3739121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3740a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 374140cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3742dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3743dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3744052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3745fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3746fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3747fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 374851c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 37499e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 375017e708baSVivien Didelot .reset = mv88e6352_g1_reset, 37519e5baf9bSVivien Didelot .rmu_disable = mv88e6352_g1_rmu_disable, 375223e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 375323e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3754f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 37550ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 37569db4a725SVivien Didelot .serdes_get_lane = mv88e6352_serdes_get_lane, 37576d91782fSAndrew Lunn .serdes_power = mv88e6352_serdes_power, 37584241ef52SVivien Didelot .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, 375961a46b41SVivien Didelot .serdes_irq_enable = mv88e6352_serdes_irq_enable, 3760907b9b9fSVivien Didelot .serdes_irq_status = mv88e6352_serdes_irq_status, 3761a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 37626c422e34SRussell King .phylink_validate = mv88e6352_phylink_validate, 3763b3469dd8SVivien Didelot }; 3764b3469dd8SVivien Didelot 3765b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6185_ops = { 37664b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6185 */ 376793e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 376893e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3769b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 37707e20cfb5SVivien Didelot .phy_read = mv88e6185_phy_ppu_read, 37717e20cfb5SVivien Didelot .phy_write = mv88e6185_phy_ppu_write, 377208ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 37737f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 377496a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 377556995cbcSAndrew Lunn .port_set_frame_mode = mv88e6085_port_set_frame_mode, 3776601aeed3SVivien Didelot .port_set_egress_floods = mv88e6185_port_set_egress_floods, 3777ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting, 3778a23b2961SAndrew Lunn .port_set_upstream_port = mv88e6095_port_set_upstream_port, 377954186b91SAndrew Lunn .port_set_pause = mv88e6185_port_set_pause, 37806c422e34SRussell King .port_link_state = mv88e6185_port_link_state, 37812d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6185_port_get_cmode, 3782121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3783a605a0feSAndrew Lunn .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 378440cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3785dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3786dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3787052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3788fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3789fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3790fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 379151c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, 379202317e68SVivien Didelot .set_cascade_port = mv88e6185_g1_set_cascade_port, 3793a199d8b6SVivien Didelot .ppu_enable = mv88e6185_g1_ppu_enable, 3794a199d8b6SVivien Didelot .ppu_disable = mv88e6185_g1_ppu_disable, 379517e708baSVivien Didelot .reset = mv88e6185_g1_reset, 3796f1394b78SVivien Didelot .vtu_getnext = mv88e6185_g1_vtu_getnext, 37970ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, 37986c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 3799b3469dd8SVivien Didelot }; 3800b3469dd8SVivien Didelot 38011a3b39ecSAndrew Lunn static const struct mv88e6xxx_ops mv88e6190_ops = { 38024b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6390 */ 3803ea89098eSAndrew Lunn .setup_errata = mv88e6390_setup_errata, 3804cd8da8bbSVivien Didelot .irl_init_all = mv88e6390_g2_irl_init_all, 380598fc3c6fSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 380698fc3c6fSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 38071a3b39ecSAndrew Lunn .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 38081a3b39ecSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 38091a3b39ecSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 38101a3b39ecSAndrew Lunn .port_set_link = mv88e6xxx_port_set_link, 38111a3b39ecSAndrew Lunn .port_set_duplex = mv88e6xxx_port_set_duplex, 38121a3b39ecSAndrew Lunn .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 38131a3b39ecSAndrew Lunn .port_set_speed = mv88e6390_port_set_speed, 38147cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6390_port_max_speed_mode, 3815ef0a7318SAndrew Lunn .port_tag_remap = mv88e6390_port_tag_remap, 3816f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 381756995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3818601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 381956995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 38200898432cSVivien Didelot .port_pause_limit = mv88e6390_port_pause_limit, 3821c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 38229dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 38236c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 38242d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3825fdc71eeaSAndrew Lunn .port_set_cmode = mv88e6390_port_set_cmode, 3826121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 382779523473SAndrew Lunn .stats_snapshot = mv88e6390_g1_stats_snapshot, 3828de227387SAndrew Lunn .stats_set_histogram = mv88e6390_g1_stats_set_histogram, 3829dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 3830dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 3831e0d8b615SAndrew Lunn .stats_get_stats = mv88e6390_stats_get_stats, 3832fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 3833fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 383461303736SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 38356e55f698SAndrew Lunn .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 38369e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 383717e708baSVivien Didelot .reset = mv88e6352_g1_reset, 38389e5baf9bSVivien Didelot .rmu_disable = mv88e6390_g1_rmu_disable, 383923e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 384023e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3841931d1822SVivien Didelot .vtu_getnext = mv88e6390_g1_vtu_getnext, 3842931d1822SVivien Didelot .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 38436335e9f2SAndrew Lunn .serdes_power = mv88e6390_serdes_power, 384417deaf5cSMarek Behún .serdes_get_lane = mv88e6390_serdes_get_lane, 38454241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 384661a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 3847907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 3848a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 38496c422e34SRussell King .phylink_validate = mv88e6390_phylink_validate, 38501a3b39ecSAndrew Lunn }; 38511a3b39ecSAndrew Lunn 38521a3b39ecSAndrew Lunn static const struct mv88e6xxx_ops mv88e6190x_ops = { 38534b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6390 */ 3854ea89098eSAndrew Lunn .setup_errata = mv88e6390_setup_errata, 3855cd8da8bbSVivien Didelot .irl_init_all = mv88e6390_g2_irl_init_all, 385698fc3c6fSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 385798fc3c6fSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 38581a3b39ecSAndrew Lunn .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 38591a3b39ecSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 38601a3b39ecSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 38611a3b39ecSAndrew Lunn .port_set_link = mv88e6xxx_port_set_link, 38621a3b39ecSAndrew Lunn .port_set_duplex = mv88e6xxx_port_set_duplex, 38631a3b39ecSAndrew Lunn .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 38641a3b39ecSAndrew Lunn .port_set_speed = mv88e6390x_port_set_speed, 38657cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6390x_port_max_speed_mode, 3866ef0a7318SAndrew Lunn .port_tag_remap = mv88e6390_port_tag_remap, 3867f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 386856995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3869601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 387056995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 38710898432cSVivien Didelot .port_pause_limit = mv88e6390_port_pause_limit, 3872c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 38739dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 38746c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 38752d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3876fdc71eeaSAndrew Lunn .port_set_cmode = mv88e6390x_port_set_cmode, 3877121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 387879523473SAndrew Lunn .stats_snapshot = mv88e6390_g1_stats_snapshot, 3879de227387SAndrew Lunn .stats_set_histogram = mv88e6390_g1_stats_set_histogram, 3880dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 3881dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 3882e0d8b615SAndrew Lunn .stats_get_stats = mv88e6390_stats_get_stats, 3883fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 3884fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 388561303736SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 38866e55f698SAndrew Lunn .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 38879e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 388817e708baSVivien Didelot .reset = mv88e6352_g1_reset, 38899e5baf9bSVivien Didelot .rmu_disable = mv88e6390_g1_rmu_disable, 389023e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 389123e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3892931d1822SVivien Didelot .vtu_getnext = mv88e6390_g1_vtu_getnext, 3893931d1822SVivien Didelot .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 3894d3cf7d8fSMarek Behún .serdes_power = mv88e6390_serdes_power, 389517deaf5cSMarek Behún .serdes_get_lane = mv88e6390x_serdes_get_lane, 38964241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 389761a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 3898907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 3899a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 39006c422e34SRussell King .phylink_validate = mv88e6390x_phylink_validate, 39011a3b39ecSAndrew Lunn }; 39021a3b39ecSAndrew Lunn 39031a3b39ecSAndrew Lunn static const struct mv88e6xxx_ops mv88e6191_ops = { 39044b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6390 */ 3905ea89098eSAndrew Lunn .setup_errata = mv88e6390_setup_errata, 3906cd8da8bbSVivien Didelot .irl_init_all = mv88e6390_g2_irl_init_all, 390798fc3c6fSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 390898fc3c6fSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 39091a3b39ecSAndrew Lunn .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 39101a3b39ecSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 39111a3b39ecSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 39121a3b39ecSAndrew Lunn .port_set_link = mv88e6xxx_port_set_link, 39131a3b39ecSAndrew Lunn .port_set_duplex = mv88e6xxx_port_set_duplex, 39141a3b39ecSAndrew Lunn .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 39151a3b39ecSAndrew Lunn .port_set_speed = mv88e6390_port_set_speed, 39167cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6390_port_max_speed_mode, 3917ef0a7318SAndrew Lunn .port_tag_remap = mv88e6390_port_tag_remap, 391856995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3919601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 392056995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 39210898432cSVivien Didelot .port_pause_limit = mv88e6390_port_pause_limit, 3922c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 39239dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 39246c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 39252d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3926fdc71eeaSAndrew Lunn .port_set_cmode = mv88e6390_port_set_cmode, 3927121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 392879523473SAndrew Lunn .stats_snapshot = mv88e6390_g1_stats_snapshot, 3929de227387SAndrew Lunn .stats_set_histogram = mv88e6390_g1_stats_set_histogram, 3930dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 3931dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 3932e0d8b615SAndrew Lunn .stats_get_stats = mv88e6390_stats_get_stats, 3933fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 3934fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 393561303736SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 39366e55f698SAndrew Lunn .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 39379e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 393817e708baSVivien Didelot .reset = mv88e6352_g1_reset, 39399e5baf9bSVivien Didelot .rmu_disable = mv88e6390_g1_rmu_disable, 394023e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 394123e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3942931d1822SVivien Didelot .vtu_getnext = mv88e6390_g1_vtu_getnext, 3943931d1822SVivien Didelot .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 39446335e9f2SAndrew Lunn .serdes_power = mv88e6390_serdes_power, 394517deaf5cSMarek Behún .serdes_get_lane = mv88e6390_serdes_get_lane, 39464241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 394761a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 3948907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 39496d2ac8eeSAndrew Lunn .avb_ops = &mv88e6390_avb_ops, 39506d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 39516c422e34SRussell King .phylink_validate = mv88e6390_phylink_validate, 39521a3b39ecSAndrew Lunn }; 39531a3b39ecSAndrew Lunn 3954b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6240_ops = { 39554b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6352 */ 395693e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 395793e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 3958cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 3959ee4dc2e7SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3960ee4dc2e7SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3961b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3962b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 3963b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 396408ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 39657f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 3966a0a0f622SVivien Didelot .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 396796a2b40cSVivien Didelot .port_set_speed = mv88e6352_port_set_speed, 3968ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 3969f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 397056995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 3971601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 397256995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 3973cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 3974ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 39750898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 3976c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 39779dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 39786c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 39792d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 3980121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 3981a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 398240cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3983dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3984dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 3985052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 3986fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 3987fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 3988fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 398951c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 39909e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 399117e708baSVivien Didelot .reset = mv88e6352_g1_reset, 39929e5baf9bSVivien Didelot .rmu_disable = mv88e6352_g1_rmu_disable, 399323e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 399423e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 3995f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 39960ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 39979db4a725SVivien Didelot .serdes_get_lane = mv88e6352_serdes_get_lane, 39986d91782fSAndrew Lunn .serdes_power = mv88e6352_serdes_power, 39994241ef52SVivien Didelot .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, 400061a46b41SVivien Didelot .serdes_irq_enable = mv88e6352_serdes_irq_enable, 4001907b9b9fSVivien Didelot .serdes_irq_status = mv88e6352_serdes_irq_status, 4002a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 40030d632c3dSBrandon Streiff .avb_ops = &mv88e6352_avb_ops, 40046d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 40056c422e34SRussell King .phylink_validate = mv88e6352_phylink_validate, 4006b3469dd8SVivien Didelot }; 4007b3469dd8SVivien Didelot 40081f71836fSRasmus Villemoes static const struct mv88e6xxx_ops mv88e6250_ops = { 40091f71836fSRasmus Villemoes /* MV88E6XXX_FAMILY_6250 */ 40101f71836fSRasmus Villemoes .ieee_pri_map = mv88e6250_g1_ieee_pri_map, 40111f71836fSRasmus Villemoes .ip_pri_map = mv88e6085_g1_ip_pri_map, 40121f71836fSRasmus Villemoes .irl_init_all = mv88e6352_g2_irl_init_all, 40131f71836fSRasmus Villemoes .get_eeprom = mv88e6xxx_g2_get_eeprom16, 40141f71836fSRasmus Villemoes .set_eeprom = mv88e6xxx_g2_set_eeprom16, 40151f71836fSRasmus Villemoes .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 40161f71836fSRasmus Villemoes .phy_read = mv88e6xxx_g2_smi_phy_read, 40171f71836fSRasmus Villemoes .phy_write = mv88e6xxx_g2_smi_phy_write, 40181f71836fSRasmus Villemoes .port_set_link = mv88e6xxx_port_set_link, 40191f71836fSRasmus Villemoes .port_set_duplex = mv88e6xxx_port_set_duplex, 40201f71836fSRasmus Villemoes .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 40211f71836fSRasmus Villemoes .port_set_speed = mv88e6250_port_set_speed, 40221f71836fSRasmus Villemoes .port_tag_remap = mv88e6095_port_tag_remap, 40231f71836fSRasmus Villemoes .port_set_frame_mode = mv88e6351_port_set_frame_mode, 40241f71836fSRasmus Villemoes .port_set_egress_floods = mv88e6352_port_set_egress_floods, 40251f71836fSRasmus Villemoes .port_set_ether_type = mv88e6351_port_set_ether_type, 40261f71836fSRasmus Villemoes .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 40271f71836fSRasmus Villemoes .port_pause_limit = mv88e6097_port_pause_limit, 40281f71836fSRasmus Villemoes .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 40291f71836fSRasmus Villemoes .port_link_state = mv88e6250_port_link_state, 40301f71836fSRasmus Villemoes .stats_snapshot = mv88e6320_g1_stats_snapshot, 40311f71836fSRasmus Villemoes .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 40321f71836fSRasmus Villemoes .stats_get_sset_count = mv88e6250_stats_get_sset_count, 40331f71836fSRasmus Villemoes .stats_get_strings = mv88e6250_stats_get_strings, 40341f71836fSRasmus Villemoes .stats_get_stats = mv88e6250_stats_get_stats, 40351f71836fSRasmus Villemoes .set_cpu_port = mv88e6095_g1_set_cpu_port, 40361f71836fSRasmus Villemoes .set_egress_port = mv88e6095_g1_set_egress_port, 40371f71836fSRasmus Villemoes .watchdog_ops = &mv88e6250_watchdog_ops, 40381f71836fSRasmus Villemoes .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 40391f71836fSRasmus Villemoes .pot_clear = mv88e6xxx_g2_pot_clear, 40401f71836fSRasmus Villemoes .reset = mv88e6250_g1_reset, 40411f71836fSRasmus Villemoes .vtu_getnext = mv88e6250_g1_vtu_getnext, 40421f71836fSRasmus Villemoes .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge, 404371509614SHubert Feurstein .avb_ops = &mv88e6352_avb_ops, 404471509614SHubert Feurstein .ptp_ops = &mv88e6250_ptp_ops, 40451f71836fSRasmus Villemoes .phylink_validate = mv88e6065_phylink_validate, 40461f71836fSRasmus Villemoes }; 40471f71836fSRasmus Villemoes 40481a3b39ecSAndrew Lunn static const struct mv88e6xxx_ops mv88e6290_ops = { 40494b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6390 */ 4050ea89098eSAndrew Lunn .setup_errata = mv88e6390_setup_errata, 4051cd8da8bbSVivien Didelot .irl_init_all = mv88e6390_g2_irl_init_all, 405298fc3c6fSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 405398fc3c6fSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 40541a3b39ecSAndrew Lunn .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 40551a3b39ecSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 40561a3b39ecSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 40571a3b39ecSAndrew Lunn .port_set_link = mv88e6xxx_port_set_link, 40581a3b39ecSAndrew Lunn .port_set_duplex = mv88e6xxx_port_set_duplex, 40591a3b39ecSAndrew Lunn .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 40601a3b39ecSAndrew Lunn .port_set_speed = mv88e6390_port_set_speed, 40617cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6390_port_max_speed_mode, 4062ef0a7318SAndrew Lunn .port_tag_remap = mv88e6390_port_tag_remap, 4063f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 406456995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4065601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 406656995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 40670898432cSVivien Didelot .port_pause_limit = mv88e6390_port_pause_limit, 4068c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 40699dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 40706c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 40712d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4072fdc71eeaSAndrew Lunn .port_set_cmode = mv88e6390_port_set_cmode, 4073121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 407479523473SAndrew Lunn .stats_snapshot = mv88e6390_g1_stats_snapshot, 4075de227387SAndrew Lunn .stats_set_histogram = mv88e6390_g1_stats_set_histogram, 4076dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 4077dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 4078e0d8b615SAndrew Lunn .stats_get_stats = mv88e6390_stats_get_stats, 4079fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 4080fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 408161303736SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 40826e55f698SAndrew Lunn .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 40839e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 408417e708baSVivien Didelot .reset = mv88e6352_g1_reset, 40859e5baf9bSVivien Didelot .rmu_disable = mv88e6390_g1_rmu_disable, 408623e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 408723e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 4088931d1822SVivien Didelot .vtu_getnext = mv88e6390_g1_vtu_getnext, 4089931d1822SVivien Didelot .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 40906335e9f2SAndrew Lunn .serdes_power = mv88e6390_serdes_power, 409117deaf5cSMarek Behún .serdes_get_lane = mv88e6390_serdes_get_lane, 40924241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 409361a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 4094907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 4095a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 40960d632c3dSBrandon Streiff .avb_ops = &mv88e6390_avb_ops, 40976d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 40986c422e34SRussell King .phylink_validate = mv88e6390_phylink_validate, 40991a3b39ecSAndrew Lunn }; 41001a3b39ecSAndrew Lunn 4101b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6320_ops = { 41024b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6320 */ 410393e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 410493e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 4105cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 4106ee4dc2e7SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom16, 4107ee4dc2e7SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom16, 4108b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 4109b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 4110b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 411108ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 41127f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 411396a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 4114ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 411556995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4116601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 411756995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4118cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4119ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 41200898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 4121c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 41229dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 41236c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 41242d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4125121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 4126a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 412740cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 4128dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 4129dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 4130052f947fSAndrew Lunn .stats_get_stats = mv88e6320_stats_get_stats, 4131fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 4132fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 41339c7f37e5SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 413451c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 41359e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 413617e708baSVivien Didelot .reset = mv88e6352_g1_reset, 4137f1394b78SVivien Didelot .vtu_getnext = mv88e6185_g1_vtu_getnext, 41380ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, 4139a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 41400d632c3dSBrandon Streiff .avb_ops = &mv88e6352_avb_ops, 41416d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 41426c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 4143b3469dd8SVivien Didelot }; 4144b3469dd8SVivien Didelot 4145b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6321_ops = { 4146bd807204SVivien Didelot /* MV88E6XXX_FAMILY_6320 */ 414793e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 414893e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 4149cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 4150ee4dc2e7SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom16, 4151ee4dc2e7SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom16, 4152b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 4153b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 4154b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 415508ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 41567f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 415796a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 4158ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 415956995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4160601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 416156995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4162cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4163ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 41640898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 4165c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 41669dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 41676c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 41682d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4169121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 4170a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 417140cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 4172dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 4173dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 4174052f947fSAndrew Lunn .stats_get_stats = mv88e6320_stats_get_stats, 4175fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 4176fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 41779c7f37e5SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 417817e708baSVivien Didelot .reset = mv88e6352_g1_reset, 4179f1394b78SVivien Didelot .vtu_getnext = mv88e6185_g1_vtu_getnext, 41800ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, 4181a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 41820d632c3dSBrandon Streiff .avb_ops = &mv88e6352_avb_ops, 41836d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 41846c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 4185b3469dd8SVivien Didelot }; 4186b3469dd8SVivien Didelot 418716e329aeSVivien Didelot static const struct mv88e6xxx_ops mv88e6341_ops = { 418816e329aeSVivien Didelot /* MV88E6XXX_FAMILY_6341 */ 418993e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 419093e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 4191cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 419216e329aeSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 419316e329aeSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 419416e329aeSVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 419516e329aeSVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 419616e329aeSVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 419716e329aeSVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 419816e329aeSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 419916e329aeSVivien Didelot .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 420026422340SMarek Behún .port_set_speed = mv88e6341_port_set_speed, 42017cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6341_port_max_speed_mode, 420216e329aeSVivien Didelot .port_tag_remap = mv88e6095_port_tag_remap, 420316e329aeSVivien Didelot .port_set_frame_mode = mv88e6351_port_set_frame_mode, 420416e329aeSVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 420516e329aeSVivien Didelot .port_set_ether_type = mv88e6351_port_set_ether_type, 4206cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 420716e329aeSVivien Didelot .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 42080898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 420916e329aeSVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 421016e329aeSVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 42116c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 42122d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 42137a3007d2SMarek Behún .port_set_cmode = mv88e6341_port_set_cmode, 4214121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 421516e329aeSVivien Didelot .stats_snapshot = mv88e6390_g1_stats_snapshot, 421640cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 421716e329aeSVivien Didelot .stats_get_sset_count = mv88e6320_stats_get_sset_count, 421816e329aeSVivien Didelot .stats_get_strings = mv88e6320_stats_get_strings, 421916e329aeSVivien Didelot .stats_get_stats = mv88e6390_stats_get_stats, 4220fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 4221fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 422216e329aeSVivien Didelot .watchdog_ops = &mv88e6390_watchdog_ops, 422316e329aeSVivien Didelot .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 42249e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 422516e329aeSVivien Didelot .reset = mv88e6352_g1_reset, 4226f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 42270ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 4228d3cf7d8fSMarek Behún .serdes_power = mv88e6390_serdes_power, 4229d3cf7d8fSMarek Behún .serdes_get_lane = mv88e6341_serdes_get_lane, 42304241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 423161a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 4232907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 4233a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 42340d632c3dSBrandon Streiff .avb_ops = &mv88e6390_avb_ops, 42356d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 4236e3af71a3SMarek Behún .phylink_validate = mv88e6341_phylink_validate, 423716e329aeSVivien Didelot }; 423816e329aeSVivien Didelot 4239b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6350_ops = { 42404b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6351 */ 424193e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 424293e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 4243cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 4244b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 4245b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 4246b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 424708ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 42487f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 424994d66ae6SAndrew Lunn .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 425096a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 4251ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 425256995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4253601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 425456995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4255cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4256ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 42570898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 4258c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 42599dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 42606c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 42612d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4262121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 4263a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 426440cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 4265dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 4266dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 4267052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 4268fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 4269fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 4270fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 427151c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 42729e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 427317e708baSVivien Didelot .reset = mv88e6352_g1_reset, 427423e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 427523e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 4276f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 42770ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 42786c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 4279b3469dd8SVivien Didelot }; 4280b3469dd8SVivien Didelot 4281b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6351_ops = { 42824b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6351 */ 428393e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 428493e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 4285cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 4286b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 4287b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 4288b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 428908ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 42907f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 429194d66ae6SAndrew Lunn .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 429296a2b40cSVivien Didelot .port_set_speed = mv88e6185_port_set_speed, 4293ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 429456995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4295601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 429656995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4297cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4298ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 42990898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 4300c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 43019dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 43026c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 43032d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4304121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 4305a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 430640cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 4307dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 4308dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 4309052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 4310fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 4311fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 4312fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 431351c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 43149e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 431517e708baSVivien Didelot .reset = mv88e6352_g1_reset, 431623e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 431723e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 4318f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 43190ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 43200d632c3dSBrandon Streiff .avb_ops = &mv88e6352_avb_ops, 43216d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 43226c422e34SRussell King .phylink_validate = mv88e6185_phylink_validate, 4323b3469dd8SVivien Didelot }; 4324b3469dd8SVivien Didelot 4325b3469dd8SVivien Didelot static const struct mv88e6xxx_ops mv88e6352_ops = { 43264b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6352 */ 432793e18d61SVivien Didelot .ieee_pri_map = mv88e6085_g1_ieee_pri_map, 432893e18d61SVivien Didelot .ip_pri_map = mv88e6085_g1_ip_pri_map, 4329cd8da8bbSVivien Didelot .irl_init_all = mv88e6352_g2_irl_init_all, 4330ee4dc2e7SVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom16, 4331ee4dc2e7SVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom16, 4332b073d4e2SVivien Didelot .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 4333b3469dd8SVivien Didelot .phy_read = mv88e6xxx_g2_smi_phy_read, 4334b3469dd8SVivien Didelot .phy_write = mv88e6xxx_g2_smi_phy_write, 433508ef7f10SVivien Didelot .port_set_link = mv88e6xxx_port_set_link, 43367f1ae07bSVivien Didelot .port_set_duplex = mv88e6xxx_port_set_duplex, 4337a0a0f622SVivien Didelot .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 433896a2b40cSVivien Didelot .port_set_speed = mv88e6352_port_set_speed, 4339ef0a7318SAndrew Lunn .port_tag_remap = mv88e6095_port_tag_remap, 4340f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 434156995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4342601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 434356995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4344cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4345ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 43460898432cSVivien Didelot .port_pause_limit = mv88e6097_port_pause_limit, 4347c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 43489dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 43496c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 43502d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4351121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 4352a605a0feSAndrew Lunn .stats_snapshot = mv88e6320_g1_stats_snapshot, 435340cff8fcSAndrew Lunn .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 4354dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6095_stats_get_sset_count, 4355dfafe449SAndrew Lunn .stats_get_strings = mv88e6095_stats_get_strings, 4356052f947fSAndrew Lunn .stats_get_stats = mv88e6095_stats_get_stats, 4357fa8d1179SVivien Didelot .set_cpu_port = mv88e6095_g1_set_cpu_port, 4358fa8d1179SVivien Didelot .set_egress_port = mv88e6095_g1_set_egress_port, 4359fcd25166SAndrew Lunn .watchdog_ops = &mv88e6097_watchdog_ops, 436051c901a7SVivien Didelot .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, 43619e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 436217e708baSVivien Didelot .reset = mv88e6352_g1_reset, 43639e5baf9bSVivien Didelot .rmu_disable = mv88e6352_g1_rmu_disable, 436423e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 436523e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 4366f1394b78SVivien Didelot .vtu_getnext = mv88e6352_g1_vtu_getnext, 43670ad5daf6SVivien Didelot .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 43689db4a725SVivien Didelot .serdes_get_lane = mv88e6352_serdes_get_lane, 43696d91782fSAndrew Lunn .serdes_power = mv88e6352_serdes_power, 43704241ef52SVivien Didelot .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, 437161a46b41SVivien Didelot .serdes_irq_enable = mv88e6352_serdes_irq_enable, 4372907b9b9fSVivien Didelot .serdes_irq_status = mv88e6352_serdes_irq_status, 4373a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 43740d632c3dSBrandon Streiff .avb_ops = &mv88e6352_avb_ops, 43756d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 4376cda9f4aaSAndrew Lunn .serdes_get_sset_count = mv88e6352_serdes_get_sset_count, 4377cda9f4aaSAndrew Lunn .serdes_get_strings = mv88e6352_serdes_get_strings, 4378cda9f4aaSAndrew Lunn .serdes_get_stats = mv88e6352_serdes_get_stats, 43796c422e34SRussell King .phylink_validate = mv88e6352_phylink_validate, 4380b3469dd8SVivien Didelot }; 4381b3469dd8SVivien Didelot 43821a3b39ecSAndrew Lunn static const struct mv88e6xxx_ops mv88e6390_ops = { 43834b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6390 */ 4384ea89098eSAndrew Lunn .setup_errata = mv88e6390_setup_errata, 4385cd8da8bbSVivien Didelot .irl_init_all = mv88e6390_g2_irl_init_all, 438698fc3c6fSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 438798fc3c6fSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 43881a3b39ecSAndrew Lunn .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 43891a3b39ecSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 43901a3b39ecSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 43911a3b39ecSAndrew Lunn .port_set_link = mv88e6xxx_port_set_link, 43921a3b39ecSAndrew Lunn .port_set_duplex = mv88e6xxx_port_set_duplex, 43931a3b39ecSAndrew Lunn .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 43941a3b39ecSAndrew Lunn .port_set_speed = mv88e6390_port_set_speed, 43957cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6390_port_max_speed_mode, 4396ef0a7318SAndrew Lunn .port_tag_remap = mv88e6390_port_tag_remap, 4397f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 439856995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4399601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 440056995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4401cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4402ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 44030898432cSVivien Didelot .port_pause_limit = mv88e6390_port_pause_limit, 4404c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 44059dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 44066c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 44072d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4408fdc71eeaSAndrew Lunn .port_set_cmode = mv88e6390_port_set_cmode, 4409121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 441079523473SAndrew Lunn .stats_snapshot = mv88e6390_g1_stats_snapshot, 4411de227387SAndrew Lunn .stats_set_histogram = mv88e6390_g1_stats_set_histogram, 4412dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 4413dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 4414e0d8b615SAndrew Lunn .stats_get_stats = mv88e6390_stats_get_stats, 4415fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 4416fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 441761303736SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 44186e55f698SAndrew Lunn .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 44199e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 442017e708baSVivien Didelot .reset = mv88e6352_g1_reset, 44219e5baf9bSVivien Didelot .rmu_disable = mv88e6390_g1_rmu_disable, 442223e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 442323e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 4424931d1822SVivien Didelot .vtu_getnext = mv88e6390_g1_vtu_getnext, 4425931d1822SVivien Didelot .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 44266335e9f2SAndrew Lunn .serdes_power = mv88e6390_serdes_power, 442717deaf5cSMarek Behún .serdes_get_lane = mv88e6390_serdes_get_lane, 44284241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 442961a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 4430907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 4431a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 44320d632c3dSBrandon Streiff .avb_ops = &mv88e6390_avb_ops, 44336d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 44340df95287SNikita Yushchenko .serdes_get_sset_count = mv88e6390_serdes_get_sset_count, 44350df95287SNikita Yushchenko .serdes_get_strings = mv88e6390_serdes_get_strings, 44360df95287SNikita Yushchenko .serdes_get_stats = mv88e6390_serdes_get_stats, 44376c422e34SRussell King .phylink_validate = mv88e6390_phylink_validate, 44381a3b39ecSAndrew Lunn }; 44391a3b39ecSAndrew Lunn 44401a3b39ecSAndrew Lunn static const struct mv88e6xxx_ops mv88e6390x_ops = { 44414b325d8cSAndrew Lunn /* MV88E6XXX_FAMILY_6390 */ 4442ea89098eSAndrew Lunn .setup_errata = mv88e6390_setup_errata, 4443cd8da8bbSVivien Didelot .irl_init_all = mv88e6390_g2_irl_init_all, 444498fc3c6fSVivien Didelot .get_eeprom = mv88e6xxx_g2_get_eeprom8, 444598fc3c6fSVivien Didelot .set_eeprom = mv88e6xxx_g2_set_eeprom8, 44461a3b39ecSAndrew Lunn .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 44471a3b39ecSAndrew Lunn .phy_read = mv88e6xxx_g2_smi_phy_read, 44481a3b39ecSAndrew Lunn .phy_write = mv88e6xxx_g2_smi_phy_write, 44491a3b39ecSAndrew Lunn .port_set_link = mv88e6xxx_port_set_link, 44501a3b39ecSAndrew Lunn .port_set_duplex = mv88e6xxx_port_set_duplex, 44511a3b39ecSAndrew Lunn .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, 44521a3b39ecSAndrew Lunn .port_set_speed = mv88e6390x_port_set_speed, 44537cbbee05SAndrew Lunn .port_max_speed_mode = mv88e6390x_port_max_speed_mode, 4454ef0a7318SAndrew Lunn .port_tag_remap = mv88e6390_port_tag_remap, 4455f3a2cd32SVivien Didelot .port_set_policy = mv88e6352_port_set_policy, 445656995cbcSAndrew Lunn .port_set_frame_mode = mv88e6351_port_set_frame_mode, 4457601aeed3SVivien Didelot .port_set_egress_floods = mv88e6352_port_set_egress_floods, 445856995cbcSAndrew Lunn .port_set_ether_type = mv88e6351_port_set_ether_type, 4459cd782656SVivien Didelot .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 4460ef70b111SAndrew Lunn .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 44610898432cSVivien Didelot .port_pause_limit = mv88e6390_port_pause_limit, 4462c8c94891SVivien Didelot .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, 44639dbfb4e1SVivien Didelot .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, 44646c422e34SRussell King .port_link_state = mv88e6352_port_link_state, 44652d2e1dd2SAndrew Lunn .port_get_cmode = mv88e6352_port_get_cmode, 4466b3dce4daSAndrew Lunn .port_set_cmode = mv88e6390x_port_set_cmode, 4467121b8fe2SHubert Feurstein .port_setup_message_port = mv88e6xxx_setup_message_port, 446879523473SAndrew Lunn .stats_snapshot = mv88e6390_g1_stats_snapshot, 4469de227387SAndrew Lunn .stats_set_histogram = mv88e6390_g1_stats_set_histogram, 4470dfafe449SAndrew Lunn .stats_get_sset_count = mv88e6320_stats_get_sset_count, 4471dfafe449SAndrew Lunn .stats_get_strings = mv88e6320_stats_get_strings, 4472e0d8b615SAndrew Lunn .stats_get_stats = mv88e6390_stats_get_stats, 4473fa8d1179SVivien Didelot .set_cpu_port = mv88e6390_g1_set_cpu_port, 4474fa8d1179SVivien Didelot .set_egress_port = mv88e6390_g1_set_egress_port, 447561303736SAndrew Lunn .watchdog_ops = &mv88e6390_watchdog_ops, 44766e55f698SAndrew Lunn .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, 44779e907d73SVivien Didelot .pot_clear = mv88e6xxx_g2_pot_clear, 447817e708baSVivien Didelot .reset = mv88e6352_g1_reset, 44799e5baf9bSVivien Didelot .rmu_disable = mv88e6390_g1_rmu_disable, 448023e8b470SAndrew Lunn .atu_get_hash = mv88e6165_g1_atu_get_hash, 448123e8b470SAndrew Lunn .atu_set_hash = mv88e6165_g1_atu_set_hash, 4482931d1822SVivien Didelot .vtu_getnext = mv88e6390_g1_vtu_getnext, 4483931d1822SVivien Didelot .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 4484d3cf7d8fSMarek Behún .serdes_power = mv88e6390_serdes_power, 448517deaf5cSMarek Behún .serdes_get_lane = mv88e6390x_serdes_get_lane, 44864241ef52SVivien Didelot .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 448761a46b41SVivien Didelot .serdes_irq_enable = mv88e6390_serdes_irq_enable, 4488907b9b9fSVivien Didelot .serdes_irq_status = mv88e6390_serdes_irq_status, 4489a73ccd61SBrandon Streiff .gpio_ops = &mv88e6352_gpio_ops, 44900d632c3dSBrandon Streiff .avb_ops = &mv88e6390_avb_ops, 44916d2ac8eeSAndrew Lunn .ptp_ops = &mv88e6352_ptp_ops, 44926c422e34SRussell King .phylink_validate = mv88e6390x_phylink_validate, 44931a3b39ecSAndrew Lunn }; 44941a3b39ecSAndrew Lunn 4495fad09c73SVivien Didelot static const struct mv88e6xxx_info mv88e6xxx_table[] = { 4496fad09c73SVivien Didelot [MV88E6085] = { 4497107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085, 4498fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6097, 4499fad09c73SVivien Didelot .name = "Marvell 88E6085", 4500fad09c73SVivien Didelot .num_databases = 4096, 4501d9ea5620SAndrew Lunn .num_macs = 8192, 4502fad09c73SVivien Didelot .num_ports = 10, 4503bc393155SAndrew Lunn .num_internal_phys = 5, 45043cf3c846SVivien Didelot .max_vid = 4095, 4505fad09c73SVivien Didelot .port_base_addr = 0x10, 45069255bacdSAndrew Lunn .phy_base_addr = 0x0, 4507a935c052SVivien Didelot .global1_addr = 0x1b, 45089069c13aSVivien Didelot .global2_addr = 0x1c, 4509acddbd21SVivien Didelot .age_time_coeff = 15000, 4510dc30c35bSAndrew Lunn .g1_irqs = 8, 4511d6c5e6afSVivien Didelot .g2_irqs = 10, 4512e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4513f3645652SVivien Didelot .pvt = true, 4514b3e05aa1SVivien Didelot .multi_chip = true, 4515443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 4516b3469dd8SVivien Didelot .ops = &mv88e6085_ops, 4517fad09c73SVivien Didelot }, 4518fad09c73SVivien Didelot 4519fad09c73SVivien Didelot [MV88E6095] = { 4520107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095, 4521fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6095, 4522fad09c73SVivien Didelot .name = "Marvell 88E6095/88E6095F", 4523fad09c73SVivien Didelot .num_databases = 256, 4524d9ea5620SAndrew Lunn .num_macs = 8192, 4525fad09c73SVivien Didelot .num_ports = 11, 4526bc393155SAndrew Lunn .num_internal_phys = 0, 45273cf3c846SVivien Didelot .max_vid = 4095, 4528fad09c73SVivien Didelot .port_base_addr = 0x10, 45299255bacdSAndrew Lunn .phy_base_addr = 0x0, 4530a935c052SVivien Didelot .global1_addr = 0x1b, 45319069c13aSVivien Didelot .global2_addr = 0x1c, 4532acddbd21SVivien Didelot .age_time_coeff = 15000, 4533dc30c35bSAndrew Lunn .g1_irqs = 8, 4534e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4535b3e05aa1SVivien Didelot .multi_chip = true, 4536443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 4537b3469dd8SVivien Didelot .ops = &mv88e6095_ops, 4538fad09c73SVivien Didelot }, 4539fad09c73SVivien Didelot 45407d381a02SStefan Eichenberger [MV88E6097] = { 4541107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097, 45427d381a02SStefan Eichenberger .family = MV88E6XXX_FAMILY_6097, 45437d381a02SStefan Eichenberger .name = "Marvell 88E6097/88E6097F", 45447d381a02SStefan Eichenberger .num_databases = 4096, 4545d9ea5620SAndrew Lunn .num_macs = 8192, 45467d381a02SStefan Eichenberger .num_ports = 11, 4547bc393155SAndrew Lunn .num_internal_phys = 8, 45483cf3c846SVivien Didelot .max_vid = 4095, 45497d381a02SStefan Eichenberger .port_base_addr = 0x10, 45509255bacdSAndrew Lunn .phy_base_addr = 0x0, 45517d381a02SStefan Eichenberger .global1_addr = 0x1b, 45529069c13aSVivien Didelot .global2_addr = 0x1c, 45537d381a02SStefan Eichenberger .age_time_coeff = 15000, 4554c534178bSStefan Eichenberger .g1_irqs = 8, 4555d6c5e6afSVivien Didelot .g2_irqs = 10, 4556e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4557f3645652SVivien Didelot .pvt = true, 4558b3e05aa1SVivien Didelot .multi_chip = true, 45592bfcfcd3SStefan Eichenberger .tag_protocol = DSA_TAG_PROTO_EDSA, 45607d381a02SStefan Eichenberger .ops = &mv88e6097_ops, 45617d381a02SStefan Eichenberger }, 45627d381a02SStefan Eichenberger 4563fad09c73SVivien Didelot [MV88E6123] = { 4564107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123, 4565fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6165, 4566fad09c73SVivien Didelot .name = "Marvell 88E6123", 4567fad09c73SVivien Didelot .num_databases = 4096, 4568d9ea5620SAndrew Lunn .num_macs = 1024, 4569fad09c73SVivien Didelot .num_ports = 3, 4570bc393155SAndrew Lunn .num_internal_phys = 5, 45713cf3c846SVivien Didelot .max_vid = 4095, 4572fad09c73SVivien Didelot .port_base_addr = 0x10, 45739255bacdSAndrew Lunn .phy_base_addr = 0x0, 4574a935c052SVivien Didelot .global1_addr = 0x1b, 45759069c13aSVivien Didelot .global2_addr = 0x1c, 4576acddbd21SVivien Didelot .age_time_coeff = 15000, 4577dc30c35bSAndrew Lunn .g1_irqs = 9, 4578d6c5e6afSVivien Didelot .g2_irqs = 10, 4579e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4580f3645652SVivien Didelot .pvt = true, 4581b3e05aa1SVivien Didelot .multi_chip = true, 45825ebe31d7SAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4583b3469dd8SVivien Didelot .ops = &mv88e6123_ops, 4584fad09c73SVivien Didelot }, 4585fad09c73SVivien Didelot 4586fad09c73SVivien Didelot [MV88E6131] = { 4587107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131, 4588fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6185, 4589fad09c73SVivien Didelot .name = "Marvell 88E6131", 4590fad09c73SVivien Didelot .num_databases = 256, 4591d9ea5620SAndrew Lunn .num_macs = 8192, 4592fad09c73SVivien Didelot .num_ports = 8, 4593bc393155SAndrew Lunn .num_internal_phys = 0, 45943cf3c846SVivien Didelot .max_vid = 4095, 4595fad09c73SVivien Didelot .port_base_addr = 0x10, 45969255bacdSAndrew Lunn .phy_base_addr = 0x0, 4597a935c052SVivien Didelot .global1_addr = 0x1b, 45989069c13aSVivien Didelot .global2_addr = 0x1c, 4599acddbd21SVivien Didelot .age_time_coeff = 15000, 4600dc30c35bSAndrew Lunn .g1_irqs = 9, 4601e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4602b3e05aa1SVivien Didelot .multi_chip = true, 4603443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 4604b3469dd8SVivien Didelot .ops = &mv88e6131_ops, 4605fad09c73SVivien Didelot }, 4606fad09c73SVivien Didelot 4607990e27b0SVivien Didelot [MV88E6141] = { 4608107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141, 4609990e27b0SVivien Didelot .family = MV88E6XXX_FAMILY_6341, 461079a68b26SUwe Kleine-König .name = "Marvell 88E6141", 4611990e27b0SVivien Didelot .num_databases = 4096, 4612d9ea5620SAndrew Lunn .num_macs = 2048, 4613990e27b0SVivien Didelot .num_ports = 6, 4614bc393155SAndrew Lunn .num_internal_phys = 5, 4615a73ccd61SBrandon Streiff .num_gpio = 11, 46163cf3c846SVivien Didelot .max_vid = 4095, 4617990e27b0SVivien Didelot .port_base_addr = 0x10, 46189255bacdSAndrew Lunn .phy_base_addr = 0x10, 4619990e27b0SVivien Didelot .global1_addr = 0x1b, 46209069c13aSVivien Didelot .global2_addr = 0x1c, 4621990e27b0SVivien Didelot .age_time_coeff = 3750, 4622990e27b0SVivien Didelot .atu_move_port_mask = 0x1f, 4623adfccf11SAndrew Lunn .g1_irqs = 9, 4624d6c5e6afSVivien Didelot .g2_irqs = 10, 4625f3645652SVivien Didelot .pvt = true, 4626b3e05aa1SVivien Didelot .multi_chip = true, 4627990e27b0SVivien Didelot .tag_protocol = DSA_TAG_PROTO_EDSA, 4628990e27b0SVivien Didelot .ops = &mv88e6141_ops, 4629990e27b0SVivien Didelot }, 4630990e27b0SVivien Didelot 4631fad09c73SVivien Didelot [MV88E6161] = { 4632107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161, 4633fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6165, 4634fad09c73SVivien Didelot .name = "Marvell 88E6161", 4635fad09c73SVivien Didelot .num_databases = 4096, 4636d9ea5620SAndrew Lunn .num_macs = 1024, 4637fad09c73SVivien Didelot .num_ports = 6, 4638bc393155SAndrew Lunn .num_internal_phys = 5, 46393cf3c846SVivien Didelot .max_vid = 4095, 4640fad09c73SVivien Didelot .port_base_addr = 0x10, 46419255bacdSAndrew Lunn .phy_base_addr = 0x0, 4642a935c052SVivien Didelot .global1_addr = 0x1b, 46439069c13aSVivien Didelot .global2_addr = 0x1c, 4644acddbd21SVivien Didelot .age_time_coeff = 15000, 4645dc30c35bSAndrew Lunn .g1_irqs = 9, 4646d6c5e6afSVivien Didelot .g2_irqs = 10, 4647e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4648f3645652SVivien Didelot .pvt = true, 4649b3e05aa1SVivien Didelot .multi_chip = true, 46505ebe31d7SAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4651dfa54348SAndrew Lunn .ptp_support = true, 4652b3469dd8SVivien Didelot .ops = &mv88e6161_ops, 4653fad09c73SVivien Didelot }, 4654fad09c73SVivien Didelot 4655fad09c73SVivien Didelot [MV88E6165] = { 4656107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165, 4657fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6165, 4658fad09c73SVivien Didelot .name = "Marvell 88E6165", 4659fad09c73SVivien Didelot .num_databases = 4096, 4660d9ea5620SAndrew Lunn .num_macs = 8192, 4661fad09c73SVivien Didelot .num_ports = 6, 4662bc393155SAndrew Lunn .num_internal_phys = 0, 46633cf3c846SVivien Didelot .max_vid = 4095, 4664fad09c73SVivien Didelot .port_base_addr = 0x10, 46659255bacdSAndrew Lunn .phy_base_addr = 0x0, 4666a935c052SVivien Didelot .global1_addr = 0x1b, 46679069c13aSVivien Didelot .global2_addr = 0x1c, 4668acddbd21SVivien Didelot .age_time_coeff = 15000, 4669dc30c35bSAndrew Lunn .g1_irqs = 9, 4670d6c5e6afSVivien Didelot .g2_irqs = 10, 4671e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4672f3645652SVivien Didelot .pvt = true, 4673b3e05aa1SVivien Didelot .multi_chip = true, 4674443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 4675dfa54348SAndrew Lunn .ptp_support = true, 4676b3469dd8SVivien Didelot .ops = &mv88e6165_ops, 4677fad09c73SVivien Didelot }, 4678fad09c73SVivien Didelot 4679fad09c73SVivien Didelot [MV88E6171] = { 4680107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171, 4681fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6351, 4682fad09c73SVivien Didelot .name = "Marvell 88E6171", 4683fad09c73SVivien Didelot .num_databases = 4096, 4684d9ea5620SAndrew Lunn .num_macs = 8192, 4685fad09c73SVivien Didelot .num_ports = 7, 4686bc393155SAndrew Lunn .num_internal_phys = 5, 46873cf3c846SVivien Didelot .max_vid = 4095, 4688fad09c73SVivien Didelot .port_base_addr = 0x10, 46899255bacdSAndrew Lunn .phy_base_addr = 0x0, 4690a935c052SVivien Didelot .global1_addr = 0x1b, 46919069c13aSVivien Didelot .global2_addr = 0x1c, 4692acddbd21SVivien Didelot .age_time_coeff = 15000, 4693dc30c35bSAndrew Lunn .g1_irqs = 9, 4694d6c5e6afSVivien Didelot .g2_irqs = 10, 4695e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4696f3645652SVivien Didelot .pvt = true, 4697b3e05aa1SVivien Didelot .multi_chip = true, 4698443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4699b3469dd8SVivien Didelot .ops = &mv88e6171_ops, 4700fad09c73SVivien Didelot }, 4701fad09c73SVivien Didelot 4702fad09c73SVivien Didelot [MV88E6172] = { 4703107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172, 4704fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6352, 4705fad09c73SVivien Didelot .name = "Marvell 88E6172", 4706fad09c73SVivien Didelot .num_databases = 4096, 4707d9ea5620SAndrew Lunn .num_macs = 8192, 4708fad09c73SVivien Didelot .num_ports = 7, 4709bc393155SAndrew Lunn .num_internal_phys = 5, 4710a73ccd61SBrandon Streiff .num_gpio = 15, 47113cf3c846SVivien Didelot .max_vid = 4095, 4712fad09c73SVivien Didelot .port_base_addr = 0x10, 47139255bacdSAndrew Lunn .phy_base_addr = 0x0, 4714a935c052SVivien Didelot .global1_addr = 0x1b, 47159069c13aSVivien Didelot .global2_addr = 0x1c, 4716acddbd21SVivien Didelot .age_time_coeff = 15000, 4717dc30c35bSAndrew Lunn .g1_irqs = 9, 4718d6c5e6afSVivien Didelot .g2_irqs = 10, 4719e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4720f3645652SVivien Didelot .pvt = true, 4721b3e05aa1SVivien Didelot .multi_chip = true, 4722443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4723b3469dd8SVivien Didelot .ops = &mv88e6172_ops, 4724fad09c73SVivien Didelot }, 4725fad09c73SVivien Didelot 4726fad09c73SVivien Didelot [MV88E6175] = { 4727107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175, 4728fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6351, 4729fad09c73SVivien Didelot .name = "Marvell 88E6175", 4730fad09c73SVivien Didelot .num_databases = 4096, 4731d9ea5620SAndrew Lunn .num_macs = 8192, 4732fad09c73SVivien Didelot .num_ports = 7, 4733bc393155SAndrew Lunn .num_internal_phys = 5, 47343cf3c846SVivien Didelot .max_vid = 4095, 4735fad09c73SVivien Didelot .port_base_addr = 0x10, 47369255bacdSAndrew Lunn .phy_base_addr = 0x0, 4737a935c052SVivien Didelot .global1_addr = 0x1b, 47389069c13aSVivien Didelot .global2_addr = 0x1c, 4739acddbd21SVivien Didelot .age_time_coeff = 15000, 4740dc30c35bSAndrew Lunn .g1_irqs = 9, 4741d6c5e6afSVivien Didelot .g2_irqs = 10, 4742e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4743f3645652SVivien Didelot .pvt = true, 4744b3e05aa1SVivien Didelot .multi_chip = true, 4745443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4746b3469dd8SVivien Didelot .ops = &mv88e6175_ops, 4747fad09c73SVivien Didelot }, 4748fad09c73SVivien Didelot 4749fad09c73SVivien Didelot [MV88E6176] = { 4750107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176, 4751fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6352, 4752fad09c73SVivien Didelot .name = "Marvell 88E6176", 4753fad09c73SVivien Didelot .num_databases = 4096, 4754d9ea5620SAndrew Lunn .num_macs = 8192, 4755fad09c73SVivien Didelot .num_ports = 7, 4756bc393155SAndrew Lunn .num_internal_phys = 5, 4757a73ccd61SBrandon Streiff .num_gpio = 15, 47583cf3c846SVivien Didelot .max_vid = 4095, 4759fad09c73SVivien Didelot .port_base_addr = 0x10, 47609255bacdSAndrew Lunn .phy_base_addr = 0x0, 4761a935c052SVivien Didelot .global1_addr = 0x1b, 47629069c13aSVivien Didelot .global2_addr = 0x1c, 4763acddbd21SVivien Didelot .age_time_coeff = 15000, 4764dc30c35bSAndrew Lunn .g1_irqs = 9, 4765d6c5e6afSVivien Didelot .g2_irqs = 10, 4766e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4767f3645652SVivien Didelot .pvt = true, 4768b3e05aa1SVivien Didelot .multi_chip = true, 4769443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4770b3469dd8SVivien Didelot .ops = &mv88e6176_ops, 4771fad09c73SVivien Didelot }, 4772fad09c73SVivien Didelot 4773fad09c73SVivien Didelot [MV88E6185] = { 4774107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185, 4775fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6185, 4776fad09c73SVivien Didelot .name = "Marvell 88E6185", 4777fad09c73SVivien Didelot .num_databases = 256, 4778d9ea5620SAndrew Lunn .num_macs = 8192, 4779fad09c73SVivien Didelot .num_ports = 10, 4780bc393155SAndrew Lunn .num_internal_phys = 0, 47813cf3c846SVivien Didelot .max_vid = 4095, 4782fad09c73SVivien Didelot .port_base_addr = 0x10, 47839255bacdSAndrew Lunn .phy_base_addr = 0x0, 4784a935c052SVivien Didelot .global1_addr = 0x1b, 47859069c13aSVivien Didelot .global2_addr = 0x1c, 4786acddbd21SVivien Didelot .age_time_coeff = 15000, 4787dc30c35bSAndrew Lunn .g1_irqs = 8, 4788e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4789b3e05aa1SVivien Didelot .multi_chip = true, 4790443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 4791b3469dd8SVivien Didelot .ops = &mv88e6185_ops, 4792fad09c73SVivien Didelot }, 4793fad09c73SVivien Didelot 47941a3b39ecSAndrew Lunn [MV88E6190] = { 4795107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190, 47961a3b39ecSAndrew Lunn .family = MV88E6XXX_FAMILY_6390, 47971a3b39ecSAndrew Lunn .name = "Marvell 88E6190", 47981a3b39ecSAndrew Lunn .num_databases = 4096, 4799d9ea5620SAndrew Lunn .num_macs = 16384, 48001a3b39ecSAndrew Lunn .num_ports = 11, /* 10 + Z80 */ 480195150f29SHeiner Kallweit .num_internal_phys = 9, 4802a73ccd61SBrandon Streiff .num_gpio = 16, 4803931d1822SVivien Didelot .max_vid = 8191, 48041a3b39ecSAndrew Lunn .port_base_addr = 0x0, 48059255bacdSAndrew Lunn .phy_base_addr = 0x0, 48061a3b39ecSAndrew Lunn .global1_addr = 0x1b, 48079069c13aSVivien Didelot .global2_addr = 0x1c, 4808443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 4809b91e055cSAndrew Lunn .age_time_coeff = 3750, 48101a3b39ecSAndrew Lunn .g1_irqs = 9, 4811d6c5e6afSVivien Didelot .g2_irqs = 14, 4812f3645652SVivien Didelot .pvt = true, 4813b3e05aa1SVivien Didelot .multi_chip = true, 4814e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 48151a3b39ecSAndrew Lunn .ops = &mv88e6190_ops, 48161a3b39ecSAndrew Lunn }, 48171a3b39ecSAndrew Lunn 48181a3b39ecSAndrew Lunn [MV88E6190X] = { 4819107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X, 48201a3b39ecSAndrew Lunn .family = MV88E6XXX_FAMILY_6390, 48211a3b39ecSAndrew Lunn .name = "Marvell 88E6190X", 48221a3b39ecSAndrew Lunn .num_databases = 4096, 4823d9ea5620SAndrew Lunn .num_macs = 16384, 48241a3b39ecSAndrew Lunn .num_ports = 11, /* 10 + Z80 */ 482595150f29SHeiner Kallweit .num_internal_phys = 9, 4826a73ccd61SBrandon Streiff .num_gpio = 16, 4827931d1822SVivien Didelot .max_vid = 8191, 48281a3b39ecSAndrew Lunn .port_base_addr = 0x0, 48299255bacdSAndrew Lunn .phy_base_addr = 0x0, 48301a3b39ecSAndrew Lunn .global1_addr = 0x1b, 48319069c13aSVivien Didelot .global2_addr = 0x1c, 4832b91e055cSAndrew Lunn .age_time_coeff = 3750, 48331a3b39ecSAndrew Lunn .g1_irqs = 9, 4834d6c5e6afSVivien Didelot .g2_irqs = 14, 4835e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 4836f3645652SVivien Didelot .pvt = true, 4837b3e05aa1SVivien Didelot .multi_chip = true, 4838443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 48391a3b39ecSAndrew Lunn .ops = &mv88e6190x_ops, 48401a3b39ecSAndrew Lunn }, 48411a3b39ecSAndrew Lunn 48421a3b39ecSAndrew Lunn [MV88E6191] = { 4843107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191, 48441a3b39ecSAndrew Lunn .family = MV88E6XXX_FAMILY_6390, 48451a3b39ecSAndrew Lunn .name = "Marvell 88E6191", 48461a3b39ecSAndrew Lunn .num_databases = 4096, 4847d9ea5620SAndrew Lunn .num_macs = 16384, 48481a3b39ecSAndrew Lunn .num_ports = 11, /* 10 + Z80 */ 484995150f29SHeiner Kallweit .num_internal_phys = 9, 4850931d1822SVivien Didelot .max_vid = 8191, 48511a3b39ecSAndrew Lunn .port_base_addr = 0x0, 48529255bacdSAndrew Lunn .phy_base_addr = 0x0, 48531a3b39ecSAndrew Lunn .global1_addr = 0x1b, 48549069c13aSVivien Didelot .global2_addr = 0x1c, 4855b91e055cSAndrew Lunn .age_time_coeff = 3750, 4856443d5a1bSAndrew Lunn .g1_irqs = 9, 4857d6c5e6afSVivien Didelot .g2_irqs = 14, 4858e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 4859f3645652SVivien Didelot .pvt = true, 4860b3e05aa1SVivien Didelot .multi_chip = true, 4861443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 48622fa8d3afSBrandon Streiff .ptp_support = true, 48632cf4cefbSVivien Didelot .ops = &mv88e6191_ops, 48641a3b39ecSAndrew Lunn }, 48651a3b39ecSAndrew Lunn 486649022647SHubert Feurstein [MV88E6220] = { 486749022647SHubert Feurstein .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6220, 486849022647SHubert Feurstein .family = MV88E6XXX_FAMILY_6250, 486949022647SHubert Feurstein .name = "Marvell 88E6220", 487049022647SHubert Feurstein .num_databases = 64, 487149022647SHubert Feurstein 487249022647SHubert Feurstein /* Ports 2-4 are not routed to pins 487349022647SHubert Feurstein * => usable ports 0, 1, 5, 6 487449022647SHubert Feurstein */ 487549022647SHubert Feurstein .num_ports = 7, 487649022647SHubert Feurstein .num_internal_phys = 2, 4877c857486aSHubert Feurstein .invalid_port_mask = BIT(2) | BIT(3) | BIT(4), 487849022647SHubert Feurstein .max_vid = 4095, 487949022647SHubert Feurstein .port_base_addr = 0x08, 488049022647SHubert Feurstein .phy_base_addr = 0x00, 488149022647SHubert Feurstein .global1_addr = 0x0f, 488249022647SHubert Feurstein .global2_addr = 0x07, 488349022647SHubert Feurstein .age_time_coeff = 15000, 488449022647SHubert Feurstein .g1_irqs = 9, 488549022647SHubert Feurstein .g2_irqs = 10, 488649022647SHubert Feurstein .atu_move_port_mask = 0xf, 488749022647SHubert Feurstein .dual_chip = true, 488849022647SHubert Feurstein .tag_protocol = DSA_TAG_PROTO_DSA, 488971509614SHubert Feurstein .ptp_support = true, 489049022647SHubert Feurstein .ops = &mv88e6250_ops, 489149022647SHubert Feurstein }, 489249022647SHubert Feurstein 4893fad09c73SVivien Didelot [MV88E6240] = { 4894107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240, 4895fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6352, 4896fad09c73SVivien Didelot .name = "Marvell 88E6240", 4897fad09c73SVivien Didelot .num_databases = 4096, 4898d9ea5620SAndrew Lunn .num_macs = 8192, 4899fad09c73SVivien Didelot .num_ports = 7, 4900bc393155SAndrew Lunn .num_internal_phys = 5, 4901a73ccd61SBrandon Streiff .num_gpio = 15, 49023cf3c846SVivien Didelot .max_vid = 4095, 4903fad09c73SVivien Didelot .port_base_addr = 0x10, 49049255bacdSAndrew Lunn .phy_base_addr = 0x0, 4905a935c052SVivien Didelot .global1_addr = 0x1b, 49069069c13aSVivien Didelot .global2_addr = 0x1c, 4907acddbd21SVivien Didelot .age_time_coeff = 15000, 4908dc30c35bSAndrew Lunn .g1_irqs = 9, 4909d6c5e6afSVivien Didelot .g2_irqs = 10, 4910e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4911f3645652SVivien Didelot .pvt = true, 4912b3e05aa1SVivien Didelot .multi_chip = true, 4913443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 49142fa8d3afSBrandon Streiff .ptp_support = true, 4915b3469dd8SVivien Didelot .ops = &mv88e6240_ops, 4916fad09c73SVivien Didelot }, 4917fad09c73SVivien Didelot 49181f71836fSRasmus Villemoes [MV88E6250] = { 49191f71836fSRasmus Villemoes .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250, 49201f71836fSRasmus Villemoes .family = MV88E6XXX_FAMILY_6250, 49211f71836fSRasmus Villemoes .name = "Marvell 88E6250", 49221f71836fSRasmus Villemoes .num_databases = 64, 49231f71836fSRasmus Villemoes .num_ports = 7, 49241f71836fSRasmus Villemoes .num_internal_phys = 5, 49251f71836fSRasmus Villemoes .max_vid = 4095, 49261f71836fSRasmus Villemoes .port_base_addr = 0x08, 49271f71836fSRasmus Villemoes .phy_base_addr = 0x00, 49281f71836fSRasmus Villemoes .global1_addr = 0x0f, 49291f71836fSRasmus Villemoes .global2_addr = 0x07, 49301f71836fSRasmus Villemoes .age_time_coeff = 15000, 49311f71836fSRasmus Villemoes .g1_irqs = 9, 49321f71836fSRasmus Villemoes .g2_irqs = 10, 49331f71836fSRasmus Villemoes .atu_move_port_mask = 0xf, 49341f71836fSRasmus Villemoes .dual_chip = true, 49351f71836fSRasmus Villemoes .tag_protocol = DSA_TAG_PROTO_DSA, 493671509614SHubert Feurstein .ptp_support = true, 49371f71836fSRasmus Villemoes .ops = &mv88e6250_ops, 49381f71836fSRasmus Villemoes }, 49391f71836fSRasmus Villemoes 49401a3b39ecSAndrew Lunn [MV88E6290] = { 4941107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290, 49421a3b39ecSAndrew Lunn .family = MV88E6XXX_FAMILY_6390, 49431a3b39ecSAndrew Lunn .name = "Marvell 88E6290", 49441a3b39ecSAndrew Lunn .num_databases = 4096, 49451a3b39ecSAndrew Lunn .num_ports = 11, /* 10 + Z80 */ 494695150f29SHeiner Kallweit .num_internal_phys = 9, 4947a73ccd61SBrandon Streiff .num_gpio = 16, 4948931d1822SVivien Didelot .max_vid = 8191, 49491a3b39ecSAndrew Lunn .port_base_addr = 0x0, 49509255bacdSAndrew Lunn .phy_base_addr = 0x0, 49511a3b39ecSAndrew Lunn .global1_addr = 0x1b, 49529069c13aSVivien Didelot .global2_addr = 0x1c, 4953b91e055cSAndrew Lunn .age_time_coeff = 3750, 49541a3b39ecSAndrew Lunn .g1_irqs = 9, 4955d6c5e6afSVivien Didelot .g2_irqs = 14, 4956e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 4957f3645652SVivien Didelot .pvt = true, 4958b3e05aa1SVivien Didelot .multi_chip = true, 4959443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 49602fa8d3afSBrandon Streiff .ptp_support = true, 49611a3b39ecSAndrew Lunn .ops = &mv88e6290_ops, 49621a3b39ecSAndrew Lunn }, 49631a3b39ecSAndrew Lunn 4964fad09c73SVivien Didelot [MV88E6320] = { 4965107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320, 4966fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6320, 4967fad09c73SVivien Didelot .name = "Marvell 88E6320", 4968fad09c73SVivien Didelot .num_databases = 4096, 4969d9ea5620SAndrew Lunn .num_macs = 8192, 4970fad09c73SVivien Didelot .num_ports = 7, 4971bc393155SAndrew Lunn .num_internal_phys = 5, 4972a73ccd61SBrandon Streiff .num_gpio = 15, 49733cf3c846SVivien Didelot .max_vid = 4095, 4974fad09c73SVivien Didelot .port_base_addr = 0x10, 49759255bacdSAndrew Lunn .phy_base_addr = 0x0, 4976a935c052SVivien Didelot .global1_addr = 0x1b, 49779069c13aSVivien Didelot .global2_addr = 0x1c, 4978acddbd21SVivien Didelot .age_time_coeff = 15000, 4979dc30c35bSAndrew Lunn .g1_irqs = 8, 4980bc393155SAndrew Lunn .g2_irqs = 10, 4981e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 4982f3645652SVivien Didelot .pvt = true, 4983b3e05aa1SVivien Didelot .multi_chip = true, 4984443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 49852fa8d3afSBrandon Streiff .ptp_support = true, 4986b3469dd8SVivien Didelot .ops = &mv88e6320_ops, 4987fad09c73SVivien Didelot }, 4988fad09c73SVivien Didelot 4989fad09c73SVivien Didelot [MV88E6321] = { 4990107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321, 4991fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6320, 4992fad09c73SVivien Didelot .name = "Marvell 88E6321", 4993fad09c73SVivien Didelot .num_databases = 4096, 4994d9ea5620SAndrew Lunn .num_macs = 8192, 4995fad09c73SVivien Didelot .num_ports = 7, 4996bc393155SAndrew Lunn .num_internal_phys = 5, 4997a73ccd61SBrandon Streiff .num_gpio = 15, 49983cf3c846SVivien Didelot .max_vid = 4095, 4999fad09c73SVivien Didelot .port_base_addr = 0x10, 50009255bacdSAndrew Lunn .phy_base_addr = 0x0, 5001a935c052SVivien Didelot .global1_addr = 0x1b, 50029069c13aSVivien Didelot .global2_addr = 0x1c, 5003acddbd21SVivien Didelot .age_time_coeff = 15000, 5004dc30c35bSAndrew Lunn .g1_irqs = 8, 5005bc393155SAndrew Lunn .g2_irqs = 10, 5006e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 5007b3e05aa1SVivien Didelot .multi_chip = true, 5008443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 50092fa8d3afSBrandon Streiff .ptp_support = true, 5010b3469dd8SVivien Didelot .ops = &mv88e6321_ops, 5011fad09c73SVivien Didelot }, 5012fad09c73SVivien Didelot 5013a75961d0SGregory CLEMENT [MV88E6341] = { 5014107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, 5015a75961d0SGregory CLEMENT .family = MV88E6XXX_FAMILY_6341, 5016a75961d0SGregory CLEMENT .name = "Marvell 88E6341", 5017a75961d0SGregory CLEMENT .num_databases = 4096, 5018d9ea5620SAndrew Lunn .num_macs = 2048, 5019bc393155SAndrew Lunn .num_internal_phys = 5, 5020a75961d0SGregory CLEMENT .num_ports = 6, 5021a73ccd61SBrandon Streiff .num_gpio = 11, 50223cf3c846SVivien Didelot .max_vid = 4095, 5023a75961d0SGregory CLEMENT .port_base_addr = 0x10, 50249255bacdSAndrew Lunn .phy_base_addr = 0x10, 5025a75961d0SGregory CLEMENT .global1_addr = 0x1b, 50269069c13aSVivien Didelot .global2_addr = 0x1c, 5027a75961d0SGregory CLEMENT .age_time_coeff = 3750, 5028e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 5029adfccf11SAndrew Lunn .g1_irqs = 9, 5030d6c5e6afSVivien Didelot .g2_irqs = 10, 5031f3645652SVivien Didelot .pvt = true, 5032b3e05aa1SVivien Didelot .multi_chip = true, 5033a75961d0SGregory CLEMENT .tag_protocol = DSA_TAG_PROTO_EDSA, 50342fa8d3afSBrandon Streiff .ptp_support = true, 5035a75961d0SGregory CLEMENT .ops = &mv88e6341_ops, 5036a75961d0SGregory CLEMENT }, 5037a75961d0SGregory CLEMENT 5038fad09c73SVivien Didelot [MV88E6350] = { 5039107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350, 5040fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6351, 5041fad09c73SVivien Didelot .name = "Marvell 88E6350", 5042fad09c73SVivien Didelot .num_databases = 4096, 5043d9ea5620SAndrew Lunn .num_macs = 8192, 5044fad09c73SVivien Didelot .num_ports = 7, 5045bc393155SAndrew Lunn .num_internal_phys = 5, 50463cf3c846SVivien Didelot .max_vid = 4095, 5047fad09c73SVivien Didelot .port_base_addr = 0x10, 50489255bacdSAndrew Lunn .phy_base_addr = 0x0, 5049a935c052SVivien Didelot .global1_addr = 0x1b, 50509069c13aSVivien Didelot .global2_addr = 0x1c, 5051acddbd21SVivien Didelot .age_time_coeff = 15000, 5052dc30c35bSAndrew Lunn .g1_irqs = 9, 5053d6c5e6afSVivien Didelot .g2_irqs = 10, 5054e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 5055f3645652SVivien Didelot .pvt = true, 5056b3e05aa1SVivien Didelot .multi_chip = true, 5057443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 5058b3469dd8SVivien Didelot .ops = &mv88e6350_ops, 5059fad09c73SVivien Didelot }, 5060fad09c73SVivien Didelot 5061fad09c73SVivien Didelot [MV88E6351] = { 5062107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6351, 5063fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6351, 5064fad09c73SVivien Didelot .name = "Marvell 88E6351", 5065fad09c73SVivien Didelot .num_databases = 4096, 5066d9ea5620SAndrew Lunn .num_macs = 8192, 5067fad09c73SVivien Didelot .num_ports = 7, 5068bc393155SAndrew Lunn .num_internal_phys = 5, 50693cf3c846SVivien Didelot .max_vid = 4095, 5070fad09c73SVivien Didelot .port_base_addr = 0x10, 50719255bacdSAndrew Lunn .phy_base_addr = 0x0, 5072a935c052SVivien Didelot .global1_addr = 0x1b, 50739069c13aSVivien Didelot .global2_addr = 0x1c, 5074acddbd21SVivien Didelot .age_time_coeff = 15000, 5075dc30c35bSAndrew Lunn .g1_irqs = 9, 5076d6c5e6afSVivien Didelot .g2_irqs = 10, 5077e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 5078f3645652SVivien Didelot .pvt = true, 5079b3e05aa1SVivien Didelot .multi_chip = true, 5080443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 5081b3469dd8SVivien Didelot .ops = &mv88e6351_ops, 5082fad09c73SVivien Didelot }, 5083fad09c73SVivien Didelot 5084fad09c73SVivien Didelot [MV88E6352] = { 5085107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352, 5086fad09c73SVivien Didelot .family = MV88E6XXX_FAMILY_6352, 5087fad09c73SVivien Didelot .name = "Marvell 88E6352", 5088fad09c73SVivien Didelot .num_databases = 4096, 5089d9ea5620SAndrew Lunn .num_macs = 8192, 5090fad09c73SVivien Didelot .num_ports = 7, 5091bc393155SAndrew Lunn .num_internal_phys = 5, 5092a73ccd61SBrandon Streiff .num_gpio = 15, 50933cf3c846SVivien Didelot .max_vid = 4095, 5094fad09c73SVivien Didelot .port_base_addr = 0x10, 50959255bacdSAndrew Lunn .phy_base_addr = 0x0, 5096a935c052SVivien Didelot .global1_addr = 0x1b, 50979069c13aSVivien Didelot .global2_addr = 0x1c, 5098acddbd21SVivien Didelot .age_time_coeff = 15000, 5099dc30c35bSAndrew Lunn .g1_irqs = 9, 5100d6c5e6afSVivien Didelot .g2_irqs = 10, 5101e606ca36SVivien Didelot .atu_move_port_mask = 0xf, 5102f3645652SVivien Didelot .pvt = true, 5103b3e05aa1SVivien Didelot .multi_chip = true, 5104443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_EDSA, 51052fa8d3afSBrandon Streiff .ptp_support = true, 5106b3469dd8SVivien Didelot .ops = &mv88e6352_ops, 5107fad09c73SVivien Didelot }, 51081a3b39ecSAndrew Lunn [MV88E6390] = { 5109107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, 51101a3b39ecSAndrew Lunn .family = MV88E6XXX_FAMILY_6390, 51111a3b39ecSAndrew Lunn .name = "Marvell 88E6390", 51121a3b39ecSAndrew Lunn .num_databases = 4096, 5113d9ea5620SAndrew Lunn .num_macs = 16384, 51141a3b39ecSAndrew Lunn .num_ports = 11, /* 10 + Z80 */ 511595150f29SHeiner Kallweit .num_internal_phys = 9, 5116a73ccd61SBrandon Streiff .num_gpio = 16, 5117931d1822SVivien Didelot .max_vid = 8191, 51181a3b39ecSAndrew Lunn .port_base_addr = 0x0, 51199255bacdSAndrew Lunn .phy_base_addr = 0x0, 51201a3b39ecSAndrew Lunn .global1_addr = 0x1b, 51219069c13aSVivien Didelot .global2_addr = 0x1c, 5122b91e055cSAndrew Lunn .age_time_coeff = 3750, 51231a3b39ecSAndrew Lunn .g1_irqs = 9, 5124d6c5e6afSVivien Didelot .g2_irqs = 14, 5125e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 5126f3645652SVivien Didelot .pvt = true, 5127b3e05aa1SVivien Didelot .multi_chip = true, 5128443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 51292fa8d3afSBrandon Streiff .ptp_support = true, 51301a3b39ecSAndrew Lunn .ops = &mv88e6390_ops, 51311a3b39ecSAndrew Lunn }, 51321a3b39ecSAndrew Lunn [MV88E6390X] = { 5133107fcc10SVivien Didelot .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X, 51341a3b39ecSAndrew Lunn .family = MV88E6XXX_FAMILY_6390, 51351a3b39ecSAndrew Lunn .name = "Marvell 88E6390X", 51361a3b39ecSAndrew Lunn .num_databases = 4096, 5137d9ea5620SAndrew Lunn .num_macs = 16384, 51381a3b39ecSAndrew Lunn .num_ports = 11, /* 10 + Z80 */ 513995150f29SHeiner Kallweit .num_internal_phys = 9, 5140a73ccd61SBrandon Streiff .num_gpio = 16, 5141931d1822SVivien Didelot .max_vid = 8191, 51421a3b39ecSAndrew Lunn .port_base_addr = 0x0, 51439255bacdSAndrew Lunn .phy_base_addr = 0x0, 51441a3b39ecSAndrew Lunn .global1_addr = 0x1b, 51459069c13aSVivien Didelot .global2_addr = 0x1c, 5146b91e055cSAndrew Lunn .age_time_coeff = 3750, 51471a3b39ecSAndrew Lunn .g1_irqs = 9, 5148d6c5e6afSVivien Didelot .g2_irqs = 14, 5149e606ca36SVivien Didelot .atu_move_port_mask = 0x1f, 5150f3645652SVivien Didelot .pvt = true, 5151b3e05aa1SVivien Didelot .multi_chip = true, 5152443d5a1bSAndrew Lunn .tag_protocol = DSA_TAG_PROTO_DSA, 51532fa8d3afSBrandon Streiff .ptp_support = true, 51541a3b39ecSAndrew Lunn .ops = &mv88e6390x_ops, 51551a3b39ecSAndrew Lunn }, 5156fad09c73SVivien Didelot }; 5157fad09c73SVivien Didelot 5158fad09c73SVivien Didelot static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num) 5159fad09c73SVivien Didelot { 5160fad09c73SVivien Didelot int i; 5161fad09c73SVivien Didelot 5162fad09c73SVivien Didelot for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i) 5163fad09c73SVivien Didelot if (mv88e6xxx_table[i].prod_num == prod_num) 5164fad09c73SVivien Didelot return &mv88e6xxx_table[i]; 5165fad09c73SVivien Didelot 5166fad09c73SVivien Didelot return NULL; 5167fad09c73SVivien Didelot } 5168fad09c73SVivien Didelot 5169fad09c73SVivien Didelot static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip) 5170fad09c73SVivien Didelot { 5171fad09c73SVivien Didelot const struct mv88e6xxx_info *info; 51728f6345b2SVivien Didelot unsigned int prod_num, rev; 51738f6345b2SVivien Didelot u16 id; 51748f6345b2SVivien Didelot int err; 5175fad09c73SVivien Didelot 5176c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 5177107fcc10SVivien Didelot err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id); 5178c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 51798f6345b2SVivien Didelot if (err) 51808f6345b2SVivien Didelot return err; 5181fad09c73SVivien Didelot 5182107fcc10SVivien Didelot prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK; 5183107fcc10SVivien Didelot rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK; 5184fad09c73SVivien Didelot 5185fad09c73SVivien Didelot info = mv88e6xxx_lookup_info(prod_num); 5186fad09c73SVivien Didelot if (!info) 5187fad09c73SVivien Didelot return -ENODEV; 5188fad09c73SVivien Didelot 5189fad09c73SVivien Didelot /* Update the compatible info with the probed one */ 5190fad09c73SVivien Didelot chip->info = info; 5191fad09c73SVivien Didelot 5192ca070c10SVivien Didelot err = mv88e6xxx_g2_require(chip); 5193ca070c10SVivien Didelot if (err) 5194ca070c10SVivien Didelot return err; 5195ca070c10SVivien Didelot 5196fad09c73SVivien Didelot dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n", 5197fad09c73SVivien Didelot chip->info->prod_num, chip->info->name, rev); 5198fad09c73SVivien Didelot 5199fad09c73SVivien Didelot return 0; 5200fad09c73SVivien Didelot } 5201fad09c73SVivien Didelot 5202fad09c73SVivien Didelot static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev) 5203fad09c73SVivien Didelot { 5204fad09c73SVivien Didelot struct mv88e6xxx_chip *chip; 5205fad09c73SVivien Didelot 5206fad09c73SVivien Didelot chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 5207fad09c73SVivien Didelot if (!chip) 5208fad09c73SVivien Didelot return NULL; 5209fad09c73SVivien Didelot 5210fad09c73SVivien Didelot chip->dev = dev; 5211fad09c73SVivien Didelot 5212fad09c73SVivien Didelot mutex_init(&chip->reg_lock); 5213a3c53be5SAndrew Lunn INIT_LIST_HEAD(&chip->mdios); 5214da7dc875SVivien Didelot idr_init(&chip->policies); 5215fad09c73SVivien Didelot 5216fad09c73SVivien Didelot return chip; 5217fad09c73SVivien Didelot } 5218fad09c73SVivien Didelot 52195ed4e3ebSFlorian Fainelli static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds, 52205ed4e3ebSFlorian Fainelli int port) 52217b314362SAndrew Lunn { 522204bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 52232bbb33beSAndrew Lunn 5224443d5a1bSAndrew Lunn return chip->info->tag_protocol; 52257b314362SAndrew Lunn } 52267b314362SAndrew Lunn 52277df8fbddSVivien Didelot static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port, 52283709aadcSVivien Didelot const struct switchdev_obj_port_mdb *mdb) 52297df8fbddSVivien Didelot { 52307df8fbddSVivien Didelot /* We don't need any dynamic resource from the kernel (yet), 52317df8fbddSVivien Didelot * so skip the prepare phase. 52327df8fbddSVivien Didelot */ 52337df8fbddSVivien Didelot 52347df8fbddSVivien Didelot return 0; 52357df8fbddSVivien Didelot } 52367df8fbddSVivien Didelot 52377df8fbddSVivien Didelot static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port, 52383709aadcSVivien Didelot const struct switchdev_obj_port_mdb *mdb) 52397df8fbddSVivien Didelot { 524004bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 52417df8fbddSVivien Didelot 5242c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 52437df8fbddSVivien Didelot if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, 524427c0e600SVivien Didelot MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC)) 5245774439e5SVivien Didelot dev_err(ds->dev, "p%d: failed to load multicast MAC address\n", 5246774439e5SVivien Didelot port); 5247c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 52487df8fbddSVivien Didelot } 52497df8fbddSVivien Didelot 52507df8fbddSVivien Didelot static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port, 52517df8fbddSVivien Didelot const struct switchdev_obj_port_mdb *mdb) 52527df8fbddSVivien Didelot { 525304bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 52547df8fbddSVivien Didelot int err; 52557df8fbddSVivien Didelot 5256c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 5257d8291a95SVivien Didelot err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, 0); 5258c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 52597df8fbddSVivien Didelot 52607df8fbddSVivien Didelot return err; 52617df8fbddSVivien Didelot } 52627df8fbddSVivien Didelot 5263f0942e00SIwan R Timmer static int mv88e6xxx_port_mirror_add(struct dsa_switch *ds, int port, 5264f0942e00SIwan R Timmer struct dsa_mall_mirror_tc_entry *mirror, 5265f0942e00SIwan R Timmer bool ingress) 5266f0942e00SIwan R Timmer { 5267f0942e00SIwan R Timmer enum mv88e6xxx_egress_direction direction = ingress ? 5268f0942e00SIwan R Timmer MV88E6XXX_EGRESS_DIR_INGRESS : 5269f0942e00SIwan R Timmer MV88E6XXX_EGRESS_DIR_EGRESS; 5270f0942e00SIwan R Timmer struct mv88e6xxx_chip *chip = ds->priv; 5271f0942e00SIwan R Timmer bool other_mirrors = false; 5272f0942e00SIwan R Timmer int i; 5273f0942e00SIwan R Timmer int err; 5274f0942e00SIwan R Timmer 5275f0942e00SIwan R Timmer if (!chip->info->ops->set_egress_port) 5276f0942e00SIwan R Timmer return -EOPNOTSUPP; 5277f0942e00SIwan R Timmer 5278f0942e00SIwan R Timmer mutex_lock(&chip->reg_lock); 5279f0942e00SIwan R Timmer if ((ingress ? chip->ingress_dest_port : chip->egress_dest_port) != 5280f0942e00SIwan R Timmer mirror->to_local_port) { 5281f0942e00SIwan R Timmer for (i = 0; i < mv88e6xxx_num_ports(chip); i++) 5282f0942e00SIwan R Timmer other_mirrors |= ingress ? 5283f0942e00SIwan R Timmer chip->ports[i].mirror_ingress : 5284f0942e00SIwan R Timmer chip->ports[i].mirror_egress; 5285f0942e00SIwan R Timmer 5286f0942e00SIwan R Timmer /* Can't change egress port when other mirror is active */ 5287f0942e00SIwan R Timmer if (other_mirrors) { 5288f0942e00SIwan R Timmer err = -EBUSY; 5289f0942e00SIwan R Timmer goto out; 5290f0942e00SIwan R Timmer } 5291f0942e00SIwan R Timmer 5292f0942e00SIwan R Timmer err = chip->info->ops->set_egress_port(chip, 5293f0942e00SIwan R Timmer direction, 5294f0942e00SIwan R Timmer mirror->to_local_port); 5295f0942e00SIwan R Timmer if (err) 5296f0942e00SIwan R Timmer goto out; 5297f0942e00SIwan R Timmer } 5298f0942e00SIwan R Timmer 5299f0942e00SIwan R Timmer err = mv88e6xxx_port_set_mirror(chip, port, direction, true); 5300f0942e00SIwan R Timmer out: 5301f0942e00SIwan R Timmer mutex_unlock(&chip->reg_lock); 5302f0942e00SIwan R Timmer 5303f0942e00SIwan R Timmer return err; 5304f0942e00SIwan R Timmer } 5305f0942e00SIwan R Timmer 5306f0942e00SIwan R Timmer static void mv88e6xxx_port_mirror_del(struct dsa_switch *ds, int port, 5307f0942e00SIwan R Timmer struct dsa_mall_mirror_tc_entry *mirror) 5308f0942e00SIwan R Timmer { 5309f0942e00SIwan R Timmer enum mv88e6xxx_egress_direction direction = mirror->ingress ? 5310f0942e00SIwan R Timmer MV88E6XXX_EGRESS_DIR_INGRESS : 5311f0942e00SIwan R Timmer MV88E6XXX_EGRESS_DIR_EGRESS; 5312f0942e00SIwan R Timmer struct mv88e6xxx_chip *chip = ds->priv; 5313f0942e00SIwan R Timmer bool other_mirrors = false; 5314f0942e00SIwan R Timmer int i; 5315f0942e00SIwan R Timmer 5316f0942e00SIwan R Timmer mutex_lock(&chip->reg_lock); 5317f0942e00SIwan R Timmer if (mv88e6xxx_port_set_mirror(chip, port, direction, false)) 5318f0942e00SIwan R Timmer dev_err(ds->dev, "p%d: failed to disable mirroring\n", port); 5319f0942e00SIwan R Timmer 5320f0942e00SIwan R Timmer for (i = 0; i < mv88e6xxx_num_ports(chip); i++) 5321f0942e00SIwan R Timmer other_mirrors |= mirror->ingress ? 5322f0942e00SIwan R Timmer chip->ports[i].mirror_ingress : 5323f0942e00SIwan R Timmer chip->ports[i].mirror_egress; 5324f0942e00SIwan R Timmer 5325f0942e00SIwan R Timmer /* Reset egress port when no other mirror is active */ 5326f0942e00SIwan R Timmer if (!other_mirrors) { 5327f0942e00SIwan R Timmer if (chip->info->ops->set_egress_port(chip, 5328f0942e00SIwan R Timmer direction, 5329f0942e00SIwan R Timmer dsa_upstream_port(ds, 53304e4637b1SColin Ian King port))) 5331f0942e00SIwan R Timmer dev_err(ds->dev, "failed to set egress port\n"); 5332f0942e00SIwan R Timmer } 5333f0942e00SIwan R Timmer 5334f0942e00SIwan R Timmer mutex_unlock(&chip->reg_lock); 5335f0942e00SIwan R Timmer } 5336f0942e00SIwan R Timmer 53374f85901fSRussell King static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, 53384f85901fSRussell King bool unicast, bool multicast) 53394f85901fSRussell King { 53404f85901fSRussell King struct mv88e6xxx_chip *chip = ds->priv; 53414f85901fSRussell King int err = -EOPNOTSUPP; 53424f85901fSRussell King 5343c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 53444f85901fSRussell King if (chip->info->ops->port_set_egress_floods) 53454f85901fSRussell King err = chip->info->ops->port_set_egress_floods(chip, port, 53464f85901fSRussell King unicast, 53474f85901fSRussell King multicast); 5348c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 53494f85901fSRussell King 53504f85901fSRussell King return err; 53514f85901fSRussell King } 53524f85901fSRussell King 5353a82f67afSFlorian Fainelli static const struct dsa_switch_ops mv88e6xxx_switch_ops = { 53547b314362SAndrew Lunn .get_tag_protocol = mv88e6xxx_get_tag_protocol, 5355fad09c73SVivien Didelot .setup = mv88e6xxx_setup, 535623e8b470SAndrew Lunn .teardown = mv88e6xxx_teardown, 5357c9a2356fSRussell King .phylink_validate = mv88e6xxx_validate, 5358c9a2356fSRussell King .phylink_mac_link_state = mv88e6xxx_link_state, 5359c9a2356fSRussell King .phylink_mac_config = mv88e6xxx_mac_config, 5360c9a2356fSRussell King .phylink_mac_link_down = mv88e6xxx_mac_link_down, 5361c9a2356fSRussell King .phylink_mac_link_up = mv88e6xxx_mac_link_up, 5362fad09c73SVivien Didelot .get_strings = mv88e6xxx_get_strings, 5363fad09c73SVivien Didelot .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 5364fad09c73SVivien Didelot .get_sset_count = mv88e6xxx_get_sset_count, 536504aca993SAndrew Lunn .port_enable = mv88e6xxx_port_enable, 536604aca993SAndrew Lunn .port_disable = mv88e6xxx_port_disable, 536708f50061SVivien Didelot .get_mac_eee = mv88e6xxx_get_mac_eee, 536808f50061SVivien Didelot .set_mac_eee = mv88e6xxx_set_mac_eee, 5369fad09c73SVivien Didelot .get_eeprom_len = mv88e6xxx_get_eeprom_len, 5370fad09c73SVivien Didelot .get_eeprom = mv88e6xxx_get_eeprom, 5371fad09c73SVivien Didelot .set_eeprom = mv88e6xxx_set_eeprom, 5372fad09c73SVivien Didelot .get_regs_len = mv88e6xxx_get_regs_len, 5373fad09c73SVivien Didelot .get_regs = mv88e6xxx_get_regs, 5374da7dc875SVivien Didelot .get_rxnfc = mv88e6xxx_get_rxnfc, 5375da7dc875SVivien Didelot .set_rxnfc = mv88e6xxx_set_rxnfc, 53762cfcd964SVivien Didelot .set_ageing_time = mv88e6xxx_set_ageing_time, 5377fad09c73SVivien Didelot .port_bridge_join = mv88e6xxx_port_bridge_join, 5378fad09c73SVivien Didelot .port_bridge_leave = mv88e6xxx_port_bridge_leave, 53794f85901fSRussell King .port_egress_floods = mv88e6xxx_port_egress_floods, 5380fad09c73SVivien Didelot .port_stp_state_set = mv88e6xxx_port_stp_state_set, 5381749efcb8SVivien Didelot .port_fast_age = mv88e6xxx_port_fast_age, 5382fad09c73SVivien Didelot .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, 5383fad09c73SVivien Didelot .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, 5384fad09c73SVivien Didelot .port_vlan_add = mv88e6xxx_port_vlan_add, 5385fad09c73SVivien Didelot .port_vlan_del = mv88e6xxx_port_vlan_del, 5386fad09c73SVivien Didelot .port_fdb_add = mv88e6xxx_port_fdb_add, 5387fad09c73SVivien Didelot .port_fdb_del = mv88e6xxx_port_fdb_del, 5388fad09c73SVivien Didelot .port_fdb_dump = mv88e6xxx_port_fdb_dump, 53897df8fbddSVivien Didelot .port_mdb_prepare = mv88e6xxx_port_mdb_prepare, 53907df8fbddSVivien Didelot .port_mdb_add = mv88e6xxx_port_mdb_add, 53917df8fbddSVivien Didelot .port_mdb_del = mv88e6xxx_port_mdb_del, 5392f0942e00SIwan R Timmer .port_mirror_add = mv88e6xxx_port_mirror_add, 5393f0942e00SIwan R Timmer .port_mirror_del = mv88e6xxx_port_mirror_del, 5394aec5ac88SVivien Didelot .crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join, 5395aec5ac88SVivien Didelot .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave, 5396c6fe0ad2SBrandon Streiff .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set, 5397c6fe0ad2SBrandon Streiff .port_hwtstamp_get = mv88e6xxx_port_hwtstamp_get, 5398c6fe0ad2SBrandon Streiff .port_txtstamp = mv88e6xxx_port_txtstamp, 5399c6fe0ad2SBrandon Streiff .port_rxtstamp = mv88e6xxx_port_rxtstamp, 5400c6fe0ad2SBrandon Streiff .get_ts_info = mv88e6xxx_get_ts_info, 540123e8b470SAndrew Lunn .devlink_param_get = mv88e6xxx_devlink_param_get, 540223e8b470SAndrew Lunn .devlink_param_set = mv88e6xxx_devlink_param_set, 5403fad09c73SVivien Didelot }; 5404fad09c73SVivien Didelot 540555ed0ce0SFlorian Fainelli static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) 5406fad09c73SVivien Didelot { 5407fad09c73SVivien Didelot struct device *dev = chip->dev; 5408fad09c73SVivien Didelot struct dsa_switch *ds; 5409fad09c73SVivien Didelot 54107e99e347SVivien Didelot ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); 5411fad09c73SVivien Didelot if (!ds) 5412fad09c73SVivien Didelot return -ENOMEM; 5413fad09c73SVivien Didelot 54147e99e347SVivien Didelot ds->dev = dev; 54157e99e347SVivien Didelot ds->num_ports = mv88e6xxx_num_ports(chip); 5416fad09c73SVivien Didelot ds->priv = chip; 5417877b7cb0SAndrew Lunn ds->dev = dev; 54189d490b4eSVivien Didelot ds->ops = &mv88e6xxx_switch_ops; 54199ff74f24SVivien Didelot ds->ageing_time_min = chip->info->age_time_coeff; 54209ff74f24SVivien Didelot ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; 5421fad09c73SVivien Didelot 5422fad09c73SVivien Didelot dev_set_drvdata(dev, ds); 5423fad09c73SVivien Didelot 542423c9ee49SVivien Didelot return dsa_register_switch(ds); 5425fad09c73SVivien Didelot } 5426fad09c73SVivien Didelot 5427fad09c73SVivien Didelot static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip) 5428fad09c73SVivien Didelot { 5429fad09c73SVivien Didelot dsa_unregister_switch(chip->ds); 5430fad09c73SVivien Didelot } 5431fad09c73SVivien Didelot 5432877b7cb0SAndrew Lunn static const void *pdata_device_get_match_data(struct device *dev) 5433877b7cb0SAndrew Lunn { 5434877b7cb0SAndrew Lunn const struct of_device_id *matches = dev->driver->of_match_table; 5435877b7cb0SAndrew Lunn const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data; 5436877b7cb0SAndrew Lunn 5437877b7cb0SAndrew Lunn for (; matches->name[0] || matches->type[0] || matches->compatible[0]; 5438877b7cb0SAndrew Lunn matches++) { 5439877b7cb0SAndrew Lunn if (!strcmp(pdata->compatible, matches->compatible)) 5440877b7cb0SAndrew Lunn return matches->data; 5441877b7cb0SAndrew Lunn } 5442877b7cb0SAndrew Lunn return NULL; 5443877b7cb0SAndrew Lunn } 5444877b7cb0SAndrew Lunn 5445bcd3d9d9SMiquel Raynal /* There is no suspend to RAM support at DSA level yet, the switch configuration 5446bcd3d9d9SMiquel Raynal * would be lost after a power cycle so prevent it to be suspended. 5447bcd3d9d9SMiquel Raynal */ 5448bcd3d9d9SMiquel Raynal static int __maybe_unused mv88e6xxx_suspend(struct device *dev) 5449bcd3d9d9SMiquel Raynal { 5450bcd3d9d9SMiquel Raynal return -EOPNOTSUPP; 5451bcd3d9d9SMiquel Raynal } 5452bcd3d9d9SMiquel Raynal 5453bcd3d9d9SMiquel Raynal static int __maybe_unused mv88e6xxx_resume(struct device *dev) 5454bcd3d9d9SMiquel Raynal { 5455bcd3d9d9SMiquel Raynal return 0; 5456bcd3d9d9SMiquel Raynal } 5457bcd3d9d9SMiquel Raynal 5458bcd3d9d9SMiquel Raynal static SIMPLE_DEV_PM_OPS(mv88e6xxx_pm_ops, mv88e6xxx_suspend, mv88e6xxx_resume); 5459bcd3d9d9SMiquel Raynal 5460fad09c73SVivien Didelot static int mv88e6xxx_probe(struct mdio_device *mdiodev) 5461fad09c73SVivien Didelot { 5462877b7cb0SAndrew Lunn struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data; 54637ddae24fSDavid S. Miller const struct mv88e6xxx_info *compat_info = NULL; 5464fad09c73SVivien Didelot struct device *dev = &mdiodev->dev; 5465fad09c73SVivien Didelot struct device_node *np = dev->of_node; 5466fad09c73SVivien Didelot struct mv88e6xxx_chip *chip; 5467877b7cb0SAndrew Lunn int port; 5468fad09c73SVivien Didelot int err; 5469fad09c73SVivien Didelot 54707bb8c996SAndrew Lunn if (!np && !pdata) 54717bb8c996SAndrew Lunn return -EINVAL; 54727bb8c996SAndrew Lunn 5473877b7cb0SAndrew Lunn if (np) 5474fad09c73SVivien Didelot compat_info = of_device_get_match_data(dev); 5475877b7cb0SAndrew Lunn 5476877b7cb0SAndrew Lunn if (pdata) { 5477877b7cb0SAndrew Lunn compat_info = pdata_device_get_match_data(dev); 5478877b7cb0SAndrew Lunn 5479877b7cb0SAndrew Lunn if (!pdata->netdev) 5480877b7cb0SAndrew Lunn return -EINVAL; 5481877b7cb0SAndrew Lunn 5482877b7cb0SAndrew Lunn for (port = 0; port < DSA_MAX_PORTS; port++) { 5483877b7cb0SAndrew Lunn if (!(pdata->enabled_ports & (1 << port))) 5484877b7cb0SAndrew Lunn continue; 5485877b7cb0SAndrew Lunn if (strcmp(pdata->cd.port_names[port], "cpu")) 5486877b7cb0SAndrew Lunn continue; 5487877b7cb0SAndrew Lunn pdata->cd.netdev[port] = &pdata->netdev->dev; 5488877b7cb0SAndrew Lunn break; 5489877b7cb0SAndrew Lunn } 5490877b7cb0SAndrew Lunn } 5491877b7cb0SAndrew Lunn 5492fad09c73SVivien Didelot if (!compat_info) 5493fad09c73SVivien Didelot return -EINVAL; 5494fad09c73SVivien Didelot 5495fad09c73SVivien Didelot chip = mv88e6xxx_alloc_chip(dev); 5496877b7cb0SAndrew Lunn if (!chip) { 5497877b7cb0SAndrew Lunn err = -ENOMEM; 5498877b7cb0SAndrew Lunn goto out; 5499877b7cb0SAndrew Lunn } 5500fad09c73SVivien Didelot 5501fad09c73SVivien Didelot chip->info = compat_info; 5502fad09c73SVivien Didelot 5503fad09c73SVivien Didelot err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr); 5504fad09c73SVivien Didelot if (err) 5505877b7cb0SAndrew Lunn goto out; 5506fad09c73SVivien Didelot 5507b4308f04SAndrew Lunn chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 5508877b7cb0SAndrew Lunn if (IS_ERR(chip->reset)) { 5509877b7cb0SAndrew Lunn err = PTR_ERR(chip->reset); 5510877b7cb0SAndrew Lunn goto out; 5511877b7cb0SAndrew Lunn } 55127b75e49dSBaruch Siach if (chip->reset) 55137b75e49dSBaruch Siach usleep_range(1000, 2000); 5514b4308f04SAndrew Lunn 5515fad09c73SVivien Didelot err = mv88e6xxx_detect(chip); 5516fad09c73SVivien Didelot if (err) 5517877b7cb0SAndrew Lunn goto out; 5518fad09c73SVivien Didelot 5519e57e5e77SVivien Didelot mv88e6xxx_phy_init(chip); 5520e57e5e77SVivien Didelot 552100baabe5SAndrew Lunn if (chip->info->ops->get_eeprom) { 552200baabe5SAndrew Lunn if (np) 552300baabe5SAndrew Lunn of_property_read_u32(np, "eeprom-length", 552400baabe5SAndrew Lunn &chip->eeprom_len); 552500baabe5SAndrew Lunn else 552600baabe5SAndrew Lunn chip->eeprom_len = pdata->eeprom_len; 552700baabe5SAndrew Lunn } 5528fad09c73SVivien Didelot 5529c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 5530dc30c35bSAndrew Lunn err = mv88e6xxx_switch_reset(chip); 5531c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 5532fad09c73SVivien Didelot if (err) 5533dc30c35bSAndrew Lunn goto out; 5534fad09c73SVivien Didelot 5535a27415deSAndrew Lunn if (np) { 5536dc30c35bSAndrew Lunn chip->irq = of_irq_get(np, 0); 5537dc30c35bSAndrew Lunn if (chip->irq == -EPROBE_DEFER) { 5538dc30c35bSAndrew Lunn err = chip->irq; 5539dc30c35bSAndrew Lunn goto out; 5540fad09c73SVivien Didelot } 5541a27415deSAndrew Lunn } 5542a27415deSAndrew Lunn 5543a27415deSAndrew Lunn if (pdata) 5544a27415deSAndrew Lunn chip->irq = pdata->irq; 5545fad09c73SVivien Didelot 5546294d711eSAndrew Lunn /* Has to be performed before the MDIO bus is created, because 5547a708767eSUwe Kleine-König * the PHYs will link their interrupts to these interrupt 5548294d711eSAndrew Lunn * controllers 5549dc30c35bSAndrew Lunn */ 5550c9acece0SRasmus Villemoes mv88e6xxx_reg_lock(chip); 5551294d711eSAndrew Lunn if (chip->irq > 0) 5552dc30c35bSAndrew Lunn err = mv88e6xxx_g1_irq_setup(chip); 5553294d711eSAndrew Lunn else 5554294d711eSAndrew Lunn err = mv88e6xxx_irq_poll_setup(chip); 5555c9acece0SRasmus Villemoes mv88e6xxx_reg_unlock(chip); 5556dc30c35bSAndrew Lunn 5557dc30c35bSAndrew Lunn if (err) 5558dc30c35bSAndrew Lunn goto out; 5559dc30c35bSAndrew Lunn 5560d6c5e6afSVivien Didelot if (chip->info->g2_irqs > 0) { 5561dc30c35bSAndrew Lunn err = mv88e6xxx_g2_irq_setup(chip); 5562dc30c35bSAndrew Lunn if (err) 5563dc30c35bSAndrew Lunn goto out_g1_irq; 5564dc30c35bSAndrew Lunn } 55650977644cSAndrew Lunn 55660977644cSAndrew Lunn err = mv88e6xxx_g1_atu_prob_irq_setup(chip); 55670977644cSAndrew Lunn if (err) 55680977644cSAndrew Lunn goto out_g2_irq; 556962eb1162SAndrew Lunn 557062eb1162SAndrew Lunn err = mv88e6xxx_g1_vtu_prob_irq_setup(chip); 557162eb1162SAndrew Lunn if (err) 557262eb1162SAndrew Lunn goto out_g1_atu_prob_irq; 5573dc30c35bSAndrew Lunn 5574a3c53be5SAndrew Lunn err = mv88e6xxx_mdios_register(chip, np); 5575dc30c35bSAndrew Lunn if (err) 557662eb1162SAndrew Lunn goto out_g1_vtu_prob_irq; 5577dc30c35bSAndrew Lunn 557855ed0ce0SFlorian Fainelli err = mv88e6xxx_register_switch(chip); 5579dc30c35bSAndrew Lunn if (err) 5580dc30c35bSAndrew Lunn goto out_mdio; 5581dc30c35bSAndrew Lunn 5582fad09c73SVivien Didelot return 0; 5583dc30c35bSAndrew Lunn 5584dc30c35bSAndrew Lunn out_mdio: 5585a3c53be5SAndrew Lunn mv88e6xxx_mdios_unregister(chip); 558662eb1162SAndrew Lunn out_g1_vtu_prob_irq: 558762eb1162SAndrew Lunn mv88e6xxx_g1_vtu_prob_irq_free(chip); 55880977644cSAndrew Lunn out_g1_atu_prob_irq: 55890977644cSAndrew Lunn mv88e6xxx_g1_atu_prob_irq_free(chip); 5590dc30c35bSAndrew Lunn out_g2_irq: 5591294d711eSAndrew Lunn if (chip->info->g2_irqs > 0) 5592dc30c35bSAndrew Lunn mv88e6xxx_g2_irq_free(chip); 5593dc30c35bSAndrew Lunn out_g1_irq: 5594294d711eSAndrew Lunn if (chip->irq > 0) 5595dc30c35bSAndrew Lunn mv88e6xxx_g1_irq_free(chip); 5596294d711eSAndrew Lunn else 5597294d711eSAndrew Lunn mv88e6xxx_irq_poll_free(chip); 5598dc30c35bSAndrew Lunn out: 5599877b7cb0SAndrew Lunn if (pdata) 5600877b7cb0SAndrew Lunn dev_put(pdata->netdev); 5601877b7cb0SAndrew Lunn 5602dc30c35bSAndrew Lunn return err; 5603fad09c73SVivien Didelot } 5604fad09c73SVivien Didelot 5605fad09c73SVivien Didelot static void mv88e6xxx_remove(struct mdio_device *mdiodev) 5606fad09c73SVivien Didelot { 5607fad09c73SVivien Didelot struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); 560804bed143SVivien Didelot struct mv88e6xxx_chip *chip = ds->priv; 5609fad09c73SVivien Didelot 5610c6fe0ad2SBrandon Streiff if (chip->info->ptp_support) { 5611c6fe0ad2SBrandon Streiff mv88e6xxx_hwtstamp_free(chip); 56122fa8d3afSBrandon Streiff mv88e6xxx_ptp_free(chip); 5613c6fe0ad2SBrandon Streiff } 56142fa8d3afSBrandon Streiff 5615930188ceSAndrew Lunn mv88e6xxx_phy_destroy(chip); 5616fad09c73SVivien Didelot mv88e6xxx_unregister_switch(chip); 5617a3c53be5SAndrew Lunn mv88e6xxx_mdios_unregister(chip); 5618dc30c35bSAndrew Lunn 561962eb1162SAndrew Lunn mv88e6xxx_g1_vtu_prob_irq_free(chip); 56200977644cSAndrew Lunn mv88e6xxx_g1_atu_prob_irq_free(chip); 562176f38f1fSAndrew Lunn 5622d6c5e6afSVivien Didelot if (chip->info->g2_irqs > 0) 5623dc30c35bSAndrew Lunn mv88e6xxx_g2_irq_free(chip); 562476f38f1fSAndrew Lunn 562576f38f1fSAndrew Lunn if (chip->irq > 0) 5626dc30c35bSAndrew Lunn mv88e6xxx_g1_irq_free(chip); 562776f38f1fSAndrew Lunn else 562876f38f1fSAndrew Lunn mv88e6xxx_irq_poll_free(chip); 5629fad09c73SVivien Didelot } 5630fad09c73SVivien Didelot 5631fad09c73SVivien Didelot static const struct of_device_id mv88e6xxx_of_match[] = { 5632fad09c73SVivien Didelot { 5633fad09c73SVivien Didelot .compatible = "marvell,mv88e6085", 5634fad09c73SVivien Didelot .data = &mv88e6xxx_table[MV88E6085], 5635fad09c73SVivien Didelot }, 56361a3b39ecSAndrew Lunn { 56371a3b39ecSAndrew Lunn .compatible = "marvell,mv88e6190", 56381a3b39ecSAndrew Lunn .data = &mv88e6xxx_table[MV88E6190], 56391a3b39ecSAndrew Lunn }, 56401f71836fSRasmus Villemoes { 56411f71836fSRasmus Villemoes .compatible = "marvell,mv88e6250", 56421f71836fSRasmus Villemoes .data = &mv88e6xxx_table[MV88E6250], 56431f71836fSRasmus Villemoes }, 5644fad09c73SVivien Didelot { /* sentinel */ }, 5645fad09c73SVivien Didelot }; 5646fad09c73SVivien Didelot 5647fad09c73SVivien Didelot MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match); 5648fad09c73SVivien Didelot 5649fad09c73SVivien Didelot static struct mdio_driver mv88e6xxx_driver = { 5650fad09c73SVivien Didelot .probe = mv88e6xxx_probe, 5651fad09c73SVivien Didelot .remove = mv88e6xxx_remove, 5652fad09c73SVivien Didelot .mdiodrv.driver = { 5653fad09c73SVivien Didelot .name = "mv88e6085", 5654fad09c73SVivien Didelot .of_match_table = mv88e6xxx_of_match, 5655bcd3d9d9SMiquel Raynal .pm = &mv88e6xxx_pm_ops, 5656fad09c73SVivien Didelot }, 5657fad09c73SVivien Didelot }; 5658fad09c73SVivien Didelot 56597324d50eSAndrew Lunn mdio_module_driver(mv88e6xxx_driver); 5660fad09c73SVivien Didelot 5661fad09c73SVivien Didelot MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>"); 5662fad09c73SVivien Didelot MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips"); 5663fad09c73SVivien Didelot MODULE_LICENSE("GPL"); 5664