linux/drivers/net/dsa/mv88e6xxx/chip.c
<<
>>
Prefs
   1/*
   2 * Marvell 88e6xxx Ethernet switch single-chip support
   3 *
   4 * Copyright (c) 2008 Marvell Semiconductor
   5 *
   6 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
   7 *
   8 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
   9 *      Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the License, or
  14 * (at your option) any later version.
  15 */
  16
  17#include <linux/delay.h>
  18#include <linux/etherdevice.h>
  19#include <linux/ethtool.h>
  20#include <linux/if_bridge.h>
  21#include <linux/interrupt.h>
  22#include <linux/irq.h>
  23#include <linux/irqdomain.h>
  24#include <linux/jiffies.h>
  25#include <linux/list.h>
  26#include <linux/mdio.h>
  27#include <linux/module.h>
  28#include <linux/of_device.h>
  29#include <linux/of_irq.h>
  30#include <linux/of_mdio.h>
  31#include <linux/platform_data/mv88e6xxx.h>
  32#include <linux/netdevice.h>
  33#include <linux/gpio/consumer.h>
  34#include <linux/phy.h>
  35#include <linux/phylink.h>
  36#include <net/dsa.h>
  37
  38#include "chip.h"
  39#include "global1.h"
  40#include "global2.h"
  41#include "hwtstamp.h"
  42#include "phy.h"
  43#include "port.h"
  44#include "ptp.h"
  45#include "serdes.h"
  46
  47static void assert_reg_lock(struct mv88e6xxx_chip *chip)
  48{
  49        if (unlikely(!mutex_is_locked(&chip->reg_lock))) {
  50                dev_err(chip->dev, "Switch registers lock not held!\n");
  51                dump_stack();
  52        }
  53}
  54
  55/* The switch ADDR[4:1] configuration pins define the chip SMI device address
  56 * (ADDR[0] is always zero, thus only even SMI addresses can be strapped).
  57 *
  58 * When ADDR is all zero, the chip uses Single-chip Addressing Mode, assuming it
  59 * is the only device connected to the SMI master. In this mode it responds to
  60 * all 32 possible SMI addresses, and thus maps directly the internal devices.
  61 *
  62 * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing
  63 * multiple devices to share the SMI interface. In this mode it responds to only
  64 * 2 registers, used to indirectly access the internal SMI devices.
  65 */
  66
  67static int mv88e6xxx_smi_read(struct mv88e6xxx_chip *chip,
  68                              int addr, int reg, u16 *val)
  69{
  70        if (!chip->smi_ops)
  71                return -EOPNOTSUPP;
  72
  73        return chip->smi_ops->read(chip, addr, reg, val);
  74}
  75
  76static int mv88e6xxx_smi_write(struct mv88e6xxx_chip *chip,
  77                               int addr, int reg, u16 val)
  78{
  79        if (!chip->smi_ops)
  80                return -EOPNOTSUPP;
  81
  82        return chip->smi_ops->write(chip, addr, reg, val);
  83}
  84
  85static int mv88e6xxx_smi_single_chip_read(struct mv88e6xxx_chip *chip,
  86                                          int addr, int reg, u16 *val)
  87{
  88        int ret;
  89
  90        ret = mdiobus_read_nested(chip->bus, addr, reg);
  91        if (ret < 0)
  92                return ret;
  93
  94        *val = ret & 0xffff;
  95
  96        return 0;
  97}
  98
  99static int mv88e6xxx_smi_single_chip_write(struct mv88e6xxx_chip *chip,
 100                                           int addr, int reg, u16 val)
 101{
 102        int ret;
 103
 104        ret = mdiobus_write_nested(chip->bus, addr, reg, val);
 105        if (ret < 0)
 106                return ret;
 107
 108        return 0;
 109}
 110
 111static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_single_chip_ops = {
 112        .read = mv88e6xxx_smi_single_chip_read,
 113        .write = mv88e6xxx_smi_single_chip_write,
 114};
 115
 116static int mv88e6xxx_smi_multi_chip_wait(struct mv88e6xxx_chip *chip)
 117{
 118        int ret;
 119        int i;
 120
 121        for (i = 0; i < 16; i++) {
 122                ret = mdiobus_read_nested(chip->bus, chip->sw_addr, SMI_CMD);
 123                if (ret < 0)
 124                        return ret;
 125
 126                if ((ret & SMI_CMD_BUSY) == 0)
 127                        return 0;
 128        }
 129
 130        return -ETIMEDOUT;
 131}
 132
 133static int mv88e6xxx_smi_multi_chip_read(struct mv88e6xxx_chip *chip,
 134                                         int addr, int reg, u16 *val)
 135{
 136        int ret;
 137
 138        /* Wait for the bus to become free. */
 139        ret = mv88e6xxx_smi_multi_chip_wait(chip);
 140        if (ret < 0)
 141                return ret;
 142
 143        /* Transmit the read command. */
 144        ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_CMD,
 145                                   SMI_CMD_OP_22_READ | (addr << 5) | reg);
 146        if (ret < 0)
 147                return ret;
 148
 149        /* Wait for the read command to complete. */
 150        ret = mv88e6xxx_smi_multi_chip_wait(chip);
 151        if (ret < 0)
 152                return ret;
 153
 154        /* Read the data. */
 155        ret = mdiobus_read_nested(chip->bus, chip->sw_addr, SMI_DATA);
 156        if (ret < 0)
 157                return ret;
 158
 159        *val = ret & 0xffff;
 160
 161        return 0;
 162}
 163
 164static int mv88e6xxx_smi_multi_chip_write(struct mv88e6xxx_chip *chip,
 165                                          int addr, int reg, u16 val)
 166{
 167        int ret;
 168
 169        /* Wait for the bus to become free. */
 170        ret = mv88e6xxx_smi_multi_chip_wait(chip);
 171        if (ret < 0)
 172                return ret;
 173
 174        /* Transmit the data to write. */
 175        ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_DATA, val);
 176        if (ret < 0)
 177                return ret;
 178
 179        /* Transmit the write command. */
 180        ret = mdiobus_write_nested(chip->bus, chip->sw_addr, SMI_CMD,
 181                                   SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
 182        if (ret < 0)
 183                return ret;
 184
 185        /* Wait for the write command to complete. */
 186        ret = mv88e6xxx_smi_multi_chip_wait(chip);
 187        if (ret < 0)
 188                return ret;
 189
 190        return 0;
 191}
 192
 193static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_multi_chip_ops = {
 194        .read = mv88e6xxx_smi_multi_chip_read,
 195        .write = mv88e6xxx_smi_multi_chip_write,
 196};
 197
 198int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)
 199{
 200        int err;
 201
 202        assert_reg_lock(chip);
 203
 204        err = mv88e6xxx_smi_read(chip, addr, reg, val);
 205        if (err)
 206                return err;
 207
 208        dev_dbg(chip->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 209                addr, reg, *val);
 210
 211        return 0;
 212}
 213
 214int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
 215{
 216        int err;
 217
 218        assert_reg_lock(chip);
 219
 220        err = mv88e6xxx_smi_write(chip, addr, reg, val);
 221        if (err)
 222                return err;
 223
 224        dev_dbg(chip->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 225                addr, reg, val);
 226
 227        return 0;
 228}
 229
 230struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
 231{
 232        struct mv88e6xxx_mdio_bus *mdio_bus;
 233
 234        mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus,
 235                                    list);
 236        if (!mdio_bus)
 237                return NULL;
 238
 239        return mdio_bus->bus;
 240}
 241
 242static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
 243{
 244        struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
 245        unsigned int n = d->hwirq;
 246
 247        chip->g1_irq.masked |= (1 << n);
 248}
 249
 250static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
 251{
 252        struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
 253        unsigned int n = d->hwirq;
 254
 255        chip->g1_irq.masked &= ~(1 << n);
 256}
 257
 258static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
 259{
 260        unsigned int nhandled = 0;
 261        unsigned int sub_irq;
 262        unsigned int n;
 263        u16 reg;
 264        int err;
 265
 266        mutex_lock(&chip->reg_lock);
 267        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
 268        mutex_unlock(&chip->reg_lock);
 269
 270        if (err)
 271                goto out;
 272
 273        for (n = 0; n < chip->g1_irq.nirqs; ++n) {
 274                if (reg & (1 << n)) {
 275                        sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
 276                        handle_nested_irq(sub_irq);
 277                        ++nhandled;
 278                }
 279        }
 280out:
 281        return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 282}
 283
 284static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
 285{
 286        struct mv88e6xxx_chip *chip = dev_id;
 287
 288        return mv88e6xxx_g1_irq_thread_work(chip);
 289}
 290
 291static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
 292{
 293        struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
 294
 295        mutex_lock(&chip->reg_lock);
 296}
 297
 298static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
 299{
 300        struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
 301        u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
 302        u16 reg;
 303        int err;
 304
 305        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &reg);
 306        if (err)
 307                goto out;
 308
 309        reg &= ~mask;
 310        reg |= (~chip->g1_irq.masked & mask);
 311
 312        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);
 313        if (err)
 314                goto out;
 315
 316out:
 317        mutex_unlock(&chip->reg_lock);
 318}
 319
 320static const struct irq_chip mv88e6xxx_g1_irq_chip = {
 321        .name                   = "mv88e6xxx-g1",
 322        .irq_mask               = mv88e6xxx_g1_irq_mask,
 323        .irq_unmask             = mv88e6xxx_g1_irq_unmask,
 324        .irq_bus_lock           = mv88e6xxx_g1_irq_bus_lock,
 325        .irq_bus_sync_unlock    = mv88e6xxx_g1_irq_bus_sync_unlock,
 326};
 327
 328static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
 329                                       unsigned int irq,
 330                                       irq_hw_number_t hwirq)
 331{
 332        struct mv88e6xxx_chip *chip = d->host_data;
 333
 334        irq_set_chip_data(irq, d->host_data);
 335        irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
 336        irq_set_noprobe(irq);
 337
 338        return 0;
 339}
 340
 341static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
 342        .map    = mv88e6xxx_g1_irq_domain_map,
 343        .xlate  = irq_domain_xlate_twocell,
 344};
 345
 346/* To be called with reg_lock held */
 347static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)
 348{
 349        int irq, virq;
 350        u16 mask;
 351
 352        mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
 353        mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
 354        mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
 355
 356        for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
 357                virq = irq_find_mapping(chip->g1_irq.domain, irq);
 358                irq_dispose_mapping(virq);
 359        }
 360
 361        irq_domain_remove(chip->g1_irq.domain);
 362}
 363
 364static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
 365{
 366        /*
 367         * free_irq must be called without reg_lock taken because the irq
 368         * handler takes this lock, too.
 369         */
 370        free_irq(chip->irq, chip);
 371
 372        mutex_lock(&chip->reg_lock);
 373        mv88e6xxx_g1_irq_free_common(chip);
 374        mutex_unlock(&chip->reg_lock);
 375}
 376
 377static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)
 378{
 379        int err, irq, virq;
 380        u16 reg, mask;
 381
 382        chip->g1_irq.nirqs = chip->info->g1_irqs;
 383        chip->g1_irq.domain = irq_domain_add_simple(
 384                NULL, chip->g1_irq.nirqs, 0,
 385                &mv88e6xxx_g1_irq_domain_ops, chip);
 386        if (!chip->g1_irq.domain)
 387                return -ENOMEM;
 388
 389        for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
 390                irq_create_mapping(chip->g1_irq.domain, irq);
 391
 392        chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
 393        chip->g1_irq.masked = ~0;
 394
 395        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &mask);
 396        if (err)
 397                goto out_mapping;
 398
 399        mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
 400
 401        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
 402        if (err)
 403                goto out_disable;
 404
 405        /* Reading the interrupt status clears (most of) them */
 406        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
 407        if (err)
 408                goto out_disable;
 409
 410        return 0;
 411
 412out_disable:
 413        mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
 414        mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
 415
 416out_mapping:
 417        for (irq = 0; irq < 16; irq++) {
 418                virq = irq_find_mapping(chip->g1_irq.domain, irq);
 419                irq_dispose_mapping(virq);
 420        }
 421
 422        irq_domain_remove(chip->g1_irq.domain);
 423
 424        return err;
 425}
 426
 427static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
 428{
 429        int err;
 430
 431        err = mv88e6xxx_g1_irq_setup_common(chip);
 432        if (err)
 433                return err;
 434
 435        err = request_threaded_irq(chip->irq, NULL,
 436                                   mv88e6xxx_g1_irq_thread_fn,
 437                                   IRQF_ONESHOT,
 438                                   dev_name(chip->dev), chip);
 439        if (err)
 440                mv88e6xxx_g1_irq_free_common(chip);
 441
 442        return err;
 443}
 444
 445static void mv88e6xxx_irq_poll(struct kthread_work *work)
 446{
 447        struct mv88e6xxx_chip *chip = container_of(work,
 448                                                   struct mv88e6xxx_chip,
 449                                                   irq_poll_work.work);
 450        mv88e6xxx_g1_irq_thread_work(chip);
 451
 452        kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
 453                                   msecs_to_jiffies(100));
 454}
 455
 456static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)
 457{
 458        int err;
 459
 460        err = mv88e6xxx_g1_irq_setup_common(chip);
 461        if (err)
 462                return err;
 463
 464        kthread_init_delayed_work(&chip->irq_poll_work,
 465                                  mv88e6xxx_irq_poll);
 466
 467        chip->kworker = kthread_create_worker(0, dev_name(chip->dev));
 468        if (IS_ERR(chip->kworker))
 469                return PTR_ERR(chip->kworker);
 470
 471        kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
 472                                   msecs_to_jiffies(100));
 473
 474        return 0;
 475}
 476
 477static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
 478{
 479        kthread_cancel_delayed_work_sync(&chip->irq_poll_work);
 480        kthread_destroy_worker(chip->kworker);
 481
 482        mutex_lock(&chip->reg_lock);
 483        mv88e6xxx_g1_irq_free_common(chip);
 484        mutex_unlock(&chip->reg_lock);
 485}
 486
 487int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
 488{
 489        int i;
 490
 491        for (i = 0; i < 16; i++) {
 492                u16 val;
 493                int err;
 494
 495                err = mv88e6xxx_read(chip, addr, reg, &val);
 496                if (err)
 497                        return err;
 498
 499                if (!(val & mask))
 500                        return 0;
 501
 502                usleep_range(1000, 2000);
 503        }
 504
 505        dev_err(chip->dev, "Timeout while waiting for switch\n");
 506        return -ETIMEDOUT;
 507}
 508
 509/* Indirect write to single pointer-data register with an Update bit */
 510int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
 511{
 512        u16 val;
 513        int err;
 514
 515        /* Wait until the previous operation is completed */
 516        err = mv88e6xxx_wait(chip, addr, reg, BIT(15));
 517        if (err)
 518                return err;
 519
 520        /* Set the Update bit to trigger a write operation */
 521        val = BIT(15) | update;
 522
 523        return mv88e6xxx_write(chip, addr, reg, val);
 524}
 525
 526static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
 527                                    int link, int speed, int duplex,
 528                                    phy_interface_t mode)
 529{
 530        int err;
 531
 532        if (!chip->info->ops->port_set_link)
 533                return 0;
 534
 535        /* Port's MAC control must not be changed unless the link is down */
 536        err = chip->info->ops->port_set_link(chip, port, 0);
 537        if (err)
 538                return err;
 539
 540        if (chip->info->ops->port_set_speed) {
 541                err = chip->info->ops->port_set_speed(chip, port, speed);
 542                if (err && err != -EOPNOTSUPP)
 543                        goto restore_link;
 544        }
 545
 546        if (chip->info->ops->port_set_duplex) {
 547                err = chip->info->ops->port_set_duplex(chip, port, duplex);
 548                if (err && err != -EOPNOTSUPP)
 549                        goto restore_link;
 550        }
 551
 552        if (chip->info->ops->port_set_rgmii_delay) {
 553                err = chip->info->ops->port_set_rgmii_delay(chip, port, mode);
 554                if (err && err != -EOPNOTSUPP)
 555                        goto restore_link;
 556        }
 557
 558        if (chip->info->ops->port_set_cmode) {
 559                err = chip->info->ops->port_set_cmode(chip, port, mode);
 560                if (err && err != -EOPNOTSUPP)
 561                        goto restore_link;
 562        }
 563
 564        err = 0;
 565restore_link:
 566        if (chip->info->ops->port_set_link(chip, port, link))
 567                dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port);
 568
 569        return err;
 570}
 571
 572/* We expect the switch to perform auto negotiation if there is a real
 573 * phy. However, in the case of a fixed link phy, we force the port
 574 * settings from the fixed link settings.
 575 */
 576static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
 577                                  struct phy_device *phydev)
 578{
 579        struct mv88e6xxx_chip *chip = ds->priv;
 580        int err;
 581
 582        if (!phy_is_pseudo_fixed_link(phydev))
 583                return;
 584
 585        mutex_lock(&chip->reg_lock);
 586        err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
 587                                       phydev->duplex, phydev->interface);
 588        mutex_unlock(&chip->reg_lock);
 589
 590        if (err && err != -EOPNOTSUPP)
 591                dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
 592}
 593
 594static void mv88e6xxx_validate(struct dsa_switch *ds, int port,
 595                               unsigned long *supported,
 596                               struct phylink_link_state *state)
 597{
 598}
 599
 600static int mv88e6xxx_link_state(struct dsa_switch *ds, int port,
 601                                struct phylink_link_state *state)
 602{
 603        struct mv88e6xxx_chip *chip = ds->priv;
 604        int err;
 605
 606        mutex_lock(&chip->reg_lock);
 607        err = mv88e6xxx_port_link_state(chip, port, state);
 608        mutex_unlock(&chip->reg_lock);
 609
 610        return err;
 611}
 612
 613static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
 614                                 unsigned int mode,
 615                                 const struct phylink_link_state *state)
 616{
 617        struct mv88e6xxx_chip *chip = ds->priv;
 618        int speed, duplex, link, err;
 619
 620        if (mode == MLO_AN_PHY)
 621                return;
 622
 623        if (mode == MLO_AN_FIXED) {
 624                link = LINK_FORCED_UP;
 625                speed = state->speed;
 626                duplex = state->duplex;
 627        } else {
 628                speed = SPEED_UNFORCED;
 629                duplex = DUPLEX_UNFORCED;
 630                link = LINK_UNFORCED;
 631        }
 632
 633        mutex_lock(&chip->reg_lock);
 634        err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
 635                                       state->interface);
 636        mutex_unlock(&chip->reg_lock);
 637
 638        if (err && err != -EOPNOTSUPP)
 639                dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
 640}
 641
 642static void mv88e6xxx_mac_link_force(struct dsa_switch *ds, int port, int link)
 643{
 644        struct mv88e6xxx_chip *chip = ds->priv;
 645        int err;
 646
 647        mutex_lock(&chip->reg_lock);
 648        err = chip->info->ops->port_set_link(chip, port, link);
 649        mutex_unlock(&chip->reg_lock);
 650
 651        if (err)
 652                dev_err(chip->dev, "p%d: failed to force MAC link\n", port);
 653}
 654
 655static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
 656                                    unsigned int mode,
 657                                    phy_interface_t interface)
 658{
 659        if (mode == MLO_AN_FIXED)
 660                mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_DOWN);
 661}
 662
 663static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
 664                                  unsigned int mode, phy_interface_t interface,
 665                                  struct phy_device *phydev)
 666{
 667        if (mode == MLO_AN_FIXED)
 668                mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP);
 669}
 670
 671static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
 672{
 673        if (!chip->info->ops->stats_snapshot)
 674                return -EOPNOTSUPP;
 675
 676        return chip->info->ops->stats_snapshot(chip, port);
 677}
 678
 679static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
 680        { "in_good_octets",             8, 0x00, STATS_TYPE_BANK0, },
 681        { "in_bad_octets",              4, 0x02, STATS_TYPE_BANK0, },
 682        { "in_unicast",                 4, 0x04, STATS_TYPE_BANK0, },
 683        { "in_broadcasts",              4, 0x06, STATS_TYPE_BANK0, },
 684        { "in_multicasts",              4, 0x07, STATS_TYPE_BANK0, },
 685        { "in_pause",                   4, 0x16, STATS_TYPE_BANK0, },
 686        { "in_undersize",               4, 0x18, STATS_TYPE_BANK0, },
 687        { "in_fragments",               4, 0x19, STATS_TYPE_BANK0, },
 688        { "in_oversize",                4, 0x1a, STATS_TYPE_BANK0, },
 689        { "in_jabber",                  4, 0x1b, STATS_TYPE_BANK0, },
 690        { "in_rx_error",                4, 0x1c, STATS_TYPE_BANK0, },
 691        { "in_fcs_error",               4, 0x1d, STATS_TYPE_BANK0, },
 692        { "out_octets",                 8, 0x0e, STATS_TYPE_BANK0, },
 693        { "out_unicast",                4, 0x10, STATS_TYPE_BANK0, },
 694        { "out_broadcasts",             4, 0x13, STATS_TYPE_BANK0, },
 695        { "out_multicasts",             4, 0x12, STATS_TYPE_BANK0, },
 696        { "out_pause",                  4, 0x15, STATS_TYPE_BANK0, },
 697        { "excessive",                  4, 0x11, STATS_TYPE_BANK0, },
 698        { "collisions",                 4, 0x1e, STATS_TYPE_BANK0, },
 699        { "deferred",                   4, 0x05, STATS_TYPE_BANK0, },
 700        { "single",                     4, 0x14, STATS_TYPE_BANK0, },
 701        { "multiple",                   4, 0x17, STATS_TYPE_BANK0, },
 702        { "out_fcs_error",              4, 0x03, STATS_TYPE_BANK0, },
 703        { "late",                       4, 0x1f, STATS_TYPE_BANK0, },
 704        { "hist_64bytes",               4, 0x08, STATS_TYPE_BANK0, },
 705        { "hist_65_127bytes",           4, 0x09, STATS_TYPE_BANK0, },
 706        { "hist_128_255bytes",          4, 0x0a, STATS_TYPE_BANK0, },
 707        { "hist_256_511bytes",          4, 0x0b, STATS_TYPE_BANK0, },
 708        { "hist_512_1023bytes",         4, 0x0c, STATS_TYPE_BANK0, },
 709        { "hist_1024_max_bytes",        4, 0x0d, STATS_TYPE_BANK0, },
 710        { "sw_in_discards",             4, 0x10, STATS_TYPE_PORT, },
 711        { "sw_in_filtered",             2, 0x12, STATS_TYPE_PORT, },
 712        { "sw_out_filtered",            2, 0x13, STATS_TYPE_PORT, },
 713        { "in_discards",                4, 0x00, STATS_TYPE_BANK1, },
 714        { "in_filtered",                4, 0x01, STATS_TYPE_BANK1, },
 715        { "in_accepted",                4, 0x02, STATS_TYPE_BANK1, },
 716        { "in_bad_accepted",            4, 0x03, STATS_TYPE_BANK1, },
 717        { "in_good_avb_class_a",        4, 0x04, STATS_TYPE_BANK1, },
 718        { "in_good_avb_class_b",        4, 0x05, STATS_TYPE_BANK1, },
 719        { "in_bad_avb_class_a",         4, 0x06, STATS_TYPE_BANK1, },
 720        { "in_bad_avb_class_b",         4, 0x07, STATS_TYPE_BANK1, },
 721        { "tcam_counter_0",             4, 0x08, STATS_TYPE_BANK1, },
 722        { "tcam_counter_1",             4, 0x09, STATS_TYPE_BANK1, },
 723        { "tcam_counter_2",             4, 0x0a, STATS_TYPE_BANK1, },
 724        { "tcam_counter_3",             4, 0x0b, STATS_TYPE_BANK1, },
 725        { "in_da_unknown",              4, 0x0e, STATS_TYPE_BANK1, },
 726        { "in_management",              4, 0x0f, STATS_TYPE_BANK1, },
 727        { "out_queue_0",                4, 0x10, STATS_TYPE_BANK1, },
 728        { "out_queue_1",                4, 0x11, STATS_TYPE_BANK1, },
 729        { "out_queue_2",                4, 0x12, STATS_TYPE_BANK1, },
 730        { "out_queue_3",                4, 0x13, STATS_TYPE_BANK1, },
 731        { "out_queue_4",                4, 0x14, STATS_TYPE_BANK1, },
 732        { "out_queue_5",                4, 0x15, STATS_TYPE_BANK1, },
 733        { "out_queue_6",                4, 0x16, STATS_TYPE_BANK1, },
 734        { "out_queue_7",                4, 0x17, STATS_TYPE_BANK1, },
 735        { "out_cut_through",            4, 0x18, STATS_TYPE_BANK1, },
 736        { "out_octets_a",               4, 0x1a, STATS_TYPE_BANK1, },
 737        { "out_octets_b",               4, 0x1b, STATS_TYPE_BANK1, },
 738        { "out_management",             4, 0x1f, STATS_TYPE_BANK1, },
 739};
 740
 741static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
 742                                            struct mv88e6xxx_hw_stat *s,
 743                                            int port, u16 bank1_select,
 744                                            u16 histogram)
 745{
 746        u32 low;
 747        u32 high = 0;
 748        u16 reg = 0;
 749        int err;
 750        u64 value;
 751
 752        switch (s->type) {
 753        case STATS_TYPE_PORT:
 754                err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
 755                if (err)
 756                        return U64_MAX;
 757
 758                low = reg;
 759                if (s->size == 4) {
 760                        err = mv88e6xxx_port_read(chip, port, s->reg + 1, &reg);
 761                        if (err)
 762                                return U64_MAX;
 763                        high = reg;
 764                }
 765                break;
 766        case STATS_TYPE_BANK1:
 767                reg = bank1_select;
 768                /* fall through */
 769        case STATS_TYPE_BANK0:
 770                reg |= s->reg | histogram;
 771                mv88e6xxx_g1_stats_read(chip, reg, &low);
 772                if (s->size == 8)
 773                        mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
 774                break;
 775        default:
 776                return U64_MAX;
 777        }
 778        value = (((u64)high) << 16) | low;
 779        return value;
 780}
 781
 782static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
 783                                       uint8_t *data, int types)
 784{
 785        struct mv88e6xxx_hw_stat *stat;
 786        int i, j;
 787
 788        for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
 789                stat = &mv88e6xxx_hw_stats[i];
 790                if (stat->type & types) {
 791                        memcpy(data + j * ETH_GSTRING_LEN, stat->string,
 792                               ETH_GSTRING_LEN);
 793                        j++;
 794                }
 795        }
 796
 797        return j;
 798}
 799
 800static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
 801                                       uint8_t *data)
 802{
 803        return mv88e6xxx_stats_get_strings(chip, data,
 804                                           STATS_TYPE_BANK0 | STATS_TYPE_PORT);
 805}
 806
 807static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
 808                                       uint8_t *data)
 809{
 810        return mv88e6xxx_stats_get_strings(chip, data,
 811                                           STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
 812}
 813
 814static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
 815        "atu_member_violation",
 816        "atu_miss_violation",
 817        "atu_full_violation",
 818        "vtu_member_violation",
 819        "vtu_miss_violation",
 820};
 821
 822static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
 823{
 824        unsigned int i;
 825
 826        for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
 827                strlcpy(data + i * ETH_GSTRING_LEN,
 828                        mv88e6xxx_atu_vtu_stats_strings[i],
 829                        ETH_GSTRING_LEN);
 830}
 831
 832static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
 833                                  u32 stringset, uint8_t *data)
 834{
 835        struct mv88e6xxx_chip *chip = ds->priv;
 836        int count = 0;
 837
 838        if (stringset != ETH_SS_STATS)
 839                return;
 840
 841        mutex_lock(&chip->reg_lock);
 842
 843        if (chip->info->ops->stats_get_strings)
 844                count = chip->info->ops->stats_get_strings(chip, data);
 845
 846        if (chip->info->ops->serdes_get_strings) {
 847                data += count * ETH_GSTRING_LEN;
 848                count = chip->info->ops->serdes_get_strings(chip, port, data);
 849        }
 850
 851        data += count * ETH_GSTRING_LEN;
 852        mv88e6xxx_atu_vtu_get_strings(data);
 853
 854        mutex_unlock(&chip->reg_lock);
 855}
 856
 857static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
 858                                          int types)
 859{
 860        struct mv88e6xxx_hw_stat *stat;
 861        int i, j;
 862
 863        for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
 864                stat = &mv88e6xxx_hw_stats[i];
 865                if (stat->type & types)
 866                        j++;
 867        }
 868        return j;
 869}
 870
 871static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
 872{
 873        return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
 874                                              STATS_TYPE_PORT);
 875}
 876
 877static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
 878{
 879        return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
 880                                              STATS_TYPE_BANK1);
 881}
 882
 883static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
 884{
 885        struct mv88e6xxx_chip *chip = ds->priv;
 886        int serdes_count = 0;
 887        int count = 0;
 888
 889        if (sset != ETH_SS_STATS)
 890                return 0;
 891
 892        mutex_lock(&chip->reg_lock);
 893        if (chip->info->ops->stats_get_sset_count)
 894                count = chip->info->ops->stats_get_sset_count(chip);
 895        if (count < 0)
 896                goto out;
 897
 898        if (chip->info->ops->serdes_get_sset_count)
 899                serdes_count = chip->info->ops->serdes_get_sset_count(chip,
 900                                                                      port);
 901        if (serdes_count < 0) {
 902                count = serdes_count;
 903                goto out;
 904        }
 905        count += serdes_count;
 906        count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);
 907
 908out:
 909        mutex_unlock(&chip->reg_lock);
 910
 911        return count;
 912}
 913
 914static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
 915                                     uint64_t *data, int types,
 916                                     u16 bank1_select, u16 histogram)
 917{
 918        struct mv88e6xxx_hw_stat *stat;
 919        int i, j;
 920
 921        for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
 922                stat = &mv88e6xxx_hw_stats[i];
 923                if (stat->type & types) {
 924                        mutex_lock(&chip->reg_lock);
 925                        data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
 926                                                              bank1_select,
 927                                                              histogram);
 928                        mutex_unlock(&chip->reg_lock);
 929
 930                        j++;
 931                }
 932        }
 933        return j;
 934}
 935
 936static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
 937                                     uint64_t *data)
 938{
 939        return mv88e6xxx_stats_get_stats(chip, port, data,
 940                                         STATS_TYPE_BANK0 | STATS_TYPE_PORT,
 941                                         0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
 942}
 943
 944static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
 945                                     uint64_t *data)
 946{
 947        return mv88e6xxx_stats_get_stats(chip, port, data,
 948                                         STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
 949                                         MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
 950                                         MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
 951}
 952
 953static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
 954                                     uint64_t *data)
 955{
 956        return mv88e6xxx_stats_get_stats(chip, port, data,
 957                                         STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
 958                                         MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
 959                                         0);
 960}
 961
 962static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
 963                                        uint64_t *data)
 964{
 965        *data++ = chip->ports[port].atu_member_violation;
 966        *data++ = chip->ports[port].atu_miss_violation;
 967        *data++ = chip->ports[port].atu_full_violation;
 968        *data++ = chip->ports[port].vtu_member_violation;
 969        *data++ = chip->ports[port].vtu_miss_violation;
 970}
 971
 972static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
 973                                uint64_t *data)
 974{
 975        int count = 0;
 976
 977        if (chip->info->ops->stats_get_stats)
 978                count = chip->info->ops->stats_get_stats(chip, port, data);
 979
 980        mutex_lock(&chip->reg_lock);
 981        if (chip->info->ops->serdes_get_stats) {
 982                data += count;
 983                count = chip->info->ops->serdes_get_stats(chip, port, data);
 984        }
 985        data += count;
 986        mv88e6xxx_atu_vtu_get_stats(chip, port, data);
 987        mutex_unlock(&chip->reg_lock);
 988}
 989
 990static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
 991                                        uint64_t *data)
 992{
 993        struct mv88e6xxx_chip *chip = ds->priv;
 994        int ret;
 995
 996        mutex_lock(&chip->reg_lock);
 997
 998        ret = mv88e6xxx_stats_snapshot(chip, port);
 999        mutex_unlock(&chip->reg_lock);
1000
1001        if (ret < 0)
1002                return;
1003
1004        mv88e6xxx_get_stats(chip, port, data);
1005
1006}
1007
1008static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
1009{
1010        return 32 * sizeof(u16);
1011}
1012
1013static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
1014                               struct ethtool_regs *regs, void *_p)
1015{
1016        struct mv88e6xxx_chip *chip = ds->priv;
1017        int err;
1018        u16 reg;
1019        u16 *p = _p;
1020        int i;
1021
1022        regs->version = 0;
1023
1024        memset(p, 0xff, 32 * sizeof(u16));
1025
1026        mutex_lock(&chip->reg_lock);
1027
1028        for (i = 0; i < 32; i++) {
1029
1030                err = mv88e6xxx_port_read(chip, port, i, &reg);
1031                if (!err)
1032                        p[i] = reg;
1033        }
1034
1035        mutex_unlock(&chip->reg_lock);
1036}
1037
1038static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
1039                                 struct ethtool_eee *e)
1040{
1041        /* Nothing to do on the port's MAC */
1042        return 0;
1043}
1044
1045static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
1046                                 struct ethtool_eee *e)
1047{
1048        /* Nothing to do on the port's MAC */
1049        return 0;
1050}
1051
1052static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
1053{
1054        struct dsa_switch *ds = NULL;
1055        struct net_device *br;
1056        u16 pvlan;
1057        int i;
1058
1059        if (dev < DSA_MAX_SWITCHES)
1060                ds = chip->ds->dst->ds[dev];
1061
1062        /* Prevent frames from unknown switch or port */
1063        if (!ds || port >= ds->num_ports)
1064                return 0;
1065
1066        /* Frames from DSA links and CPU ports can egress any local port */
1067        if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
1068                return mv88e6xxx_port_mask(chip);
1069
1070        br = ds->ports[port].bridge_dev;
1071        pvlan = 0;
1072
1073        /* Frames from user ports can egress any local DSA links and CPU ports,
1074         * as well as any local member of their bridge group.
1075         */
1076        for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
1077                if (dsa_is_cpu_port(chip->ds, i) ||
1078                    dsa_is_dsa_port(chip->ds, i) ||
1079                    (br && dsa_to_port(chip->ds, i)->bridge_dev == br))
1080                        pvlan |= BIT(i);
1081
1082        return pvlan;
1083}
1084
1085static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
1086{
1087        u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
1088
1089        /* prevent frames from going back out of the port they came in on */
1090        output_ports &= ~BIT(port);
1091
1092        return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
1093}
1094
1095static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
1096                                         u8 state)
1097{
1098        struct mv88e6xxx_chip *chip = ds->priv;
1099        int err;
1100
1101        mutex_lock(&chip->reg_lock);
1102        err = mv88e6xxx_port_set_state(chip, port, state);
1103        mutex_unlock(&chip->reg_lock);
1104
1105        if (err)
1106                dev_err(ds->dev, "p%d: failed to update state\n", port);
1107}
1108
1109static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip)
1110{
1111        int err;
1112
1113        if (chip->info->ops->ieee_pri_map) {
1114                err = chip->info->ops->ieee_pri_map(chip);
1115                if (err)
1116                        return err;
1117        }
1118
1119        if (chip->info->ops->ip_pri_map) {
1120                err = chip->info->ops->ip_pri_map(chip);
1121                if (err)
1122                        return err;
1123        }
1124
1125        return 0;
1126}
1127
1128static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
1129{
1130        int target, port;
1131        int err;
1132
1133        if (!chip->info->global2_addr)
1134                return 0;
1135
1136        /* Initialize the routing port to the 32 possible target devices */
1137        for (target = 0; target < 32; target++) {
1138                port = 0x1f;
1139                if (target < DSA_MAX_SWITCHES)
1140                        if (chip->ds->rtable[target] != DSA_RTABLE_NONE)
1141                                port = chip->ds->rtable[target];
1142
1143                err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
1144                if (err)
1145                        return err;
1146        }
1147
1148        if (chip->info->ops->set_cascade_port) {
1149                port = MV88E6XXX_CASCADE_PORT_MULTIPLE;
1150                err = chip->info->ops->set_cascade_port(chip, port);
1151                if (err)
1152                        return err;
1153        }
1154
1155        err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index);
1156        if (err)
1157                return err;
1158
1159        return 0;
1160}
1161
1162static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip)
1163{
1164        /* Clear all trunk masks and mapping */
1165        if (chip->info->global2_addr)
1166                return mv88e6xxx_g2_trunk_clear(chip);
1167
1168        return 0;
1169}
1170
1171static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip)
1172{
1173        if (chip->info->ops->rmu_disable)
1174                return chip->info->ops->rmu_disable(chip);
1175
1176        return 0;
1177}
1178
1179static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
1180{
1181        if (chip->info->ops->pot_clear)
1182                return chip->info->ops->pot_clear(chip);
1183
1184        return 0;
1185}
1186
1187static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip)
1188{
1189        if (chip->info->ops->mgmt_rsvd2cpu)
1190                return chip->info->ops->mgmt_rsvd2cpu(chip);
1191
1192        return 0;
1193}
1194
1195static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
1196{
1197        int err;
1198
1199        err = mv88e6xxx_g1_atu_flush(chip, 0, true);
1200        if (err)
1201                return err;
1202
1203        err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
1204        if (err)
1205                return err;
1206
1207        return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
1208}
1209
1210static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
1211{
1212        int port;
1213        int err;
1214
1215        if (!chip->info->ops->irl_init_all)
1216                return 0;
1217
1218        for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
1219                /* Disable ingress rate limiting by resetting all per port
1220                 * ingress rate limit resources to their initial state.
1221                 */
1222                err = chip->info->ops->irl_init_all(chip, port);
1223                if (err)
1224                        return err;
1225        }
1226
1227        return 0;
1228}
1229
1230static int mv88e6xxx_mac_setup(struct mv88e6xxx_chip *chip)
1231{
1232        if (chip->info->ops->set_switch_mac) {
1233                u8 addr[ETH_ALEN];
1234
1235                eth_random_addr(addr);
1236
1237                return chip->info->ops->set_switch_mac(chip, addr);
1238        }
1239
1240        return 0;
1241}
1242
1243static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
1244{
1245        u16 pvlan = 0;
1246
1247        if (!mv88e6xxx_has_pvt(chip))
1248                return -EOPNOTSUPP;
1249
1250        /* Skip the local source device, which uses in-chip port VLAN */
1251        if (dev != chip->ds->index)
1252                pvlan = mv88e6xxx_port_vlan(chip, dev, port);
1253
1254        return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan);
1255}
1256
1257static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
1258{
1259        int dev, port;
1260        int err;
1261
1262        if (!mv88e6xxx_has_pvt(chip))
1263                return 0;
1264
1265        /* Clear 5 Bit Port for usage with Marvell Link Street devices:
1266         * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev.
1267         */
1268        err = mv88e6xxx_g2_misc_4_bit_port(chip);
1269        if (err)
1270                return err;
1271
1272        for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; ++dev) {
1273                for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; ++port) {
1274                        err = mv88e6xxx_pvt_map(chip, dev, port);
1275                        if (err)
1276                                return err;
1277                }
1278        }
1279
1280        return 0;
1281}
1282
1283static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
1284{
1285        struct mv88e6xxx_chip *chip = ds->priv;
1286        int err;
1287
1288        mutex_lock(&chip->reg_lock);
1289        err = mv88e6xxx_g1_atu_remove(chip, 0, port, false);
1290        mutex_unlock(&chip->reg_lock);
1291
1292        if (err)
1293                dev_err(ds->dev, "p%d: failed to flush ATU\n", port);
1294}
1295
1296static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
1297{
1298        if (!chip->info->max_vid)
1299                return 0;
1300
1301        return mv88e6xxx_g1_vtu_flush(chip);
1302}
1303
1304static int mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip,
1305                                 struct mv88e6xxx_vtu_entry *entry)
1306{
1307        if (!chip->info->ops->vtu_getnext)
1308                return -EOPNOTSUPP;
1309
1310        return chip->info->ops->vtu_getnext(chip, entry);
1311}
1312
1313static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
1314                                   struct mv88e6xxx_vtu_entry *entry)
1315{
1316        if (!chip->info->ops->vtu_loadpurge)
1317                return -EOPNOTSUPP;
1318
1319        return chip->info->ops->vtu_loadpurge(chip, entry);
1320}
1321
1322static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
1323{
1324        DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
1325        struct mv88e6xxx_vtu_entry vlan = {
1326                .vid = chip->info->max_vid,
1327        };
1328        int i, err;
1329
1330        bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
1331
1332        /* Set every FID bit used by the (un)bridged ports */
1333        for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1334                err = mv88e6xxx_port_get_fid(chip, i, fid);
1335                if (err)
1336                        return err;
1337
1338                set_bit(*fid, fid_bitmap);
1339        }
1340
1341        /* Set every FID bit used by the VLAN entries */
1342        do {
1343                err = mv88e6xxx_vtu_getnext(chip, &vlan);
1344                if (err)
1345                        return err;
1346
1347                if (!vlan.valid)
1348                        break;
1349
1350                set_bit(vlan.fid, fid_bitmap);
1351        } while (vlan.vid < chip->info->max_vid);
1352
1353        /* The reset value 0x000 is used to indicate that multiple address
1354         * databases are not needed. Return the next positive available.
1355         */
1356        *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
1357        if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
1358                return -ENOSPC;
1359
1360        /* Clear the database */
1361        return mv88e6xxx_g1_atu_flush(chip, *fid, true);
1362}
1363
1364static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
1365                             struct mv88e6xxx_vtu_entry *entry, bool new)
1366{
1367        int err;
1368
1369        if (!vid)
1370                return -EINVAL;
1371
1372        entry->vid = vid - 1;
1373        entry->valid = false;
1374
1375        err = mv88e6xxx_vtu_getnext(chip, entry);
1376        if (err)
1377                return err;
1378
1379        if (entry->vid == vid && entry->valid)
1380                return 0;
1381
1382        if (new) {
1383                int i;
1384
1385                /* Initialize a fresh VLAN entry */
1386                memset(entry, 0, sizeof(*entry));
1387                entry->valid = true;
1388                entry->vid = vid;
1389
1390                /* Exclude all ports */
1391                for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
1392                        entry->member[i] =
1393                                MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1394
1395                return mv88e6xxx_atu_new(chip, &entry->fid);
1396        }
1397
1398        /* switchdev expects -EOPNOTSUPP to honor software VLANs */
1399        return -EOPNOTSUPP;
1400}
1401
1402static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
1403                                        u16 vid_begin, u16 vid_end)
1404{
1405        struct mv88e6xxx_chip *chip = ds->priv;
1406        struct mv88e6xxx_vtu_entry vlan = {
1407                .vid = vid_begin - 1,
1408        };
1409        int i, err;
1410
1411        /* DSA and CPU ports have to be members of multiple vlans */
1412        if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
1413                return 0;
1414
1415        if (!vid_begin)
1416                return -EOPNOTSUPP;
1417
1418        mutex_lock(&chip->reg_lock);
1419
1420        do {
1421                err = mv88e6xxx_vtu_getnext(chip, &vlan);
1422                if (err)
1423                        goto unlock;
1424
1425                if (!vlan.valid)
1426                        break;
1427
1428                if (vlan.vid > vid_end)
1429                        break;
1430
1431                for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1432                        if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
1433                                continue;
1434
1435                        if (!ds->ports[i].slave)
1436                                continue;
1437
1438                        if (vlan.member[i] ==
1439                            MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1440                                continue;
1441
1442                        if (dsa_to_port(ds, i)->bridge_dev ==
1443                            ds->ports[port].bridge_dev)
1444                                break; /* same bridge, check next VLAN */
1445
1446                        if (!dsa_to_port(ds, i)->bridge_dev)
1447                                continue;
1448
1449                        dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n",
1450                                port, vlan.vid, i,
1451                                netdev_name(dsa_to_port(ds, i)->bridge_dev));
1452                        err = -EOPNOTSUPP;
1453                        goto unlock;
1454                }
1455        } while (vlan.vid < vid_end);
1456
1457unlock:
1458        mutex_unlock(&chip->reg_lock);
1459
1460        return err;
1461}
1462
1463static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
1464                                         bool vlan_filtering)
1465{
1466        struct mv88e6xxx_chip *chip = ds->priv;
1467        u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
1468                MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
1469        int err;
1470
1471        if (!chip->info->max_vid)
1472                return -EOPNOTSUPP;
1473
1474        mutex_lock(&chip->reg_lock);
1475        err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
1476        mutex_unlock(&chip->reg_lock);
1477
1478        return err;
1479}
1480
1481static int
1482mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
1483                            const struct switchdev_obj_port_vlan *vlan)
1484{
1485        struct mv88e6xxx_chip *chip = ds->priv;
1486        int err;
1487
1488        if (!chip->info->max_vid)
1489                return -EOPNOTSUPP;
1490
1491        /* If the requested port doesn't belong to the same bridge as the VLAN
1492         * members, do not support it (yet) and fallback to software VLAN.
1493         */
1494        err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin,
1495                                           vlan->vid_end);
1496        if (err)
1497                return err;
1498
1499        /* We don't need any dynamic resource from the kernel (yet),
1500         * so skip the prepare phase.
1501         */
1502        return 0;
1503}
1504
1505static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
1506                                        const unsigned char *addr, u16 vid,
1507                                        u8 state)
1508{
1509        struct mv88e6xxx_vtu_entry vlan;
1510        struct mv88e6xxx_atu_entry entry;
1511        int err;
1512
1513        /* Null VLAN ID corresponds to the port private database */
1514        if (vid == 0)
1515                err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
1516        else
1517                err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
1518        if (err)
1519                return err;
1520
1521        entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
1522        ether_addr_copy(entry.mac, addr);
1523        eth_addr_dec(entry.mac);
1524
1525        err = mv88e6xxx_g1_atu_getnext(chip, vlan.fid, &entry);
1526        if (err)
1527                return err;
1528
1529        /* Initialize a fresh ATU entry if it isn't found */
1530        if (entry.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ||
1531            !ether_addr_equal(entry.mac, addr)) {
1532                memset(&entry, 0, sizeof(entry));
1533                ether_addr_copy(entry.mac, addr);
1534        }
1535
1536        /* Purge the ATU entry only if no port is using it anymore */
1537        if (state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED) {
1538                entry.portvec &= ~BIT(port);
1539                if (!entry.portvec)
1540                        entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
1541        } else {
1542                entry.portvec |= BIT(port);
1543                entry.state = state;
1544        }
1545
1546        return mv88e6xxx_g1_atu_loadpurge(chip, vlan.fid, &entry);
1547}
1548
1549static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port,
1550                                        u16 vid)
1551{
1552        const char broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1553        u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC;
1554
1555        return mv88e6xxx_port_db_load_purge(chip, port, broadcast, vid, state);
1556}
1557
1558static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid)
1559{
1560        int port;
1561        int err;
1562
1563        for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
1564                err = mv88e6xxx_port_add_broadcast(chip, port, vid);
1565                if (err)
1566                        return err;
1567        }
1568
1569        return 0;
1570}
1571
1572static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
1573                                    u16 vid, u8 member)
1574{
1575        struct mv88e6xxx_vtu_entry vlan;
1576        int err;
1577
1578        err = mv88e6xxx_vtu_get(chip, vid, &vlan, true);
1579        if (err)
1580                return err;
1581
1582        vlan.member[port] = member;
1583
1584        err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
1585        if (err)
1586                return err;
1587
1588        return mv88e6xxx_broadcast_setup(chip, vid);
1589}
1590
1591static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
1592                                    const struct switchdev_obj_port_vlan *vlan)
1593{
1594        struct mv88e6xxx_chip *chip = ds->priv;
1595        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
1596        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1597        u8 member;
1598        u16 vid;
1599
1600        if (!chip->info->max_vid)
1601                return;
1602
1603        if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
1604                member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED;
1605        else if (untagged)
1606                member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED;
1607        else
1608                member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED;
1609
1610        mutex_lock(&chip->reg_lock);
1611
1612        for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
1613                if (_mv88e6xxx_port_vlan_add(chip, port, vid, member))
1614                        dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
1615                                vid, untagged ? 'u' : 't');
1616
1617        if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
1618                dev_err(ds->dev, "p%d: failed to set PVID %d\n", port,
1619                        vlan->vid_end);
1620
1621        mutex_unlock(&chip->reg_lock);
1622}
1623
1624static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
1625                                    int port, u16 vid)
1626{
1627        struct mv88e6xxx_vtu_entry vlan;
1628        int i, err;
1629
1630        err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
1631        if (err)
1632                return err;
1633
1634        /* Tell switchdev if this VLAN is handled in software */
1635        if (vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1636                return -EOPNOTSUPP;
1637
1638        vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1639
1640        /* keep the VLAN unless all ports are excluded */
1641        vlan.valid = false;
1642        for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1643                if (vlan.member[i] !=
1644                    MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
1645                        vlan.valid = true;
1646                        break;
1647                }
1648        }
1649
1650        err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
1651        if (err)
1652                return err;
1653
1654        return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
1655}
1656
1657static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
1658                                   const struct switchdev_obj_port_vlan *vlan)
1659{
1660        struct mv88e6xxx_chip *chip = ds->priv;
1661        u16 pvid, vid;
1662        int err = 0;
1663
1664        if (!chip->info->max_vid)
1665                return -EOPNOTSUPP;
1666
1667        mutex_lock(&chip->reg_lock);
1668
1669        err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
1670        if (err)
1671                goto unlock;
1672
1673        for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
1674                err = _mv88e6xxx_port_vlan_del(chip, port, vid);
1675                if (err)
1676                        goto unlock;
1677
1678                if (vid == pvid) {
1679                        err = mv88e6xxx_port_set_pvid(chip, port, 0);
1680                        if (err)
1681                                goto unlock;
1682                }
1683        }
1684
1685unlock:
1686        mutex_unlock(&chip->reg_lock);
1687
1688        return err;
1689}
1690
1691static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
1692                                  const unsigned char *addr, u16 vid)
1693{
1694        struct mv88e6xxx_chip *chip = ds->priv;
1695        int err;
1696
1697        mutex_lock(&chip->reg_lock);
1698        err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
1699                                           MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
1700        mutex_unlock(&chip->reg_lock);
1701
1702        return err;
1703}
1704
1705static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1706                                  const unsigned char *addr, u16 vid)
1707{
1708        struct mv88e6xxx_chip *chip = ds->priv;
1709        int err;
1710
1711        mutex_lock(&chip->reg_lock);
1712        err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
1713                                           MV88E6XXX_G1_ATU_DATA_STATE_UNUSED);
1714        mutex_unlock(&chip->reg_lock);
1715
1716        return err;
1717}
1718
1719static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
1720                                      u16 fid, u16 vid, int port,
1721                                      dsa_fdb_dump_cb_t *cb, void *data)
1722{
1723        struct mv88e6xxx_atu_entry addr;
1724        bool is_static;
1725        int err;
1726
1727        addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
1728        eth_broadcast_addr(addr.mac);
1729
1730        do {
1731                mutex_lock(&chip->reg_lock);
1732                err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
1733                mutex_unlock(&chip->reg_lock);
1734                if (err)
1735                        return err;
1736
1737                if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED)
1738                        break;
1739
1740                if (addr.trunk || (addr.portvec & BIT(port)) == 0)
1741                        continue;
1742
1743                if (!is_unicast_ether_addr(addr.mac))
1744                        continue;
1745
1746                is_static = (addr.state ==
1747                             MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
1748                err = cb(addr.mac, vid, is_static, data);
1749                if (err)
1750                        return err;
1751        } while (!is_broadcast_ether_addr(addr.mac));
1752
1753        return err;
1754}
1755
1756static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1757                                  dsa_fdb_dump_cb_t *cb, void *data)
1758{
1759        struct mv88e6xxx_vtu_entry vlan = {
1760                .vid = chip->info->max_vid,
1761        };
1762        u16 fid;
1763        int err;
1764
1765        /* Dump port's default Filtering Information Database (VLAN ID 0) */
1766        mutex_lock(&chip->reg_lock);
1767        err = mv88e6xxx_port_get_fid(chip, port, &fid);
1768        mutex_unlock(&chip->reg_lock);
1769
1770        if (err)
1771                return err;
1772
1773        err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data);
1774        if (err)
1775                return err;
1776
1777        /* Dump VLANs' Filtering Information Databases */
1778        do {
1779                mutex_lock(&chip->reg_lock);
1780                err = mv88e6xxx_vtu_getnext(chip, &vlan);
1781                mutex_unlock(&chip->reg_lock);
1782                if (err)
1783                        return err;
1784
1785                if (!vlan.valid)
1786                        break;
1787
1788                err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
1789                                                 cb, data);
1790                if (err)
1791                        return err;
1792        } while (vlan.vid < chip->info->max_vid);
1793
1794        return err;
1795}
1796
1797static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
1798                                   dsa_fdb_dump_cb_t *cb, void *data)
1799{
1800        struct mv88e6xxx_chip *chip = ds->priv;
1801
1802        return mv88e6xxx_port_db_dump(chip, port, cb, data);
1803}
1804
1805static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
1806                                struct net_device *br)
1807{
1808        struct dsa_switch *ds;
1809        int port;
1810        int dev;
1811        int err;
1812
1813        /* Remap the Port VLAN of each local bridge group member */
1814        for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
1815                if (chip->ds->ports[port].bridge_dev == br) {
1816                        err = mv88e6xxx_port_vlan_map(chip, port);
1817                        if (err)
1818                                return err;
1819                }
1820        }
1821
1822        if (!mv88e6xxx_has_pvt(chip))
1823                return 0;
1824
1825        /* Remap the Port VLAN of each cross-chip bridge group member */
1826        for (dev = 0; dev < DSA_MAX_SWITCHES; ++dev) {
1827                ds = chip->ds->dst->ds[dev];
1828                if (!ds)
1829                        break;
1830
1831                for (port = 0; port < ds->num_ports; ++port) {
1832                        if (ds->ports[port].bridge_dev == br) {
1833                                err = mv88e6xxx_pvt_map(chip, dev, port);
1834                                if (err)
1835                                        return err;
1836                        }
1837                }
1838        }
1839
1840        return 0;
1841}
1842
1843static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
1844                                      struct net_device *br)
1845{
1846        struct mv88e6xxx_chip *chip = ds->priv;
1847        int err;
1848
1849        mutex_lock(&chip->reg_lock);
1850        err = mv88e6xxx_bridge_map(chip, br);
1851        mutex_unlock(&chip->reg_lock);
1852
1853        return err;
1854}
1855
1856static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
1857                                        struct net_device *br)
1858{
1859        struct mv88e6xxx_chip *chip = ds->priv;
1860
1861        mutex_lock(&chip->reg_lock);
1862        if (mv88e6xxx_bridge_map(chip, br) ||
1863            mv88e6xxx_port_vlan_map(chip, port))
1864                dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
1865        mutex_unlock(&chip->reg_lock);
1866}
1867
1868static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev,
1869                                           int port, struct net_device *br)
1870{
1871        struct mv88e6xxx_chip *chip = ds->priv;
1872        int err;
1873
1874        if (!mv88e6xxx_has_pvt(chip))
1875                return 0;
1876
1877        mutex_lock(&chip->reg_lock);
1878        err = mv88e6xxx_pvt_map(chip, dev, port);
1879        mutex_unlock(&chip->reg_lock);
1880
1881        return err;
1882}
1883
1884static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev,
1885                                             int port, struct net_device *br)
1886{
1887        struct mv88e6xxx_chip *chip = ds->priv;
1888
1889        if (!mv88e6xxx_has_pvt(chip))
1890                return;
1891
1892        mutex_lock(&chip->reg_lock);
1893        if (mv88e6xxx_pvt_map(chip, dev, port))
1894                dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
1895        mutex_unlock(&chip->reg_lock);
1896}
1897
1898static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
1899{
1900        if (chip->info->ops->reset)
1901                return chip->info->ops->reset(chip);
1902
1903        return 0;
1904}
1905
1906static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
1907{
1908        struct gpio_desc *gpiod = chip->reset;
1909
1910        /* If there is a GPIO connected to the reset pin, toggle it */
1911        if (gpiod) {
1912                gpiod_set_value_cansleep(gpiod, 1);
1913                usleep_range(10000, 20000);
1914                gpiod_set_value_cansleep(gpiod, 0);
1915                usleep_range(10000, 20000);
1916        }
1917}
1918
1919static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
1920{
1921        int i, err;
1922
1923        /* Set all ports to the Disabled state */
1924        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
1925                err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED);
1926                if (err)
1927                        return err;
1928        }
1929
1930        /* Wait for transmit queues to drain,
1931         * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
1932         */
1933        usleep_range(2000, 4000);
1934
1935        return 0;
1936}
1937
1938static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
1939{
1940        int err;
1941
1942        err = mv88e6xxx_disable_ports(chip);
1943        if (err)
1944                return err;
1945
1946        mv88e6xxx_hardware_reset(chip);
1947
1948        return mv88e6xxx_software_reset(chip);
1949}
1950
1951static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
1952                                   enum mv88e6xxx_frame_mode frame,
1953                                   enum mv88e6xxx_egress_mode egress, u16 etype)
1954{
1955        int err;
1956
1957        if (!chip->info->ops->port_set_frame_mode)
1958                return -EOPNOTSUPP;
1959
1960        err = mv88e6xxx_port_set_egress_mode(chip, port, egress);
1961        if (err)
1962                return err;
1963
1964        err = chip->info->ops->port_set_frame_mode(chip, port, frame);
1965        if (err)
1966                return err;
1967
1968        if (chip->info->ops->port_set_ether_type)
1969                return chip->info->ops->port_set_ether_type(chip, port, etype);
1970
1971        return 0;
1972}
1973
1974static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port)
1975{
1976        return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
1977                                       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
1978                                       MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
1979}
1980
1981static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
1982{
1983        return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
1984                                       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
1985                                       MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
1986}
1987
1988static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
1989{
1990        return mv88e6xxx_set_port_mode(chip, port,
1991                                       MV88E6XXX_FRAME_MODE_ETHERTYPE,
1992                                       MV88E6XXX_EGRESS_MODE_ETHERTYPE,
1993                                       ETH_P_EDSA);
1994}
1995
1996static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
1997{
1998        if (dsa_is_dsa_port(chip->ds, port))
1999                return mv88e6xxx_set_port_mode_dsa(chip, port);
2000
2001        if (dsa_is_user_port(chip->ds, port))
2002                return mv88e6xxx_set_port_mode_normal(chip, port);
2003
2004        /* Setup CPU port mode depending on its supported tag format */
2005        if (chip->info->tag_protocol == DSA_TAG_PROTO_DSA)
2006                return mv88e6xxx_set_port_mode_dsa(chip, port);
2007
2008        if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA)
2009                return mv88e6xxx_set_port_mode_edsa(chip, port);
2010
2011        return -EINVAL;
2012}
2013
2014static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
2015{
2016        bool message = dsa_is_dsa_port(chip->ds, port);
2017
2018        return mv88e6xxx_port_set_message_port(chip, port, message);
2019}
2020
2021static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
2022{
2023        struct dsa_switch *ds = chip->ds;
2024        bool flood;
2025
2026        /* Upstream ports flood frames with unknown unicast or multicast DA */
2027        flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port);
2028        if (chip->info->ops->port_set_egress_floods)
2029                return chip->info->ops->port_set_egress_floods(chip, port,
2030                                                               flood, flood);
2031
2032        return 0;
2033}
2034
2035static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
2036                                  bool on)
2037{
2038        if (chip->info->ops->serdes_power)
2039                return chip->info->ops->serdes_power(chip, port, on);
2040
2041        return 0;
2042}
2043
2044static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
2045{
2046        struct dsa_switch *ds = chip->ds;
2047        int upstream_port;
2048        int err;
2049
2050        upstream_port = dsa_upstream_port(ds, port);
2051        if (chip->info->ops->port_set_upstream_port) {
2052                err = chip->info->ops->port_set_upstream_port(chip, port,
2053                                                              upstream_port);
2054                if (err)
2055                        return err;
2056        }
2057
2058        if (port == upstream_port) {
2059                if (chip->info->ops->set_cpu_port) {
2060                        err = chip->info->ops->set_cpu_port(chip,
2061                                                            upstream_port);
2062                        if (err)
2063                                return err;
2064                }
2065
2066                if (chip->info->ops->set_egress_port) {
2067                        err = chip->info->ops->set_egress_port(chip,
2068                                                               upstream_port);
2069                        if (err)
2070                                return err;
2071                }
2072        }
2073
2074        return 0;
2075}
2076
2077static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
2078{
2079        struct dsa_switch *ds = chip->ds;
2080        int err;
2081        u16 reg;
2082
2083        /* MAC Forcing register: don't force link, speed, duplex or flow control
2084         * state to any particular values on physical ports, but force the CPU
2085         * port and all DSA ports to their maximum bandwidth and full duplex.
2086         */
2087        if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
2088                err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
2089                                               SPEED_MAX, DUPLEX_FULL,
2090                                               PHY_INTERFACE_MODE_NA);
2091        else
2092                err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
2093                                               SPEED_UNFORCED, DUPLEX_UNFORCED,
2094                                               PHY_INTERFACE_MODE_NA);
2095        if (err)
2096                return err;
2097
2098        /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
2099         * disable Header mode, enable IGMP/MLD snooping, disable VLAN
2100         * tunneling, determine priority by looking at 802.1p and IP
2101         * priority fields (IP prio has precedence), and set STP state
2102         * to Forwarding.
2103         *
2104         * If this is the CPU link, use DSA or EDSA tagging depending
2105         * on which tagging mode was configured.
2106         *
2107         * If this is a link to another switch, use DSA tagging mode.
2108         *
2109         * If this is the upstream port for this switch, enable
2110         * forwarding of unknown unicasts and multicasts.
2111         */
2112        reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
2113                MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
2114                MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
2115        err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
2116        if (err)
2117                return err;
2118
2119        err = mv88e6xxx_setup_port_mode(chip, port);
2120        if (err)
2121                return err;
2122
2123        err = mv88e6xxx_setup_egress_floods(chip, port);
2124        if (err)
2125                return err;
2126
2127        /* Enable the SERDES interface for DSA and CPU ports. Normal
2128         * ports SERDES are enabled when the port is enabled, thus
2129         * saving a bit of power.
2130         */
2131        if ((dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))) {
2132                err = mv88e6xxx_serdes_power(chip, port, true);
2133                if (err)
2134                        return err;
2135        }
2136
2137        /* Port Control 2: don't force a good FCS, set the maximum frame size to
2138         * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
2139         * untagged frames on this port, do a destination address lookup on all
2140         * received packets as usual, disable ARP mirroring and don't send a
2141         * copy of all transmitted/received frames on this port to the CPU.
2142         */
2143        err = mv88e6xxx_port_set_map_da(chip, port);
2144        if (err)
2145                return err;
2146
2147        err = mv88e6xxx_setup_upstream_port(chip, port);
2148        if (err)
2149                return err;
2150
2151        err = mv88e6xxx_port_set_8021q_mode(chip, port,
2152                                MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED);
2153        if (err)
2154                return err;
2155
2156        if (chip->info->ops->port_set_jumbo_size) {
2157                err = chip->info->ops->port_set_jumbo_size(chip, port, 10240);
2158                if (err)
2159                        return err;
2160        }
2161
2162        /* Port Association Vector: when learning source addresses
2163         * of packets, add the address to the address database using
2164         * a port bitmap that has only the bit for this port set and
2165         * the other bits clear.
2166         */
2167        reg = 1 << port;
2168        /* Disable learning for CPU port */
2169        if (dsa_is_cpu_port(ds, port))
2170                reg = 0;
2171
2172        err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
2173                                   reg);
2174        if (err)
2175                return err;
2176
2177        /* Egress rate control 2: disable egress rate control. */
2178        err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2,
2179                                   0x0000);
2180        if (err)
2181                return err;
2182
2183        if (chip->info->ops->port_pause_limit) {
2184                err = chip->info->ops->port_pause_limit(chip, port, 0, 0);
2185                if (err)
2186                        return err;
2187        }
2188
2189        if (chip->info->ops->port_disable_learn_limit) {
2190                err = chip->info->ops->port_disable_learn_limit(chip, port);
2191                if (err)
2192                        return err;
2193        }
2194
2195        if (chip->info->ops->port_disable_pri_override) {
2196                err = chip->info->ops->port_disable_pri_override(chip, port);
2197                if (err)
2198                        return err;
2199        }
2200
2201        if (chip->info->ops->port_tag_remap) {
2202                err = chip->info->ops->port_tag_remap(chip, port);
2203                if (err)
2204                        return err;
2205        }
2206
2207        if (chip->info->ops->port_egress_rate_limiting) {
2208                err = chip->info->ops->port_egress_rate_limiting(chip, port);
2209                if (err)
2210                        return err;
2211        }
2212
2213        err = mv88e6xxx_setup_message_port(chip, port);
2214        if (err)
2215                return err;
2216
2217        /* Port based VLAN map: give each port the same default address
2218         * database, and allow bidirectional communication between the
2219         * CPU and DSA port(s), and the other ports.
2220         */
2221        err = mv88e6xxx_port_set_fid(chip, port, 0);
2222        if (err)
2223                return err;
2224
2225        err = mv88e6xxx_port_vlan_map(chip, port);
2226        if (err)
2227                return err;
2228
2229        /* Default VLAN ID and priority: don't set a default VLAN
2230         * ID, and set the default packet priority to zero.
2231         */
2232        return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
2233}
2234
2235static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
2236                                 struct phy_device *phydev)
2237{
2238        struct mv88e6xxx_chip *chip = ds->priv;
2239        int err;
2240
2241        mutex_lock(&chip->reg_lock);
2242        err = mv88e6xxx_serdes_power(chip, port, true);
2243        mutex_unlock(&chip->reg_lock);
2244
2245        return err;
2246}
2247
2248static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port,
2249                                   struct phy_device *phydev)
2250{
2251        struct mv88e6xxx_chip *chip = ds->priv;
2252
2253        mutex_lock(&chip->reg_lock);
2254        if (mv88e6xxx_serdes_power(chip, port, false))
2255                dev_err(chip->dev, "failed to power off SERDES\n");
2256        mutex_unlock(&chip->reg_lock);
2257}
2258
2259static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds,
2260                                     unsigned int ageing_time)
2261{
2262        struct mv88e6xxx_chip *chip = ds->priv;
2263        int err;
2264
2265        mutex_lock(&chip->reg_lock);
2266        err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time);
2267        mutex_unlock(&chip->reg_lock);
2268
2269        return err;
2270}
2271
2272static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
2273{
2274        int err;
2275
2276        /* Initialize the statistics unit */
2277        if (chip->info->ops->stats_set_histogram) {
2278                err = chip->info->ops->stats_set_histogram(chip);
2279                if (err)
2280                        return err;
2281        }
2282
2283        return mv88e6xxx_g1_stats_clear(chip);
2284}
2285
2286static int mv88e6xxx_setup(struct dsa_switch *ds)
2287{
2288        struct mv88e6xxx_chip *chip = ds->priv;
2289        int err;
2290        int i;
2291
2292        chip->ds = ds;
2293        ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
2294
2295        mutex_lock(&chip->reg_lock);
2296
2297        /* Setup Switch Port Registers */
2298        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
2299                if (dsa_is_unused_port(ds, i))
2300                        continue;
2301
2302                err = mv88e6xxx_setup_port(chip, i);
2303                if (err)
2304                        goto unlock;
2305        }
2306
2307        err = mv88e6xxx_irl_setup(chip);
2308        if (err)
2309                goto unlock;
2310
2311        err = mv88e6xxx_mac_setup(chip);
2312        if (err)
2313                goto unlock;
2314
2315        err = mv88e6xxx_phy_setup(chip);
2316        if (err)
2317                goto unlock;
2318
2319        err = mv88e6xxx_vtu_setup(chip);
2320        if (err)
2321                goto unlock;
2322
2323        err = mv88e6xxx_pvt_setup(chip);
2324        if (err)
2325                goto unlock;
2326
2327        err = mv88e6xxx_atu_setup(chip);
2328        if (err)
2329                goto unlock;
2330
2331        err = mv88e6xxx_broadcast_setup(chip, 0);
2332        if (err)
2333                goto unlock;
2334
2335        err = mv88e6xxx_pot_setup(chip);
2336        if (err)
2337                goto unlock;
2338
2339        err = mv88e6xxx_rmu_setup(chip);
2340        if (err)
2341                goto unlock;
2342
2343        err = mv88e6xxx_rsvd2cpu_setup(chip);
2344        if (err)
2345                goto unlock;
2346
2347        err = mv88e6xxx_trunk_setup(chip);
2348        if (err)
2349                goto unlock;
2350
2351        err = mv88e6xxx_devmap_setup(chip);
2352        if (err)
2353                goto unlock;
2354
2355        err = mv88e6xxx_pri_setup(chip);
2356        if (err)
2357                goto unlock;
2358
2359        /* Setup PTP Hardware Clock and timestamping */
2360        if (chip->info->ptp_support) {
2361                err = mv88e6xxx_ptp_setup(chip);
2362                if (err)
2363                        goto unlock;
2364
2365                err = mv88e6xxx_hwtstamp_setup(chip);
2366                if (err)
2367                        goto unlock;
2368        }
2369
2370        err = mv88e6xxx_stats_setup(chip);
2371        if (err)
2372                goto unlock;
2373
2374unlock:
2375        mutex_unlock(&chip->reg_lock);
2376
2377        return err;
2378}
2379
2380static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
2381{
2382        struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
2383        struct mv88e6xxx_chip *chip = mdio_bus->chip;
2384        u16 val;
2385        int err;
2386
2387        if (!chip->info->ops->phy_read)
2388                return -EOPNOTSUPP;
2389
2390        mutex_lock(&chip->reg_lock);
2391        err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
2392        mutex_unlock(&chip->reg_lock);
2393
2394        if (reg == MII_PHYSID2) {
2395                /* Some internal PHYS don't have a model number.  Use
2396                 * the mv88e6390 family model number instead.
2397                 */
2398                if (!(val & 0x3f0))
2399                        val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
2400        }
2401
2402        return err ? err : val;
2403}
2404
2405static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
2406{
2407        struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
2408        struct mv88e6xxx_chip *chip = mdio_bus->chip;
2409        int err;
2410
2411        if (!chip->info->ops->phy_write)
2412                return -EOPNOTSUPP;
2413
2414        mutex_lock(&chip->reg_lock);
2415        err = chip->info->ops->phy_write(chip, bus, phy, reg, val);
2416        mutex_unlock(&chip->reg_lock);
2417
2418        return err;
2419}
2420
2421static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
2422                                   struct device_node *np,
2423                                   bool external)
2424{
2425        static int index;
2426        struct mv88e6xxx_mdio_bus *mdio_bus;
2427        struct mii_bus *bus;
2428        int err;
2429
2430        if (external) {
2431                mutex_lock(&chip->reg_lock);
2432                err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true);
2433                mutex_unlock(&chip->reg_lock);
2434
2435                if (err)
2436                        return err;
2437        }
2438
2439        bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus));
2440        if (!bus)
2441                return -ENOMEM;
2442
2443        mdio_bus = bus->priv;
2444        mdio_bus->bus = bus;
2445        mdio_bus->chip = chip;
2446        INIT_LIST_HEAD(&mdio_bus->list);
2447        mdio_bus->external = external;
2448
2449        if (np) {
2450                bus->name = np->full_name;
2451                snprintf(bus->id, MII_BUS_ID_SIZE, "%pOF", np);
2452        } else {
2453                bus->name = "mv88e6xxx SMI";
2454                snprintf(bus->id, MII_BUS_ID_SIZE, "mv88e6xxx-%d", index++);
2455        }
2456
2457        bus->read = mv88e6xxx_mdio_read;
2458        bus->write = mv88e6xxx_mdio_write;
2459        bus->parent = chip->dev;
2460
2461        if (!external) {
2462                err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
2463                if (err)
2464                        return err;
2465        }
2466
2467        err = of_mdiobus_register(bus, np);
2468        if (err) {
2469                dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
2470                mv88e6xxx_g2_irq_mdio_free(chip, bus);
2471                return err;
2472        }
2473
2474        if (external)
2475                list_add_tail(&mdio_bus->list, &chip->mdios);
2476        else
2477                list_add(&mdio_bus->list, &chip->mdios);
2478
2479        return 0;
2480}
2481
2482static const struct of_device_id mv88e6xxx_mdio_external_match[] = {
2483        { .compatible = "marvell,mv88e6xxx-mdio-external",
2484          .data = (void *)true },
2485        { },
2486};
2487
2488static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)
2489
2490{
2491        struct mv88e6xxx_mdio_bus *mdio_bus;
2492        struct mii_bus *bus;
2493
2494        list_for_each_entry(mdio_bus, &chip->mdios, list) {
2495                bus = mdio_bus->bus;
2496
2497                if (!mdio_bus->external)
2498                        mv88e6xxx_g2_irq_mdio_free(chip, bus);
2499
2500                mdiobus_unregister(bus);
2501        }
2502}
2503
2504static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
2505                                    struct device_node *np)
2506{
2507        const struct of_device_id *match;
2508        struct device_node *child;
2509        int err;
2510
2511        /* Always register one mdio bus for the internal/default mdio
2512         * bus. This maybe represented in the device tree, but is
2513         * optional.
2514         */
2515        child = of_get_child_by_name(np, "mdio");
2516        err = mv88e6xxx_mdio_register(chip, child, false);
2517        if (err)
2518                return err;
2519
2520        /* Walk the device tree, and see if there are any other nodes
2521         * which say they are compatible with the external mdio
2522         * bus.
2523         */
2524        for_each_available_child_of_node(np, child) {
2525                match = of_match_node(mv88e6xxx_mdio_external_match, child);
2526                if (match) {
2527                        err = mv88e6xxx_mdio_register(chip, child, true);
2528                        if (err) {
2529                                mv88e6xxx_mdios_unregister(chip);
2530                                return err;
2531                        }
2532                }
2533        }
2534
2535        return 0;
2536}
2537
2538static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
2539{
2540        struct mv88e6xxx_chip *chip = ds->priv;
2541
2542        return chip->eeprom_len;
2543}
2544
2545static int mv88e6xxx_get_eeprom(struct dsa_switch *ds,
2546                                struct ethtool_eeprom *eeprom, u8 *data)
2547{
2548        struct mv88e6xxx_chip *chip = ds->priv;
2549        int err;
2550
2551        if (!chip->info->ops->get_eeprom)
2552                return -EOPNOTSUPP;
2553
2554        mutex_lock(&chip->reg_lock);
2555        err = chip->info->ops->get_eeprom(chip, eeprom, data);
2556        mutex_unlock(&chip->reg_lock);
2557
2558        if (err)
2559                return err;
2560
2561        eeprom->magic = 0xc3ec4951;
2562
2563        return 0;
2564}
2565
2566static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
2567                                struct ethtool_eeprom *eeprom, u8 *data)
2568{
2569        struct mv88e6xxx_chip *chip = ds->priv;
2570        int err;
2571
2572        if (!chip->info->ops->set_eeprom)
2573                return -EOPNOTSUPP;
2574
2575        if (eeprom->magic != 0xc3ec4951)
2576                return -EINVAL;
2577
2578        mutex_lock(&chip->reg_lock);
2579        err = chip->info->ops->set_eeprom(chip, eeprom, data);
2580        mutex_unlock(&chip->reg_lock);
2581
2582        return err;
2583}
2584
2585static const struct mv88e6xxx_ops mv88e6085_ops = {
2586        /* MV88E6XXX_FAMILY_6097 */
2587        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2588        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2589        .irl_init_all = mv88e6352_g2_irl_init_all,
2590        .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2591        .phy_read = mv88e6185_phy_ppu_read,
2592        .phy_write = mv88e6185_phy_ppu_write,
2593        .port_set_link = mv88e6xxx_port_set_link,
2594        .port_set_duplex = mv88e6xxx_port_set_duplex,
2595        .port_set_speed = mv88e6185_port_set_speed,
2596        .port_tag_remap = mv88e6095_port_tag_remap,
2597        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2598        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2599        .port_set_ether_type = mv88e6351_port_set_ether_type,
2600        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2601        .port_pause_limit = mv88e6097_port_pause_limit,
2602        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2603        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2604        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2605        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2606        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2607        .stats_get_strings = mv88e6095_stats_get_strings,
2608        .stats_get_stats = mv88e6095_stats_get_stats,
2609        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2610        .set_egress_port = mv88e6095_g1_set_egress_port,
2611        .watchdog_ops = &mv88e6097_watchdog_ops,
2612        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2613        .pot_clear = mv88e6xxx_g2_pot_clear,
2614        .ppu_enable = mv88e6185_g1_ppu_enable,
2615        .ppu_disable = mv88e6185_g1_ppu_disable,
2616        .reset = mv88e6185_g1_reset,
2617        .rmu_disable = mv88e6085_g1_rmu_disable,
2618        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2619        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2620};
2621
2622static const struct mv88e6xxx_ops mv88e6095_ops = {
2623        /* MV88E6XXX_FAMILY_6095 */
2624        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2625        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2626        .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2627        .phy_read = mv88e6185_phy_ppu_read,
2628        .phy_write = mv88e6185_phy_ppu_write,
2629        .port_set_link = mv88e6xxx_port_set_link,
2630        .port_set_duplex = mv88e6xxx_port_set_duplex,
2631        .port_set_speed = mv88e6185_port_set_speed,
2632        .port_set_frame_mode = mv88e6085_port_set_frame_mode,
2633        .port_set_egress_floods = mv88e6185_port_set_egress_floods,
2634        .port_set_upstream_port = mv88e6095_port_set_upstream_port,
2635        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2636        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2637        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2638        .stats_get_strings = mv88e6095_stats_get_strings,
2639        .stats_get_stats = mv88e6095_stats_get_stats,
2640        .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
2641        .ppu_enable = mv88e6185_g1_ppu_enable,
2642        .ppu_disable = mv88e6185_g1_ppu_disable,
2643        .reset = mv88e6185_g1_reset,
2644        .vtu_getnext = mv88e6185_g1_vtu_getnext,
2645        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
2646};
2647
2648static const struct mv88e6xxx_ops mv88e6097_ops = {
2649        /* MV88E6XXX_FAMILY_6097 */
2650        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2651        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2652        .irl_init_all = mv88e6352_g2_irl_init_all,
2653        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2654        .phy_read = mv88e6xxx_g2_smi_phy_read,
2655        .phy_write = mv88e6xxx_g2_smi_phy_write,
2656        .port_set_link = mv88e6xxx_port_set_link,
2657        .port_set_duplex = mv88e6xxx_port_set_duplex,
2658        .port_set_speed = mv88e6185_port_set_speed,
2659        .port_tag_remap = mv88e6095_port_tag_remap,
2660        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2661        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2662        .port_set_ether_type = mv88e6351_port_set_ether_type,
2663        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2664        .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
2665        .port_pause_limit = mv88e6097_port_pause_limit,
2666        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2667        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2668        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2669        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2670        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2671        .stats_get_strings = mv88e6095_stats_get_strings,
2672        .stats_get_stats = mv88e6095_stats_get_stats,
2673        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2674        .set_egress_port = mv88e6095_g1_set_egress_port,
2675        .watchdog_ops = &mv88e6097_watchdog_ops,
2676        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2677        .pot_clear = mv88e6xxx_g2_pot_clear,
2678        .reset = mv88e6352_g1_reset,
2679        .rmu_disable = mv88e6085_g1_rmu_disable,
2680        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2681        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2682};
2683
2684static const struct mv88e6xxx_ops mv88e6123_ops = {
2685        /* MV88E6XXX_FAMILY_6165 */
2686        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2687        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2688        .irl_init_all = mv88e6352_g2_irl_init_all,
2689        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2690        .phy_read = mv88e6xxx_g2_smi_phy_read,
2691        .phy_write = mv88e6xxx_g2_smi_phy_write,
2692        .port_set_link = mv88e6xxx_port_set_link,
2693        .port_set_duplex = mv88e6xxx_port_set_duplex,
2694        .port_set_speed = mv88e6185_port_set_speed,
2695        .port_set_frame_mode = mv88e6085_port_set_frame_mode,
2696        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2697        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2698        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2699        .stats_snapshot = mv88e6320_g1_stats_snapshot,
2700        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2701        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2702        .stats_get_strings = mv88e6095_stats_get_strings,
2703        .stats_get_stats = mv88e6095_stats_get_stats,
2704        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2705        .set_egress_port = mv88e6095_g1_set_egress_port,
2706        .watchdog_ops = &mv88e6097_watchdog_ops,
2707        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2708        .pot_clear = mv88e6xxx_g2_pot_clear,
2709        .reset = mv88e6352_g1_reset,
2710        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2711        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2712};
2713
2714static const struct mv88e6xxx_ops mv88e6131_ops = {
2715        /* MV88E6XXX_FAMILY_6185 */
2716        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2717        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2718        .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
2719        .phy_read = mv88e6185_phy_ppu_read,
2720        .phy_write = mv88e6185_phy_ppu_write,
2721        .port_set_link = mv88e6xxx_port_set_link,
2722        .port_set_duplex = mv88e6xxx_port_set_duplex,
2723        .port_set_speed = mv88e6185_port_set_speed,
2724        .port_tag_remap = mv88e6095_port_tag_remap,
2725        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2726        .port_set_egress_floods = mv88e6185_port_set_egress_floods,
2727        .port_set_ether_type = mv88e6351_port_set_ether_type,
2728        .port_set_upstream_port = mv88e6095_port_set_upstream_port,
2729        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2730        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2731        .port_pause_limit = mv88e6097_port_pause_limit,
2732        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2733        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2734        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2735        .stats_get_strings = mv88e6095_stats_get_strings,
2736        .stats_get_stats = mv88e6095_stats_get_stats,
2737        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2738        .set_egress_port = mv88e6095_g1_set_egress_port,
2739        .watchdog_ops = &mv88e6097_watchdog_ops,
2740        .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
2741        .ppu_enable = mv88e6185_g1_ppu_enable,
2742        .set_cascade_port = mv88e6185_g1_set_cascade_port,
2743        .ppu_disable = mv88e6185_g1_ppu_disable,
2744        .reset = mv88e6185_g1_reset,
2745        .vtu_getnext = mv88e6185_g1_vtu_getnext,
2746        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
2747};
2748
2749static const struct mv88e6xxx_ops mv88e6141_ops = {
2750        /* MV88E6XXX_FAMILY_6341 */
2751        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2752        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2753        .irl_init_all = mv88e6352_g2_irl_init_all,
2754        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
2755        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
2756        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2757        .phy_read = mv88e6xxx_g2_smi_phy_read,
2758        .phy_write = mv88e6xxx_g2_smi_phy_write,
2759        .port_set_link = mv88e6xxx_port_set_link,
2760        .port_set_duplex = mv88e6xxx_port_set_duplex,
2761        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
2762        .port_set_speed = mv88e6390_port_set_speed,
2763        .port_tag_remap = mv88e6095_port_tag_remap,
2764        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2765        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2766        .port_set_ether_type = mv88e6351_port_set_ether_type,
2767        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2768        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2769        .port_pause_limit = mv88e6097_port_pause_limit,
2770        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2771        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2772        .stats_snapshot = mv88e6390_g1_stats_snapshot,
2773        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2774        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
2775        .stats_get_strings = mv88e6320_stats_get_strings,
2776        .stats_get_stats = mv88e6390_stats_get_stats,
2777        .set_cpu_port = mv88e6390_g1_set_cpu_port,
2778        .set_egress_port = mv88e6390_g1_set_egress_port,
2779        .watchdog_ops = &mv88e6390_watchdog_ops,
2780        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
2781        .pot_clear = mv88e6xxx_g2_pot_clear,
2782        .reset = mv88e6352_g1_reset,
2783        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2784        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2785        .serdes_power = mv88e6341_serdes_power,
2786        .gpio_ops = &mv88e6352_gpio_ops,
2787};
2788
2789static const struct mv88e6xxx_ops mv88e6161_ops = {
2790        /* MV88E6XXX_FAMILY_6165 */
2791        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2792        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2793        .irl_init_all = mv88e6352_g2_irl_init_all,
2794        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2795        .phy_read = mv88e6xxx_g2_smi_phy_read,
2796        .phy_write = mv88e6xxx_g2_smi_phy_write,
2797        .port_set_link = mv88e6xxx_port_set_link,
2798        .port_set_duplex = mv88e6xxx_port_set_duplex,
2799        .port_set_speed = mv88e6185_port_set_speed,
2800        .port_tag_remap = mv88e6095_port_tag_remap,
2801        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2802        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2803        .port_set_ether_type = mv88e6351_port_set_ether_type,
2804        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2805        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2806        .port_pause_limit = mv88e6097_port_pause_limit,
2807        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2808        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2809        .stats_snapshot = mv88e6320_g1_stats_snapshot,
2810        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2811        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2812        .stats_get_strings = mv88e6095_stats_get_strings,
2813        .stats_get_stats = mv88e6095_stats_get_stats,
2814        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2815        .set_egress_port = mv88e6095_g1_set_egress_port,
2816        .watchdog_ops = &mv88e6097_watchdog_ops,
2817        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2818        .pot_clear = mv88e6xxx_g2_pot_clear,
2819        .reset = mv88e6352_g1_reset,
2820        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2821        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2822};
2823
2824static const struct mv88e6xxx_ops mv88e6165_ops = {
2825        /* MV88E6XXX_FAMILY_6165 */
2826        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2827        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2828        .irl_init_all = mv88e6352_g2_irl_init_all,
2829        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2830        .phy_read = mv88e6165_phy_read,
2831        .phy_write = mv88e6165_phy_write,
2832        .port_set_link = mv88e6xxx_port_set_link,
2833        .port_set_duplex = mv88e6xxx_port_set_duplex,
2834        .port_set_speed = mv88e6185_port_set_speed,
2835        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2836        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2837        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2838        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2839        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2840        .stats_get_strings = mv88e6095_stats_get_strings,
2841        .stats_get_stats = mv88e6095_stats_get_stats,
2842        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2843        .set_egress_port = mv88e6095_g1_set_egress_port,
2844        .watchdog_ops = &mv88e6097_watchdog_ops,
2845        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2846        .pot_clear = mv88e6xxx_g2_pot_clear,
2847        .reset = mv88e6352_g1_reset,
2848        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2849        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2850};
2851
2852static const struct mv88e6xxx_ops mv88e6171_ops = {
2853        /* MV88E6XXX_FAMILY_6351 */
2854        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2855        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2856        .irl_init_all = mv88e6352_g2_irl_init_all,
2857        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2858        .phy_read = mv88e6xxx_g2_smi_phy_read,
2859        .phy_write = mv88e6xxx_g2_smi_phy_write,
2860        .port_set_link = mv88e6xxx_port_set_link,
2861        .port_set_duplex = mv88e6xxx_port_set_duplex,
2862        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
2863        .port_set_speed = mv88e6185_port_set_speed,
2864        .port_tag_remap = mv88e6095_port_tag_remap,
2865        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2866        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2867        .port_set_ether_type = mv88e6351_port_set_ether_type,
2868        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2869        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2870        .port_pause_limit = mv88e6097_port_pause_limit,
2871        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2872        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2873        .stats_snapshot = mv88e6320_g1_stats_snapshot,
2874        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2875        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2876        .stats_get_strings = mv88e6095_stats_get_strings,
2877        .stats_get_stats = mv88e6095_stats_get_stats,
2878        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2879        .set_egress_port = mv88e6095_g1_set_egress_port,
2880        .watchdog_ops = &mv88e6097_watchdog_ops,
2881        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2882        .pot_clear = mv88e6xxx_g2_pot_clear,
2883        .reset = mv88e6352_g1_reset,
2884        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2885        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2886};
2887
2888static const struct mv88e6xxx_ops mv88e6172_ops = {
2889        /* MV88E6XXX_FAMILY_6352 */
2890        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2891        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2892        .irl_init_all = mv88e6352_g2_irl_init_all,
2893        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
2894        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
2895        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2896        .phy_read = mv88e6xxx_g2_smi_phy_read,
2897        .phy_write = mv88e6xxx_g2_smi_phy_write,
2898        .port_set_link = mv88e6xxx_port_set_link,
2899        .port_set_duplex = mv88e6xxx_port_set_duplex,
2900        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
2901        .port_set_speed = mv88e6352_port_set_speed,
2902        .port_tag_remap = mv88e6095_port_tag_remap,
2903        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2904        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2905        .port_set_ether_type = mv88e6351_port_set_ether_type,
2906        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2907        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2908        .port_pause_limit = mv88e6097_port_pause_limit,
2909        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2910        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2911        .stats_snapshot = mv88e6320_g1_stats_snapshot,
2912        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2913        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2914        .stats_get_strings = mv88e6095_stats_get_strings,
2915        .stats_get_stats = mv88e6095_stats_get_stats,
2916        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2917        .set_egress_port = mv88e6095_g1_set_egress_port,
2918        .watchdog_ops = &mv88e6097_watchdog_ops,
2919        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2920        .pot_clear = mv88e6xxx_g2_pot_clear,
2921        .reset = mv88e6352_g1_reset,
2922        .rmu_disable = mv88e6352_g1_rmu_disable,
2923        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2924        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2925        .serdes_power = mv88e6352_serdes_power,
2926        .gpio_ops = &mv88e6352_gpio_ops,
2927};
2928
2929static const struct mv88e6xxx_ops mv88e6175_ops = {
2930        /* MV88E6XXX_FAMILY_6351 */
2931        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2932        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2933        .irl_init_all = mv88e6352_g2_irl_init_all,
2934        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2935        .phy_read = mv88e6xxx_g2_smi_phy_read,
2936        .phy_write = mv88e6xxx_g2_smi_phy_write,
2937        .port_set_link = mv88e6xxx_port_set_link,
2938        .port_set_duplex = mv88e6xxx_port_set_duplex,
2939        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
2940        .port_set_speed = mv88e6185_port_set_speed,
2941        .port_tag_remap = mv88e6095_port_tag_remap,
2942        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2943        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2944        .port_set_ether_type = mv88e6351_port_set_ether_type,
2945        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2946        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2947        .port_pause_limit = mv88e6097_port_pause_limit,
2948        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2949        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2950        .stats_snapshot = mv88e6320_g1_stats_snapshot,
2951        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2952        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2953        .stats_get_strings = mv88e6095_stats_get_strings,
2954        .stats_get_stats = mv88e6095_stats_get_stats,
2955        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2956        .set_egress_port = mv88e6095_g1_set_egress_port,
2957        .watchdog_ops = &mv88e6097_watchdog_ops,
2958        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2959        .pot_clear = mv88e6xxx_g2_pot_clear,
2960        .reset = mv88e6352_g1_reset,
2961        .vtu_getnext = mv88e6352_g1_vtu_getnext,
2962        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2963};
2964
2965static const struct mv88e6xxx_ops mv88e6176_ops = {
2966        /* MV88E6XXX_FAMILY_6352 */
2967        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
2968        .ip_pri_map = mv88e6085_g1_ip_pri_map,
2969        .irl_init_all = mv88e6352_g2_irl_init_all,
2970        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
2971        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
2972        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
2973        .phy_read = mv88e6xxx_g2_smi_phy_read,
2974        .phy_write = mv88e6xxx_g2_smi_phy_write,
2975        .port_set_link = mv88e6xxx_port_set_link,
2976        .port_set_duplex = mv88e6xxx_port_set_duplex,
2977        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
2978        .port_set_speed = mv88e6352_port_set_speed,
2979        .port_tag_remap = mv88e6095_port_tag_remap,
2980        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
2981        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
2982        .port_set_ether_type = mv88e6351_port_set_ether_type,
2983        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2984        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2985        .port_pause_limit = mv88e6097_port_pause_limit,
2986        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
2987        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
2988        .stats_snapshot = mv88e6320_g1_stats_snapshot,
2989        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2990        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
2991        .stats_get_strings = mv88e6095_stats_get_strings,
2992        .stats_get_stats = mv88e6095_stats_get_stats,
2993        .set_cpu_port = mv88e6095_g1_set_cpu_port,
2994        .set_egress_port = mv88e6095_g1_set_egress_port,
2995        .watchdog_ops = &mv88e6097_watchdog_ops,
2996        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
2997        .pot_clear = mv88e6xxx_g2_pot_clear,
2998        .reset = mv88e6352_g1_reset,
2999        .rmu_disable = mv88e6352_g1_rmu_disable,
3000        .vtu_getnext = mv88e6352_g1_vtu_getnext,
3001        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3002        .serdes_power = mv88e6352_serdes_power,
3003        .gpio_ops = &mv88e6352_gpio_ops,
3004};
3005
3006static const struct mv88e6xxx_ops mv88e6185_ops = {
3007        /* MV88E6XXX_FAMILY_6185 */
3008        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3009        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3010        .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3011        .phy_read = mv88e6185_phy_ppu_read,
3012        .phy_write = mv88e6185_phy_ppu_write,
3013        .port_set_link = mv88e6xxx_port_set_link,
3014        .port_set_duplex = mv88e6xxx_port_set_duplex,
3015        .port_set_speed = mv88e6185_port_set_speed,
3016        .port_set_frame_mode = mv88e6085_port_set_frame_mode,
3017        .port_set_egress_floods = mv88e6185_port_set_egress_floods,
3018        .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
3019        .port_set_upstream_port = mv88e6095_port_set_upstream_port,
3020        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3021        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3022        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3023        .stats_get_strings = mv88e6095_stats_get_strings,
3024        .stats_get_stats = mv88e6095_stats_get_stats,
3025        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3026        .set_egress_port = mv88e6095_g1_set_egress_port,
3027        .watchdog_ops = &mv88e6097_watchdog_ops,
3028        .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
3029        .set_cascade_port = mv88e6185_g1_set_cascade_port,
3030        .ppu_enable = mv88e6185_g1_ppu_enable,
3031        .ppu_disable = mv88e6185_g1_ppu_disable,
3032        .reset = mv88e6185_g1_reset,
3033        .vtu_getnext = mv88e6185_g1_vtu_getnext,
3034        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3035};
3036
3037static const struct mv88e6xxx_ops mv88e6190_ops = {
3038        /* MV88E6XXX_FAMILY_6390 */
3039        .irl_init_all = mv88e6390_g2_irl_init_all,
3040        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3041        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3042        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3043        .phy_read = mv88e6xxx_g2_smi_phy_read,
3044        .phy_write = mv88e6xxx_g2_smi_phy_write,
3045        .port_set_link = mv88e6xxx_port_set_link,
3046        .port_set_duplex = mv88e6xxx_port_set_duplex,
3047        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3048        .port_set_speed = mv88e6390_port_set_speed,
3049        .port_tag_remap = mv88e6390_port_tag_remap,
3050        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3051        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3052        .port_set_ether_type = mv88e6351_port_set_ether_type,
3053        .port_pause_limit = mv88e6390_port_pause_limit,
3054        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3055        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3056        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3057        .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3058        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3059        .stats_get_strings = mv88e6320_stats_get_strings,
3060        .stats_get_stats = mv88e6390_stats_get_stats,
3061        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3062        .set_egress_port = mv88e6390_g1_set_egress_port,
3063        .watchdog_ops = &mv88e6390_watchdog_ops,
3064        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3065        .pot_clear = mv88e6xxx_g2_pot_clear,
3066        .reset = mv88e6352_g1_reset,
3067        .rmu_disable = mv88e6390_g1_rmu_disable,
3068        .vtu_getnext = mv88e6390_g1_vtu_getnext,
3069        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3070        .serdes_power = mv88e6390_serdes_power,
3071        .gpio_ops = &mv88e6352_gpio_ops,
3072};
3073
3074static const struct mv88e6xxx_ops mv88e6190x_ops = {
3075        /* MV88E6XXX_FAMILY_6390 */
3076        .irl_init_all = mv88e6390_g2_irl_init_all,
3077        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3078        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3079        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3080        .phy_read = mv88e6xxx_g2_smi_phy_read,
3081        .phy_write = mv88e6xxx_g2_smi_phy_write,
3082        .port_set_link = mv88e6xxx_port_set_link,
3083        .port_set_duplex = mv88e6xxx_port_set_duplex,
3084        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3085        .port_set_speed = mv88e6390x_port_set_speed,
3086        .port_tag_remap = mv88e6390_port_tag_remap,
3087        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3088        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3089        .port_set_ether_type = mv88e6351_port_set_ether_type,
3090        .port_pause_limit = mv88e6390_port_pause_limit,
3091        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3092        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3093        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3094        .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3095        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3096        .stats_get_strings = mv88e6320_stats_get_strings,
3097        .stats_get_stats = mv88e6390_stats_get_stats,
3098        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3099        .set_egress_port = mv88e6390_g1_set_egress_port,
3100        .watchdog_ops = &mv88e6390_watchdog_ops,
3101        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3102        .pot_clear = mv88e6xxx_g2_pot_clear,
3103        .reset = mv88e6352_g1_reset,
3104        .rmu_disable = mv88e6390_g1_rmu_disable,
3105        .vtu_getnext = mv88e6390_g1_vtu_getnext,
3106        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3107        .serdes_power = mv88e6390_serdes_power,
3108        .gpio_ops = &mv88e6352_gpio_ops,
3109};
3110
3111static const struct mv88e6xxx_ops mv88e6191_ops = {
3112        /* MV88E6XXX_FAMILY_6390 */
3113        .irl_init_all = mv88e6390_g2_irl_init_all,
3114        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3115        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3116        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3117        .phy_read = mv88e6xxx_g2_smi_phy_read,
3118        .phy_write = mv88e6xxx_g2_smi_phy_write,
3119        .port_set_link = mv88e6xxx_port_set_link,
3120        .port_set_duplex = mv88e6xxx_port_set_duplex,
3121        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3122        .port_set_speed = mv88e6390_port_set_speed,
3123        .port_tag_remap = mv88e6390_port_tag_remap,
3124        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3125        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3126        .port_set_ether_type = mv88e6351_port_set_ether_type,
3127        .port_pause_limit = mv88e6390_port_pause_limit,
3128        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3129        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3130        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3131        .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3132        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3133        .stats_get_strings = mv88e6320_stats_get_strings,
3134        .stats_get_stats = mv88e6390_stats_get_stats,
3135        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3136        .set_egress_port = mv88e6390_g1_set_egress_port,
3137        .watchdog_ops = &mv88e6390_watchdog_ops,
3138        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3139        .pot_clear = mv88e6xxx_g2_pot_clear,
3140        .reset = mv88e6352_g1_reset,
3141        .rmu_disable = mv88e6390_g1_rmu_disable,
3142        .vtu_getnext = mv88e6390_g1_vtu_getnext,
3143        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3144        .serdes_power = mv88e6390_serdes_power,
3145};
3146
3147static const struct mv88e6xxx_ops mv88e6240_ops = {
3148        /* MV88E6XXX_FAMILY_6352 */
3149        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3150        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3151        .irl_init_all = mv88e6352_g2_irl_init_all,
3152        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3153        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3154        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3155        .phy_read = mv88e6xxx_g2_smi_phy_read,
3156        .phy_write = mv88e6xxx_g2_smi_phy_write,
3157        .port_set_link = mv88e6xxx_port_set_link,
3158        .port_set_duplex = mv88e6xxx_port_set_duplex,
3159        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3160        .port_set_speed = mv88e6352_port_set_speed,
3161        .port_tag_remap = mv88e6095_port_tag_remap,
3162        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3163        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3164        .port_set_ether_type = mv88e6351_port_set_ether_type,
3165        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3166        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3167        .port_pause_limit = mv88e6097_port_pause_limit,
3168        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3169        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3170        .stats_snapshot = mv88e6320_g1_stats_snapshot,
3171        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3172        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3173        .stats_get_strings = mv88e6095_stats_get_strings,
3174        .stats_get_stats = mv88e6095_stats_get_stats,
3175        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3176        .set_egress_port = mv88e6095_g1_set_egress_port,
3177        .watchdog_ops = &mv88e6097_watchdog_ops,
3178        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3179        .pot_clear = mv88e6xxx_g2_pot_clear,
3180        .reset = mv88e6352_g1_reset,
3181        .rmu_disable = mv88e6352_g1_rmu_disable,
3182        .vtu_getnext = mv88e6352_g1_vtu_getnext,
3183        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3184        .serdes_power = mv88e6352_serdes_power,
3185        .gpio_ops = &mv88e6352_gpio_ops,
3186        .avb_ops = &mv88e6352_avb_ops,
3187};
3188
3189static const struct mv88e6xxx_ops mv88e6290_ops = {
3190        /* MV88E6XXX_FAMILY_6390 */
3191        .irl_init_all = mv88e6390_g2_irl_init_all,
3192        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3193        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3194        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3195        .phy_read = mv88e6xxx_g2_smi_phy_read,
3196        .phy_write = mv88e6xxx_g2_smi_phy_write,
3197        .port_set_link = mv88e6xxx_port_set_link,
3198        .port_set_duplex = mv88e6xxx_port_set_duplex,
3199        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3200        .port_set_speed = mv88e6390_port_set_speed,
3201        .port_tag_remap = mv88e6390_port_tag_remap,
3202        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3203        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3204        .port_set_ether_type = mv88e6351_port_set_ether_type,
3205        .port_pause_limit = mv88e6390_port_pause_limit,
3206        .port_set_cmode = mv88e6390x_port_set_cmode,
3207        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3208        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3209        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3210        .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3211        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3212        .stats_get_strings = mv88e6320_stats_get_strings,
3213        .stats_get_stats = mv88e6390_stats_get_stats,
3214        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3215        .set_egress_port = mv88e6390_g1_set_egress_port,
3216        .watchdog_ops = &mv88e6390_watchdog_ops,
3217        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3218        .pot_clear = mv88e6xxx_g2_pot_clear,
3219        .reset = mv88e6352_g1_reset,
3220        .rmu_disable = mv88e6390_g1_rmu_disable,
3221        .vtu_getnext = mv88e6390_g1_vtu_getnext,
3222        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3223        .serdes_power = mv88e6390_serdes_power,
3224        .gpio_ops = &mv88e6352_gpio_ops,
3225        .avb_ops = &mv88e6390_avb_ops,
3226};
3227
3228static const struct mv88e6xxx_ops mv88e6320_ops = {
3229        /* MV88E6XXX_FAMILY_6320 */
3230        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3231        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3232        .irl_init_all = mv88e6352_g2_irl_init_all,
3233        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3234        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3235        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3236        .phy_read = mv88e6xxx_g2_smi_phy_read,
3237        .phy_write = mv88e6xxx_g2_smi_phy_write,
3238        .port_set_link = mv88e6xxx_port_set_link,
3239        .port_set_duplex = mv88e6xxx_port_set_duplex,
3240        .port_set_speed = mv88e6185_port_set_speed,
3241        .port_tag_remap = mv88e6095_port_tag_remap,
3242        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3243        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3244        .port_set_ether_type = mv88e6351_port_set_ether_type,
3245        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3246        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3247        .port_pause_limit = mv88e6097_port_pause_limit,
3248        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3249        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3250        .stats_snapshot = mv88e6320_g1_stats_snapshot,
3251        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3252        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3253        .stats_get_strings = mv88e6320_stats_get_strings,
3254        .stats_get_stats = mv88e6320_stats_get_stats,
3255        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3256        .set_egress_port = mv88e6095_g1_set_egress_port,
3257        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3258        .pot_clear = mv88e6xxx_g2_pot_clear,
3259        .reset = mv88e6352_g1_reset,
3260        .vtu_getnext = mv88e6185_g1_vtu_getnext,
3261        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3262        .gpio_ops = &mv88e6352_gpio_ops,
3263        .avb_ops = &mv88e6352_avb_ops,
3264};
3265
3266static const struct mv88e6xxx_ops mv88e6321_ops = {
3267        /* MV88E6XXX_FAMILY_6320 */
3268        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3269        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3270        .irl_init_all = mv88e6352_g2_irl_init_all,
3271        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3272        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3273        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3274        .phy_read = mv88e6xxx_g2_smi_phy_read,
3275        .phy_write = mv88e6xxx_g2_smi_phy_write,
3276        .port_set_link = mv88e6xxx_port_set_link,
3277        .port_set_duplex = mv88e6xxx_port_set_duplex,
3278        .port_set_speed = mv88e6185_port_set_speed,
3279        .port_tag_remap = mv88e6095_port_tag_remap,
3280        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3281        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3282        .port_set_ether_type = mv88e6351_port_set_ether_type,
3283        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3284        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3285        .port_pause_limit = mv88e6097_port_pause_limit,
3286        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3287        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3288        .stats_snapshot = mv88e6320_g1_stats_snapshot,
3289        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3290        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3291        .stats_get_strings = mv88e6320_stats_get_strings,
3292        .stats_get_stats = mv88e6320_stats_get_stats,
3293        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3294        .set_egress_port = mv88e6095_g1_set_egress_port,
3295        .reset = mv88e6352_g1_reset,
3296        .vtu_getnext = mv88e6185_g1_vtu_getnext,
3297        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
3298        .gpio_ops = &mv88e6352_gpio_ops,
3299        .avb_ops = &mv88e6352_avb_ops,
3300};
3301
3302static const struct mv88e6xxx_ops mv88e6341_ops = {
3303        /* MV88E6XXX_FAMILY_6341 */
3304        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3305        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3306        .irl_init_all = mv88e6352_g2_irl_init_all,
3307        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3308        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3309        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3310        .phy_read = mv88e6xxx_g2_smi_phy_read,
3311        .phy_write = mv88e6xxx_g2_smi_phy_write,
3312        .port_set_link = mv88e6xxx_port_set_link,
3313        .port_set_duplex = mv88e6xxx_port_set_duplex,
3314        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3315        .port_set_speed = mv88e6390_port_set_speed,
3316        .port_tag_remap = mv88e6095_port_tag_remap,
3317        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3318        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3319        .port_set_ether_type = mv88e6351_port_set_ether_type,
3320        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3321        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3322        .port_pause_limit = mv88e6097_port_pause_limit,
3323        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3324        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3325        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3326        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3327        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3328        .stats_get_strings = mv88e6320_stats_get_strings,
3329        .stats_get_stats = mv88e6390_stats_get_stats,
3330        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3331        .set_egress_port = mv88e6390_g1_set_egress_port,
3332        .watchdog_ops = &mv88e6390_watchdog_ops,
3333        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
3334        .pot_clear = mv88e6xxx_g2_pot_clear,
3335        .reset = mv88e6352_g1_reset,
3336        .vtu_getnext = mv88e6352_g1_vtu_getnext,
3337        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3338        .serdes_power = mv88e6341_serdes_power,
3339        .gpio_ops = &mv88e6352_gpio_ops,
3340        .avb_ops = &mv88e6390_avb_ops,
3341};
3342
3343static const struct mv88e6xxx_ops mv88e6350_ops = {
3344        /* MV88E6XXX_FAMILY_6351 */
3345        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3346        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3347        .irl_init_all = mv88e6352_g2_irl_init_all,
3348        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3349        .phy_read = mv88e6xxx_g2_smi_phy_read,
3350        .phy_write = mv88e6xxx_g2_smi_phy_write,
3351        .port_set_link = mv88e6xxx_port_set_link,
3352        .port_set_duplex = mv88e6xxx_port_set_duplex,
3353        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3354        .port_set_speed = mv88e6185_port_set_speed,
3355        .port_tag_remap = mv88e6095_port_tag_remap,
3356        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3357        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3358        .port_set_ether_type = mv88e6351_port_set_ether_type,
3359        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3360        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3361        .port_pause_limit = mv88e6097_port_pause_limit,
3362        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3363        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3364        .stats_snapshot = mv88e6320_g1_stats_snapshot,
3365        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3366        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3367        .stats_get_strings = mv88e6095_stats_get_strings,
3368        .stats_get_stats = mv88e6095_stats_get_stats,
3369        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3370        .set_egress_port = mv88e6095_g1_set_egress_port,
3371        .watchdog_ops = &mv88e6097_watchdog_ops,
3372        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3373        .pot_clear = mv88e6xxx_g2_pot_clear,
3374        .reset = mv88e6352_g1_reset,
3375        .vtu_getnext = mv88e6352_g1_vtu_getnext,
3376        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3377};
3378
3379static const struct mv88e6xxx_ops mv88e6351_ops = {
3380        /* MV88E6XXX_FAMILY_6351 */
3381        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3382        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3383        .irl_init_all = mv88e6352_g2_irl_init_all,
3384        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3385        .phy_read = mv88e6xxx_g2_smi_phy_read,
3386        .phy_write = mv88e6xxx_g2_smi_phy_write,
3387        .port_set_link = mv88e6xxx_port_set_link,
3388        .port_set_duplex = mv88e6xxx_port_set_duplex,
3389        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3390        .port_set_speed = mv88e6185_port_set_speed,
3391        .port_tag_remap = mv88e6095_port_tag_remap,
3392        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3393        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3394        .port_set_ether_type = mv88e6351_port_set_ether_type,
3395        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3396        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3397        .port_pause_limit = mv88e6097_port_pause_limit,
3398        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3399        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3400        .stats_snapshot = mv88e6320_g1_stats_snapshot,
3401        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3402        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3403        .stats_get_strings = mv88e6095_stats_get_strings,
3404        .stats_get_stats = mv88e6095_stats_get_stats,
3405        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3406        .set_egress_port = mv88e6095_g1_set_egress_port,
3407        .watchdog_ops = &mv88e6097_watchdog_ops,
3408        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3409        .pot_clear = mv88e6xxx_g2_pot_clear,
3410        .reset = mv88e6352_g1_reset,
3411        .vtu_getnext = mv88e6352_g1_vtu_getnext,
3412        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3413        .avb_ops = &mv88e6352_avb_ops,
3414};
3415
3416static const struct mv88e6xxx_ops mv88e6352_ops = {
3417        /* MV88E6XXX_FAMILY_6352 */
3418        .ieee_pri_map = mv88e6085_g1_ieee_pri_map,
3419        .ip_pri_map = mv88e6085_g1_ip_pri_map,
3420        .irl_init_all = mv88e6352_g2_irl_init_all,
3421        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3422        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3423        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3424        .phy_read = mv88e6xxx_g2_smi_phy_read,
3425        .phy_write = mv88e6xxx_g2_smi_phy_write,
3426        .port_set_link = mv88e6xxx_port_set_link,
3427        .port_set_duplex = mv88e6xxx_port_set_duplex,
3428        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3429        .port_set_speed = mv88e6352_port_set_speed,
3430        .port_tag_remap = mv88e6095_port_tag_remap,
3431        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3432        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3433        .port_set_ether_type = mv88e6351_port_set_ether_type,
3434        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3435        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3436        .port_pause_limit = mv88e6097_port_pause_limit,
3437        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3438        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3439        .stats_snapshot = mv88e6320_g1_stats_snapshot,
3440        .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3441        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3442        .stats_get_strings = mv88e6095_stats_get_strings,
3443        .stats_get_stats = mv88e6095_stats_get_stats,
3444        .set_cpu_port = mv88e6095_g1_set_cpu_port,
3445        .set_egress_port = mv88e6095_g1_set_egress_port,
3446        .watchdog_ops = &mv88e6097_watchdog_ops,
3447        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3448        .pot_clear = mv88e6xxx_g2_pot_clear,
3449        .reset = mv88e6352_g1_reset,
3450        .rmu_disable = mv88e6352_g1_rmu_disable,
3451        .vtu_getnext = mv88e6352_g1_vtu_getnext,
3452        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3453        .serdes_power = mv88e6352_serdes_power,
3454        .gpio_ops = &mv88e6352_gpio_ops,
3455        .avb_ops = &mv88e6352_avb_ops,
3456        .serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
3457        .serdes_get_strings = mv88e6352_serdes_get_strings,
3458        .serdes_get_stats = mv88e6352_serdes_get_stats,
3459};
3460
3461static const struct mv88e6xxx_ops mv88e6390_ops = {
3462        /* MV88E6XXX_FAMILY_6390 */
3463        .irl_init_all = mv88e6390_g2_irl_init_all,
3464        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3465        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3466        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3467        .phy_read = mv88e6xxx_g2_smi_phy_read,
3468        .phy_write = mv88e6xxx_g2_smi_phy_write,
3469        .port_set_link = mv88e6xxx_port_set_link,
3470        .port_set_duplex = mv88e6xxx_port_set_duplex,
3471        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3472        .port_set_speed = mv88e6390_port_set_speed,
3473        .port_tag_remap = mv88e6390_port_tag_remap,
3474        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3475        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3476        .port_set_ether_type = mv88e6351_port_set_ether_type,
3477        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3478        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3479        .port_pause_limit = mv88e6390_port_pause_limit,
3480        .port_set_cmode = mv88e6390x_port_set_cmode,
3481        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3482        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3483        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3484        .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3485        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3486        .stats_get_strings = mv88e6320_stats_get_strings,
3487        .stats_get_stats = mv88e6390_stats_get_stats,
3488        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3489        .set_egress_port = mv88e6390_g1_set_egress_port,
3490        .watchdog_ops = &mv88e6390_watchdog_ops,
3491        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3492        .pot_clear = mv88e6xxx_g2_pot_clear,
3493        .reset = mv88e6352_g1_reset,
3494        .rmu_disable = mv88e6390_g1_rmu_disable,
3495        .vtu_getnext = mv88e6390_g1_vtu_getnext,
3496        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3497        .serdes_power = mv88e6390_serdes_power,
3498        .gpio_ops = &mv88e6352_gpio_ops,
3499        .avb_ops = &mv88e6390_avb_ops,
3500};
3501
3502static const struct mv88e6xxx_ops mv88e6390x_ops = {
3503        /* MV88E6XXX_FAMILY_6390 */
3504        .irl_init_all = mv88e6390_g2_irl_init_all,
3505        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
3506        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
3507        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3508        .phy_read = mv88e6xxx_g2_smi_phy_read,
3509        .phy_write = mv88e6xxx_g2_smi_phy_write,
3510        .port_set_link = mv88e6xxx_port_set_link,
3511        .port_set_duplex = mv88e6xxx_port_set_duplex,
3512        .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3513        .port_set_speed = mv88e6390x_port_set_speed,
3514        .port_tag_remap = mv88e6390_port_tag_remap,
3515        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3516        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3517        .port_set_ether_type = mv88e6351_port_set_ether_type,
3518        .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
3519        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3520        .port_pause_limit = mv88e6390_port_pause_limit,
3521        .port_set_cmode = mv88e6390x_port_set_cmode,
3522        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
3523        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3524        .stats_snapshot = mv88e6390_g1_stats_snapshot,
3525        .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3526        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3527        .stats_get_strings = mv88e6320_stats_get_strings,
3528        .stats_get_stats = mv88e6390_stats_get_stats,
3529        .set_cpu_port = mv88e6390_g1_set_cpu_port,
3530        .set_egress_port = mv88e6390_g1_set_egress_port,
3531        .watchdog_ops = &mv88e6390_watchdog_ops,
3532        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
3533        .pot_clear = mv88e6xxx_g2_pot_clear,
3534        .reset = mv88e6352_g1_reset,
3535        .rmu_disable = mv88e6390_g1_rmu_disable,
3536        .vtu_getnext = mv88e6390_g1_vtu_getnext,
3537        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
3538        .serdes_power = mv88e6390_serdes_power,
3539        .gpio_ops = &mv88e6352_gpio_ops,
3540        .avb_ops = &mv88e6390_avb_ops,
3541};
3542
3543static const struct mv88e6xxx_info mv88e6xxx_table[] = {
3544        [MV88E6085] = {
3545                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
3546                .family = MV88E6XXX_FAMILY_6097,
3547                .name = "Marvell 88E6085",
3548                .num_databases = 4096,
3549                .num_ports = 10,
3550                .num_internal_phys = 5,
3551                .max_vid = 4095,
3552                .port_base_addr = 0x10,
3553                .phy_base_addr = 0x0,
3554                .global1_addr = 0x1b,
3555                .global2_addr = 0x1c,
3556                .age_time_coeff = 15000,
3557                .g1_irqs = 8,
3558                .g2_irqs = 10,
3559                .atu_move_port_mask = 0xf,
3560                .pvt = true,
3561                .multi_chip = true,
3562                .tag_protocol = DSA_TAG_PROTO_DSA,
3563                .ops = &mv88e6085_ops,
3564        },
3565
3566        [MV88E6095] = {
3567                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095,
3568                .family = MV88E6XXX_FAMILY_6095,
3569                .name = "Marvell 88E6095/88E6095F",
3570                .num_databases = 256,
3571                .num_ports = 11,
3572                .num_internal_phys = 0,
3573                .max_vid = 4095,
3574                .port_base_addr = 0x10,
3575                .phy_base_addr = 0x0,
3576                .global1_addr = 0x1b,
3577                .global2_addr = 0x1c,
3578                .age_time_coeff = 15000,
3579                .g1_irqs = 8,
3580                .atu_move_port_mask = 0xf,
3581                .multi_chip = true,
3582                .tag_protocol = DSA_TAG_PROTO_DSA,
3583                .ops = &mv88e6095_ops,
3584        },
3585
3586        [MV88E6097] = {
3587                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097,
3588                .family = MV88E6XXX_FAMILY_6097,
3589                .name = "Marvell 88E6097/88E6097F",
3590                .num_databases = 4096,
3591                .num_ports = 11,
3592                .num_internal_phys = 8,
3593                .max_vid = 4095,
3594                .port_base_addr = 0x10,
3595                .phy_base_addr = 0x0,
3596                .global1_addr = 0x1b,
3597                .global2_addr = 0x1c,
3598                .age_time_coeff = 15000,
3599                .g1_irqs = 8,
3600                .g2_irqs = 10,
3601                .atu_move_port_mask = 0xf,
3602                .pvt = true,
3603                .multi_chip = true,
3604                .tag_protocol = DSA_TAG_PROTO_EDSA,
3605                .ops = &mv88e6097_ops,
3606        },
3607
3608        [MV88E6123] = {
3609                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123,
3610                .family = MV88E6XXX_FAMILY_6165,
3611                .name = "Marvell 88E6123",
3612                .num_databases = 4096,
3613                .num_ports = 3,
3614                .num_internal_phys = 5,
3615                .max_vid = 4095,
3616                .port_base_addr = 0x10,
3617                .phy_base_addr = 0x0,
3618                .global1_addr = 0x1b,
3619                .global2_addr = 0x1c,
3620                .age_time_coeff = 15000,
3621                .g1_irqs = 9,
3622                .g2_irqs = 10,
3623                .atu_move_port_mask = 0xf,
3624                .pvt = true,
3625                .multi_chip = true,
3626                .tag_protocol = DSA_TAG_PROTO_EDSA,
3627                .ops = &mv88e6123_ops,
3628        },
3629
3630        [MV88E6131] = {
3631                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131,
3632                .family = MV88E6XXX_FAMILY_6185,
3633                .name = "Marvell 88E6131",
3634                .num_databases = 256,
3635                .num_ports = 8,
3636                .num_internal_phys = 0,
3637                .max_vid = 4095,
3638                .port_base_addr = 0x10,
3639                .phy_base_addr = 0x0,
3640                .global1_addr = 0x1b,
3641                .global2_addr = 0x1c,
3642                .age_time_coeff = 15000,
3643                .g1_irqs = 9,
3644                .atu_move_port_mask = 0xf,
3645                .multi_chip = true,
3646                .tag_protocol = DSA_TAG_PROTO_DSA,
3647                .ops = &mv88e6131_ops,
3648        },
3649
3650        [MV88E6141] = {
3651                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
3652                .family = MV88E6XXX_FAMILY_6341,
3653                .name = "Marvell 88E6141",
3654                .num_databases = 4096,
3655                .num_ports = 6,
3656                .num_internal_phys = 5,
3657                .num_gpio = 11,
3658                .max_vid = 4095,
3659                .port_base_addr = 0x10,
3660                .phy_base_addr = 0x10,
3661                .global1_addr = 0x1b,
3662                .global2_addr = 0x1c,
3663                .age_time_coeff = 3750,
3664                .atu_move_port_mask = 0x1f,
3665                .g1_irqs = 9,
3666                .g2_irqs = 10,
3667                .pvt = true,
3668                .multi_chip = true,
3669                .tag_protocol = DSA_TAG_PROTO_EDSA,
3670                .ops = &mv88e6141_ops,
3671        },
3672
3673        [MV88E6161] = {
3674                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161,
3675                .family = MV88E6XXX_FAMILY_6165,
3676                .name = "Marvell 88E6161",
3677                .num_databases = 4096,
3678                .num_ports = 6,
3679                .num_internal_phys = 5,
3680                .max_vid = 4095,
3681                .port_base_addr = 0x10,
3682                .phy_base_addr = 0x0,
3683                .global1_addr = 0x1b,
3684                .global2_addr = 0x1c,
3685                .age_time_coeff = 15000,
3686                .g1_irqs = 9,
3687                .g2_irqs = 10,
3688                .atu_move_port_mask = 0xf,
3689                .pvt = true,
3690                .multi_chip = true,
3691                .tag_protocol = DSA_TAG_PROTO_EDSA,
3692                .ops = &mv88e6161_ops,
3693        },
3694
3695        [MV88E6165] = {
3696                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165,
3697                .family = MV88E6XXX_FAMILY_6165,
3698                .name = "Marvell 88E6165",
3699                .num_databases = 4096,
3700                .num_ports = 6,
3701                .num_internal_phys = 0,
3702                .max_vid = 4095,
3703                .port_base_addr = 0x10,
3704                .phy_base_addr = 0x0,
3705                .global1_addr = 0x1b,
3706                .global2_addr = 0x1c,
3707                .age_time_coeff = 15000,
3708                .g1_irqs = 9,
3709                .g2_irqs = 10,
3710                .atu_move_port_mask = 0xf,
3711                .pvt = true,
3712                .multi_chip = true,
3713                .tag_protocol = DSA_TAG_PROTO_DSA,
3714                .ops = &mv88e6165_ops,
3715        },
3716
3717        [MV88E6171] = {
3718                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171,
3719                .family = MV88E6XXX_FAMILY_6351,
3720                .name = "Marvell 88E6171",
3721                .num_databases = 4096,
3722                .num_ports = 7,
3723                .num_internal_phys = 5,
3724                .max_vid = 4095,
3725                .port_base_addr = 0x10,
3726                .phy_base_addr = 0x0,
3727                .global1_addr = 0x1b,
3728                .global2_addr = 0x1c,
3729                .age_time_coeff = 15000,
3730                .g1_irqs = 9,
3731                .g2_irqs = 10,
3732                .atu_move_port_mask = 0xf,
3733                .pvt = true,
3734                .multi_chip = true,
3735                .tag_protocol = DSA_TAG_PROTO_EDSA,
3736                .ops = &mv88e6171_ops,
3737        },
3738
3739        [MV88E6172] = {
3740                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172,
3741                .family = MV88E6XXX_FAMILY_6352,
3742                .name = "Marvell 88E6172",
3743                .num_databases = 4096,
3744                .num_ports = 7,
3745                .num_internal_phys = 5,
3746                .num_gpio = 15,
3747                .max_vid = 4095,
3748                .port_base_addr = 0x10,
3749                .phy_base_addr = 0x0,
3750                .global1_addr = 0x1b,
3751                .global2_addr = 0x1c,
3752                .age_time_coeff = 15000,
3753                .g1_irqs = 9,
3754                .g2_irqs = 10,
3755                .atu_move_port_mask = 0xf,
3756                .pvt = true,
3757                .multi_chip = true,
3758                .tag_protocol = DSA_TAG_PROTO_EDSA,
3759                .ops = &mv88e6172_ops,
3760        },
3761
3762        [MV88E6175] = {
3763                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175,
3764                .family = MV88E6XXX_FAMILY_6351,
3765                .name = "Marvell 88E6175",
3766                .num_databases = 4096,
3767                .num_ports = 7,
3768                .num_internal_phys = 5,
3769                .max_vid = 4095,
3770                .port_base_addr = 0x10,
3771                .phy_base_addr = 0x0,
3772                .global1_addr = 0x1b,
3773                .global2_addr = 0x1c,
3774                .age_time_coeff = 15000,
3775                .g1_irqs = 9,
3776                .g2_irqs = 10,
3777                .atu_move_port_mask = 0xf,
3778                .pvt = true,
3779                .multi_chip = true,
3780                .tag_protocol = DSA_TAG_PROTO_EDSA,
3781                .ops = &mv88e6175_ops,
3782        },
3783
3784        [MV88E6176] = {
3785                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176,
3786                .family = MV88E6XXX_FAMILY_6352,
3787                .name = "Marvell 88E6176",
3788                .num_databases = 4096,
3789                .num_ports = 7,
3790                .num_internal_phys = 5,
3791                .num_gpio = 15,
3792                .max_vid = 4095,
3793                .port_base_addr = 0x10,
3794                .phy_base_addr = 0x0,
3795                .global1_addr = 0x1b,
3796                .global2_addr = 0x1c,
3797                .age_time_coeff = 15000,
3798                .g1_irqs = 9,
3799                .g2_irqs = 10,
3800                .atu_move_port_mask = 0xf,
3801                .pvt = true,
3802                .multi_chip = true,
3803                .tag_protocol = DSA_TAG_PROTO_EDSA,
3804                .ops = &mv88e6176_ops,
3805        },
3806
3807        [MV88E6185] = {
3808                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185,
3809                .family = MV88E6XXX_FAMILY_6185,
3810                .name = "Marvell 88E6185",
3811                .num_databases = 256,
3812                .num_ports = 10,
3813                .num_internal_phys = 0,
3814                .max_vid = 4095,
3815                .port_base_addr = 0x10,
3816                .phy_base_addr = 0x0,
3817                .global1_addr = 0x1b,
3818                .global2_addr = 0x1c,
3819                .age_time_coeff = 15000,
3820                .g1_irqs = 8,
3821                .atu_move_port_mask = 0xf,
3822                .multi_chip = true,
3823                .tag_protocol = DSA_TAG_PROTO_EDSA,
3824                .ops = &mv88e6185_ops,
3825        },
3826
3827        [MV88E6190] = {
3828                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190,
3829                .family = MV88E6XXX_FAMILY_6390,
3830                .name = "Marvell 88E6190",
3831                .num_databases = 4096,
3832                .num_ports = 11,        /* 10 + Z80 */
3833                .num_internal_phys = 11,
3834                .num_gpio = 16,
3835                .max_vid = 8191,
3836                .port_base_addr = 0x0,
3837                .phy_base_addr = 0x0,
3838                .global1_addr = 0x1b,
3839                .global2_addr = 0x1c,
3840                .tag_protocol = DSA_TAG_PROTO_DSA,
3841                .age_time_coeff = 3750,
3842                .g1_irqs = 9,
3843                .g2_irqs = 14,
3844                .pvt = true,
3845                .multi_chip = true,
3846                .atu_move_port_mask = 0x1f,
3847                .ops = &mv88e6190_ops,
3848        },
3849
3850        [MV88E6190X] = {
3851                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X,
3852                .family = MV88E6XXX_FAMILY_6390,
3853                .name = "Marvell 88E6190X",
3854                .num_databases = 4096,
3855                .num_ports = 11,        /* 10 + Z80 */
3856                .num_internal_phys = 11,
3857                .num_gpio = 16,
3858                .max_vid = 8191,
3859                .port_base_addr = 0x0,
3860                .phy_base_addr = 0x0,
3861                .global1_addr = 0x1b,
3862                .global2_addr = 0x1c,
3863                .age_time_coeff = 3750,
3864                .g1_irqs = 9,
3865                .g2_irqs = 14,
3866                .atu_move_port_mask = 0x1f,
3867                .pvt = true,
3868                .multi_chip = true,
3869                .tag_protocol = DSA_TAG_PROTO_DSA,
3870                .ops = &mv88e6190x_ops,
3871        },
3872
3873        [MV88E6191] = {
3874                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191,
3875                .family = MV88E6XXX_FAMILY_6390,
3876                .name = "Marvell 88E6191",
3877                .num_databases = 4096,
3878                .num_ports = 11,        /* 10 + Z80 */
3879                .num_internal_phys = 11,
3880                .max_vid = 8191,
3881                .port_base_addr = 0x0,
3882                .phy_base_addr = 0x0,
3883                .global1_addr = 0x1b,
3884                .global2_addr = 0x1c,
3885                .age_time_coeff = 3750,
3886                .g1_irqs = 9,
3887                .g2_irqs = 14,
3888                .atu_move_port_mask = 0x1f,
3889                .pvt = true,
3890                .multi_chip = true,
3891                .tag_protocol = DSA_TAG_PROTO_DSA,
3892                .ptp_support = true,
3893                .ops = &mv88e6191_ops,
3894        },
3895
3896        [MV88E6240] = {
3897                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240,
3898                .family = MV88E6XXX_FAMILY_6352,
3899                .name = "Marvell 88E6240",
3900                .num_databases = 4096,
3901                .num_ports = 7,
3902                .num_internal_phys = 5,
3903                .num_gpio = 15,
3904                .max_vid = 4095,
3905                .port_base_addr = 0x10,
3906                .phy_base_addr = 0x0,
3907                .global1_addr = 0x1b,
3908                .global2_addr = 0x1c,
3909                .age_time_coeff = 15000,
3910                .g1_irqs = 9,
3911                .g2_irqs = 10,
3912                .atu_move_port_mask = 0xf,
3913                .pvt = true,
3914                .multi_chip = true,
3915                .tag_protocol = DSA_TAG_PROTO_EDSA,
3916                .ptp_support = true,
3917                .ops = &mv88e6240_ops,
3918        },
3919
3920        [MV88E6290] = {
3921                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
3922                .family = MV88E6XXX_FAMILY_6390,
3923                .name = "Marvell 88E6290",
3924                .num_databases = 4096,
3925                .num_ports = 11,        /* 10 + Z80 */
3926                .num_internal_phys = 11,
3927                .num_gpio = 16,
3928                .max_vid = 8191,
3929                .port_base_addr = 0x0,
3930                .phy_base_addr = 0x0,
3931                .global1_addr = 0x1b,
3932                .global2_addr = 0x1c,
3933                .age_time_coeff = 3750,
3934                .g1_irqs = 9,
3935                .g2_irqs = 14,
3936                .atu_move_port_mask = 0x1f,
3937                .pvt = true,
3938                .multi_chip = true,
3939                .tag_protocol = DSA_TAG_PROTO_DSA,
3940                .ptp_support = true,
3941                .ops = &mv88e6290_ops,
3942        },
3943
3944        [MV88E6320] = {
3945                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320,
3946                .family = MV88E6XXX_FAMILY_6320,
3947                .name = "Marvell 88E6320",
3948                .num_databases = 4096,
3949                .num_ports = 7,
3950                .num_internal_phys = 5,
3951                .num_gpio = 15,
3952                .max_vid = 4095,
3953                .port_base_addr = 0x10,
3954                .phy_base_addr = 0x0,
3955                .global1_addr = 0x1b,
3956                .global2_addr = 0x1c,
3957                .age_time_coeff = 15000,
3958                .g1_irqs = 8,
3959                .g2_irqs = 10,
3960                .atu_move_port_mask = 0xf,
3961                .pvt = true,
3962                .multi_chip = true,
3963                .tag_protocol = DSA_TAG_PROTO_EDSA,
3964                .ptp_support = true,
3965                .ops = &mv88e6320_ops,
3966        },
3967
3968        [MV88E6321] = {
3969                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321,
3970                .family = MV88E6XXX_FAMILY_6320,
3971                .name = "Marvell 88E6321",
3972                .num_databases = 4096,
3973                .num_ports = 7,
3974                .num_internal_phys = 5,
3975                .num_gpio = 15,
3976                .max_vid = 4095,
3977                .port_base_addr = 0x10,
3978                .phy_base_addr = 0x0,
3979                .global1_addr = 0x1b,
3980                .global2_addr = 0x1c,
3981                .age_time_coeff = 15000,
3982                .g1_irqs = 8,
3983                .g2_irqs = 10,
3984                .atu_move_port_mask = 0xf,
3985                .multi_chip = true,
3986                .tag_protocol = DSA_TAG_PROTO_EDSA,
3987                .ptp_support = true,
3988                .ops = &mv88e6321_ops,
3989        },
3990
3991        [MV88E6341] = {
3992                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
3993                .family = MV88E6XXX_FAMILY_6341,
3994                .name = "Marvell 88E6341",
3995                .num_databases = 4096,
3996                .num_internal_phys = 5,
3997                .num_ports = 6,
3998                .num_gpio = 11,
3999                .max_vid = 4095,
4000                .port_base_addr = 0x10,
4001                .phy_base_addr = 0x10,
4002                .global1_addr = 0x1b,
4003                .global2_addr = 0x1c,
4004                .age_time_coeff = 3750,
4005                .atu_move_port_mask = 0x1f,
4006                .g1_irqs = 9,
4007                .g2_irqs = 10,
4008                .pvt = true,
4009                .multi_chip = true,
4010                .tag_protocol = DSA_TAG_PROTO_EDSA,
4011                .ptp_support = true,
4012                .ops = &mv88e6341_ops,
4013        },
4014
4015        [MV88E6350] = {
4016                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350,
4017                .family = MV88E6XXX_FAMILY_6351,
4018                .name = "Marvell 88E6350",
4019                .num_databases = 4096,
4020                .num_ports = 7,
4021                .num_internal_phys = 5,
4022                .max_vid = 4095,
4023                .port_base_addr = 0x10,
4024                .phy_base_addr = 0x0,
4025                .global1_addr = 0x1b,
4026                .global2_addr = 0x1c,
4027                .age_time_coeff = 15000,
4028                .g1_irqs = 9,
4029                .g2_irqs = 10,
4030                .atu_move_port_mask = 0xf,
4031                .pvt = true,
4032                .multi_chip = true,
4033                .tag_protocol = DSA_TAG_PROTO_EDSA,
4034                .ops = &mv88e6350_ops,
4035        },
4036
4037        [MV88E6351] = {
4038                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6351,
4039                .family = MV88E6XXX_FAMILY_6351,
4040                .name = "Marvell 88E6351",
4041                .num_databases = 4096,
4042                .num_ports = 7,
4043                .num_internal_phys = 5,
4044                .max_vid = 4095,
4045                .port_base_addr = 0x10,
4046                .phy_base_addr = 0x0,
4047                .global1_addr = 0x1b,
4048                .global2_addr = 0x1c,
4049                .age_time_coeff = 15000,
4050                .g1_irqs = 9,
4051                .g2_irqs = 10,
4052                .atu_move_port_mask = 0xf,
4053                .pvt = true,
4054                .multi_chip = true,
4055                .tag_protocol = DSA_TAG_PROTO_EDSA,
4056                .ops = &mv88e6351_ops,
4057        },
4058
4059        [MV88E6352] = {
4060                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352,
4061                .family = MV88E6XXX_FAMILY_6352,
4062                .name = "Marvell 88E6352",
4063                .num_databases = 4096,
4064                .num_ports = 7,
4065                .num_internal_phys = 5,
4066                .num_gpio = 15,
4067                .max_vid = 4095,
4068                .port_base_addr = 0x10,
4069                .phy_base_addr = 0x0,
4070                .global1_addr = 0x1b,
4071                .global2_addr = 0x1c,
4072                .age_time_coeff = 15000,
4073                .g1_irqs = 9,
4074                .g2_irqs = 10,
4075                .atu_move_port_mask = 0xf,
4076                .pvt = true,
4077                .multi_chip = true,
4078                .tag_protocol = DSA_TAG_PROTO_EDSA,
4079                .ptp_support = true,
4080                .ops = &mv88e6352_ops,
4081        },
4082        [MV88E6390] = {
4083                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
4084                .family = MV88E6XXX_FAMILY_6390,
4085                .name = "Marvell 88E6390",
4086                .num_databases = 4096,
4087                .num_ports = 11,        /* 10 + Z80 */
4088                .num_internal_phys = 11,
4089                .num_gpio = 16,
4090                .max_vid = 8191,
4091                .port_base_addr = 0x0,
4092                .phy_base_addr = 0x0,
4093                .global1_addr = 0x1b,
4094                .global2_addr = 0x1c,
4095                .age_time_coeff = 3750,
4096                .g1_irqs = 9,
4097                .g2_irqs = 14,
4098                .atu_move_port_mask = 0x1f,
4099                .pvt = true,
4100                .multi_chip = true,
4101                .tag_protocol = DSA_TAG_PROTO_DSA,
4102                .ptp_support = true,
4103                .ops = &mv88e6390_ops,
4104        },
4105        [MV88E6390X] = {
4106                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X,
4107                .family = MV88E6XXX_FAMILY_6390,
4108                .name = "Marvell 88E6390X",
4109                .num_databases = 4096,
4110                .num_ports = 11,        /* 10 + Z80 */
4111                .num_internal_phys = 11,
4112                .num_gpio = 16,
4113                .max_vid = 8191,
4114                .port_base_addr = 0x0,
4115                .phy_base_addr = 0x0,
4116                .global1_addr = 0x1b,
4117                .global2_addr = 0x1c,
4118                .age_time_coeff = 3750,
4119                .g1_irqs = 9,
4120                .g2_irqs = 14,
4121                .atu_move_port_mask = 0x1f,
4122                .pvt = true,
4123                .multi_chip = true,
4124                .tag_protocol = DSA_TAG_PROTO_DSA,
4125                .ptp_support = true,
4126                .ops = &mv88e6390x_ops,
4127        },
4128};
4129
4130static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
4131{
4132        int i;
4133
4134        for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
4135                if (mv88e6xxx_table[i].prod_num == prod_num)
4136                        return &mv88e6xxx_table[i];
4137
4138        return NULL;
4139}
4140
4141static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
4142{
4143        const struct mv88e6xxx_info *info;
4144        unsigned int prod_num, rev;
4145        u16 id;
4146        int err;
4147
4148        mutex_lock(&chip->reg_lock);
4149        err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id);
4150        mutex_unlock(&chip->reg_lock);
4151        if (err)
4152                return err;
4153
4154        prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK;
4155        rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK;
4156
4157        info = mv88e6xxx_lookup_info(prod_num);
4158        if (!info)
4159                return -ENODEV;
4160
4161        /* Update the compatible info with the probed one */
4162        chip->info = info;
4163
4164        err = mv88e6xxx_g2_require(chip);
4165        if (err)
4166                return err;
4167
4168        dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n",
4169                 chip->info->prod_num, chip->info->name, rev);
4170
4171        return 0;
4172}
4173
4174static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
4175{
4176        struct mv88e6xxx_chip *chip;
4177
4178        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
4179        if (!chip)
4180                return NULL;
4181
4182        chip->dev = dev;
4183
4184        mutex_init(&chip->reg_lock);
4185        INIT_LIST_HEAD(&chip->mdios);
4186
4187        return chip;
4188}
4189
4190static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
4191                              struct mii_bus *bus, int sw_addr)
4192{
4193        if (sw_addr == 0)
4194                chip->smi_ops = &mv88e6xxx_smi_single_chip_ops;
4195        else if (chip->info->multi_chip)
4196                chip->smi_ops = &mv88e6xxx_smi_multi_chip_ops;
4197        else
4198                return -EINVAL;
4199
4200        chip->bus = bus;
4201        chip->sw_addr = sw_addr;
4202
4203        return 0;
4204}
4205
4206static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
4207                                                        int port)
4208{
4209        struct mv88e6xxx_chip *chip = ds->priv;
4210
4211        return chip->info->tag_protocol;
4212}
4213
4214#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
4215static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
4216                                       struct device *host_dev, int sw_addr,
4217                                       void **priv)
4218{
4219        struct mv88e6xxx_chip *chip;
4220        struct mii_bus *bus;
4221        int err;
4222
4223        bus = dsa_host_dev_to_mii_bus(host_dev);
4224        if (!bus)
4225                return NULL;
4226
4227        chip = mv88e6xxx_alloc_chip(dsa_dev);
4228        if (!chip)
4229                return NULL;
4230
4231        /* Legacy SMI probing will only support chips similar to 88E6085 */
4232        chip->info = &mv88e6xxx_table[MV88E6085];
4233
4234        err = mv88e6xxx_smi_init(chip, bus, sw_addr);
4235        if (err)
4236                goto free;
4237
4238        err = mv88e6xxx_detect(chip);
4239        if (err)
4240                goto free;
4241
4242        mutex_lock(&chip->reg_lock);
4243        err = mv88e6xxx_switch_reset(chip);
4244        mutex_unlock(&chip->reg_lock);
4245        if (err)
4246                goto free;
4247
4248        mv88e6xxx_phy_init(chip);
4249
4250        err = mv88e6xxx_mdios_register(chip, NULL);
4251        if (err)
4252                goto free;
4253
4254        *priv = chip;
4255
4256        return chip->info->name;
4257free:
4258        devm_kfree(dsa_dev, chip);
4259
4260        return NULL;
4261}
4262#endif
4263
4264static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port,
4265                                      const struct switchdev_obj_port_mdb *mdb)
4266{
4267        /* We don't need any dynamic resource from the kernel (yet),
4268         * so skip the prepare phase.
4269         */
4270
4271        return 0;
4272}
4273
4274static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
4275                                   const struct switchdev_obj_port_mdb *mdb)
4276{
4277        struct mv88e6xxx_chip *chip = ds->priv;
4278
4279        mutex_lock(&chip->reg_lock);
4280        if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4281                                         MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC))
4282                dev_err(ds->dev, "p%d: failed to load multicast MAC address\n",
4283                        port);
4284        mutex_unlock(&chip->reg_lock);
4285}
4286
4287static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
4288                                  const struct switchdev_obj_port_mdb *mdb)
4289{
4290        struct mv88e6xxx_chip *chip = ds->priv;
4291        int err;
4292
4293        mutex_lock(&chip->reg_lock);
4294        err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4295                                           MV88E6XXX_G1_ATU_DATA_STATE_UNUSED);
4296        mutex_unlock(&chip->reg_lock);
4297
4298        return err;
4299}
4300
4301static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
4302#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
4303        .probe                  = mv88e6xxx_drv_probe,
4304#endif
4305        .get_tag_protocol       = mv88e6xxx_get_tag_protocol,
4306        .setup                  = mv88e6xxx_setup,
4307        .adjust_link            = mv88e6xxx_adjust_link,
4308        .phylink_validate       = mv88e6xxx_validate,
4309        .phylink_mac_link_state = mv88e6xxx_link_state,
4310        .phylink_mac_config     = mv88e6xxx_mac_config,
4311        .phylink_mac_link_down  = mv88e6xxx_mac_link_down,
4312        .phylink_mac_link_up    = mv88e6xxx_mac_link_up,
4313        .get_strings            = mv88e6xxx_get_strings,
4314        .get_ethtool_stats      = mv88e6xxx_get_ethtool_stats,
4315        .get_sset_count         = mv88e6xxx_get_sset_count,
4316        .port_enable            = mv88e6xxx_port_enable,
4317        .port_disable           = mv88e6xxx_port_disable,
4318        .get_mac_eee            = mv88e6xxx_get_mac_eee,
4319        .set_mac_eee            = mv88e6xxx_set_mac_eee,
4320        .get_eeprom_len         = mv88e6xxx_get_eeprom_len,
4321        .get_eeprom             = mv88e6xxx_get_eeprom,
4322        .set_eeprom             = mv88e6xxx_set_eeprom,
4323        .get_regs_len           = mv88e6xxx_get_regs_len,
4324        .get_regs               = mv88e6xxx_get_regs,
4325        .set_ageing_time        = mv88e6xxx_set_ageing_time,
4326        .port_bridge_join       = mv88e6xxx_port_bridge_join,
4327        .port_bridge_leave      = mv88e6xxx_port_bridge_leave,
4328        .port_stp_state_set     = mv88e6xxx_port_stp_state_set,
4329        .port_fast_age          = mv88e6xxx_port_fast_age,
4330        .port_vlan_filtering    = mv88e6xxx_port_vlan_filtering,
4331        .port_vlan_prepare      = mv88e6xxx_port_vlan_prepare,
4332        .port_vlan_add          = mv88e6xxx_port_vlan_add,
4333        .port_vlan_del          = mv88e6xxx_port_vlan_del,
4334        .port_fdb_add           = mv88e6xxx_port_fdb_add,
4335        .port_fdb_del           = mv88e6xxx_port_fdb_del,
4336        .port_fdb_dump          = mv88e6xxx_port_fdb_dump,
4337        .port_mdb_prepare       = mv88e6xxx_port_mdb_prepare,
4338        .port_mdb_add           = mv88e6xxx_port_mdb_add,
4339        .port_mdb_del           = mv88e6xxx_port_mdb_del,
4340        .crosschip_bridge_join  = mv88e6xxx_crosschip_bridge_join,
4341        .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave,
4342        .port_hwtstamp_set      = mv88e6xxx_port_hwtstamp_set,
4343        .port_hwtstamp_get      = mv88e6xxx_port_hwtstamp_get,
4344        .port_txtstamp          = mv88e6xxx_port_txtstamp,
4345        .port_rxtstamp          = mv88e6xxx_port_rxtstamp,
4346        .get_ts_info            = mv88e6xxx_get_ts_info,
4347};
4348
4349static struct dsa_switch_driver mv88e6xxx_switch_drv = {
4350        .ops                    = &mv88e6xxx_switch_ops,
4351};
4352
4353static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
4354{
4355        struct device *dev = chip->dev;
4356        struct dsa_switch *ds;
4357
4358        ds = dsa_switch_alloc(dev, mv88e6xxx_num_ports(chip));
4359        if (!ds)
4360                return -ENOMEM;
4361
4362        ds->priv = chip;
4363        ds->dev = dev;
4364        ds->ops = &mv88e6xxx_switch_ops;
4365        ds->ageing_time_min = chip->info->age_time_coeff;
4366        ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
4367
4368        dev_set_drvdata(dev, ds);
4369
4370        return dsa_register_switch(ds);
4371}
4372
4373static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip)
4374{
4375        dsa_unregister_switch(chip->ds);
4376}
4377
4378static const void *pdata_device_get_match_data(struct device *dev)
4379{
4380        const struct of_device_id *matches = dev->driver->of_match_table;
4381        const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data;
4382
4383        for (; matches->name[0] || matches->type[0] || matches->compatible[0];
4384             matches++) {
4385                if (!strcmp(pdata->compatible, matches->compatible))
4386                        return matches->data;
4387        }
4388        return NULL;
4389}
4390
4391static int mv88e6xxx_probe(struct mdio_device *mdiodev)
4392{
4393        struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
4394        const struct mv88e6xxx_info *compat_info = NULL;
4395        struct device *dev = &mdiodev->dev;
4396        struct device_node *np = dev->of_node;
4397        struct mv88e6xxx_chip *chip;
4398        int port;
4399        int err;
4400
4401        if (!np && !pdata)
4402                return -EINVAL;
4403
4404        if (np)
4405                compat_info = of_device_get_match_data(dev);
4406
4407        if (pdata) {
4408                compat_info = pdata_device_get_match_data(dev);
4409
4410                if (!pdata->netdev)
4411                        return -EINVAL;
4412
4413                for (port = 0; port < DSA_MAX_PORTS; port++) {
4414                        if (!(pdata->enabled_ports & (1 << port)))
4415                                continue;
4416                        if (strcmp(pdata->cd.port_names[port], "cpu"))
4417                                continue;
4418                        pdata->cd.netdev[port] = &pdata->netdev->dev;
4419                        break;
4420                }
4421        }
4422
4423        if (!compat_info)
4424                return -EINVAL;
4425
4426        chip = mv88e6xxx_alloc_chip(dev);
4427        if (!chip) {
4428                err = -ENOMEM;
4429                goto out;
4430        }
4431
4432        chip->info = compat_info;
4433
4434        err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
4435        if (err)
4436                goto out;
4437
4438        chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
4439        if (IS_ERR(chip->reset)) {
4440                err = PTR_ERR(chip->reset);
4441                goto out;
4442        }
4443
4444        err = mv88e6xxx_detect(chip);
4445        if (err)
4446                goto out;
4447
4448        mv88e6xxx_phy_init(chip);
4449
4450        if (chip->info->ops->get_eeprom) {
4451                if (np)
4452                        of_property_read_u32(np, "eeprom-length",
4453                                             &chip->eeprom_len);
4454                else
4455                        chip->eeprom_len = pdata->eeprom_len;
4456        }
4457
4458        mutex_lock(&chip->reg_lock);
4459        err = mv88e6xxx_switch_reset(chip);
4460        mutex_unlock(&chip->reg_lock);
4461        if (err)
4462                goto out;
4463
4464        chip->irq = of_irq_get(np, 0);
4465        if (chip->irq == -EPROBE_DEFER) {
4466                err = chip->irq;
4467                goto out;
4468        }
4469
4470        /* Has to be performed before the MDIO bus is created, because
4471         * the PHYs will link their interrupts to these interrupt
4472         * controllers
4473         */
4474        mutex_lock(&chip->reg_lock);
4475        if (chip->irq > 0)
4476                err = mv88e6xxx_g1_irq_setup(chip);
4477        else
4478                err = mv88e6xxx_irq_poll_setup(chip);
4479        mutex_unlock(&chip->reg_lock);
4480
4481        if (err)
4482                goto out;
4483
4484        if (chip->info->g2_irqs > 0) {
4485                err = mv88e6xxx_g2_irq_setup(chip);
4486                if (err)
4487                        goto out_g1_irq;
4488        }
4489
4490        err = mv88e6xxx_g1_atu_prob_irq_setup(chip);
4491        if (err)
4492                goto out_g2_irq;
4493
4494        err = mv88e6xxx_g1_vtu_prob_irq_setup(chip);
4495        if (err)
4496                goto out_g1_atu_prob_irq;
4497
4498        err = mv88e6xxx_mdios_register(chip, np);
4499        if (err)
4500                goto out_g1_vtu_prob_irq;
4501
4502        err = mv88e6xxx_register_switch(chip);
4503        if (err)
4504                goto out_mdio;
4505
4506        return 0;
4507
4508out_mdio:
4509        mv88e6xxx_mdios_unregister(chip);
4510out_g1_vtu_prob_irq:
4511        mv88e6xxx_g1_vtu_prob_irq_free(chip);
4512out_g1_atu_prob_irq:
4513        mv88e6xxx_g1_atu_prob_irq_free(chip);
4514out_g2_irq:
4515        if (chip->info->g2_irqs > 0)
4516                mv88e6xxx_g2_irq_free(chip);
4517out_g1_irq:
4518        if (chip->irq > 0)
4519                mv88e6xxx_g1_irq_free(chip);
4520        else
4521                mv88e6xxx_irq_poll_free(chip);
4522out:
4523        if (pdata)
4524                dev_put(pdata->netdev);
4525
4526        return err;
4527}
4528
4529static void mv88e6xxx_remove(struct mdio_device *mdiodev)
4530{
4531        struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
4532        struct mv88e6xxx_chip *chip = ds->priv;
4533
4534        if (chip->info->ptp_support) {
4535                mv88e6xxx_hwtstamp_free(chip);
4536                mv88e6xxx_ptp_free(chip);
4537        }
4538
4539        mv88e6xxx_phy_destroy(chip);
4540        mv88e6xxx_unregister_switch(chip);
4541        mv88e6xxx_mdios_unregister(chip);
4542
4543        mv88e6xxx_g1_vtu_prob_irq_free(chip);
4544        mv88e6xxx_g1_atu_prob_irq_free(chip);
4545
4546        if (chip->info->g2_irqs > 0)
4547                mv88e6xxx_g2_irq_free(chip);
4548
4549        if (chip->irq > 0)
4550                mv88e6xxx_g1_irq_free(chip);
4551        else
4552                mv88e6xxx_irq_poll_free(chip);
4553}
4554
4555static const struct of_device_id mv88e6xxx_of_match[] = {
4556        {
4557                .compatible = "marvell,mv88e6085",
4558                .data = &mv88e6xxx_table[MV88E6085],
4559        },
4560        {
4561                .compatible = "marvell,mv88e6190",
4562                .data = &mv88e6xxx_table[MV88E6190],
4563        },
4564        { /* sentinel */ },
4565};
4566
4567MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);
4568
4569static struct mdio_driver mv88e6xxx_driver = {
4570        .probe  = mv88e6xxx_probe,
4571        .remove = mv88e6xxx_remove,
4572        .mdiodrv.driver = {
4573                .name = "mv88e6085",
4574                .of_match_table = mv88e6xxx_of_match,
4575        },
4576};
4577
4578static int __init mv88e6xxx_init(void)
4579{
4580        register_switch_driver(&mv88e6xxx_switch_drv);
4581        return mdio_driver_register(&mv88e6xxx_driver);
4582}
4583module_init(mv88e6xxx_init);
4584
4585static void __exit mv88e6xxx_cleanup(void)
4586{
4587        mdio_driver_unregister(&mv88e6xxx_driver);
4588        unregister_switch_driver(&mv88e6xxx_switch_drv);
4589}
4590module_exit(mv88e6xxx_cleanup);
4591
4592MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
4593MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
4594MODULE_LICENSE("GPL");
4595