1
2
3
4
5
6
7#ifndef __SPARX5_MAIN_H__
8#define __SPARX5_MAIN_H__
9
10#include <linux/types.h>
11#include <linux/phy/phy.h>
12#include <linux/netdevice.h>
13#include <linux/phy.h>
14#include <linux/if_vlan.h>
15#include <linux/bitmap.h>
16#include <linux/phylink.h>
17#include <linux/hrtimer.h>
18
19
20enum spx5_target_chiptype {
21 SPX5_TARGET_CT_7546 = 0x7546,
22 SPX5_TARGET_CT_7549 = 0x7549,
23 SPX5_TARGET_CT_7552 = 0x7552,
24 SPX5_TARGET_CT_7556 = 0x7556,
25 SPX5_TARGET_CT_7558 = 0x7558,
26 SPX5_TARGET_CT_7546TSN = 0x47546,
27 SPX5_TARGET_CT_7549TSN = 0x47549,
28 SPX5_TARGET_CT_7552TSN = 0x47552,
29 SPX5_TARGET_CT_7556TSN = 0x47556,
30 SPX5_TARGET_CT_7558TSN = 0x47558,
31};
32
33enum sparx5_port_max_tags {
34 SPX5_PORT_MAX_TAGS_NONE,
35 SPX5_PORT_MAX_TAGS_ONE,
36 SPX5_PORT_MAX_TAGS_TWO
37};
38
39enum sparx5_vlan_port_type {
40 SPX5_VLAN_PORT_TYPE_UNAWARE,
41 SPX5_VLAN_PORT_TYPE_C,
42 SPX5_VLAN_PORT_TYPE_S,
43 SPX5_VLAN_PORT_TYPE_S_CUSTOM
44};
45
46#define SPX5_PORTS 65
47#define SPX5_PORT_CPU (SPX5_PORTS)
48#define SPX5_PORT_CPU_0 (SPX5_PORT_CPU + 0)
49#define SPX5_PORT_CPU_1 (SPX5_PORT_CPU + 1)
50#define SPX5_PORT_VD0 (SPX5_PORT_CPU + 2)
51#define SPX5_PORT_VD1 (SPX5_PORT_CPU + 3)
52#define SPX5_PORT_VD2 (SPX5_PORT_CPU + 4)
53#define SPX5_PORTS_ALL (SPX5_PORT_CPU + 5)
54
55#define PGID_BASE SPX5_PORTS
56#define PGID_UC_FLOOD (PGID_BASE + 0)
57#define PGID_MC_FLOOD (PGID_BASE + 1)
58#define PGID_IPV4_MC_DATA (PGID_BASE + 2)
59#define PGID_IPV4_MC_CTRL (PGID_BASE + 3)
60#define PGID_IPV6_MC_DATA (PGID_BASE + 4)
61#define PGID_IPV6_MC_CTRL (PGID_BASE + 5)
62#define PGID_BCAST (PGID_BASE + 6)
63#define PGID_CPU (PGID_BASE + 7)
64
65#define IFH_LEN 9
66#define NULL_VID 0
67#define SPX5_MACT_PULL_DELAY (2 * HZ)
68#define SPX5_STATS_CHECK_DELAY (1 * HZ)
69#define SPX5_PRIOS 8
70#define SPX5_BUFFER_CELL_SZ 184
71#define SPX5_BUFFER_MEMORY 4194280
72
73#define XTR_QUEUE 0
74#define INJ_QUEUE 0
75
76#define FDMA_DCB_MAX 64
77#define FDMA_RX_DCB_MAX_DBS 15
78#define FDMA_TX_DCB_MAX_DBS 1
79
80struct sparx5;
81
82struct sparx5_db_hw {
83 u64 dataptr;
84 u64 status;
85};
86
87struct sparx5_rx_dcb_hw {
88 u64 nextptr;
89 u64 info;
90 struct sparx5_db_hw db[FDMA_RX_DCB_MAX_DBS];
91};
92
93struct sparx5_tx_dcb_hw {
94 u64 nextptr;
95 u64 info;
96 struct sparx5_db_hw db[FDMA_TX_DCB_MAX_DBS];
97};
98
99
100
101
102
103
104
105struct sparx5_rx {
106 struct sparx5_rx_dcb_hw *dcb_entries;
107 struct sparx5_rx_dcb_hw *last_entry;
108 struct sk_buff *skb[FDMA_DCB_MAX][FDMA_RX_DCB_MAX_DBS];
109 int db_index;
110 int dcb_index;
111 dma_addr_t dma;
112 struct napi_struct napi;
113 u32 channel_id;
114 struct net_device *ndev;
115 u64 packets;
116};
117
118
119
120
121struct sparx5_tx {
122 struct sparx5_tx_dcb_hw *curr_entry;
123 struct sparx5_tx_dcb_hw *first_entry;
124 struct list_head db_list;
125 dma_addr_t dma;
126 u32 channel_id;
127 u64 packets;
128 u64 dropped;
129};
130
131struct sparx5_port_config {
132 phy_interface_t portmode;
133 u32 bandwidth;
134 int speed;
135 int duplex;
136 enum phy_media media;
137 bool inband;
138 bool power_down;
139 bool autoneg;
140 bool serdes_reset;
141 u32 pause;
142 u32 pause_adv;
143 phy_interface_t phy_mode;
144 u32 sd_sgpio;
145};
146
147struct sparx5_port {
148 struct net_device *ndev;
149 struct sparx5 *sparx5;
150 struct device_node *of_node;
151 struct phy *serdes;
152 struct sparx5_port_config conf;
153 struct phylink_config phylink_config;
154 struct phylink *phylink;
155 struct phylink_pcs phylink_pcs;
156 u16 portno;
157
158 u16 pvid;
159
160 u16 vid;
161 bool signd_internal;
162 bool signd_active_high;
163 bool signd_enable;
164 bool flow_control;
165 enum sparx5_port_max_tags max_vlan_tags;
166 enum sparx5_vlan_port_type vlan_type;
167 u32 custom_etype;
168 u32 ifh[IFH_LEN];
169 bool vlan_aware;
170 struct hrtimer inj_timer;
171};
172
173enum sparx5_core_clockfreq {
174 SPX5_CORE_CLOCK_DEFAULT,
175 SPX5_CORE_CLOCK_250MHZ,
176 SPX5_CORE_CLOCK_500MHZ,
177 SPX5_CORE_CLOCK_625MHZ,
178};
179
180struct sparx5 {
181 struct platform_device *pdev;
182 struct device *dev;
183 u32 chip_id;
184 enum spx5_target_chiptype target_ct;
185 void __iomem *regs[NUM_TARGETS];
186 int port_count;
187 struct mutex lock;
188
189 struct sparx5_port *ports[SPX5_PORTS];
190 enum sparx5_core_clockfreq coreclock;
191
192 u32 num_stats;
193 u32 num_ethtool_stats;
194 const char * const *stats_layout;
195 u64 *stats;
196
197 struct mutex queue_stats_lock;
198 struct delayed_work stats_work;
199 struct workqueue_struct *stats_queue;
200
201 struct notifier_block netdevice_nb;
202 struct notifier_block switchdev_nb;
203 struct notifier_block switchdev_blocking_nb;
204
205 u8 base_mac[ETH_ALEN];
206
207 struct net_device *hw_bridge_dev;
208
209 DECLARE_BITMAP(bridge_mask, SPX5_PORTS);
210 DECLARE_BITMAP(bridge_fwd_mask, SPX5_PORTS);
211 DECLARE_BITMAP(bridge_lrn_mask, SPX5_PORTS);
212 DECLARE_BITMAP(vlan_mask[VLAN_N_VID], SPX5_PORTS);
213
214 struct list_head mact_entries;
215
216 struct mutex mact_lock;
217 struct delayed_work mact_work;
218 struct workqueue_struct *mact_queue;
219
220 bool sd_sgpio_remapping;
221
222 int xtr_irq;
223
224 int fdma_irq;
225 struct sparx5_rx rx;
226 struct sparx5_tx tx;
227};
228
229
230int sparx5_register_notifier_blocks(struct sparx5 *sparx5);
231void sparx5_unregister_notifier_blocks(struct sparx5 *sparx5);
232
233
234struct frame_info {
235 int src_port;
236};
237
238void sparx5_xtr_flush(struct sparx5 *sparx5, u8 grp);
239void sparx5_ifh_parse(u32 *ifh, struct frame_info *info);
240irqreturn_t sparx5_xtr_handler(int irq, void *_priv);
241int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev);
242int sparx5_manual_injection_mode(struct sparx5 *sparx5);
243void sparx5_port_inj_timer_setup(struct sparx5_port *port);
244
245
246int sparx5_fdma_start(struct sparx5 *sparx5);
247int sparx5_fdma_stop(struct sparx5 *sparx5);
248int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb);
249irqreturn_t sparx5_fdma_handler(int irq, void *args);
250
251
252void sparx5_mact_pull_work(struct work_struct *work);
253int sparx5_mact_learn(struct sparx5 *sparx5, int port,
254 const unsigned char mac[ETH_ALEN], u16 vid);
255bool sparx5_mact_getnext(struct sparx5 *sparx5,
256 unsigned char mac[ETH_ALEN], u16 *vid, u32 *pcfg2);
257int sparx5_mact_forget(struct sparx5 *sparx5,
258 const unsigned char mac[ETH_ALEN], u16 vid);
259int sparx5_add_mact_entry(struct sparx5 *sparx5,
260 struct sparx5_port *port,
261 const unsigned char *addr, u16 vid);
262int sparx5_del_mact_entry(struct sparx5 *sparx5,
263 const unsigned char *addr,
264 u16 vid);
265int sparx5_mc_sync(struct net_device *dev, const unsigned char *addr);
266int sparx5_mc_unsync(struct net_device *dev, const unsigned char *addr);
267void sparx5_set_ageing(struct sparx5 *sparx5, int msecs);
268void sparx5_mact_init(struct sparx5 *sparx5);
269
270
271void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable);
272void sparx5_update_fwd(struct sparx5 *sparx5);
273void sparx5_vlan_init(struct sparx5 *sparx5);
274void sparx5_vlan_port_setup(struct sparx5 *sparx5, int portno);
275int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
276 bool untagged);
277int sparx5_vlan_vid_del(struct sparx5_port *port, u16 vid);
278void sparx5_vlan_port_apply(struct sparx5 *sparx5, struct sparx5_port *port);
279
280
281int sparx5_config_auto_calendar(struct sparx5 *sparx5);
282int sparx5_config_dsm_calendar(struct sparx5 *sparx5);
283
284
285void sparx5_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats);
286int sparx_stats_init(struct sparx5 *sparx5);
287
288
289bool sparx5_netdevice_check(const struct net_device *dev);
290struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno);
291int sparx5_register_netdevs(struct sparx5 *sparx5);
292void sparx5_destroy_netdevs(struct sparx5 *sparx5);
293void sparx5_unregister_netdevs(struct sparx5 *sparx5);
294
295
296static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
297{
298 switch (cclock) {
299 case SPX5_CORE_CLOCK_250MHZ:
300 return 4000;
301 case SPX5_CORE_CLOCK_500MHZ:
302 return 2000;
303 case SPX5_CORE_CLOCK_625MHZ:
304 default:
305 return 1600;
306 }
307}
308
309static inline bool sparx5_is_baser(phy_interface_t interface)
310{
311 return interface == PHY_INTERFACE_MODE_5GBASER ||
312 interface == PHY_INTERFACE_MODE_10GBASER ||
313 interface == PHY_INTERFACE_MODE_25GBASER;
314}
315
316extern const struct phylink_mac_ops sparx5_phylink_mac_ops;
317extern const struct phylink_pcs_ops sparx5_phylink_pcs_ops;
318extern const struct ethtool_ops sparx5_ethtool_ops;
319
320
321static inline __pure int spx5_offset(int id, int tinst, int tcnt,
322 int gbase, int ginst,
323 int gcnt, int gwidth,
324 int raddr, int rinst,
325 int rcnt, int rwidth)
326{
327 WARN_ON((tinst) >= tcnt);
328 WARN_ON((ginst) >= gcnt);
329 WARN_ON((rinst) >= rcnt);
330 return gbase + ((ginst) * gwidth) +
331 raddr + ((rinst) * rwidth);
332}
333
334
335
336
337static inline void __iomem *spx5_addr(void __iomem *base[],
338 int id, int tinst, int tcnt,
339 int gbase, int ginst,
340 int gcnt, int gwidth,
341 int raddr, int rinst,
342 int rcnt, int rwidth)
343{
344 WARN_ON((tinst) >= tcnt);
345 WARN_ON((ginst) >= gcnt);
346 WARN_ON((rinst) >= rcnt);
347 return base[id + (tinst)] +
348 gbase + ((ginst) * gwidth) +
349 raddr + ((rinst) * rwidth);
350}
351
352static inline void __iomem *spx5_inst_addr(void __iomem *base,
353 int gbase, int ginst,
354 int gcnt, int gwidth,
355 int raddr, int rinst,
356 int rcnt, int rwidth)
357{
358 WARN_ON((ginst) >= gcnt);
359 WARN_ON((rinst) >= rcnt);
360 return base +
361 gbase + ((ginst) * gwidth) +
362 raddr + ((rinst) * rwidth);
363}
364
365static inline u32 spx5_rd(struct sparx5 *sparx5, int id, int tinst, int tcnt,
366 int gbase, int ginst, int gcnt, int gwidth,
367 int raddr, int rinst, int rcnt, int rwidth)
368{
369 return readl(spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst,
370 gcnt, gwidth, raddr, rinst, rcnt, rwidth));
371}
372
373static inline u32 spx5_inst_rd(void __iomem *iomem, int id, int tinst, int tcnt,
374 int gbase, int ginst, int gcnt, int gwidth,
375 int raddr, int rinst, int rcnt, int rwidth)
376{
377 return readl(spx5_inst_addr(iomem, gbase, ginst,
378 gcnt, gwidth, raddr, rinst, rcnt, rwidth));
379}
380
381static inline void spx5_wr(u32 val, struct sparx5 *sparx5,
382 int id, int tinst, int tcnt,
383 int gbase, int ginst, int gcnt, int gwidth,
384 int raddr, int rinst, int rcnt, int rwidth)
385{
386 writel(val, spx5_addr(sparx5->regs, id, tinst, tcnt,
387 gbase, ginst, gcnt, gwidth,
388 raddr, rinst, rcnt, rwidth));
389}
390
391static inline void spx5_inst_wr(u32 val, void __iomem *iomem,
392 int id, int tinst, int tcnt,
393 int gbase, int ginst, int gcnt, int gwidth,
394 int raddr, int rinst, int rcnt, int rwidth)
395{
396 writel(val, spx5_inst_addr(iomem,
397 gbase, ginst, gcnt, gwidth,
398 raddr, rinst, rcnt, rwidth));
399}
400
401static inline void spx5_rmw(u32 val, u32 mask, struct sparx5 *sparx5,
402 int id, int tinst, int tcnt,
403 int gbase, int ginst, int gcnt, int gwidth,
404 int raddr, int rinst, int rcnt, int rwidth)
405{
406 u32 nval;
407
408 nval = readl(spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst,
409 gcnt, gwidth, raddr, rinst, rcnt, rwidth));
410 nval = (nval & ~mask) | (val & mask);
411 writel(nval, spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst,
412 gcnt, gwidth, raddr, rinst, rcnt, rwidth));
413}
414
415static inline void spx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
416 int id, int tinst, int tcnt,
417 int gbase, int ginst, int gcnt, int gwidth,
418 int raddr, int rinst, int rcnt, int rwidth)
419{
420 u32 nval;
421
422 nval = readl(spx5_inst_addr(iomem, gbase, ginst, gcnt, gwidth, raddr,
423 rinst, rcnt, rwidth));
424 nval = (nval & ~mask) | (val & mask);
425 writel(nval, spx5_inst_addr(iomem, gbase, ginst, gcnt, gwidth, raddr,
426 rinst, rcnt, rwidth));
427}
428
429static inline void __iomem *spx5_inst_get(struct sparx5 *sparx5, int id, int tinst)
430{
431 return sparx5->regs[id + tinst];
432}
433
434static inline void __iomem *spx5_reg_get(struct sparx5 *sparx5,
435 int id, int tinst, int tcnt,
436 int gbase, int ginst, int gcnt, int gwidth,
437 int raddr, int rinst, int rcnt, int rwidth)
438{
439 return spx5_addr(sparx5->regs, id, tinst, tcnt,
440 gbase, ginst, gcnt, gwidth,
441 raddr, rinst, rcnt, rwidth);
442}
443
444#endif
445