079932d025c974ffc8b949820f180705b5108529
[openwrt/staging/mkresin.git] /
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
5
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.
10
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.
16
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).
21
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
26 embedded MIPS).
27
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.
33
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
37 device tree though.
38
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>
42 ---
43 MAINTAINERS | 1 +
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
57
58 --- a/MAINTAINERS
59 +++ b/MAINTAINERS
60 @@ -17359,6 +17359,7 @@ M: Vladimir Oltean <vladimir.oltean@nxp.
61 M: Claudiu Manoil <claudiu.manoil@nxp.com>
62 L: netdev@vger.kernel.org
63 S: Maintained
64 +F: drivers/net/dsa/ocelot/*
65 F: net/dsa/tag_ocelot.c
66
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
71
72 source "drivers/net/dsa/mv88e6xxx/Kconfig"
73
74 +source "drivers/net/dsa/ocelot/Kconfig"
75 +
76 source "drivers/net/dsa/sja1105/Kconfig"
77
78 config NET_DSA_QCA8K
79 --- a/drivers/net/dsa/Makefile
80 +++ b/drivers/net/dsa/Makefile
81 @@ -20,4 +20,5 @@ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_SPI
82 obj-y += b53/
83 obj-y += microchip/
84 obj-y += mv88e6xxx/
85 +obj-y += ocelot/
86 obj-y += sja1105/
87 --- /dev/null
88 +++ b/drivers/net/dsa/ocelot/Kconfig
89 @@ -0,0 +1,11 @@
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
96 + help
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
100 + endpoint.
101 --- /dev/null
102 +++ b/drivers/net/dsa/ocelot/Makefile
103 @@ -0,0 +1,6 @@
104 +# SPDX-License-Identifier: GPL-2.0-only
105 +obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
106 +
107 +mscc_felix-objs := \
108 + felix.o \
109 + felix_vsc9959.o
110 --- /dev/null
111 +++ b/drivers/net/dsa/ocelot/felix.c
112 @@ -0,0 +1,441 @@
113 +// SPDX-License-Identifier: GPL-2.0
114 +/* Copyright 2019 NXP Semiconductors
115 + */
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>
122 +#include "felix.h"
123 +
124 +static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
125 + int port)
126 +{
127 + return DSA_TAG_PROTO_OCELOT;
128 +}
129 +
130 +static int felix_set_ageing_time(struct dsa_switch *ds,
131 + unsigned int ageing_time)
132 +{
133 + struct ocelot *ocelot = ds->priv;
134 +
135 + ocelot_set_ageing_time(ocelot, ageing_time);
136 +
137 + return 0;
138 +}
139 +
140 +static void felix_adjust_link(struct dsa_switch *ds, int port,
141 + struct phy_device *phydev)
142 +{
143 + struct ocelot *ocelot = ds->priv;
144 +
145 + ocelot_adjust_link(ocelot, port, phydev);
146 +}
147 +
148 +static int felix_fdb_dump(struct dsa_switch *ds, int port,
149 + dsa_fdb_dump_cb_t *cb, void *data)
150 +{
151 + struct ocelot *ocelot = ds->priv;
152 +
153 + return ocelot_fdb_dump(ocelot, port, cb, data);
154 +}
155 +
156 +static int felix_fdb_add(struct dsa_switch *ds, int port,
157 + const unsigned char *addr, u16 vid)
158 +{
159 + struct ocelot *ocelot = ds->priv;
160 + bool vlan_aware;
161 +
162 + vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port));
163 +
164 + return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware);
165 +}
166 +
167 +static int felix_fdb_del(struct dsa_switch *ds, int port,
168 + const unsigned char *addr, u16 vid)
169 +{
170 + struct ocelot *ocelot = ds->priv;
171 +
172 + return ocelot_fdb_del(ocelot, port, addr, vid);
173 +}
174 +
175 +static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port,
176 + u8 state)
177 +{
178 + struct ocelot *ocelot = ds->priv;
179 +
180 + return ocelot_bridge_stp_state_set(ocelot, port, state);
181 +}
182 +
183 +static int felix_bridge_join(struct dsa_switch *ds, int port,
184 + struct net_device *br)
185 +{
186 + struct ocelot *ocelot = ds->priv;
187 +
188 + return ocelot_port_bridge_join(ocelot, port, br);
189 +}
190 +
191 +static void felix_bridge_leave(struct dsa_switch *ds, int port,
192 + struct net_device *br)
193 +{
194 + struct ocelot *ocelot = ds->priv;
195 +
196 + ocelot_port_bridge_leave(ocelot, port, br);
197 +}
198 +
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)
202 +{
203 + return 0;
204 +}
205 +
206 +static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
207 +{
208 + struct ocelot *ocelot = ds->priv;
209 +
210 + ocelot_port_vlan_filtering(ocelot, port, enabled);
211 +
212 + return 0;
213 +}
214 +
215 +static void felix_vlan_add(struct dsa_switch *ds, int port,
216 + const struct switchdev_obj_port_vlan *vlan)
217 +{
218 + struct ocelot *ocelot = ds->priv;
219 + u16 vid;
220 + int err;
221 +
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);
226 + if (err) {
227 + dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n",
228 + vid, port, err);
229 + return;
230 + }
231 + }
232 +}
233 +
234 +static int felix_vlan_del(struct dsa_switch *ds, int port,
235 + const struct switchdev_obj_port_vlan *vlan)
236 +{
237 + struct ocelot *ocelot = ds->priv;
238 + u16 vid;
239 + int err;
240 +
241 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
242 + err = ocelot_vlan_del(ocelot, port, vid);
243 + if (err) {
244 + dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n",
245 + vid, port, err);
246 + return err;
247 + }
248 + }
249 + return 0;
250 +}
251 +
252 +static int felix_port_enable(struct dsa_switch *ds, int port,
253 + struct phy_device *phy)
254 +{
255 + struct ocelot *ocelot = ds->priv;
256 +
257 + ocelot_port_enable(ocelot, port, phy);
258 +
259 + return 0;
260 +}
261 +
262 +static void felix_port_disable(struct dsa_switch *ds, int port)
263 +{
264 + struct ocelot *ocelot = ds->priv;
265 +
266 + return ocelot_port_disable(ocelot, port);
267 +}
268 +
269 +static void felix_get_strings(struct dsa_switch *ds, int port,
270 + u32 stringset, u8 *data)
271 +{
272 + struct ocelot *ocelot = ds->priv;
273 +
274 + return ocelot_get_strings(ocelot, port, stringset, data);
275 +}
276 +
277 +static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
278 +{
279 + struct ocelot *ocelot = ds->priv;
280 +
281 + ocelot_get_ethtool_stats(ocelot, port, data);
282 +}
283 +
284 +static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset)
285 +{
286 + struct ocelot *ocelot = ds->priv;
287 +
288 + return ocelot_get_sset_count(ocelot, port, sset);
289 +}
290 +
291 +static int felix_get_ts_info(struct dsa_switch *ds, int port,
292 + struct ethtool_ts_info *info)
293 +{
294 + struct ocelot *ocelot = ds->priv;
295 +
296 + return ocelot_get_ts_info(ocelot, port, info);
297 +}
298 +
299 +static int felix_init_structs(struct felix *felix, int num_phys_ports)
300 +{
301 + struct ocelot *ocelot = &felix->ocelot;
302 + resource_size_t base;
303 + int port, i, err;
304 +
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)
309 + return -ENOMEM;
310 +
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;
316 +
317 + base = pci_resource_start(felix->pdev, felix->info->pci_bar);
318 +
319 + for (i = 0; i < TARGET_MAX; i++) {
320 + struct regmap *target;
321 + struct resource *res;
322 +
323 + if (!felix->info->target_io_res[i].name)
324 + continue;
325 +
326 + res = &felix->info->target_io_res[i];
327 + res->flags = IORESOURCE_MEM;
328 + res->start += base;
329 + res->end += base;
330 +
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);
336 + }
337 +
338 + ocelot->targets[i] = target;
339 + }
340 +
341 + err = ocelot_regfields_init(ocelot, felix->info->regfields);
342 + if (err) {
343 + dev_err(ocelot->dev, "failed to init reg fields map\n");
344 + return err;
345 + }
346 +
347 + for (port = 0; port < num_phys_ports; port++) {
348 + struct ocelot_port *ocelot_port;
349 + void __iomem *port_regs;
350 + struct resource *res;
351 +
352 + ocelot_port = devm_kzalloc(ocelot->dev,
353 + sizeof(struct ocelot_port),
354 + GFP_KERNEL);
355 + if (!ocelot_port) {
356 + dev_err(ocelot->dev,
357 + "failed to allocate port memory\n");
358 + return -ENOMEM;
359 + }
360 +
361 + res = &felix->info->port_io_res[port];
362 + res->flags = IORESOURCE_MEM;
363 + res->start += base;
364 + res->end += base;
365 +
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);
371 + }
372 +
373 + ocelot_port->ocelot = ocelot;
374 + ocelot_port->regs = port_regs;
375 + ocelot->ports[port] = ocelot_port;
376 + }
377 +
378 + return 0;
379 +}
380 +
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).
385 + */
386 +static int felix_setup(struct dsa_switch *ds)
387 +{
388 + struct ocelot *ocelot = ds->priv;
389 + struct felix *felix = ocelot_to_felix(ocelot);
390 + int port, err;
391 +
392 + err = felix_init_structs(felix, ds->num_ports);
393 + if (err)
394 + return err;
395 +
396 + ocelot_init(ocelot);
397 +
398 + for (port = 0; port < ds->num_ports; port++) {
399 + ocelot_init_port(ocelot, port);
400 +
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);
405 + }
406 +
407 + return 0;
408 +}
409 +
410 +static void felix_teardown(struct dsa_switch *ds)
411 +{
412 + struct ocelot *ocelot = ds->priv;
413 +
414 + /* stop workqueue thread */
415 + ocelot_deinit(ocelot);
416 +}
417 +
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,
440 +};
441 +
442 +static struct felix_info *felix_instance_tbl[] = {
443 + [FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959,
444 +};
445 +
446 +static int felix_pci_probe(struct pci_dev *pdev,
447 + const struct pci_device_id *id)
448 +{
449 + enum felix_instance instance = id->driver_data;
450 + struct dsa_switch *ds;
451 + struct ocelot *ocelot;
452 + struct felix *felix;
453 + int err;
454 +
455 + err = pci_enable_device(pdev);
456 + if (err) {
457 + dev_err(&pdev->dev, "device enable failed\n");
458 + goto err_pci_enable;
459 + }
460 +
461 + /* set up for high or low dma */
462 + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
463 + if (err) {
464 + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
465 + if (err) {
466 + dev_err(&pdev->dev,
467 + "DMA configuration failed: 0x%x\n", err);
468 + goto err_dma;
469 + }
470 + }
471 +
472 + felix = kzalloc(sizeof(struct felix), GFP_KERNEL);
473 + if (!felix) {
474 + err = -ENOMEM;
475 + dev_err(&pdev->dev, "Failed to allocate driver memory\n");
476 + goto err_alloc_felix;
477 + }
478 +
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];
484 +
485 + pci_set_master(pdev);
486 +
487 + ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
488 + if (!ds) {
489 + err = -ENOMEM;
490 + dev_err(&pdev->dev, "Failed to allocate DSA switch\n");
491 + goto err_alloc_ds;
492 + }
493 +
494 + ds->dev = &pdev->dev;
495 + ds->num_ports = felix->info->num_ports;
496 + ds->ops = &felix_switch_ops;
497 + ds->priv = ocelot;
498 + felix->ds = ds;
499 +
500 + err = dsa_register_switch(ds);
501 + if (err) {
502 + dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
503 + goto err_register_ds;
504 + }
505 +
506 + return 0;
507 +
508 +err_register_ds:
509 + kfree(ds);
510 +err_alloc_ds:
511 +err_alloc_felix:
512 + kfree(felix);
513 +err_dma:
514 + pci_disable_device(pdev);
515 +err_pci_enable:
516 + return err;
517 +}
518 +
519 +static void felix_pci_remove(struct pci_dev *pdev)
520 +{
521 + struct felix *felix;
522 +
523 + felix = pci_get_drvdata(pdev);
524 +
525 + dsa_unregister_switch(felix->ds);
526 +
527 + kfree(felix->ds);
528 + kfree(felix);
529 +
530 + pci_disable_device(pdev);
531 +}
532 +
533 +static struct pci_device_id felix_ids[] = {
534 + {
535 + /* NXP LS1028A */
536 + PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0),
537 + .driver_data = FELIX_INSTANCE_VSC9959,
538 + },
539 + { 0, }
540 +};
541 +MODULE_DEVICE_TABLE(pci, felix_ids);
542 +
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,
548 +};
549 +
550 +module_pci_driver(felix_pci_driver);
551 +
552 +MODULE_DESCRIPTION("Felix Switch driver");
553 +MODULE_LICENSE("GPL v2");
554 --- /dev/null
555 +++ b/drivers/net/dsa/ocelot/felix.h
556 @@ -0,0 +1,37 @@
557 +/* SPDX-License-Identifier: GPL-2.0 */
558 +/* Copyright 2019 NXP Semiconductors
559 + */
560 +#ifndef _MSCC_FELIX_H
561 +#define _MSCC_FELIX_H
562 +
563 +#define ocelot_to_felix(o) container_of((o), struct felix, ocelot)
564 +
565 +/* Platform-specific information */
566 +struct felix_info {
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;
575 + int num_ports;
576 + int pci_bar;
577 +};
578 +
579 +extern struct felix_info felix_info_vsc9959;
580 +
581 +enum felix_instance {
582 + FELIX_INSTANCE_VSC9959 = 0,
583 +};
584 +
585 +/* DSA glue / front-end for struct ocelot */
586 +struct felix {
587 + struct dsa_switch *ds;
588 + struct pci_dev *pdev;
589 + struct felix_info *info;
590 + struct ocelot ocelot;
591 +};
592 +
593 +#endif
594 --- /dev/null
595 +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
596 @@ -0,0 +1,567 @@
597 +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
598 +/* Copyright 2017 Microsemi Corporation
599 + * Copyright 2018-2019 NXP Semiconductors
600 + */
601 +#include <soc/mscc/ocelot_sys.h>
602 +#include <soc/mscc/ocelot.h>
603 +#include <linux/iopoll.h>
604 +#include <linux/pci.h>
605 +#include "felix.h"
606 +
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),
707 +};
708 +
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),
722 +};
723 +
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),
732 +};
733 +
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),
806 +};
807 +
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),
822 +};
823 +
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),
879 +};
880 +
881 +static const u32 vsc9959_gcb_regmap[] = {
882 + REG(GCB_SOFT_RST, 0x000004),
883 +};
884 +
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,
893 +};
894 +
895 +/* Addresses are relative to the PCI device's base address and
896 + * will be fixed up at ioremap time.
897 + */
898 +static struct resource vsc9959_target_io_res[] = {
899 + [ANA] = {
900 + .start = 0x0280000,
901 + .end = 0x028ffff,
902 + .name = "ana",
903 + },
904 + [QS] = {
905 + .start = 0x0080000,
906 + .end = 0x00800ff,
907 + .name = "qs",
908 + },
909 + [QSYS] = {
910 + .start = 0x0200000,
911 + .end = 0x021ffff,
912 + .name = "qsys",
913 + },
914 + [REW] = {
915 + .start = 0x0030000,
916 + .end = 0x003ffff,
917 + .name = "rew",
918 + },
919 + [SYS] = {
920 + .start = 0x0010000,
921 + .end = 0x001ffff,
922 + .name = "sys",
923 + },
924 + [S2] = {
925 + .start = 0x0060000,
926 + .end = 0x00603ff,
927 + .name = "s2",
928 + },
929 + [GCB] = {
930 + .start = 0x0070000,
931 + .end = 0x00701ff,
932 + .name = "devcpu_gcb",
933 + },
934 +};
935 +
936 +static struct resource vsc9959_port_io_res[] = {
937 + {
938 + .start = 0x0100000,
939 + .end = 0x010ffff,
940 + .name = "port0",
941 + },
942 + {
943 + .start = 0x0110000,
944 + .end = 0x011ffff,
945 + .name = "port1",
946 + },
947 + {
948 + .start = 0x0120000,
949 + .end = 0x012ffff,
950 + .name = "port2",
951 + },
952 + {
953 + .start = 0x0130000,
954 + .end = 0x013ffff,
955 + .name = "port3",
956 + },
957 + {
958 + .start = 0x0140000,
959 + .end = 0x014ffff,
960 + .name = "port4",
961 + },
962 + {
963 + .start = 0x0150000,
964 + .end = 0x015ffff,
965 + .name = "port5",
966 + },
967 +};
968 +
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),
1003 +};
1004 +
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", },
1098 +};
1099 +
1100 +#define VSC9959_INIT_TIMEOUT 50000
1101 +#define VSC9959_GCB_RST_SLEEP 100
1102 +#define VSC9959_SYS_RAMINIT_SLEEP 80
1103 +
1104 +static int vsc9959_gcb_soft_rst_status(struct ocelot *ocelot)
1105 +{
1106 + int val;
1107 +
1108 + regmap_field_read(ocelot->regfields[GCB_SOFT_RST_SWC_RST], &val);
1109 +
1110 + return val;
1111 +}
1112 +
1113 +static int vsc9959_sys_ram_init_status(struct ocelot *ocelot)
1114 +{
1115 + return ocelot_read(ocelot, SYS_RAM_INIT);
1116 +}
1117 +
1118 +static int vsc9959_reset(struct ocelot *ocelot)
1119 +{
1120 + int val, err;
1121 +
1122 + /* soft-reset the switch core */
1123 + regmap_field_write(ocelot->regfields[GCB_SOFT_RST_SWC_RST], 1);
1124 +
1125 + err = readx_poll_timeout(vsc9959_gcb_soft_rst_status, ocelot, val, !val,
1126 + VSC9959_GCB_RST_SLEEP, VSC9959_INIT_TIMEOUT);
1127 + if (err) {
1128 + dev_err(ocelot->dev, "timeout: switch core reset\n");
1129 + return err;
1130 + }
1131 +
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);
1137 + if (err) {
1138 + dev_err(ocelot->dev, "timeout: switch sram init\n");
1139 + return err;
1140 + }
1141 +
1142 + /* enable switch core */
1143 + regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
1144 +
1145 + return 0;
1146 +}
1147 +
1148 +static const struct ocelot_ops vsc9959_ops = {
1149 + .reset = vsc9959_reset,
1150 +};
1151 +
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,
1161 + .num_ports = 6,
1162 + .pci_bar = 4,
1163 +};