1 From 469b6adff1484015369993dbb86a2936b6517a7d Mon Sep 17 00:00:00 2001
2 From: Vladimir Oltean <vladimir.oltean@nxp.com>
3 Date: Thu, 14 Nov 2019 17:03:30 +0200
4 Subject: [PATCH] net: dsa: ocelot: add driver for Felix switch family
6 This supports an Ethernet switching core from Vitesse / Microsemi /
7 Microchip (VSC9959) which is part of the Ocelot family (a brand name),
8 and whose code name is Felix. The switch can be (and is) integrated on
9 different SoCs as a PCIe endpoint device.
11 The functionality is provided by the core of the Ocelot switch driver
12 (drivers/net/ethernet/mscc). In this regard, the current driver is an
13 instance of Microsemi's Ocelot core driver, with a DSA front-end. It
14 inherits its name from VSC9959's code name, to distinguish itself from
15 the switchdev ocelot driver.
17 The patch adds the logic for probing a PCI device and defines the
18 register map for the VSC9959 switch core, since it has some differences
19 in register addresses and bitfield mappings compared to the other Ocelot
20 switches (VSC7511, VSC7512, VSC7513, VSC7514).
22 The Felix driver declares the register map as part of the "instance
23 table". Currently the VSC9959 inside NXP LS1028A is the only instance,
24 but presumably it can support other switches in the Ocelot family, when
25 used in DSA mode (Linux running on the external CPU, and not on the
28 In a few cases, some h/w operations have to be done differently on
29 VSC9959 due to missing bitfields. This is the case for the switch core
30 reset and init. Because for this operation Ocelot uses some bits that
31 are not present on Felix, the latter has to use a register from the
32 global registers block (GCB) instead.
34 Although it is a PCI driver, it relies on DT bindings for compatibility
35 with DSA (CPU port link, PHY library). It does not have any custom
36 device tree bindings, since we would like to minimize its dependency on
39 Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
40 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
41 Signed-off-by: David S. Miller <davem@davemloft.net>
44 drivers/net/dsa/Kconfig | 2 +
45 drivers/net/dsa/Makefile | 1 +
46 drivers/net/dsa/ocelot/Kconfig | 11 +
47 drivers/net/dsa/ocelot/Makefile | 6 +
48 drivers/net/dsa/ocelot/felix.c | 441 +++++++++++++++++++++++++
49 drivers/net/dsa/ocelot/felix.h | 37 +++
50 drivers/net/dsa/ocelot/felix_vsc9959.c | 567 +++++++++++++++++++++++++++++++++
51 8 files changed, 1066 insertions(+)
52 create mode 100644 drivers/net/dsa/ocelot/Kconfig
53 create mode 100644 drivers/net/dsa/ocelot/Makefile
54 create mode 100644 drivers/net/dsa/ocelot/felix.c
55 create mode 100644 drivers/net/dsa/ocelot/felix.h
56 create mode 100644 drivers/net/dsa/ocelot/felix_vsc9959.c
60 @@ -17360,6 +17360,7 @@ M: Vladimir Oltean <vladimir.oltean@nxp.
61 M: Claudiu Manoil <claudiu.manoil@nxp.com>
62 L: netdev@vger.kernel.org
64 +F: drivers/net/dsa/ocelot/*
65 F: net/dsa/tag_ocelot.c
67 VIVID VIRTUAL VIDEO DRIVER
68 --- a/drivers/net/dsa/Kconfig
69 +++ b/drivers/net/dsa/Kconfig
70 @@ -52,6 +52,8 @@ source "drivers/net/dsa/microchip/Kconfi
72 source "drivers/net/dsa/mv88e6xxx/Kconfig"
74 +source "drivers/net/dsa/ocelot/Kconfig"
76 source "drivers/net/dsa/sja1105/Kconfig"
79 --- a/drivers/net/dsa/Makefile
80 +++ b/drivers/net/dsa/Makefile
81 @@ -20,4 +20,5 @@ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_SPI
88 +++ b/drivers/net/dsa/ocelot/Kconfig
90 +# SPDX-License-Identifier: GPL-2.0-only
91 +config NET_DSA_MSCC_FELIX
92 + tristate "Ocelot / Felix Ethernet switch support"
93 + depends on NET_DSA && PCI
94 + select MSCC_OCELOT_SWITCH
95 + select NET_DSA_TAG_OCELOT
97 + This driver supports the VSC9959 network switch, which is a member of
98 + the Vitesse / Microsemi / Microchip Ocelot family of switching cores.
99 + It is embedded as a PCIe function of the NXP LS1028A ENETC integrated
102 +++ b/drivers/net/dsa/ocelot/Makefile
104 +# SPDX-License-Identifier: GPL-2.0-only
105 +obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
107 +mscc_felix-objs := \
111 +++ b/drivers/net/dsa/ocelot/felix.c
113 +// SPDX-License-Identifier: GPL-2.0
114 +/* Copyright 2019 NXP Semiconductors
116 +#include <uapi/linux/if_bridge.h>
117 +#include <soc/mscc/ocelot.h>
118 +#include <linux/module.h>
119 +#include <linux/pci.h>
120 +#include <linux/of.h>
121 +#include <net/dsa.h>
124 +static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
127 + return DSA_TAG_PROTO_OCELOT;
130 +static int felix_set_ageing_time(struct dsa_switch *ds,
131 + unsigned int ageing_time)
133 + struct ocelot *ocelot = ds->priv;
135 + ocelot_set_ageing_time(ocelot, ageing_time);
140 +static void felix_adjust_link(struct dsa_switch *ds, int port,
141 + struct phy_device *phydev)
143 + struct ocelot *ocelot = ds->priv;
145 + ocelot_adjust_link(ocelot, port, phydev);
148 +static int felix_fdb_dump(struct dsa_switch *ds, int port,
149 + dsa_fdb_dump_cb_t *cb, void *data)
151 + struct ocelot *ocelot = ds->priv;
153 + return ocelot_fdb_dump(ocelot, port, cb, data);
156 +static int felix_fdb_add(struct dsa_switch *ds, int port,
157 + const unsigned char *addr, u16 vid)
159 + struct ocelot *ocelot = ds->priv;
162 + vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port));
164 + return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware);
167 +static int felix_fdb_del(struct dsa_switch *ds, int port,
168 + const unsigned char *addr, u16 vid)
170 + struct ocelot *ocelot = ds->priv;
172 + return ocelot_fdb_del(ocelot, port, addr, vid);
175 +static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port,
178 + struct ocelot *ocelot = ds->priv;
180 + return ocelot_bridge_stp_state_set(ocelot, port, state);
183 +static int felix_bridge_join(struct dsa_switch *ds, int port,
184 + struct net_device *br)
186 + struct ocelot *ocelot = ds->priv;
188 + return ocelot_port_bridge_join(ocelot, port, br);
191 +static void felix_bridge_leave(struct dsa_switch *ds, int port,
192 + struct net_device *br)
194 + struct ocelot *ocelot = ds->priv;
196 + ocelot_port_bridge_leave(ocelot, port, br);
199 +/* This callback needs to be present */
200 +static int felix_vlan_prepare(struct dsa_switch *ds, int port,
201 + const struct switchdev_obj_port_vlan *vlan)
206 +static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
208 + struct ocelot *ocelot = ds->priv;
210 + ocelot_port_vlan_filtering(ocelot, port, enabled);
215 +static void felix_vlan_add(struct dsa_switch *ds, int port,
216 + const struct switchdev_obj_port_vlan *vlan)
218 + struct ocelot *ocelot = ds->priv;
222 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
223 + err = ocelot_vlan_add(ocelot, port, vid,
224 + vlan->flags & BRIDGE_VLAN_INFO_PVID,
225 + vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
227 + dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n",
234 +static int felix_vlan_del(struct dsa_switch *ds, int port,
235 + const struct switchdev_obj_port_vlan *vlan)
237 + struct ocelot *ocelot = ds->priv;
241 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
242 + err = ocelot_vlan_del(ocelot, port, vid);
244 + dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n",
252 +static int felix_port_enable(struct dsa_switch *ds, int port,
253 + struct phy_device *phy)
255 + struct ocelot *ocelot = ds->priv;
257 + ocelot_port_enable(ocelot, port, phy);
262 +static void felix_port_disable(struct dsa_switch *ds, int port)
264 + struct ocelot *ocelot = ds->priv;
266 + return ocelot_port_disable(ocelot, port);
269 +static void felix_get_strings(struct dsa_switch *ds, int port,
270 + u32 stringset, u8 *data)
272 + struct ocelot *ocelot = ds->priv;
274 + return ocelot_get_strings(ocelot, port, stringset, data);
277 +static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
279 + struct ocelot *ocelot = ds->priv;
281 + ocelot_get_ethtool_stats(ocelot, port, data);
284 +static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset)
286 + struct ocelot *ocelot = ds->priv;
288 + return ocelot_get_sset_count(ocelot, port, sset);
291 +static int felix_get_ts_info(struct dsa_switch *ds, int port,
292 + struct ethtool_ts_info *info)
294 + struct ocelot *ocelot = ds->priv;
296 + return ocelot_get_ts_info(ocelot, port, info);
299 +static int felix_init_structs(struct felix *felix, int num_phys_ports)
301 + struct ocelot *ocelot = &felix->ocelot;
302 + resource_size_t base;
305 + ocelot->num_phys_ports = num_phys_ports;
306 + ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports,
307 + sizeof(struct ocelot_port *), GFP_KERNEL);
308 + if (!ocelot->ports)
311 + ocelot->map = felix->info->map;
312 + ocelot->stats_layout = felix->info->stats_layout;
313 + ocelot->num_stats = felix->info->num_stats;
314 + ocelot->shared_queue_sz = felix->info->shared_queue_sz;
315 + ocelot->ops = felix->info->ops;
317 + base = pci_resource_start(felix->pdev, felix->info->pci_bar);
319 + for (i = 0; i < TARGET_MAX; i++) {
320 + struct regmap *target;
321 + struct resource *res;
323 + if (!felix->info->target_io_res[i].name)
326 + res = &felix->info->target_io_res[i];
327 + res->flags = IORESOURCE_MEM;
328 + res->start += base;
331 + target = ocelot_regmap_init(ocelot, res);
332 + if (IS_ERR(target)) {
333 + dev_err(ocelot->dev,
334 + "Failed to map device memory space\n");
335 + return PTR_ERR(target);
338 + ocelot->targets[i] = target;
341 + err = ocelot_regfields_init(ocelot, felix->info->regfields);
343 + dev_err(ocelot->dev, "failed to init reg fields map\n");
347 + for (port = 0; port < num_phys_ports; port++) {
348 + struct ocelot_port *ocelot_port;
349 + void __iomem *port_regs;
350 + struct resource *res;
352 + ocelot_port = devm_kzalloc(ocelot->dev,
353 + sizeof(struct ocelot_port),
355 + if (!ocelot_port) {
356 + dev_err(ocelot->dev,
357 + "failed to allocate port memory\n");
361 + res = &felix->info->port_io_res[port];
362 + res->flags = IORESOURCE_MEM;
363 + res->start += base;
366 + port_regs = devm_ioremap_resource(ocelot->dev, res);
367 + if (IS_ERR(port_regs)) {
368 + dev_err(ocelot->dev,
369 + "failed to map registers for port %d\n", port);
370 + return PTR_ERR(port_regs);
373 + ocelot_port->ocelot = ocelot;
374 + ocelot_port->regs = port_regs;
375 + ocelot->ports[port] = ocelot_port;
381 +/* Hardware initialization done here so that we can allocate structures with
382 + * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
383 + * us to allocate structures twice (leak memory) and map PCI memory twice
384 + * (which will not work).
386 +static int felix_setup(struct dsa_switch *ds)
388 + struct ocelot *ocelot = ds->priv;
389 + struct felix *felix = ocelot_to_felix(ocelot);
392 + err = felix_init_structs(felix, ds->num_ports);
396 + ocelot_init(ocelot);
398 + for (port = 0; port < ds->num_ports; port++) {
399 + ocelot_init_port(ocelot, port);
401 + if (port == dsa_upstream_port(ds, port))
402 + ocelot_set_cpu_port(ocelot, port,
403 + OCELOT_TAG_PREFIX_NONE,
404 + OCELOT_TAG_PREFIX_LONG);
410 +static void felix_teardown(struct dsa_switch *ds)
412 + struct ocelot *ocelot = ds->priv;
414 + /* stop workqueue thread */
415 + ocelot_deinit(ocelot);
418 +static const struct dsa_switch_ops felix_switch_ops = {
419 + .get_tag_protocol = felix_get_tag_protocol,
420 + .setup = felix_setup,
421 + .teardown = felix_teardown,
422 + .set_ageing_time = felix_set_ageing_time,
423 + .get_strings = felix_get_strings,
424 + .get_ethtool_stats = felix_get_ethtool_stats,
425 + .get_sset_count = felix_get_sset_count,
426 + .get_ts_info = felix_get_ts_info,
427 + .adjust_link = felix_adjust_link,
428 + .port_enable = felix_port_enable,
429 + .port_disable = felix_port_disable,
430 + .port_fdb_dump = felix_fdb_dump,
431 + .port_fdb_add = felix_fdb_add,
432 + .port_fdb_del = felix_fdb_del,
433 + .port_bridge_join = felix_bridge_join,
434 + .port_bridge_leave = felix_bridge_leave,
435 + .port_stp_state_set = felix_bridge_stp_state_set,
436 + .port_vlan_prepare = felix_vlan_prepare,
437 + .port_vlan_filtering = felix_vlan_filtering,
438 + .port_vlan_add = felix_vlan_add,
439 + .port_vlan_del = felix_vlan_del,
442 +static struct felix_info *felix_instance_tbl[] = {
443 + [FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959,
446 +static int felix_pci_probe(struct pci_dev *pdev,
447 + const struct pci_device_id *id)
449 + enum felix_instance instance = id->driver_data;
450 + struct dsa_switch *ds;
451 + struct ocelot *ocelot;
452 + struct felix *felix;
455 + err = pci_enable_device(pdev);
457 + dev_err(&pdev->dev, "device enable failed\n");
458 + goto err_pci_enable;
461 + /* set up for high or low dma */
462 + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
464 + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
466 + dev_err(&pdev->dev,
467 + "DMA configuration failed: 0x%x\n", err);
472 + felix = kzalloc(sizeof(struct felix), GFP_KERNEL);
475 + dev_err(&pdev->dev, "Failed to allocate driver memory\n");
476 + goto err_alloc_felix;
479 + pci_set_drvdata(pdev, felix);
480 + ocelot = &felix->ocelot;
481 + ocelot->dev = &pdev->dev;
482 + felix->pdev = pdev;
483 + felix->info = felix_instance_tbl[instance];
485 + pci_set_master(pdev);
487 + ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
490 + dev_err(&pdev->dev, "Failed to allocate DSA switch\n");
494 + ds->dev = &pdev->dev;
495 + ds->num_ports = felix->info->num_ports;
496 + ds->ops = &felix_switch_ops;
500 + err = dsa_register_switch(ds);
502 + dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
503 + goto err_register_ds;
514 + pci_disable_device(pdev);
519 +static void felix_pci_remove(struct pci_dev *pdev)
521 + struct felix *felix;
523 + felix = pci_get_drvdata(pdev);
525 + dsa_unregister_switch(felix->ds);
530 + pci_disable_device(pdev);
533 +static struct pci_device_id felix_ids[] = {
536 + PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0),
537 + .driver_data = FELIX_INSTANCE_VSC9959,
541 +MODULE_DEVICE_TABLE(pci, felix_ids);
543 +static struct pci_driver felix_pci_driver = {
544 + .name = KBUILD_MODNAME,
545 + .id_table = felix_ids,
546 + .probe = felix_pci_probe,
547 + .remove = felix_pci_remove,
550 +module_pci_driver(felix_pci_driver);
552 +MODULE_DESCRIPTION("Felix Switch driver");
553 +MODULE_LICENSE("GPL v2");
555 +++ b/drivers/net/dsa/ocelot/felix.h
557 +/* SPDX-License-Identifier: GPL-2.0 */
558 +/* Copyright 2019 NXP Semiconductors
560 +#ifndef _MSCC_FELIX_H
561 +#define _MSCC_FELIX_H
563 +#define ocelot_to_felix(o) container_of((o), struct felix, ocelot)
565 +/* Platform-specific information */
567 + struct resource *target_io_res;
568 + struct resource *port_io_res;
569 + const struct reg_field *regfields;
570 + const u32 *const *map;
571 + const struct ocelot_ops *ops;
572 + int shared_queue_sz;
573 + const struct ocelot_stat_layout *stats_layout;
574 + unsigned int num_stats;
579 +extern struct felix_info felix_info_vsc9959;
581 +enum felix_instance {
582 + FELIX_INSTANCE_VSC9959 = 0,
585 +/* DSA glue / front-end for struct ocelot */
587 + struct dsa_switch *ds;
588 + struct pci_dev *pdev;
589 + struct felix_info *info;
590 + struct ocelot ocelot;
595 +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
597 +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
598 +/* Copyright 2017 Microsemi Corporation
599 + * Copyright 2018-2019 NXP Semiconductors
601 +#include <soc/mscc/ocelot_sys.h>
602 +#include <soc/mscc/ocelot.h>
603 +#include <linux/iopoll.h>
604 +#include <linux/pci.h>
607 +static const u32 vsc9959_ana_regmap[] = {
608 + REG(ANA_ADVLEARN, 0x0089a0),
609 + REG(ANA_VLANMASK, 0x0089a4),
610 + REG_RESERVED(ANA_PORT_B_DOMAIN),
611 + REG(ANA_ANAGEFIL, 0x0089ac),
612 + REG(ANA_ANEVENTS, 0x0089b0),
613 + REG(ANA_STORMLIMIT_BURST, 0x0089b4),
614 + REG(ANA_STORMLIMIT_CFG, 0x0089b8),
615 + REG(ANA_ISOLATED_PORTS, 0x0089c8),
616 + REG(ANA_COMMUNITY_PORTS, 0x0089cc),
617 + REG(ANA_AUTOAGE, 0x0089d0),
618 + REG(ANA_MACTOPTIONS, 0x0089d4),
619 + REG(ANA_LEARNDISC, 0x0089d8),
620 + REG(ANA_AGENCTRL, 0x0089dc),
621 + REG(ANA_MIRRORPORTS, 0x0089e0),
622 + REG(ANA_EMIRRORPORTS, 0x0089e4),
623 + REG(ANA_FLOODING, 0x0089e8),
624 + REG(ANA_FLOODING_IPMC, 0x008a08),
625 + REG(ANA_SFLOW_CFG, 0x008a0c),
626 + REG(ANA_PORT_MODE, 0x008a28),
627 + REG(ANA_CUT_THRU_CFG, 0x008a48),
628 + REG(ANA_PGID_PGID, 0x008400),
629 + REG(ANA_TABLES_ANMOVED, 0x007f1c),
630 + REG(ANA_TABLES_MACHDATA, 0x007f20),
631 + REG(ANA_TABLES_MACLDATA, 0x007f24),
632 + REG(ANA_TABLES_STREAMDATA, 0x007f28),
633 + REG(ANA_TABLES_MACACCESS, 0x007f2c),
634 + REG(ANA_TABLES_MACTINDX, 0x007f30),
635 + REG(ANA_TABLES_VLANACCESS, 0x007f34),
636 + REG(ANA_TABLES_VLANTIDX, 0x007f38),
637 + REG(ANA_TABLES_ISDXACCESS, 0x007f3c),
638 + REG(ANA_TABLES_ISDXTIDX, 0x007f40),
639 + REG(ANA_TABLES_ENTRYLIM, 0x007f00),
640 + REG(ANA_TABLES_PTP_ID_HIGH, 0x007f44),
641 + REG(ANA_TABLES_PTP_ID_LOW, 0x007f48),
642 + REG(ANA_TABLES_STREAMACCESS, 0x007f4c),
643 + REG(ANA_TABLES_STREAMTIDX, 0x007f50),
644 + REG(ANA_TABLES_SEQ_HISTORY, 0x007f54),
645 + REG(ANA_TABLES_SEQ_MASK, 0x007f58),
646 + REG(ANA_TABLES_SFID_MASK, 0x007f5c),
647 + REG(ANA_TABLES_SFIDACCESS, 0x007f60),
648 + REG(ANA_TABLES_SFIDTIDX, 0x007f64),
649 + REG(ANA_MSTI_STATE, 0x008600),
650 + REG(ANA_OAM_UPM_LM_CNT, 0x008000),
651 + REG(ANA_SG_ACCESS_CTRL, 0x008a64),
652 + REG(ANA_SG_CONFIG_REG_1, 0x007fb0),
653 + REG(ANA_SG_CONFIG_REG_2, 0x007fb4),
654 + REG(ANA_SG_CONFIG_REG_3, 0x007fb8),
655 + REG(ANA_SG_CONFIG_REG_4, 0x007fbc),
656 + REG(ANA_SG_CONFIG_REG_5, 0x007fc0),
657 + REG(ANA_SG_GCL_GS_CONFIG, 0x007f80),
658 + REG(ANA_SG_GCL_TI_CONFIG, 0x007f90),
659 + REG(ANA_SG_STATUS_REG_1, 0x008980),
660 + REG(ANA_SG_STATUS_REG_2, 0x008984),
661 + REG(ANA_SG_STATUS_REG_3, 0x008988),
662 + REG(ANA_PORT_VLAN_CFG, 0x007800),
663 + REG(ANA_PORT_DROP_CFG, 0x007804),
664 + REG(ANA_PORT_QOS_CFG, 0x007808),
665 + REG(ANA_PORT_VCAP_CFG, 0x00780c),
666 + REG(ANA_PORT_VCAP_S1_KEY_CFG, 0x007810),
667 + REG(ANA_PORT_VCAP_S2_CFG, 0x00781c),
668 + REG(ANA_PORT_PCP_DEI_MAP, 0x007820),
669 + REG(ANA_PORT_CPU_FWD_CFG, 0x007860),
670 + REG(ANA_PORT_CPU_FWD_BPDU_CFG, 0x007864),
671 + REG(ANA_PORT_CPU_FWD_GARP_CFG, 0x007868),
672 + REG(ANA_PORT_CPU_FWD_CCM_CFG, 0x00786c),
673 + REG(ANA_PORT_PORT_CFG, 0x007870),
674 + REG(ANA_PORT_POL_CFG, 0x007874),
675 + REG(ANA_PORT_PTP_CFG, 0x007878),
676 + REG(ANA_PORT_PTP_DLY1_CFG, 0x00787c),
677 + REG(ANA_PORT_PTP_DLY2_CFG, 0x007880),
678 + REG(ANA_PORT_SFID_CFG, 0x007884),
679 + REG(ANA_PFC_PFC_CFG, 0x008800),
680 + REG_RESERVED(ANA_PFC_PFC_TIMER),
681 + REG_RESERVED(ANA_IPT_OAM_MEP_CFG),
682 + REG_RESERVED(ANA_IPT_IPT),
683 + REG_RESERVED(ANA_PPT_PPT),
684 + REG_RESERVED(ANA_FID_MAP_FID_MAP),
685 + REG(ANA_AGGR_CFG, 0x008a68),
686 + REG(ANA_CPUQ_CFG, 0x008a6c),
687 + REG_RESERVED(ANA_CPUQ_CFG2),
688 + REG(ANA_CPUQ_8021_CFG, 0x008a74),
689 + REG(ANA_DSCP_CFG, 0x008ab4),
690 + REG(ANA_DSCP_REWR_CFG, 0x008bb4),
691 + REG(ANA_VCAP_RNG_TYPE_CFG, 0x008bf4),
692 + REG(ANA_VCAP_RNG_VAL_CFG, 0x008c14),
693 + REG_RESERVED(ANA_VRAP_CFG),
694 + REG_RESERVED(ANA_VRAP_HDR_DATA),
695 + REG_RESERVED(ANA_VRAP_HDR_MASK),
696 + REG(ANA_DISCARD_CFG, 0x008c40),
697 + REG(ANA_FID_CFG, 0x008c44),
698 + REG(ANA_POL_PIR_CFG, 0x004000),
699 + REG(ANA_POL_CIR_CFG, 0x004004),
700 + REG(ANA_POL_MODE_CFG, 0x004008),
701 + REG(ANA_POL_PIR_STATE, 0x00400c),
702 + REG(ANA_POL_CIR_STATE, 0x004010),
703 + REG_RESERVED(ANA_POL_STATE),
704 + REG(ANA_POL_FLOWC, 0x008c48),
705 + REG(ANA_POL_HYST, 0x008cb4),
706 + REG_RESERVED(ANA_POL_MISC_CFG),
709 +static const u32 vsc9959_qs_regmap[] = {
710 + REG(QS_XTR_GRP_CFG, 0x000000),
711 + REG(QS_XTR_RD, 0x000008),
712 + REG(QS_XTR_FRM_PRUNING, 0x000010),
713 + REG(QS_XTR_FLUSH, 0x000018),
714 + REG(QS_XTR_DATA_PRESENT, 0x00001c),
715 + REG(QS_XTR_CFG, 0x000020),
716 + REG(QS_INJ_GRP_CFG, 0x000024),
717 + REG(QS_INJ_WR, 0x00002c),
718 + REG(QS_INJ_CTRL, 0x000034),
719 + REG(QS_INJ_STATUS, 0x00003c),
720 + REG(QS_INJ_ERR, 0x000040),
721 + REG_RESERVED(QS_INH_DBG),
724 +static const u32 vsc9959_s2_regmap[] = {
725 + REG(S2_CORE_UPDATE_CTRL, 0x000000),
726 + REG(S2_CORE_MV_CFG, 0x000004),
727 + REG(S2_CACHE_ENTRY_DAT, 0x000008),
728 + REG(S2_CACHE_MASK_DAT, 0x000108),
729 + REG(S2_CACHE_ACTION_DAT, 0x000208),
730 + REG(S2_CACHE_CNT_DAT, 0x000308),
731 + REG(S2_CACHE_TG_DAT, 0x000388),
734 +static const u32 vsc9959_qsys_regmap[] = {
735 + REG(QSYS_PORT_MODE, 0x00f460),
736 + REG(QSYS_SWITCH_PORT_MODE, 0x00f480),
737 + REG(QSYS_STAT_CNT_CFG, 0x00f49c),
738 + REG(QSYS_EEE_CFG, 0x00f4a0),
739 + REG(QSYS_EEE_THRES, 0x00f4b8),
740 + REG(QSYS_IGR_NO_SHARING, 0x00f4bc),
741 + REG(QSYS_EGR_NO_SHARING, 0x00f4c0),
742 + REG(QSYS_SW_STATUS, 0x00f4c4),
743 + REG(QSYS_EXT_CPU_CFG, 0x00f4e0),
744 + REG_RESERVED(QSYS_PAD_CFG),
745 + REG(QSYS_CPU_GROUP_MAP, 0x00f4e8),
746 + REG_RESERVED(QSYS_QMAP),
747 + REG_RESERVED(QSYS_ISDX_SGRP),
748 + REG_RESERVED(QSYS_TIMED_FRAME_ENTRY),
749 + REG(QSYS_TFRM_MISC, 0x00f50c),
750 + REG(QSYS_TFRM_PORT_DLY, 0x00f510),
751 + REG(QSYS_TFRM_TIMER_CFG_1, 0x00f514),
752 + REG(QSYS_TFRM_TIMER_CFG_2, 0x00f518),
753 + REG(QSYS_TFRM_TIMER_CFG_3, 0x00f51c),
754 + REG(QSYS_TFRM_TIMER_CFG_4, 0x00f520),
755 + REG(QSYS_TFRM_TIMER_CFG_5, 0x00f524),
756 + REG(QSYS_TFRM_TIMER_CFG_6, 0x00f528),
757 + REG(QSYS_TFRM_TIMER_CFG_7, 0x00f52c),
758 + REG(QSYS_TFRM_TIMER_CFG_8, 0x00f530),
759 + REG(QSYS_RED_PROFILE, 0x00f534),
760 + REG(QSYS_RES_QOS_MODE, 0x00f574),
761 + REG(QSYS_RES_CFG, 0x00c000),
762 + REG(QSYS_RES_STAT, 0x00c004),
763 + REG(QSYS_EGR_DROP_MODE, 0x00f578),
764 + REG(QSYS_EQ_CTRL, 0x00f57c),
765 + REG_RESERVED(QSYS_EVENTS_CORE),
766 + REG(QSYS_QMAXSDU_CFG_0, 0x00f584),
767 + REG(QSYS_QMAXSDU_CFG_1, 0x00f5a0),
768 + REG(QSYS_QMAXSDU_CFG_2, 0x00f5bc),
769 + REG(QSYS_QMAXSDU_CFG_3, 0x00f5d8),
770 + REG(QSYS_QMAXSDU_CFG_4, 0x00f5f4),
771 + REG(QSYS_QMAXSDU_CFG_5, 0x00f610),
772 + REG(QSYS_QMAXSDU_CFG_6, 0x00f62c),
773 + REG(QSYS_QMAXSDU_CFG_7, 0x00f648),
774 + REG(QSYS_PREEMPTION_CFG, 0x00f664),
775 + REG_RESERVED(QSYS_CIR_CFG),
776 + REG(QSYS_EIR_CFG, 0x000004),
777 + REG(QSYS_SE_CFG, 0x000008),
778 + REG(QSYS_SE_DWRR_CFG, 0x00000c),
779 + REG_RESERVED(QSYS_SE_CONNECT),
780 + REG(QSYS_SE_DLB_SENSE, 0x000040),
781 + REG(QSYS_CIR_STATE, 0x000044),
782 + REG(QSYS_EIR_STATE, 0x000048),
783 + REG_RESERVED(QSYS_SE_STATE),
784 + REG(QSYS_HSCH_MISC_CFG, 0x00f67c),
785 + REG(QSYS_TAG_CONFIG, 0x00f680),
786 + REG(QSYS_TAS_PARAM_CFG_CTRL, 0x00f698),
787 + REG(QSYS_PORT_MAX_SDU, 0x00f69c),
788 + REG(QSYS_PARAM_CFG_REG_1, 0x00f440),
789 + REG(QSYS_PARAM_CFG_REG_2, 0x00f444),
790 + REG(QSYS_PARAM_CFG_REG_3, 0x00f448),
791 + REG(QSYS_PARAM_CFG_REG_4, 0x00f44c),
792 + REG(QSYS_PARAM_CFG_REG_5, 0x00f450),
793 + REG(QSYS_GCL_CFG_REG_1, 0x00f454),
794 + REG(QSYS_GCL_CFG_REG_2, 0x00f458),
795 + REG(QSYS_PARAM_STATUS_REG_1, 0x00f400),
796 + REG(QSYS_PARAM_STATUS_REG_2, 0x00f404),
797 + REG(QSYS_PARAM_STATUS_REG_3, 0x00f408),
798 + REG(QSYS_PARAM_STATUS_REG_4, 0x00f40c),
799 + REG(QSYS_PARAM_STATUS_REG_5, 0x00f410),
800 + REG(QSYS_PARAM_STATUS_REG_6, 0x00f414),
801 + REG(QSYS_PARAM_STATUS_REG_7, 0x00f418),
802 + REG(QSYS_PARAM_STATUS_REG_8, 0x00f41c),
803 + REG(QSYS_PARAM_STATUS_REG_9, 0x00f420),
804 + REG(QSYS_GCL_STATUS_REG_1, 0x00f424),
805 + REG(QSYS_GCL_STATUS_REG_2, 0x00f428),
808 +static const u32 vsc9959_rew_regmap[] = {
809 + REG(REW_PORT_VLAN_CFG, 0x000000),
810 + REG(REW_TAG_CFG, 0x000004),
811 + REG(REW_PORT_CFG, 0x000008),
812 + REG(REW_DSCP_CFG, 0x00000c),
813 + REG(REW_PCP_DEI_QOS_MAP_CFG, 0x000010),
814 + REG(REW_PTP_CFG, 0x000050),
815 + REG(REW_PTP_DLY1_CFG, 0x000054),
816 + REG(REW_RED_TAG_CFG, 0x000058),
817 + REG(REW_DSCP_REMAP_DP1_CFG, 0x000410),
818 + REG(REW_DSCP_REMAP_CFG, 0x000510),
819 + REG_RESERVED(REW_STAT_CFG),
820 + REG_RESERVED(REW_REW_STICKY),
821 + REG_RESERVED(REW_PPT),
824 +static const u32 vsc9959_sys_regmap[] = {
825 + REG(SYS_COUNT_RX_OCTETS, 0x000000),
826 + REG(SYS_COUNT_RX_MULTICAST, 0x000008),
827 + REG(SYS_COUNT_RX_SHORTS, 0x000010),
828 + REG(SYS_COUNT_RX_FRAGMENTS, 0x000014),
829 + REG(SYS_COUNT_RX_JABBERS, 0x000018),
830 + REG(SYS_COUNT_RX_64, 0x000024),
831 + REG(SYS_COUNT_RX_65_127, 0x000028),
832 + REG(SYS_COUNT_RX_128_255, 0x00002c),
833 + REG(SYS_COUNT_RX_256_1023, 0x000030),
834 + REG(SYS_COUNT_RX_1024_1526, 0x000034),
835 + REG(SYS_COUNT_RX_1527_MAX, 0x000038),
836 + REG(SYS_COUNT_RX_LONGS, 0x000044),
837 + REG(SYS_COUNT_TX_OCTETS, 0x000200),
838 + REG(SYS_COUNT_TX_COLLISION, 0x000210),
839 + REG(SYS_COUNT_TX_DROPS, 0x000214),
840 + REG(SYS_COUNT_TX_64, 0x00021c),
841 + REG(SYS_COUNT_TX_65_127, 0x000220),
842 + REG(SYS_COUNT_TX_128_511, 0x000224),
843 + REG(SYS_COUNT_TX_512_1023, 0x000228),
844 + REG(SYS_COUNT_TX_1024_1526, 0x00022c),
845 + REG(SYS_COUNT_TX_1527_MAX, 0x000230),
846 + REG(SYS_COUNT_TX_AGING, 0x000278),
847 + REG(SYS_RESET_CFG, 0x000e00),
848 + REG(SYS_SR_ETYPE_CFG, 0x000e04),
849 + REG(SYS_VLAN_ETYPE_CFG, 0x000e08),
850 + REG(SYS_PORT_MODE, 0x000e0c),
851 + REG(SYS_FRONT_PORT_MODE, 0x000e2c),
852 + REG(SYS_FRM_AGING, 0x000e44),
853 + REG(SYS_STAT_CFG, 0x000e48),
854 + REG(SYS_SW_STATUS, 0x000e4c),
855 + REG_RESERVED(SYS_MISC_CFG),
856 + REG(SYS_REW_MAC_HIGH_CFG, 0x000e6c),
857 + REG(SYS_REW_MAC_LOW_CFG, 0x000e84),
858 + REG(SYS_TIMESTAMP_OFFSET, 0x000e9c),
859 + REG(SYS_PAUSE_CFG, 0x000ea0),
860 + REG(SYS_PAUSE_TOT_CFG, 0x000ebc),
861 + REG(SYS_ATOP, 0x000ec0),
862 + REG(SYS_ATOP_TOT_CFG, 0x000edc),
863 + REG(SYS_MAC_FC_CFG, 0x000ee0),
864 + REG(SYS_MMGT, 0x000ef8),
865 + REG_RESERVED(SYS_MMGT_FAST),
866 + REG_RESERVED(SYS_EVENTS_DIF),
867 + REG_RESERVED(SYS_EVENTS_CORE),
868 + REG_RESERVED(SYS_CNT),
869 + REG(SYS_PTP_STATUS, 0x000f14),
870 + REG(SYS_PTP_TXSTAMP, 0x000f18),
871 + REG(SYS_PTP_NXT, 0x000f1c),
872 + REG(SYS_PTP_CFG, 0x000f20),
873 + REG(SYS_RAM_INIT, 0x000f24),
874 + REG_RESERVED(SYS_CM_ADDR),
875 + REG_RESERVED(SYS_CM_DATA_WR),
876 + REG_RESERVED(SYS_CM_DATA_RD),
877 + REG_RESERVED(SYS_CM_OP),
878 + REG_RESERVED(SYS_CM_DATA),
881 +static const u32 vsc9959_gcb_regmap[] = {
882 + REG(GCB_SOFT_RST, 0x000004),
885 +static const u32 *vsc9959_regmap[] = {
886 + [ANA] = vsc9959_ana_regmap,
887 + [QS] = vsc9959_qs_regmap,
888 + [QSYS] = vsc9959_qsys_regmap,
889 + [REW] = vsc9959_rew_regmap,
890 + [SYS] = vsc9959_sys_regmap,
891 + [S2] = vsc9959_s2_regmap,
892 + [GCB] = vsc9959_gcb_regmap,
895 +/* Addresses are relative to the PCI device's base address and
896 + * will be fixed up at ioremap time.
898 +static struct resource vsc9959_target_io_res[] = {
900 + .start = 0x0280000,
905 + .start = 0x0080000,
910 + .start = 0x0200000,
915 + .start = 0x0030000,
920 + .start = 0x0010000,
925 + .start = 0x0060000,
930 + .start = 0x0070000,
932 + .name = "devcpu_gcb",
936 +static struct resource vsc9959_port_io_res[] = {
938 + .start = 0x0100000,
943 + .start = 0x0110000,
948 + .start = 0x0120000,
953 + .start = 0x0130000,
958 + .start = 0x0140000,
963 + .start = 0x0150000,
969 +static const struct reg_field vsc9959_regfields[] = {
970 + [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),
971 + [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5),
972 + [ANA_ANEVENTS_FLOOD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 30, 30),
973 + [ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 26, 26),
974 + [ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 24, 24),
975 + [ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 23, 23),
976 + [ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 22, 22),
977 + [ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 21, 21),
978 + [ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 20, 20),
979 + [ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 19, 19),
980 + [ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 18, 18),
981 + [ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 17, 17),
982 + [ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 15, 15),
983 + [ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 14, 14),
984 + [ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 13, 13),
985 + [ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 12, 12),
986 + [ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 11, 11),
987 + [ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 10, 10),
988 + [ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 9, 9),
989 + [ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 8, 8),
990 + [ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 7, 7),
991 + [ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),
992 + [ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),
993 + [ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 4, 4),
994 + [ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 3, 3),
995 + [ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 2, 2),
996 + [ANA_ANEVENTS_SEQ_GEN_ERR_0] = REG_FIELD(ANA_ANEVENTS, 1, 1),
997 + [ANA_ANEVENTS_SEQ_GEN_ERR_1] = REG_FIELD(ANA_ANEVENTS, 0, 0),
998 + [ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 16, 16),
999 + [ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 11, 12),
1000 + [ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10),
1001 + [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 0, 0),
1002 + [GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0),
1005 +static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
1006 + { .offset = 0x00, .name = "rx_octets", },
1007 + { .offset = 0x01, .name = "rx_unicast", },
1008 + { .offset = 0x02, .name = "rx_multicast", },
1009 + { .offset = 0x03, .name = "rx_broadcast", },
1010 + { .offset = 0x04, .name = "rx_shorts", },
1011 + { .offset = 0x05, .name = "rx_fragments", },
1012 + { .offset = 0x06, .name = "rx_jabbers", },
1013 + { .offset = 0x07, .name = "rx_crc_align_errs", },
1014 + { .offset = 0x08, .name = "rx_sym_errs", },
1015 + { .offset = 0x09, .name = "rx_frames_below_65_octets", },
1016 + { .offset = 0x0A, .name = "rx_frames_65_to_127_octets", },
1017 + { .offset = 0x0B, .name = "rx_frames_128_to_255_octets", },
1018 + { .offset = 0x0C, .name = "rx_frames_256_to_511_octets", },
1019 + { .offset = 0x0D, .name = "rx_frames_512_to_1023_octets", },
1020 + { .offset = 0x0E, .name = "rx_frames_1024_to_1526_octets", },
1021 + { .offset = 0x0F, .name = "rx_frames_over_1526_octets", },
1022 + { .offset = 0x10, .name = "rx_pause", },
1023 + { .offset = 0x11, .name = "rx_control", },
1024 + { .offset = 0x12, .name = "rx_longs", },
1025 + { .offset = 0x13, .name = "rx_classified_drops", },
1026 + { .offset = 0x14, .name = "rx_red_prio_0", },
1027 + { .offset = 0x15, .name = "rx_red_prio_1", },
1028 + { .offset = 0x16, .name = "rx_red_prio_2", },
1029 + { .offset = 0x17, .name = "rx_red_prio_3", },
1030 + { .offset = 0x18, .name = "rx_red_prio_4", },
1031 + { .offset = 0x19, .name = "rx_red_prio_5", },
1032 + { .offset = 0x1A, .name = "rx_red_prio_6", },
1033 + { .offset = 0x1B, .name = "rx_red_prio_7", },
1034 + { .offset = 0x1C, .name = "rx_yellow_prio_0", },
1035 + { .offset = 0x1D, .name = "rx_yellow_prio_1", },
1036 + { .offset = 0x1E, .name = "rx_yellow_prio_2", },
1037 + { .offset = 0x1F, .name = "rx_yellow_prio_3", },
1038 + { .offset = 0x20, .name = "rx_yellow_prio_4", },
1039 + { .offset = 0x21, .name = "rx_yellow_prio_5", },
1040 + { .offset = 0x22, .name = "rx_yellow_prio_6", },
1041 + { .offset = 0x23, .name = "rx_yellow_prio_7", },
1042 + { .offset = 0x24, .name = "rx_green_prio_0", },
1043 + { .offset = 0x25, .name = "rx_green_prio_1", },
1044 + { .offset = 0x26, .name = "rx_green_prio_2", },
1045 + { .offset = 0x27, .name = "rx_green_prio_3", },
1046 + { .offset = 0x28, .name = "rx_green_prio_4", },
1047 + { .offset = 0x29, .name = "rx_green_prio_5", },
1048 + { .offset = 0x2A, .name = "rx_green_prio_6", },
1049 + { .offset = 0x2B, .name = "rx_green_prio_7", },
1050 + { .offset = 0x80, .name = "tx_octets", },
1051 + { .offset = 0x81, .name = "tx_unicast", },
1052 + { .offset = 0x82, .name = "tx_multicast", },
1053 + { .offset = 0x83, .name = "tx_broadcast", },
1054 + { .offset = 0x84, .name = "tx_collision", },
1055 + { .offset = 0x85, .name = "tx_drops", },
1056 + { .offset = 0x86, .name = "tx_pause", },
1057 + { .offset = 0x87, .name = "tx_frames_below_65_octets", },
1058 + { .offset = 0x88, .name = "tx_frames_65_to_127_octets", },
1059 + { .offset = 0x89, .name = "tx_frames_128_255_octets", },
1060 + { .offset = 0x8B, .name = "tx_frames_256_511_octets", },
1061 + { .offset = 0x8C, .name = "tx_frames_1024_1526_octets", },
1062 + { .offset = 0x8D, .name = "tx_frames_over_1526_octets", },
1063 + { .offset = 0x8E, .name = "tx_yellow_prio_0", },
1064 + { .offset = 0x8F, .name = "tx_yellow_prio_1", },
1065 + { .offset = 0x90, .name = "tx_yellow_prio_2", },
1066 + { .offset = 0x91, .name = "tx_yellow_prio_3", },
1067 + { .offset = 0x92, .name = "tx_yellow_prio_4", },
1068 + { .offset = 0x93, .name = "tx_yellow_prio_5", },
1069 + { .offset = 0x94, .name = "tx_yellow_prio_6", },
1070 + { .offset = 0x95, .name = "tx_yellow_prio_7", },
1071 + { .offset = 0x96, .name = "tx_green_prio_0", },
1072 + { .offset = 0x97, .name = "tx_green_prio_1", },
1073 + { .offset = 0x98, .name = "tx_green_prio_2", },
1074 + { .offset = 0x99, .name = "tx_green_prio_3", },
1075 + { .offset = 0x9A, .name = "tx_green_prio_4", },
1076 + { .offset = 0x9B, .name = "tx_green_prio_5", },
1077 + { .offset = 0x9C, .name = "tx_green_prio_6", },
1078 + { .offset = 0x9D, .name = "tx_green_prio_7", },
1079 + { .offset = 0x9E, .name = "tx_aged", },
1080 + { .offset = 0x100, .name = "drop_local", },
1081 + { .offset = 0x101, .name = "drop_tail", },
1082 + { .offset = 0x102, .name = "drop_yellow_prio_0", },
1083 + { .offset = 0x103, .name = "drop_yellow_prio_1", },
1084 + { .offset = 0x104, .name = "drop_yellow_prio_2", },
1085 + { .offset = 0x105, .name = "drop_yellow_prio_3", },
1086 + { .offset = 0x106, .name = "drop_yellow_prio_4", },
1087 + { .offset = 0x107, .name = "drop_yellow_prio_5", },
1088 + { .offset = 0x108, .name = "drop_yellow_prio_6", },
1089 + { .offset = 0x109, .name = "drop_yellow_prio_7", },
1090 + { .offset = 0x10A, .name = "drop_green_prio_0", },
1091 + { .offset = 0x10B, .name = "drop_green_prio_1", },
1092 + { .offset = 0x10C, .name = "drop_green_prio_2", },
1093 + { .offset = 0x10D, .name = "drop_green_prio_3", },
1094 + { .offset = 0x10E, .name = "drop_green_prio_4", },
1095 + { .offset = 0x10F, .name = "drop_green_prio_5", },
1096 + { .offset = 0x110, .name = "drop_green_prio_6", },
1097 + { .offset = 0x111, .name = "drop_green_prio_7", },
1100 +#define VSC9959_INIT_TIMEOUT 50000
1101 +#define VSC9959_GCB_RST_SLEEP 100
1102 +#define VSC9959_SYS_RAMINIT_SLEEP 80
1104 +static int vsc9959_gcb_soft_rst_status(struct ocelot *ocelot)
1108 + regmap_field_read(ocelot->regfields[GCB_SOFT_RST_SWC_RST], &val);
1113 +static int vsc9959_sys_ram_init_status(struct ocelot *ocelot)
1115 + return ocelot_read(ocelot, SYS_RAM_INIT);
1118 +static int vsc9959_reset(struct ocelot *ocelot)
1122 + /* soft-reset the switch core */
1123 + regmap_field_write(ocelot->regfields[GCB_SOFT_RST_SWC_RST], 1);
1125 + err = readx_poll_timeout(vsc9959_gcb_soft_rst_status, ocelot, val, !val,
1126 + VSC9959_GCB_RST_SLEEP, VSC9959_INIT_TIMEOUT);
1128 + dev_err(ocelot->dev, "timeout: switch core reset\n");
1132 + /* initialize switch mem ~40us */
1133 + ocelot_write(ocelot, SYS_RAM_INIT_RAM_INIT, SYS_RAM_INIT);
1134 + err = readx_poll_timeout(vsc9959_sys_ram_init_status, ocelot, val, !val,
1135 + VSC9959_SYS_RAMINIT_SLEEP,
1136 + VSC9959_INIT_TIMEOUT);
1138 + dev_err(ocelot->dev, "timeout: switch sram init\n");
1142 + /* enable switch core */
1143 + regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
1148 +static const struct ocelot_ops vsc9959_ops = {
1149 + .reset = vsc9959_reset,
1152 +struct felix_info felix_info_vsc9959 = {
1153 + .target_io_res = vsc9959_target_io_res,
1154 + .port_io_res = vsc9959_port_io_res,
1155 + .regfields = vsc9959_regfields,
1156 + .map = vsc9959_regmap,
1157 + .ops = &vsc9959_ops,
1158 + .stats_layout = vsc9959_stats_layout,
1159 + .num_stats = ARRAY_SIZE(vsc9959_stats_layout),
1160 + .shared_queue_sz = 128 * 1024,