1 From 36b446d44d66a6d6a072d3f5e87ebb05e0b88d98 Mon Sep 17 00:00:00 2001
2 From: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
3 Date: Fri, 29 Nov 2019 14:28:37 +0800
4 Subject: [PATCH] net: dsa: ocelot: add tsn support for felix switch
6 Support tsn capabilities in DSA felix switch driver. This felix tsn
7 driver is using tsn configuration of ocelot, and registered on each
8 switch port through DSA port setup.
10 Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
12 drivers/net/dsa/ocelot/Kconfig | 8 +
13 drivers/net/dsa/ocelot/Makefile | 2 +
14 drivers/net/dsa/ocelot/felix.c | 50 ++++
15 drivers/net/dsa/ocelot/felix_tsn.c | 432 +++++++++++++++++++++++++++++++++
16 drivers/net/dsa/ocelot/felix_tsn.h | 61 +++++
17 drivers/net/dsa/ocelot/felix_vsc9959.c | 8 +-
18 include/net/dsa.h | 1 +
20 8 files changed, 564 insertions(+), 2 deletions(-)
21 create mode 100644 drivers/net/dsa/ocelot/felix_tsn.c
22 create mode 100644 drivers/net/dsa/ocelot/felix_tsn.h
24 --- a/drivers/net/dsa/ocelot/Kconfig
25 +++ b/drivers/net/dsa/ocelot/Kconfig
26 @@ -9,3 +9,11 @@ config NET_DSA_MSCC_FELIX
27 the Vitesse / Microsemi / Microchip Ocelot family of switching cores.
28 It is embedded as a PCIe function of the NXP LS1028A ENETC integrated
31 +config MSCC_FELIX_SWITCH_TSN
32 + tristate "TSN on FELIX switch driver"
33 + depends on NET_DSA_MSCC_FELIX
36 + This driver supports TSN on felix switch.
38 --- a/drivers/net/dsa/ocelot/Makefile
39 +++ b/drivers/net/dsa/ocelot/Makefile
40 @@ -4,3 +4,5 @@ obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc
45 +obj-$(CONFIG_MSCC_FELIX_SWITCH_TSN) += felix_tsn.o
46 --- a/drivers/net/dsa/ocelot/felix.c
47 +++ b/drivers/net/dsa/ocelot/felix.c
52 +#include "felix_tsn.h"
54 +#ifdef CONFIG_MSCC_FELIX_SWITCH_TSN
55 +const struct tsn_ops switch_tsn_ops = {
56 + .device_init = felix_tsn_init,
57 + .get_capability = felix_tsn_get_cap,
58 + .qbv_set = felix_qbv_set,
59 + .qbv_get = felix_qbv_get,
60 + .qbv_get_status = felix_qbv_get_status,
61 + .qbu_set = felix_qbu_set,
62 + .qbu_get = felix_qbu_get,
63 + .cb_streamid_set = felix_cb_streamid_set,
64 + .cb_streamid_get = felix_cb_streamid_get,
65 + .cb_streamid_counters_get = felix_cb_streamid_counters_get,
66 + .qci_sfi_set = felix_qci_sfi_set,
67 + .qci_sfi_get = felix_qci_sfi_get,
68 + .qci_sfi_counters_get = felix_qci_sfi_counters_get,
69 + .qci_get_maxcap = felix_qci_max_cap_get,
70 + .qci_sgi_set = felix_qci_sgi_set,
71 + .qci_sgi_get = felix_qci_sgi_get,
72 + .qci_sgi_status_get = felix_qci_sgi_status_get,
73 + .qci_fmi_set = felix_qci_fmi_set,
74 + .qci_fmi_get = felix_qci_fmi_get,
75 + .cbs_set = felix_cbs_set,
76 + .cbs_get = felix_cbs_get,
77 + .ct_set = felix_cut_thru_set,
78 + .cbgen_set = felix_seq_gen_set,
79 + .cbrec_set = felix_seq_rec_set,
80 + .cb_get = felix_cb_get,
81 + .dscp_set = felix_dscp_set,
85 static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
87 @@ -138,6 +170,21 @@ static int felix_vlan_del(struct dsa_swi
91 +#ifdef CONFIG_MSCC_FELIX_SWITCH_TSN
92 +static int felix_tsn_enable(struct dsa_port *dp)
94 + struct net_device *dev;
96 + if (dp->type == DSA_PORT_TYPE_USER) {
98 + tsn_port_register(dev,
99 + (struct tsn_ops *)&switch_tsn_ops,
100 + GROUP_OFFSET_SWITCH);
106 static int felix_port_enable(struct dsa_switch *ds, int port,
107 struct phy_device *phy)
109 @@ -386,6 +433,9 @@ static const struct dsa_switch_ops felix
110 .port_hwtstamp_set = felix_hwtstamp_set,
111 .port_rxtstamp = felix_rxtstamp,
112 .port_txtstamp = felix_txtstamp,
113 +#ifdef CONFIG_MSCC_FELIX_SWITCH_TSN
114 + .port_tsn_enable = felix_tsn_enable,
118 static struct felix_info *felix_instance_tbl[] = {
120 +++ b/drivers/net/dsa/ocelot/felix_tsn.c
122 +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
123 +/* Felix Switch TSN driver
125 + * Copyright 2018-2019 NXP
128 +#include <linux/io.h>
129 +#include <linux/module.h>
130 +#include <linux/kernel.h>
131 +#include <linux/pci.h>
132 +#include <soc/mscc/ocelot.h>
133 +#include <net/tsn.h>
136 +static struct ocelot *felix_dev_to_ocelot(struct net_device *ndev)
138 + struct pci_dev *pdev;
139 + struct felix *felix;
141 + pdev = list_entry(ndev->dev.parent, struct pci_dev, dev);
142 + felix = pci_get_drvdata(pdev);
146 + return &felix->ocelot;
149 +static int felix_dev_to_port(struct net_device *ndev, struct ocelot *ocelot)
151 + struct felix *felix = ocelot_to_felix(ocelot);
152 + struct dsa_switch *ds = felix->ds;
153 + struct dsa_port *dp;
156 + for (i = 0; i < ds->num_ports; i++) {
157 + dp = &ds->ports[i];
158 + if (dp->dn == ndev->dev.of_node)
165 +u32 felix_tsn_get_cap(struct net_device *ndev)
169 + cap = (TSN_CAP_QBV | TSN_CAP_QCI | TSN_CAP_QBU | TSN_CAP_CBS |
170 + TSN_CAP_CB | TSN_CAP_TBS | TSN_CAP_CTH);
175 +int felix_qbv_set(struct net_device *ndev,
176 + struct tsn_qbv_conf *shaper_config)
178 + struct ocelot *ocelot;
181 + ocelot = felix_dev_to_ocelot(ndev);
184 + port = felix_dev_to_port(ndev, ocelot);
188 + return ocelot_qbv_set(ocelot, port, shaper_config);
191 +int felix_qbv_get(struct net_device *ndev,
192 + struct tsn_qbv_conf *shaper_config)
194 + struct ocelot *ocelot;
197 + ocelot = felix_dev_to_ocelot(ndev);
200 + port = felix_dev_to_port(ndev, ocelot);
204 + return ocelot_qbv_get(ocelot, port, shaper_config);
207 +int felix_qbv_get_status(struct net_device *ndev,
208 + struct tsn_qbv_status *qbvstatus)
210 + struct ocelot *ocelot;
213 + ocelot = felix_dev_to_ocelot(ndev);
216 + port = felix_dev_to_port(ndev, ocelot);
220 + return ocelot_qbv_get_status(ocelot, port, qbvstatus);
223 +int felix_qbu_set(struct net_device *ndev, u8 preemptible)
225 + struct ocelot *ocelot;
228 + ocelot = felix_dev_to_ocelot(ndev);
231 + port = felix_dev_to_port(ndev, ocelot);
235 + return ocelot_qbu_set(ocelot, port, preemptible);
238 +int felix_qbu_get(struct net_device *ndev, struct tsn_preempt_status *c)
240 + struct ocelot *ocelot;
243 + ocelot = felix_dev_to_ocelot(ndev);
246 + port = felix_dev_to_port(ndev, ocelot);
250 + return ocelot_qbu_get(ocelot, port, c);
253 +int felix_cb_streamid_set(struct net_device *ndev, u32 index, bool enable,
254 + struct tsn_cb_streamid *streamid)
256 + struct ocelot *ocelot;
259 + ocelot = felix_dev_to_ocelot(ndev);
262 + port = felix_dev_to_port(ndev, ocelot);
266 + return ocelot_cb_streamid_set(ocelot, port, index, enable, streamid);
269 +int felix_cb_streamid_get(struct net_device *ndev, u32 index,
270 + struct tsn_cb_streamid *streamid)
272 + struct ocelot *ocelot;
275 + ocelot = felix_dev_to_ocelot(ndev);
278 + port = felix_dev_to_port(ndev, ocelot);
282 + return ocelot_cb_streamid_get(ocelot, port, index, streamid);
285 +int felix_cb_streamid_counters_get(struct net_device *ndev, u32 index,
286 + struct tsn_cb_streamid_counters *sc)
291 +int felix_qci_sfi_set(struct net_device *ndev, u32 index, bool enable,
292 + struct tsn_qci_psfp_sfi_conf *sfi)
294 + struct ocelot *ocelot;
297 + ocelot = felix_dev_to_ocelot(ndev);
300 + port = felix_dev_to_port(ndev, ocelot);
304 + return ocelot_qci_sfi_set(ocelot, port, index, enable, sfi);
307 +int felix_qci_sfi_get(struct net_device *ndev, u32 index,
308 + struct tsn_qci_psfp_sfi_conf *sfi)
310 + struct ocelot *ocelot;
313 + ocelot = felix_dev_to_ocelot(ndev);
316 + port = felix_dev_to_port(ndev, ocelot);
320 + return ocelot_qci_sfi_get(ocelot, port, index, sfi);
323 +int felix_qci_sfi_counters_get(struct net_device *ndev, u32 index,
324 + struct tsn_qci_psfp_sfi_counters *sfi_cnt)
326 + struct ocelot *ocelot;
329 + ocelot = felix_dev_to_ocelot(ndev);
332 + port = felix_dev_to_port(ndev, ocelot);
336 + return ocelot_qci_sfi_counters_get(ocelot, port, index, sfi_cnt);
339 +int felix_qci_max_cap_get(struct net_device *ndev,
340 + struct tsn_qci_psfp_stream_param *stream_para)
342 + struct ocelot *ocelot;
344 + ocelot = felix_dev_to_ocelot(ndev);
348 + return ocelot_qci_max_cap_get(ocelot, stream_para);
351 +int felix_qci_sgi_set(struct net_device *ndev, u32 index,
352 + struct tsn_qci_psfp_sgi_conf *sgi_conf)
354 + struct ocelot *ocelot;
357 + ocelot = felix_dev_to_ocelot(ndev);
360 + port = felix_dev_to_port(ndev, ocelot);
364 + return ocelot_qci_sgi_set(ocelot, port, index, sgi_conf);
367 +int felix_qci_sgi_get(struct net_device *ndev, u32 index,
368 + struct tsn_qci_psfp_sgi_conf *sgi_conf)
370 + struct ocelot *ocelot;
373 + ocelot = felix_dev_to_ocelot(ndev);
376 + port = felix_dev_to_port(ndev, ocelot);
380 + return ocelot_qci_sgi_get(ocelot, port, index, sgi_conf);
383 +int felix_qci_sgi_status_get(struct net_device *ndev, u32 index,
384 + struct tsn_psfp_sgi_status *sgi_status)
386 + struct ocelot *ocelot;
389 + ocelot = felix_dev_to_ocelot(ndev);
392 + port = felix_dev_to_port(ndev, ocelot);
396 + return ocelot_qci_sgi_status_get(ocelot, port, index, sgi_status);
399 +int felix_qci_fmi_set(struct net_device *ndev, u32 index,
400 + bool enable, struct tsn_qci_psfp_fmi *fmi)
402 + struct ocelot *ocelot;
405 + ocelot = felix_dev_to_ocelot(ndev);
408 + port = felix_dev_to_port(ndev, ocelot);
412 + return ocelot_qci_fmi_set(ocelot, port, index, enable, fmi);
415 +int felix_qci_fmi_get(struct net_device *ndev, u32 index,
416 + struct tsn_qci_psfp_fmi *fmi,
417 + struct tsn_qci_psfp_fmi_counters *counters)
419 + struct ocelot *ocelot;
422 + ocelot = felix_dev_to_ocelot(ndev);
425 + port = felix_dev_to_port(ndev, ocelot);
429 + return ocelot_qci_fmi_get(ocelot, port, index, fmi, counters);
432 +int felix_cbs_set(struct net_device *ndev, u8 tc, u8 bw)
434 + struct ocelot *ocelot;
437 + ocelot = felix_dev_to_ocelot(ndev);
440 + port = felix_dev_to_port(ndev, ocelot);
444 + return ocelot_cbs_set(ocelot, port, tc, bw);
447 +int felix_cbs_get(struct net_device *ndev, u8 tc)
449 + struct ocelot *ocelot;
452 + ocelot = felix_dev_to_ocelot(ndev);
455 + port = felix_dev_to_port(ndev, ocelot);
459 + return ocelot_cbs_get(ocelot, port, tc);
462 +int felix_cut_thru_set(struct net_device *ndev, u8 cut_thru)
464 + struct ocelot *ocelot;
467 + ocelot = felix_dev_to_ocelot(ndev);
470 + port = felix_dev_to_port(ndev, ocelot);
474 + return ocelot_cut_thru_set(ocelot, port, cut_thru);
477 +int felix_seq_gen_set(struct net_device *ndev, u32 index,
478 + struct tsn_seq_gen_conf *sg_conf)
480 + struct ocelot *ocelot;
483 + ocelot = felix_dev_to_ocelot(ndev);
486 + port = felix_dev_to_port(ndev, ocelot);
490 + return ocelot_seq_gen_set(ocelot, port, index, sg_conf);
493 +int felix_seq_rec_set(struct net_device *ndev, u32 index,
494 + struct tsn_seq_rec_conf *sr_conf)
496 + struct ocelot *ocelot;
499 + ocelot = felix_dev_to_ocelot(ndev);
502 + port = felix_dev_to_port(ndev, ocelot);
506 + return ocelot_seq_rec_set(ocelot, port, index, sr_conf);
509 +int felix_cb_get(struct net_device *ndev, u32 index,
510 + struct tsn_cb_status *c)
512 + struct ocelot *ocelot;
515 + ocelot = felix_dev_to_ocelot(ndev);
518 + port = felix_dev_to_port(ndev, ocelot);
522 + return ocelot_cb_get(ocelot, port, index, c);
525 +int felix_dscp_set(struct net_device *ndev, bool enable, const u8 dscp_ix,
526 + struct tsn_qos_switch_dscp_conf *c)
528 + struct ocelot *ocelot;
531 + ocelot = felix_dev_to_ocelot(ndev);
534 + port = felix_dev_to_port(ndev, ocelot);
538 + return ocelot_dscp_set(ocelot, port, enable, dscp_ix, c);
541 +void felix_tsn_init(struct net_device *ndev)
543 + struct ocelot *ocelot;
546 + ocelot = felix_dev_to_ocelot(ndev);
549 + port = felix_dev_to_port(ndev, ocelot);
551 + ocelot_pcp_map_enable(ocelot, port);
552 + ocelot_rtag_parse_enable(ocelot, port);
555 +++ b/drivers/net/dsa/ocelot/felix_tsn.h
557 +/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
559 + * TSN_SWITCH driver
561 + * Copyright 2018-2019 NXP
564 +#ifndef _MSCC_FELIX_SWITCH_TSN_H_
565 +#define _MSCC_FELIX_SWITCH_TSN_H_
566 +#include <net/tsn.h>
568 +u32 felix_tsn_get_cap(struct net_device *ndev);
569 +int felix_qbv_set(struct net_device *ndev,
570 + struct tsn_qbv_conf *shaper_config);
571 +int felix_qbv_get(struct net_device *ndev,
572 + struct tsn_qbv_conf *shaper_config);
573 +int felix_qbv_get_status(struct net_device *ndev,
574 + struct tsn_qbv_status *qbvstatus);
575 +int felix_cut_thru_set(struct net_device *ndev, u8 cut_thru);
576 +int felix_cbs_set(struct net_device *ndev, u8 tc, u8 bw);
577 +int felix_cbs_get(struct net_device *ndev, u8 tc);
578 +int felix_qbu_set(struct net_device *ndev, u8 preemptible);
579 +int felix_qbu_get(struct net_device *ndev, struct tsn_preempt_status *c);
580 +int felix_cb_streamid_get(struct net_device *ndev, u32 index,
581 + struct tsn_cb_streamid *streamid);
582 +int felix_cb_streamid_set(struct net_device *ndev, u32 index,
583 + bool enable, struct tsn_cb_streamid *streamid);
584 +int felix_cb_streamid_counters_get(struct net_device *ndev, u32 index,
585 + struct tsn_cb_streamid_counters *sc);
586 +int felix_qci_sfi_get(struct net_device *ndev, u32 index,
587 + struct tsn_qci_psfp_sfi_conf *sfi);
588 +int felix_qci_sfi_set(struct net_device *ndev, u32 index,
589 + bool enable, struct tsn_qci_psfp_sfi_conf *sfi);
590 +int felix_cb_streamid_counters_get(struct net_device *ndev, u32 index,
591 + struct tsn_cb_streamid_counters *s_counters);
592 +int felix_qci_sfi_counters_get(struct net_device *ndev, u32 index,
593 + struct tsn_qci_psfp_sfi_counters *sfi_counters);
594 +int felix_qci_max_cap_get(struct net_device *ndev,
595 + struct tsn_qci_psfp_stream_param *stream_para);
596 +int felix_qci_sgi_set(struct net_device *ndev, u32 index,
597 + struct tsn_qci_psfp_sgi_conf *sgi_conf);
598 +int felix_qci_sgi_get(struct net_device *ndev, u32 index,
599 + struct tsn_qci_psfp_sgi_conf *sgi_conf);
600 +int felix_qci_sgi_status_get(struct net_device *ndev, u16 index,
601 + struct tsn_psfp_sgi_status *sgi_status);
602 +int felix_qci_fmi_set(struct net_device *ndev, u32 index,
603 + bool enable, struct tsn_qci_psfp_fmi *fmi);
604 +int felix_qci_fmi_get(struct net_device *ndev, u32 index,
605 + struct tsn_qci_psfp_fmi *fmi,
606 + struct tsn_qci_psfp_fmi_counters *counters);
607 +int felix_seq_gen_set(struct net_device *ndev, u32 index,
608 + struct tsn_seq_gen_conf *sg_conf);
609 +int felix_seq_rec_set(struct net_device *ndev, u32 index,
610 + struct tsn_seq_rec_conf *sr_conf);
611 +int felix_cb_get(struct net_device *ndev, u32 index,
612 + struct tsn_cb_status *c);
613 +int felix_dscp_set(struct net_device *ndev, bool enable, const u8 dscp_ix,
614 + struct tsn_qos_switch_dscp_conf *c);
616 +void felix_tsn_init(struct net_device *ndev);
618 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c
619 +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
620 @@ -176,7 +176,7 @@ static const u32 vsc9959_qsys_regmap[] =
621 REG(QSYS_QMAXSDU_CFG_6, 0x00f62c),
622 REG(QSYS_QMAXSDU_CFG_7, 0x00f648),
623 REG(QSYS_PREEMPTION_CFG, 0x00f664),
624 - REG_RESERVED(QSYS_CIR_CFG),
625 + REG(QSYS_CIR_CFG, 0x000000),
626 REG(QSYS_EIR_CFG, 0x000004),
627 REG(QSYS_SE_CFG, 0x000008),
628 REG(QSYS_SE_DWRR_CFG, 0x00000c),
629 @@ -269,7 +269,7 @@ static const u32 vsc9959_sys_regmap[] =
630 REG_RESERVED(SYS_MMGT_FAST),
631 REG_RESERVED(SYS_EVENTS_DIF),
632 REG_RESERVED(SYS_EVENTS_CORE),
633 - REG_RESERVED(SYS_CNT),
634 + REG(SYS_CNT, 0x000000),
635 REG(SYS_PTP_STATUS, 0x000f14),
636 REG(SYS_PTP_TXSTAMP, 0x000f18),
637 REG(SYS_PTP_NXT, 0x000f1c),
638 @@ -290,6 +290,10 @@ static const u32 vsc9959_ptp_regmap[] =
639 REG(PTP_CFG_MISC, 0x0000a0),
640 REG(PTP_CLK_CFG_ADJ_CFG, 0x0000a4),
641 REG(PTP_CLK_CFG_ADJ_FREQ, 0x0000a8),
642 + REG(PTP_CUR_NSF, 0x0000bc),
643 + REG(PTP_CUR_NSEC, 0x0000c0),
644 + REG(PTP_CUR_SEC_LSB, 0x0000c4),
645 + REG(PTP_CUR_SEC_MSB, 0x0000c8),
648 static const u32 vsc9959_gcb_regmap[] = {
649 --- a/include/net/dsa.h
650 +++ b/include/net/dsa.h
651 @@ -554,6 +554,7 @@ struct dsa_switch_ops {
653 netdev_tx_t (*port_deferred_xmit)(struct dsa_switch *ds, int port,
654 struct sk_buff *skb);
655 + int (*port_tsn_enable)(struct dsa_port *dp);
658 struct dsa_switch_driver {
661 @@ -323,6 +323,10 @@ static int dsa_port_setup(struct dsa_por
665 + /* Enable TSN function on switch port */
666 + if (ds->ops->port_tsn_enable)
667 + ds->ops->port_tsn_enable(dp);
669 devlink_port_type_eth_set(dlp, dp->slave);