1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/*
* Copyright 2025-2026 NXP
*/
#ifndef _NETC_SWITCH_H
#define _NETC_SWITCH_H
#include <linux/dsa/tag_netc.h>
#include <linux/fsl/netc_global.h>
#include <linux/fsl/ntmp.h>
#include <linux/of_device.h>
#include <linux/of_net.h>
#include <linux/pci.h>
#include "netc_switch_hw.h"
#define NETC_REGS_BAR 0
#define NETC_REGS_SIZE 0x80000
#define NETC_MSIX_TBL_BAR 2
#define NETC_REGS_PORT_BASE 0x4000
/* register block size per port */
#define NETC_REGS_PORT_SIZE 0x4000
#define PORT_IOBASE(p) (NETC_REGS_PORT_SIZE * (p))
#define NETC_REGS_GLOBAL_BASE 0x70000
#define NETC_SWITCH_REV_4_3 0x0403
#define NETC_TC_NUM 8
#define NETC_CBDR_NUM 2
#define NETC_IPV_NUM 8
#define NETC_MAX_FRAME_LEN 9600
#define NETC_STANDALONE_PVID 0
#define NETC_VLAN_UNAWARE_PVID(br_id) (4096 - (br_id))
/* Threshold format: MANT (bits 11:4) * 2^EXP (bits 3:0)
* Unit: Memory words (average of 20 bytes each)
* NETC_BP_THRESH = 0x8c3, MANT = 0x8c, EXP = 3. Threshold: 1120 words
* NETC_FC_THRESH_ON = 0x733, MANT = 0x73, EXP = 3. Threshold: 920 words
* NETC_FC_THRESH_OFF = 0x263, MANT = 0x26, EXP = 3. Threshold: 304 words
*/
#define NETC_BP_THRESH 0x8c3
#define NETC_FC_THRESH_ON 0x733
#define NETC_FC_THRESH_OFF 0x263
/* PAUSE quanta: 0xFFFF = 65535 quanta (each quanta = 512 bit times) */
#define NETC_PAUSE_QUANTA 0xFFFF
/* PAUSE refresh threshold: send refresh when timer reaches this value */
#define NETC_PAUSE_THRESH 0x7FFF
#define NETC_FDBT_AGEING_DELAY (3 * HZ)
#define NETC_FDBT_AGEING_THRESH 100
struct netc_switch;
struct netc_switch_info {
u32 num_ports;
void (*phylink_get_caps)(int port, struct phylink_config *config);
};
struct netc_port_caps {
u32 half_duplex:1; /* indicates whether the port support half-duplex */
u32 pmac:1; /* indicates whether the port has preemption MAC */
u32 pseudo_link:1;
};
enum netc_host_reason {
/* Software defined host reasons */
NETC_HR_HOST_FLOOD = 8,
};
struct netc_port {
void __iomem *iobase;
struct netc_switch *switch_priv;
struct netc_port_caps caps;
struct dsa_port *dp;
struct clk *ref_clk; /* RGMII/RMII reference clock */
struct mii_bus *emdio;
int ett_offset;
u16 enable:1;
u16 uc:1;
u16 mc:1;
u16 pvid;
struct ipft_entry_data *host_flood;
};
struct netc_switch_regs {
void __iomem *base;
void __iomem *port;
void __iomem *global;
};
struct netc_fdb_entry {
u32 entry_id;
struct fdbt_cfge_data cfge;
struct fdbt_keye_data keye;
struct hlist_node node;
};
struct netc_vlan_entry {
u16 vid;
u32 ect_gid;
u32 untagged_port_bitmap;
struct vft_cfge_data cfge;
struct hlist_node node;
};
struct netc_port_stat {
int reg;
char name[ETH_GSTRING_LEN] __nonstring;
};
struct netc_switch {
struct pci_dev *pdev;
struct device *dev;
struct dsa_switch *ds;
u16 revision;
const struct netc_switch_info *info;
struct netc_switch_regs regs;
struct netc_port **ports;
u32 port_bitmap; /* bitmap of available ports */
struct ntmp_user ntmp;
struct hlist_head fdb_list;
struct mutex fdbt_lock; /* FDB table lock */
struct delayed_work fdbt_ageing_work;
/* (fdbt_ageing_delay * NETC_FDBT_AGEING_THRESH) is ageing time */
unsigned long fdbt_ageing_delay;
atomic_t br_cnt;
struct hlist_head vlan_list;
struct mutex vft_lock; /* VLAN filter table lock */
/* Switch hardware capabilities */
u32 htmcapr_num_words;
u32 num_bp;
struct bpt_cfge_data *bpt_list;
};
#define NETC_PRIV(ds) ((struct netc_switch *)((ds)->priv))
#define NETC_PORT(ds, port_id) (NETC_PRIV(ds)->ports[(port_id)])
/* Write/Read Switch base registers */
#define netc_base_rd(r, o) netc_read((r)->base + (o))
#define netc_base_wr(r, o, v) netc_write((r)->base + (o), v)
/* Write/Read registers of Switch Port (including pseudo MAC port) */
#define netc_port_rd(p, o) netc_read((p)->iobase + (o))
#define netc_port_rd64(p, o) netc_read64((p)->iobase + (o))
#define netc_port_wr(p, o, v) netc_write((p)->iobase + (o), v)
/* Write/Read Switch global registers */
#define netc_glb_rd(r, o) netc_read((r)->global + (o))
#define netc_glb_wr(r, o, v) netc_write((r)->global + (o), v)
static inline bool is_netc_pseudo_port(struct netc_port *np)
{
return np->caps.pseudo_link;
}
static inline void netc_add_fdb_entry(struct netc_switch *priv,
struct netc_fdb_entry *entry)
{
hlist_add_head(&entry->node, &priv->fdb_list);
}
static inline void netc_del_fdb_entry(struct netc_fdb_entry *entry)
{
hlist_del(&entry->node);
kfree(entry);
}
static inline void netc_add_vlan_entry(struct netc_switch *priv,
struct netc_vlan_entry *entry)
{
hlist_add_head(&entry->node, &priv->vlan_list);
}
static inline void netc_del_vlan_entry(struct netc_vlan_entry *entry)
{
hlist_del(&entry->node);
kfree(entry);
}
int netc_switch_platform_probe(struct netc_switch *priv);
/* ethtool APIs */
void netc_port_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats);
void netc_port_get_rmon_stats(struct dsa_switch *ds, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges);
void netc_port_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats);
void netc_port_get_eth_mac_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_mac_stats *mac_stats);
int netc_port_get_sset_count(struct dsa_switch *ds, int port, int sset);
void netc_port_get_strings(struct dsa_switch *ds, int port,
u32 sset, u8 *data);
void netc_port_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data);
#endif
|