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