xref: /freebsd-13-stable/sys/mips/nlm/dev/net/nae.c (revision 3bc80996974a61a4223eae4c1ccd47b6ee32a48a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2003-2012 Broadcom Corporation
5  * All Rights Reserved
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 #include <sys/types.h>
33 #include <sys/systm.h>
34 
35 #include <mips/nlm/hal/mips-extns.h>
36 #include <mips/nlm/hal/haldefs.h>
37 #include <mips/nlm/hal/iomap.h>
38 #include <mips/nlm/hal/sys.h>
39 #include <mips/nlm/hal/nae.h>
40 #include <mips/nlm/hal/mdio.h>
41 #include <mips/nlm/hal/sgmii.h>
42 #include <mips/nlm/hal/xaui.h>
43 
44 #include <mips/nlm/board.h>
45 #include <mips/nlm/xlp.h>
46 
47 void
nlm_nae_flush_free_fifo(uint64_t nae_base,int nblocks)48 nlm_nae_flush_free_fifo(uint64_t nae_base, int nblocks)
49 {
50 	uint32_t data, fifo_mask;
51 
52 	fifo_mask = (1 << (4 * nblocks)) - 1;
53 
54 	nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP, fifo_mask);
55 	do {
56 		data = nlm_read_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP);
57 	} while (data != fifo_mask);
58 
59 	nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP, 0);
60 }
61 
62 void
nlm_program_nae_parser_seq_fifo(uint64_t nae_base,int maxports,struct nae_port_config * cfg)63 nlm_program_nae_parser_seq_fifo(uint64_t nae_base, int maxports,
64     struct nae_port_config *cfg)
65 {
66 	uint32_t val;
67 	int start = 0, size, i;
68 
69 	for (i = 0; i < maxports; i++) {
70 		size = cfg[i].pseq_fifo_size;
71 		val = (((size & 0x1fff) << 17) |
72 		    ((start & 0xfff) << 5) |
73 		    (i & 0x1f));
74 		nlm_write_nae_reg(nae_base, NAE_PARSER_SEQ_FIFO_CFG, val);
75 		start += size;
76 	}
77 }
78 
79 void
nlm_setup_rx_cal_cfg(uint64_t nae_base,int total_num_ports,struct nae_port_config * cfg)80 nlm_setup_rx_cal_cfg(uint64_t nae_base, int total_num_ports,
81     struct nae_port_config *cfg)
82 {
83 	int rx_slots = 0, port;
84 	int cal_len, cal = 0, last_free = 0;
85 	uint32_t val;
86 
87 	for (port = 0; port < total_num_ports; port++) {
88 		if (cfg[port].rx_slots_reqd)
89 		    rx_slots += cfg[port].rx_slots_reqd;
90 		if (rx_slots > MAX_CAL_SLOTS) {
91 			rx_slots = MAX_CAL_SLOTS;
92 			break;
93 		}
94 	}
95 
96 	cal_len = rx_slots - 1;
97 
98 	do {
99 		if (cal >= MAX_CAL_SLOTS)
100 			break;
101 		last_free = cal;
102 		for (port = 0; port < total_num_ports; port++) {
103 			if (cfg[port].rx_slots_reqd > 0) {
104 				val = (cal_len << 16) | (port << 8) | cal;
105 				nlm_write_nae_reg(nae_base,
106 				    NAE_RX_IF_SLOT_CAL, val);
107 				cal++;
108 				cfg[port].rx_slots_reqd--;
109 			}
110 		}
111 		if (last_free == cal)
112 			break;
113 	} while (1);
114 }
115 
116 void
nlm_setup_tx_cal_cfg(uint64_t nae_base,int total_num_ports,struct nae_port_config * cfg)117 nlm_setup_tx_cal_cfg(uint64_t nae_base, int total_num_ports,
118     struct nae_port_config *cfg)
119 {
120 	int tx_slots = 0, port;
121 	int cal = 0, last_free = 0;
122 	uint32_t val;
123 
124 	for (port = 0; port < total_num_ports; port++) {
125 		if (cfg[port].tx_slots_reqd)
126 			tx_slots += cfg[port].tx_slots_reqd;
127 		if (tx_slots > MAX_CAL_SLOTS) {
128 			tx_slots = MAX_CAL_SLOTS;
129 			break;
130 		}
131 	}
132 
133 	nlm_write_nae_reg(nae_base, NAE_EGR_NIOR_CAL_LEN_REG, tx_slots - 1);
134 	do {
135 		if (cal >= MAX_CAL_SLOTS)
136 			break;
137 		last_free = cal;
138 		for (port = 0; port < total_num_ports; port++) {
139 			if (cfg[port].tx_slots_reqd > 0) {
140 				val = (port << 7) | (cal << 1) | 1;
141 				nlm_write_nae_reg(nae_base,
142 				    NAE_EGR_NIOR_CRDT_CAL_PROG, val);
143 				cal++;
144 				cfg[port].tx_slots_reqd--;
145 			}
146 		}
147 		if (last_free == cal)
148 			break;
149 	} while (1);
150 }
151 
152 void
nlm_deflate_frin_fifo_carving(uint64_t nae_base,int total_num_ports)153 nlm_deflate_frin_fifo_carving(uint64_t nae_base, int total_num_ports)
154 {
155 	const int minimum_size = 8;
156 	uint32_t value;
157 	int intf, start;
158 
159 	for (intf = 0; intf < total_num_ports; intf++) {
160 		start = minimum_size * intf;
161 		value = (minimum_size << 20) | (start << 8) | (intf);
162 		nlm_write_nae_reg(nae_base, NAE_FREE_IN_FIFO_CFG, value);
163 	}
164 }
165 
166 void
nlm_reset_nae(int node)167 nlm_reset_nae(int node)
168 {
169 	uint64_t sysbase;
170 	uint64_t nae_base;
171 	uint64_t nae_pcibase;
172 	uint32_t rx_config;
173 	uint32_t bar0;
174 	int reset_bit;
175 
176 	sysbase  = nlm_get_sys_regbase(node);
177 	nae_base = nlm_get_nae_regbase(node);
178 	nae_pcibase = nlm_get_nae_pcibase(node);
179 
180 	bar0 = nlm_read_pci_reg(nae_pcibase, XLP_PCI_CFGREG4);
181 
182 #if BYTE_ORDER == LITTLE_ENDIAN
183 	if (nlm_is_xlp8xx_ax()) {
184 		uint8_t	val;
185 		/* membar fixup */
186 		val = (bar0 >> 24) & 0xff;
187 		bar0 = (val << 24) | (val << 16) | (val << 8) | val;
188 	}
189 #endif
190 
191 	if (nlm_is_xlp3xx())
192 		reset_bit = 6;
193 	else
194 		reset_bit = 9;
195 
196 	/* Reset NAE */
197 	nlm_write_sys_reg(sysbase, SYS_RESET, (1 << reset_bit));
198 
199 	/* XXXJC - 1s delay here may be too high */
200 	DELAY(1000000);
201 	nlm_write_sys_reg(sysbase, SYS_RESET, (0 << reset_bit));
202 	DELAY(1000000);
203 
204 	rx_config = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
205 	nlm_write_pci_reg(nae_pcibase, XLP_PCI_CFGREG4, bar0);
206 }
207 
208 void
nlm_setup_poe_class_config(uint64_t nae_base,int max_poe_classes,int num_contexts,int * poe_cl_tbl)209 nlm_setup_poe_class_config(uint64_t nae_base, int max_poe_classes,
210     int num_contexts, int *poe_cl_tbl)
211 {
212 	uint32_t val;
213 	int i, max_poe_class_ctxt_tbl_sz;
214 
215 	max_poe_class_ctxt_tbl_sz = num_contexts/max_poe_classes;
216 	for (i = 0; i < max_poe_class_ctxt_tbl_sz; i++) {
217 		val = (poe_cl_tbl[(i/max_poe_classes) & 0x7] << 8) | i;
218 		nlm_write_nae_reg(nae_base, NAE_POE_CLASS_SETUP_CFG, val);
219 	}
220 }
221 
222 void
nlm_setup_vfbid_mapping(uint64_t nae_base)223 nlm_setup_vfbid_mapping(uint64_t nae_base)
224 {
225 	uint32_t val;
226 	int dest_vc, vfbid;
227 
228 	/* 127 is max vfbid */
229 	for (vfbid = 127; vfbid >= 0; vfbid--) {
230 		dest_vc = nlm_get_vfbid_mapping(vfbid);
231 		if (dest_vc < 0)
232 			continue;
233 		val = (dest_vc << 16) | (vfbid << 4) | 1;
234 		nlm_write_nae_reg(nae_base, NAE_VFBID_DESTMAP_CMD, val);
235 	}
236 }
237 
238 void
nlm_setup_flow_crc_poly(uint64_t nae_base,uint32_t poly)239 nlm_setup_flow_crc_poly(uint64_t nae_base, uint32_t poly)
240 {
241 	nlm_write_nae_reg(nae_base, NAE_FLOW_CRC16_POLY_CFG, poly);
242 }
243 
244 void
nlm_setup_iface_fifo_cfg(uint64_t nae_base,int maxports,struct nae_port_config * cfg)245 nlm_setup_iface_fifo_cfg(uint64_t nae_base, int maxports,
246     struct nae_port_config *cfg)
247 {
248 	uint32_t reg;
249 	int fifo_xoff_thresh = 12;
250 	int i, size;
251 	int cur_iface_start = 0;
252 
253 	for (i = 0; i < maxports; i++) {
254 		size = cfg[i].iface_fifo_size;
255 		reg = ((fifo_xoff_thresh << 25) |
256 		    ((size & 0x1ff) << 16) |
257 		    ((cur_iface_start & 0xff) << 8) |
258 		    (i & 0x1f));
259 		nlm_write_nae_reg(nae_base, NAE_IFACE_FIFO_CFG, reg);
260 		cur_iface_start += size;
261 	}
262 }
263 
264 void
nlm_setup_rx_base_config(uint64_t nae_base,int maxports,struct nae_port_config * cfg)265 nlm_setup_rx_base_config(uint64_t nae_base, int maxports,
266     struct nae_port_config *cfg)
267 {
268 	int base = 0;
269 	uint32_t val;
270 	int i;
271 	int id;
272 
273 	for (i = 0; i < (maxports/2); i++) {
274 		id = 0x12 + i; /* RX_IF_BASE_CONFIG0 */
275 
276 		val = (base & 0x3ff);
277 		base += cfg[(i * 2)].num_channels;
278 
279 		val |= ((base & 0x3ff) << 16);
280 		base += cfg[(i * 2) + 1].num_channels;
281 
282 		nlm_write_nae_reg(nae_base, NAE_REG(7, 0, id), val);
283 	}
284 }
285 
286 void
nlm_setup_rx_buf_config(uint64_t nae_base,int maxports,struct nae_port_config * cfg)287 nlm_setup_rx_buf_config(uint64_t nae_base, int maxports,
288     struct nae_port_config *cfg)
289 {
290 	uint32_t val;
291 	int i, sz, k;
292 	int context = 0;
293 	int base = 0;
294 
295 	for (i = 0; i < maxports; i++) {
296 		if (cfg[i].type == UNKNOWN)
297 			continue;
298 		for (k = 0; k < cfg[i].num_channels; k++) {
299 			/* write index (context num) */
300 			nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH_ADDR,
301 			    (context+k));
302 
303 			/* write value (rx buf sizes) */
304 			sz = cfg[i].rxbuf_size;
305 			val = 0x80000000 | ((base << 2) & 0x3fff); /* base */
306 			val |= (((sz << 2)  & 0x3fff) << 16); /* size */
307 
308 			nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH, val);
309 			nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH,
310 			    (0x7fffffff & val));
311 			base += sz;
312 		}
313 		context += cfg[i].num_channels;
314 	}
315 }
316 
317 void
nlm_setup_freein_fifo_cfg(uint64_t nae_base,struct nae_port_config * cfg)318 nlm_setup_freein_fifo_cfg(uint64_t nae_base, struct nae_port_config *cfg)
319 {
320 	int size, i;
321 	uint32_t reg;
322 	int start = 0, maxbufpool;
323 
324 	if (nlm_is_xlp8xx())
325 		maxbufpool = MAX_FREE_FIFO_POOL_8XX;
326 	else
327 		maxbufpool = MAX_FREE_FIFO_POOL_3XX;
328 	for (i = 0; i < maxbufpool; i++) {
329 		/* Each entry represents 2 descs; hence division by 2 */
330 		size = (cfg[i].num_free_descs / 2);
331 		if (size == 0)
332 			size = 8;
333 		reg = ((size  & 0x3ff ) << 20) | /* fcSize */
334 		    ((start & 0x1ff)  << 8) | /* fcStart */
335 		    (i & 0x1f);
336 
337 		nlm_write_nae_reg(nae_base, NAE_FREE_IN_FIFO_CFG, reg);
338 		start += size;
339 	}
340 }
341 
342 /* XXX function name */
343 int
nlm_get_flow_mask(int num_ports)344 nlm_get_flow_mask(int num_ports)
345 {
346 	const int max_bits = 5; /* upto 32 ports */
347 	int i;
348 
349 	/* Compute the number of bits to needed to
350 	 * represent all the ports */
351 	for (i = 0; i < max_bits; i++) {
352 		if (num_ports <= (2 << i))
353 			return (i + 1);
354 	}
355 	return (max_bits);
356 }
357 
358 void
nlm_program_flow_cfg(uint64_t nae_base,int port,uint32_t cur_flow_base,uint32_t flow_mask)359 nlm_program_flow_cfg(uint64_t nae_base, int port,
360     uint32_t cur_flow_base, uint32_t flow_mask)
361 {
362 	uint32_t val;
363 
364 	val = (cur_flow_base << 16) | port;
365 	val |= ((flow_mask & 0x1f) << 8);
366 	nlm_write_nae_reg(nae_base, NAE_FLOW_BASEMASK_CFG, val);
367 }
368 
369 void
xlp_ax_nae_lane_reset_txpll(uint64_t nae_base,int block,int lane_ctrl,int mode)370 xlp_ax_nae_lane_reset_txpll(uint64_t nae_base, int block, int lane_ctrl,
371     int mode)
372 {
373 	uint32_t val = 0, saved_data;
374 	int rext_sel = 0;
375 
376 	val = PHY_LANE_CTRL_RST |
377 	    PHY_LANE_CTRL_PWRDOWN |
378 	    (mode << PHY_LANE_CTRL_PHYMODE_POS);
379 
380 	/* set comma bypass for XAUI */
381 	if (mode != PHYMODE_SGMII)
382 		val |= PHY_LANE_CTRL_BPC_XAUI;
383 
384 	nlm_write_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl), val);
385 
386 	if (lane_ctrl != 4) {
387 		rext_sel = (1 << 23);
388 		if (mode != PHYMODE_SGMII)
389 			rext_sel |= PHY_LANE_CTRL_BPC_XAUI;
390 
391 		val = nlm_read_nae_reg(nae_base,
392 		    NAE_REG(block, PHY, lane_ctrl));
393 		val &= ~PHY_LANE_CTRL_RST;
394 		val |= rext_sel;
395 
396 		/* Resetting PMA for non-zero lanes */
397 		nlm_write_nae_reg(nae_base,
398 		    NAE_REG(block, PHY, lane_ctrl), val);
399 
400 		DELAY(20000);	/* 20 ms delay, XXXJC: needed? */
401 
402 		val |= PHY_LANE_CTRL_RST;
403 		nlm_write_nae_reg(nae_base,
404 		    NAE_REG(block, PHY, lane_ctrl), val);
405 
406 		val = 0;
407 	}
408 
409 	/* Come out of reset for TXPLL */
410 	saved_data = nlm_read_nae_reg(nae_base,
411 	    NAE_REG(block, PHY, lane_ctrl)) & 0xFFC00000;
412 
413 	nlm_write_nae_reg(nae_base,
414 	    NAE_REG(block, PHY, lane_ctrl),
415 	    (0x66 << PHY_LANE_CTRL_ADDR_POS)
416 	    | PHY_LANE_CTRL_CMD_READ
417 	    | PHY_LANE_CTRL_CMD_START
418 	    | PHY_LANE_CTRL_RST
419 	    | rext_sel
420 	    | val );
421 
422 	while (((val = nlm_read_nae_reg(nae_base,
423 	    NAE_REG(block, PHY, lane_ctrl))) &
424 	    PHY_LANE_CTRL_CMD_PENDING));
425 
426 	val &= 0xFF;
427 	/* set bit[4] to 0 */
428 	val &= ~(1 << 4);
429 	nlm_write_nae_reg(nae_base,
430 	    NAE_REG(block, PHY, lane_ctrl),
431 	    (0x66 << PHY_LANE_CTRL_ADDR_POS)
432 	    | PHY_LANE_CTRL_CMD_WRITE
433 	    | PHY_LANE_CTRL_CMD_START
434 	    | (0x0 << 19) /* (0x4 << 19) */
435 	    | rext_sel
436 	    | saved_data
437 	    | val );
438 
439 	/* re-do */
440 	nlm_write_nae_reg(nae_base,
441 	    NAE_REG(block, PHY, lane_ctrl),
442 	    (0x66 << PHY_LANE_CTRL_ADDR_POS)
443 	    | PHY_LANE_CTRL_CMD_WRITE
444 	    | PHY_LANE_CTRL_CMD_START
445 	    | (0x0 << 19) /* (0x4 << 19) */
446 	    | rext_sel
447 	    | saved_data
448 	    | val );
449 
450 	while (!((val = nlm_read_nae_reg(nae_base,
451 	    NAE_REG(block, PHY, (lane_ctrl - PHY_LANE_0_CTRL)))) &
452 	    PHY_LANE_STAT_PCR));
453 
454 	/* Clear the Power Down bit */
455 	val = nlm_read_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl));
456 	val &= ~((1 << 29) | (0x7ffff));
457 	nlm_write_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl),
458 	    (rext_sel | val));
459 }
460 
461 void
xlp_nae_lane_reset_txpll(uint64_t nae_base,int block,int lane_ctrl,int mode)462 xlp_nae_lane_reset_txpll(uint64_t nae_base, int block, int lane_ctrl,
463     int mode)
464 {
465 	uint32_t val = 0;
466 	int rext_sel = 0;
467 
468 	if (lane_ctrl != 4)
469 		rext_sel = (1 << 23);
470 
471 	val = nlm_read_nae_reg(nae_base,
472 	    NAE_REG(block, PHY, lane_ctrl));
473 
474 	/* set comma bypass for XAUI */
475 	if (mode != PHYMODE_SGMII)
476 		val |= PHY_LANE_CTRL_BPC_XAUI;
477 	val |= 0x100000;
478 	val |= (mode << PHY_LANE_CTRL_PHYMODE_POS);
479 	val &= ~(0x20000);
480 	nlm_write_nae_reg(nae_base,
481 	    NAE_REG(block, PHY, lane_ctrl), val);
482 
483 	val = nlm_read_nae_reg(nae_base,
484 	    NAE_REG(block, PHY, lane_ctrl));
485 	val |= 0x40000000;
486 	nlm_write_nae_reg(nae_base,
487 	    NAE_REG(block, PHY, lane_ctrl), val);
488 
489 	/* clear the power down bit */
490 	val = nlm_read_nae_reg(nae_base,
491 	    NAE_REG(block, PHY, lane_ctrl));
492 	val &= ~( (1 << 29) | (0x7ffff));
493 	nlm_write_nae_reg(nae_base,
494 	    NAE_REG(block, PHY, lane_ctrl), rext_sel | val);
495 }
496 
497 void
xlp_nae_config_lane_gmac(uint64_t nae_base,int cplx_mask)498 xlp_nae_config_lane_gmac(uint64_t nae_base, int cplx_mask)
499 {
500 	int block, lane_ctrl;
501 	int cplx_lane_enable;
502 	int lane_enable = 0;
503 
504 	cplx_lane_enable = LM_SGMII |
505 	    (LM_SGMII << 4) |
506 	    (LM_SGMII << 8) |
507 	    (LM_SGMII << 12);
508 
509 	/*  Lane mode progamming */
510 	block = 7;
511 
512 	/* Complexes 0, 1 */
513 	if (cplx_mask & 0x1)
514 		lane_enable |= cplx_lane_enable;
515 
516 	if (cplx_mask & 0x2)
517 		lane_enable |= (cplx_lane_enable << 16);
518 
519 	if (lane_enable) {
520 		nlm_write_nae_reg(nae_base,
521 		    NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1),
522 		    lane_enable);
523 		lane_enable = 0;
524 	}
525 	/* Complexes 2 3 */
526 	if (cplx_mask & 0x4)
527 		lane_enable |= cplx_lane_enable;
528 
529 	if (cplx_mask & 0x8)
530 		lane_enable |= (cplx_lane_enable << 16);
531 
532 	nlm_write_nae_reg(nae_base,
533 	    NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3),
534 	    lane_enable);
535 
536 	/* complex 4 */
537 	/* XXXJC : fix duplicate code */
538 	if (cplx_mask & 0x10) {
539 		nlm_write_nae_reg(nae_base,
540 		    NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_4),
541 		    ((LM_SGMII << 4) | LM_SGMII));
542 		for (lane_ctrl = PHY_LANE_0_CTRL;
543 		    lane_ctrl <= PHY_LANE_1_CTRL; lane_ctrl++) {
544 			if (!nlm_is_xlp8xx_ax())
545 				xlp_nae_lane_reset_txpll(nae_base,
546 				    4, lane_ctrl, PHYMODE_SGMII);
547 			else
548 				xlp_ax_nae_lane_reset_txpll(nae_base, 4,
549 				    lane_ctrl, PHYMODE_SGMII);
550 		}
551 	}
552 
553 	for (block = 0; block < 4; block++) {
554 		if ((cplx_mask & (1 << block)) == 0)
555 			continue;
556 
557 		for (lane_ctrl = PHY_LANE_0_CTRL;
558 		    lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) {
559 			if (!nlm_is_xlp8xx_ax())
560 				xlp_nae_lane_reset_txpll(nae_base,
561 				    block, lane_ctrl, PHYMODE_SGMII);
562 			else
563 				xlp_ax_nae_lane_reset_txpll(nae_base, block,
564 				    lane_ctrl, PHYMODE_SGMII);
565 		}
566 	}
567 }
568 
569 void
config_egress_fifo_carvings(uint64_t nae_base,int hwport,int start_ctxt,int num_ctxts,int max_ctxts,struct nae_port_config * cfg)570 config_egress_fifo_carvings(uint64_t nae_base, int hwport, int start_ctxt,
571     int num_ctxts, int max_ctxts, struct nae_port_config *cfg)
572 {
573 	static uint32_t cur_start[6] = {0, 0, 0, 0, 0, 0};
574 	uint32_t data = 0;
575 	uint32_t start = 0, size, offset;
576 	int i, limit;
577 
578 	limit = start_ctxt + num_ctxts;
579 	/* Stage 2 FIFO */
580 	start = cur_start[0];
581 	for (i = start_ctxt; i < limit; i++) {
582 		size = cfg[hwport].stg2_fifo_size / max_ctxts;
583 		if (size)
584 			offset = size - 1;
585 		else
586 			offset = size;
587 		if (offset > cfg[hwport].max_stg2_offset)
588 			offset = cfg[hwport].max_stg2_offset;
589 		data = offset << 23  |
590 		    start << 11 |
591 		    i << 1      |
592 		    1;
593 		nlm_write_nae_reg(nae_base, NAE_STG2_PMEM_PROG, data);
594 		start += size;
595 	}
596 	cur_start[0] = start;
597 
598 	/* EH FIFO */
599 	start  = cur_start[1];
600 	for (i = start_ctxt; i < limit; i++) {
601 		size = cfg[hwport].eh_fifo_size / max_ctxts;
602 		if (size)
603 			offset = size - 1;
604 		else
605 			offset = size ;
606 		if (offset > cfg[hwport].max_eh_offset)
607 		    offset = cfg[hwport].max_eh_offset;
608 		data = offset << 23  |
609 		    start << 11 |
610 		    i << 1      |
611 		    1;
612 		nlm_write_nae_reg(nae_base, NAE_EH_PMEM_PROG, data);
613 		start += size;
614 	}
615 	cur_start[1] = start;
616 
617 	/* FROUT FIFO */
618 	start  = cur_start[2];
619 	for (i = start_ctxt; i < limit; i++) {
620 		size = cfg[hwport].frout_fifo_size / max_ctxts;
621 		if (size)
622 			offset = size - 1;
623 		else
624 			offset = size ;
625 		if (offset > cfg[hwport].max_frout_offset)
626 			offset = cfg[hwport].max_frout_offset;
627 		data = offset << 23  |
628 		    start << 11 |
629 		    i << 1      |
630 		    1;
631 		nlm_write_nae_reg(nae_base, NAE_FREE_PMEM_PROG, data);
632 		start += size;
633 	}
634 	cur_start[2] = start;
635 
636 	/* MS FIFO */
637 	start = cur_start[3];
638 	for (i = start_ctxt; i < limit; i++) {
639 		size = cfg[hwport].ms_fifo_size / max_ctxts;
640 		if (size)
641 			offset = size - 1;
642 		else
643 			offset = size ;
644 		if (offset > cfg[hwport].max_ms_offset)
645 			offset = cfg[hwport].max_ms_offset;
646 		data = offset << 22  |	/* FIXME in PRM */
647 		    start << 11 |
648 		    i << 1      |
649 		    1;
650 		nlm_write_nae_reg(nae_base, NAE_STR_PMEM_CMD, data);
651 		start += size;
652 	}
653 	cur_start[3] = start;
654 
655 	/* PKT FIFO */
656 	start  = cur_start[4];
657 	for (i = start_ctxt; i < limit; i++) {
658 		size = cfg[hwport].pkt_fifo_size / max_ctxts;
659 		if (size)
660 			offset = size - 1;
661 		else
662 			offset = size ;
663 		if (offset > cfg[hwport].max_pmem_offset)
664 			offset = cfg[hwport].max_pmem_offset;
665 		nlm_write_nae_reg(nae_base, NAE_TX_PKT_PMEM_CMD1, offset);
666 
667 		data = start << 11	|
668 		    i << 1		|
669 		    1;
670 		nlm_write_nae_reg(nae_base, NAE_TX_PKT_PMEM_CMD0, data);
671 		start += size;
672 	}
673 	cur_start[4] = start;
674 
675 	/* PKT LEN FIFO */
676 	start  = cur_start[5];
677 	for (i = start_ctxt; i < limit; i++) {
678 		size = cfg[hwport].pktlen_fifo_size / max_ctxts;
679 		if (size)
680 			offset = size - 1;
681 		else
682 			offset = size ;
683 		data = offset  << 22	|
684 		    start << 11		|
685 		    i << 1		|
686 		    1;
687 		nlm_write_nae_reg(nae_base, NAE_TX_PKTLEN_PMEM_CMD, data);
688 		start += size;
689 	}
690 	cur_start[5] = start;
691 }
692 
693 void
config_egress_fifo_credits(uint64_t nae_base,int hwport,int start_ctxt,int num_ctxts,int max_ctxts,struct nae_port_config * cfg)694 config_egress_fifo_credits(uint64_t nae_base, int hwport, int start_ctxt,
695     int num_ctxts, int max_ctxts, struct nae_port_config *cfg)
696 {
697 	uint32_t data, credit, max_credit;
698 	int i, limit;
699 
700 	limit = start_ctxt + num_ctxts;
701 	/* Stage1 -> Stage2 */
702 	max_credit = cfg[hwport].max_stg2_offset + 1;
703 	for (i = start_ctxt; i < limit; i++) {
704 		credit = cfg[hwport].stg1_2_credit / max_ctxts;
705 		if (credit > max_credit)
706 		    credit = max_credit;
707 		data = credit << 16	|
708 		    i << 4		|
709 		    1;
710 		nlm_write_nae_reg(nae_base, NAE_STG1_STG2CRDT_CMD, data);
711 	}
712 
713 	/* Stage2 -> EH */
714 	max_credit = cfg[hwport].max_eh_offset + 1;
715 	for (i = start_ctxt; i < limit; i++) {
716 		credit = cfg[hwport].stg2_eh_credit / max_ctxts;
717 		if (credit > max_credit)
718 			credit = max_credit;
719 		data = credit << 16	|
720 		    i << 4		|
721 		    1;
722 		nlm_write_nae_reg(nae_base, NAE_STG2_EHCRDT_CMD, data);
723 	}
724 
725 	/* Stage2 -> Frout */
726 	max_credit = cfg[hwport].max_frout_offset + 1;
727 	for (i = start_ctxt; i < limit; i++) {
728 		credit = cfg[hwport].stg2_frout_credit / max_ctxts;
729 		if (credit > max_credit)
730 			credit = max_credit;
731 		data = credit << 16	|
732 		    i << 4		|
733 		    1;
734 		nlm_write_nae_reg(nae_base, NAE_EH_FREECRDT_CMD, data);
735 	}
736 
737 	/* Stage2 -> MS */
738 	max_credit = cfg[hwport].max_ms_offset + 1;
739 	for (i = start_ctxt; i < limit; i++) {
740 		credit = cfg[hwport].stg2_ms_credit / max_ctxts;
741 		if (credit > max_credit)
742 			credit = max_credit;
743 		data = credit << 16	|
744 		    i << 4		|
745 		    1;
746 		nlm_write_nae_reg(nae_base, NAE_STG2_STRCRDT_CMD, data);
747 	}
748 }
749 
750 void
nlm_config_freein_fifo_uniq_cfg(uint64_t nae_base,int port,int nblock_free_desc)751 nlm_config_freein_fifo_uniq_cfg(uint64_t nae_base, int port,
752     int nblock_free_desc)
753 {
754 	uint32_t val;
755 	int size_in_clines;
756 
757 	size_in_clines = (nblock_free_desc / NAE_CACHELINE_SIZE);
758 	val = (size_in_clines << 8) | (port & 0x1f);
759 	nlm_write_nae_reg(nae_base, NAE_FREEIN_FIFO_UNIQ_SZ_CFG, val);
760 }
761 
762 /* XXXJC: redundant, see ucore_spray_config() */
763 void
nlm_config_ucore_iface_mask_cfg(uint64_t nae_base,int port,int nblock_ucore_mask)764 nlm_config_ucore_iface_mask_cfg(uint64_t nae_base, int port,
765     int nblock_ucore_mask)
766 {
767 	uint32_t val;
768 
769 	val = ( 0x1U << 31) | ((nblock_ucore_mask & 0xffff) << 8) |
770 	    (port & 0x1f);
771 	nlm_write_nae_reg(nae_base, NAE_UCORE_IFACEMASK_CFG, val);
772 }
773 
774 int
nlm_nae_init_netior(uint64_t nae_base,int nblocks)775 nlm_nae_init_netior(uint64_t nae_base, int nblocks)
776 {
777 	uint32_t ctrl1, ctrl2, ctrl3;
778 
779 	if (nblocks == 5)
780 		ctrl3 = 0x07 << 18;
781 	else
782 		ctrl3 = 0;
783 
784 	switch (nblocks) {
785 	case 2:
786 		ctrl1 = 0xff;
787 		ctrl2 = 0x0707;
788 		break;
789 	case 4:
790 	case 5:
791 		ctrl1 = 0xfffff;
792 		ctrl2 = 0x07070707;
793 		break;
794 	default:
795 		printf("WARNING: unsupported blocks %d\n", nblocks);
796 		return (-1);
797 	}
798 
799 	nlm_write_nae_reg(nae_base, NAE_LANE_CFG_SOFTRESET, 0);
800 	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL3, ctrl3);
801 	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL2, ctrl2);
802 	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL1, ctrl1);
803 	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL1, 0x0);
804 	return (0);
805 }
806 
807 void
nlm_nae_init_ingress(uint64_t nae_base,uint32_t desc_size)808 nlm_nae_init_ingress(uint64_t nae_base, uint32_t desc_size)
809 {
810 	uint32_t rx_cfg;
811 	uint32_t parser_threshold = 384;
812 
813 	rx_cfg = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
814 	rx_cfg &= ~(0x3 << 1);		/* reset max message size */
815 	rx_cfg &= ~(0xff << 4);		/* clear freein desc cluster size */
816 	rx_cfg &= ~(0x3f << 24);	/* reset rx status mask */ /*XXX: why not 7f */
817 
818 	rx_cfg |= 1;			/* rx enable */
819 	rx_cfg |= (0x0 << 1);		/* max message size */
820 	rx_cfg |= (0x43 & 0x7f) << 24;	/* rx status mask */
821 	rx_cfg |= ((desc_size / 64) & 0xff) << 4; /* freein desc cluster size */
822 	nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, rx_cfg);
823 	nlm_write_nae_reg(nae_base, NAE_PARSER_CONFIG,
824 	    (parser_threshold & 0x3ff) |
825 	    (((parser_threshold / desc_size) + 1) & 0xff) << 12 |
826 	    (((parser_threshold / 64) % desc_size) & 0xff) << 20);
827 
828 	/*nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_THRESH, 33);*/
829 }
830 
831 void
nlm_nae_init_egress(uint64_t nae_base)832 nlm_nae_init_egress(uint64_t nae_base)
833 {
834 	uint32_t tx_cfg;
835 
836 	tx_cfg = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG);
837 	if (!nlm_is_xlp8xx_ax()) {
838 		nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
839 		    tx_cfg	|
840 		    0x1		|	/* tx enable */
841 		    0x2		|	/* tx ace */
842 		    0x4		|	/* tx compatible */
843 		    (1 << 3));
844 	} else {
845 		nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
846 		    tx_cfg	|
847 		    0x1		|	/* tx enable */
848 		    0x2);		/* tx ace */
849 	}
850 }
851 
852 uint32_t
ucore_spray_config(uint32_t interface,uint32_t ucore_mask,int cmd)853 ucore_spray_config(uint32_t interface, uint32_t ucore_mask, int cmd)
854 {
855 	return ((cmd & 0x1) << 31) | ((ucore_mask & 0xffff) << 8) |
856 	    (interface & 0x1f);
857 }
858 
859 void
nlm_nae_init_ucore(uint64_t nae_base,int if_num,u_int ucore_mask)860 nlm_nae_init_ucore(uint64_t nae_base, int if_num, u_int ucore_mask)
861 {
862 	uint32_t ucfg;
863 
864 	ucfg = ucore_spray_config(if_num, ucore_mask, 1); /* 1 : write */
865 	nlm_write_nae_reg(nae_base, NAE_UCORE_IFACEMASK_CFG, ucfg);
866 }
867 
868 uint64_t
nae_tx_desc(u_int type,u_int rdex,u_int fbid,u_int len,uint64_t addr)869 nae_tx_desc(u_int type, u_int rdex, u_int fbid, u_int len, uint64_t addr)
870 {
871 	return ((uint64_t)type  << 62) |
872 		((uint64_t)rdex << 61) |
873 		((uint64_t)fbid << 54) |
874 		((uint64_t)len  << 40) | addr;
875 }
876 
877 void
nlm_setup_l2type(uint64_t nae_base,int hwport,uint32_t l2extlen,uint32_t l2extoff,uint32_t extra_hdrsize,uint32_t proto_offset,uint32_t fixed_hdroff,uint32_t l2proto)878 nlm_setup_l2type(uint64_t nae_base, int hwport, uint32_t l2extlen,
879     uint32_t l2extoff, uint32_t extra_hdrsize, uint32_t proto_offset,
880     uint32_t fixed_hdroff, uint32_t l2proto)
881 {
882 	uint32_t val;
883 
884 	val = ((l2extlen & 0x3f) << 26)		|
885 	    ((l2extoff & 0x3f) << 20)		|
886 	    ((extra_hdrsize & 0x3f) << 14)	|
887 	    ((proto_offset & 0x3f) << 8)	|
888 	    ((fixed_hdroff & 0x3f) << 2)	|
889 	    (l2proto & 0x3);
890 	nlm_write_nae_reg(nae_base, (NAE_L2_TYPE_PORT0 + hwport), val);
891 }
892 
893 void
nlm_setup_l3ctable_mask(uint64_t nae_base,int hwport,uint32_t ptmask,uint32_t l3portmask)894 nlm_setup_l3ctable_mask(uint64_t nae_base, int hwport, uint32_t ptmask,
895     uint32_t l3portmask)
896 {
897 	uint32_t val;
898 
899 	val = ((ptmask & 0x1) << 6)	|
900 	    ((l3portmask & 0x1) << 5)	|
901 	    (hwport & 0x1f);
902 	nlm_write_nae_reg(nae_base, NAE_L3_CTABLE_MASK0, val);
903 }
904 
905 void
nlm_setup_l3ctable_even(uint64_t nae_base,int entry,uint32_t l3hdroff,uint32_t ipcsum_en,uint32_t l4protooff,uint32_t l2proto,uint32_t eth_type)906 nlm_setup_l3ctable_even(uint64_t nae_base, int entry, uint32_t l3hdroff,
907     uint32_t ipcsum_en, uint32_t l4protooff,
908     uint32_t l2proto, uint32_t eth_type)
909 {
910 	uint32_t val;
911 
912 	val = ((l3hdroff & 0x3f) << 26)	|
913 	    ((l4protooff & 0x3f) << 20)	|
914 	    ((ipcsum_en & 0x1) << 18)	|
915 	    ((l2proto & 0x3) << 16)	|
916 	    (eth_type & 0xffff);
917 	nlm_write_nae_reg(nae_base, (NAE_L3CTABLE0 + (entry * 2)), val);
918 }
919 
920 void
nlm_setup_l3ctable_odd(uint64_t nae_base,int entry,uint32_t l3off0,uint32_t l3len0,uint32_t l3off1,uint32_t l3len1,uint32_t l3off2,uint32_t l3len2)921 nlm_setup_l3ctable_odd(uint64_t nae_base, int entry, uint32_t l3off0,
922     uint32_t l3len0, uint32_t l3off1, uint32_t l3len1,
923     uint32_t l3off2, uint32_t l3len2)
924 {
925 	uint32_t val;
926 
927 	val = ((l3off0 & 0x3f) << 26)	|
928 	    ((l3len0 & 0x1f) << 21)	|
929 	    ((l3off1 & 0x3f) << 15)	|
930 	    ((l3len1 & 0x1f) << 10)	|
931 	    ((l3off2 & 0x3f) << 4)	|
932 	    (l3len2 & 0xf);
933 	nlm_write_nae_reg(nae_base, (NAE_L3CTABLE0 + ((entry * 2) + 1)), val);
934 }
935 
936 void
nlm_setup_l4ctable_even(uint64_t nae_base,int entry,uint32_t im,uint32_t l3cm,uint32_t l4pm,uint32_t port,uint32_t l3camaddr,uint32_t l4proto)937 nlm_setup_l4ctable_even(uint64_t nae_base, int entry, uint32_t im,
938     uint32_t l3cm, uint32_t l4pm, uint32_t port,
939     uint32_t l3camaddr, uint32_t l4proto)
940 {
941 	uint32_t val;
942 
943 	val = ((im & 0x1) << 19)	|
944 	    ((l3cm & 0x1) << 18)	|
945 	    ((l4pm & 0x1) << 17)	|
946 	    ((port & 0x1f) << 12)	|
947 	    ((l3camaddr & 0xf) << 8)	|
948 	    (l4proto & 0xff);
949 	nlm_write_nae_reg(nae_base, (NAE_L4CTABLE0 + (entry * 2)), val);
950 }
951 
952 void
nlm_setup_l4ctable_odd(uint64_t nae_base,int entry,uint32_t l4off0,uint32_t l4len0,uint32_t l4off1,uint32_t l4len1)953 nlm_setup_l4ctable_odd(uint64_t nae_base, int entry, uint32_t l4off0,
954     uint32_t l4len0, uint32_t l4off1, uint32_t l4len1)
955 {
956 	uint32_t val;
957 
958 	val = ((l4off0 & 0x3f) << 21)	|
959 	    ((l4len0 & 0xf) << 17)	|
960 	    ((l4off1 & 0x3f) << 11)	|
961 	    (l4len1 & 0xf);
962 	nlm_write_nae_reg(nae_base, (NAE_L4CTABLE0 + ((entry * 2) + 1)), val);
963 }
964 
965 void
nlm_enable_hardware_parser(uint64_t nae_base)966 nlm_enable_hardware_parser(uint64_t nae_base)
967 {
968 	uint32_t val;
969 
970 	val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
971 	val |= (1 << 12); /* hardware parser enable */
972 	nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val);
973 
974 	/***********************************************
975 	 * program L3 CAM table
976 	 ***********************************************/
977 
978 	/*
979 	 *  entry-0 is ipv4 MPLS type 1 label
980 	 */
981 	 /* l3hdroff = 4 bytes, ether_type = 0x8847 for MPLS_type1 */
982 	nlm_setup_l3ctable_even(nae_base, 0, 4, 1, 9, 1, 0x8847);
983 	/* l3off0 (8 bytes) -> l3len0 (1 byte) := ip proto
984 	 * l3off1 (12 bytes) -> l3len1 (4 bytes) := src ip
985 	 * l3off2 (16 bytes) -> l3len2 (4 bytes) := dst ip
986 	 */
987 	nlm_setup_l3ctable_odd(nae_base, 0, 9, 1, 12, 4, 16, 4);
988 
989 	/*
990 	 * entry-1 is for ethernet IPv4 packets
991 	 */
992 	nlm_setup_l3ctable_even(nae_base, 1, 0, 1, 9, 1, 0x0800);
993 	/* l3off0 (8 bytes) -> l3len0 (1 byte) := ip proto
994 	 * l3off1 (12 bytes) -> l3len1 (4 bytes) := src ip
995 	 * l3off2 (16 bytes) -> l3len2 (4 bytes) := dst ip
996 	 */
997 	nlm_setup_l3ctable_odd(nae_base, 1, 9, 1, 12, 4, 16, 4);
998 
999 	/*
1000 	 * entry-2 is for ethernet IPv6 packets
1001 	 */
1002 	nlm_setup_l3ctable_even(nae_base, 2, 0, 1, 6, 1, 0x86dd);
1003 	/* l3off0 (6 bytes) -> l3len0 (1 byte) := next header (ip proto)
1004 	 * l3off1 (8 bytes) -> l3len1 (16 bytes) := src ip
1005 	 * l3off2 (24 bytes) -> l3len2 (16 bytes) := dst ip
1006 	 */
1007 	nlm_setup_l3ctable_odd(nae_base, 2, 6, 1, 8, 16, 24, 16);
1008 
1009 	/*
1010 	 * entry-3 is for ethernet ARP packets
1011 	 */
1012 	nlm_setup_l3ctable_even(nae_base, 3, 0, 0, 9, 1, 0x0806);
1013 	/* extract 30 bytes from packet start */
1014 	nlm_setup_l3ctable_odd(nae_base, 3, 0, 30, 0, 0, 0, 0);
1015 
1016 	/*
1017 	 * entry-4 is for ethernet FCoE packets
1018 	 */
1019 	nlm_setup_l3ctable_even(nae_base, 4, 0, 0, 9, 1, 0x8906);
1020 	/* FCoE packet consists of 4 byte start-of-frame,
1021 	 * and 24 bytes of frame header, followed by
1022 	 * 64 bytes of optional-header (ESP, network..),
1023 	 * 2048 bytes of payload, 36 bytes of optional
1024 	 * "fill bytes" or ESP trailer, 4 bytes of CRC,
1025 	 * and 4 bytes of end-of-frame
1026 	 * We extract the first 4 + 24 = 28 bytes
1027 	 */
1028 	nlm_setup_l3ctable_odd(nae_base, 4, 0, 28, 0, 0, 0, 0);
1029 
1030 	/*
1031 	 * entry-5 is for vlan tagged frames (0x8100)
1032 	 */
1033 	nlm_setup_l3ctable_even(nae_base, 5, 0, 0, 9, 1, 0x8100);
1034 	/* we extract 31 bytes from the payload */
1035 	nlm_setup_l3ctable_odd(nae_base, 5, 0, 31, 0, 0, 0, 0);
1036 
1037 	/*
1038 	 * entry-6 is for ieee 802.1ad provider bridging
1039 	 * tagged frames (0x88a8)
1040 	 */
1041 	nlm_setup_l3ctable_even(nae_base, 6, 0, 0, 9, 1, 0x88a8);
1042 	/* we extract 31 bytes from the payload */
1043 	nlm_setup_l3ctable_odd(nae_base, 6, 0, 31, 0, 0, 0, 0);
1044 
1045 	/*
1046 	 * entry-7 is for Cisco's Q-in-Q tagged frames (0x9100)
1047 	 */
1048 	nlm_setup_l3ctable_even(nae_base, 7, 0, 0, 9, 1, 0x9100);
1049 	/* we extract 31 bytes from the payload */
1050 	nlm_setup_l3ctable_odd(nae_base, 7, 0, 31, 0, 0, 0, 0);
1051 
1052 	/*
1053 	 * entry-8 is for Ethernet Jumbo frames (0x8870)
1054 	 */
1055 	nlm_setup_l3ctable_even(nae_base, 8, 0, 0, 9, 1, 0x8870);
1056 	/* we extract 31 bytes from the payload */
1057 	nlm_setup_l3ctable_odd(nae_base, 8, 0, 31, 0, 0, 0, 0);
1058 
1059 	/*
1060 	 * entry-9 is for MPLS Multicast frames (0x8848)
1061 	 */
1062 	nlm_setup_l3ctable_even(nae_base, 9, 0, 0, 9, 1, 0x8848);
1063 	/* we extract 31 bytes from the payload */
1064 	nlm_setup_l3ctable_odd(nae_base, 9, 0, 31, 0, 0, 0, 0);
1065 
1066 	/*
1067 	 * entry-10 is for IEEE 802.1ae MAC Security frames (0x88e5)
1068 	 */
1069 	nlm_setup_l3ctable_even(nae_base, 10, 0, 0, 9, 1, 0x88e5);
1070 	/* we extract 31 bytes from the payload */
1071 	nlm_setup_l3ctable_odd(nae_base, 10, 0, 31, 0, 0, 0, 0);
1072 
1073 	/*
1074 	 * entry-11 is for PTP frames (0x88f7)
1075 	 */
1076 	nlm_setup_l3ctable_even(nae_base, 11, 0, 0, 9, 1, 0x88f7);
1077 	/* PTP messages can be sent as UDP messages over
1078 	 * IPv4 or IPv6; and as a raw ethernet message
1079 	 * with ethertype 0x88f7. The message contents
1080 	 * are the same for UDP or ethernet based encapsulations
1081 	 * The header is 34 bytes long, and we extract
1082 	 * it all out.
1083 	 */
1084 	nlm_setup_l3ctable_odd(nae_base, 11, 0, 31, 31, 2, 0, 0);
1085 
1086 	/*
1087 	 * entry-12 is for ethernet Link Control Protocol (LCP)
1088 	 * used with PPPoE
1089 	 */
1090 	nlm_setup_l3ctable_even(nae_base, 12, 0, 0, 9, 1, 0xc021);
1091 	/* LCP packet consists of 1 byte of code, 1 byte of
1092 	 * identifier and two bytes of length followed by
1093 	 * data (upto length bytes).
1094 	 * We extract 4 bytes from start of packet
1095 	 */
1096 	nlm_setup_l3ctable_odd(nae_base, 12, 0, 4, 0, 0, 0, 0);
1097 
1098 	/*
1099 	 * entry-13 is for ethernet Link Quality Report (0xc025)
1100 	 * used with PPPoE
1101 	 */
1102 	nlm_setup_l3ctable_even(nae_base, 13, 0, 0, 9, 1, 0xc025);
1103 	/* We extract 31 bytes from packet start */
1104 	nlm_setup_l3ctable_odd(nae_base, 13, 0, 31, 0, 0, 0, 0);
1105 
1106 	/*
1107 	 * entry-14 is for PPPoE Session (0x8864)
1108 	 */
1109 	nlm_setup_l3ctable_even(nae_base, 14, 0, 0, 9, 1, 0x8864);
1110 	/* We extract 31 bytes from packet start */
1111 	nlm_setup_l3ctable_odd(nae_base, 14, 0, 31, 0, 0, 0, 0);
1112 
1113 	/*
1114 	 * entry-15 - default entry
1115 	 */
1116 	nlm_setup_l3ctable_even(nae_base, 15, 0, 0, 0, 0, 0x0000);
1117 	/* We extract 31 bytes from packet start */
1118 	nlm_setup_l3ctable_odd(nae_base, 15, 0, 31, 0, 0, 0, 0);
1119 
1120 	/***********************************************
1121 	 * program L4 CAM table
1122 	 ***********************************************/
1123 
1124 	/*
1125 	 * entry-0 - tcp packets (0x6)
1126 	 */
1127 	nlm_setup_l4ctable_even(nae_base, 0, 0, 0, 1, 0, 0, 0x6);
1128 	/* tcp header is 20 bytes without tcp options
1129 	 * We extract 20 bytes from tcp start */
1130 	nlm_setup_l4ctable_odd(nae_base, 0, 0, 15, 15, 5);
1131 
1132 	/*
1133 	 * entry-1 - udp packets (0x11)
1134 	 */
1135 	nlm_setup_l4ctable_even(nae_base, 1, 0, 0, 1, 0, 0, 0x11);
1136 	/* udp header is 8 bytes in size.
1137 	 * We extract 8 bytes from udp start */
1138 	nlm_setup_l4ctable_odd(nae_base, 1, 0, 8, 0, 0);
1139 
1140 	/*
1141 	 * entry-2 - sctp packets (0x84)
1142 	 */
1143 	nlm_setup_l4ctable_even(nae_base, 2, 0, 0, 1, 0, 0, 0x84);
1144 	/* sctp packets have a 12 byte generic header
1145 	 * and various chunks.
1146 	 * We extract 12 bytes from sctp start */
1147 	nlm_setup_l4ctable_odd(nae_base, 2, 0, 12, 0, 0);
1148 
1149 	/*
1150 	 * entry-3 - RDP packets (0x1b)
1151 	 */
1152 	nlm_setup_l4ctable_even(nae_base, 3, 0, 0, 1, 0, 0, 0x1b);
1153 	/* RDP packets have 18 bytes of generic header
1154 	 * before variable header starts.
1155 	 * We extract 18 bytes from rdp start */
1156 	nlm_setup_l4ctable_odd(nae_base, 3, 0, 15, 15, 3);
1157 
1158 	/*
1159 	 * entry-4 - DCCP packets (0x21)
1160 	 */
1161 	nlm_setup_l4ctable_even(nae_base, 4, 0, 0, 1, 0, 0, 0x21);
1162 	/* DCCP has two types of generic headers of
1163 	 * sizes 16 bytes and 12 bytes if X = 1.
1164 	 * We extract 16 bytes from dccp start */
1165 	nlm_setup_l4ctable_odd(nae_base, 4, 0, 15, 15, 1);
1166 
1167 	/*
1168 	 * entry-5 - ipv6 encapsulated in ipv4 packets (0x29)
1169 	 */
1170 	nlm_setup_l4ctable_even(nae_base, 5, 0, 0, 1, 0, 0, 0x29);
1171 	/* ipv4 header is 20 bytes excluding IP options.
1172 	 * We extract 20 bytes from IPv4 start */
1173 	nlm_setup_l4ctable_odd(nae_base, 5, 0, 15, 15, 5);
1174 
1175 	/*
1176 	 * entry-6 - ip in ip encapsulation packets (0x04)
1177 	 */
1178 	nlm_setup_l4ctable_even(nae_base, 6, 0, 0, 1, 0, 0, 0x04);
1179 	/* ipv4 header is 20 bytes excluding IP options.
1180 	 * We extract 20 bytes from ipv4 start */
1181 	nlm_setup_l4ctable_odd(nae_base, 6, 0, 15, 15, 5);
1182 
1183 	/*
1184 	 * entry-7 - default entry (0x0)
1185 	 */
1186 	nlm_setup_l4ctable_even(nae_base, 7, 0, 0, 1, 0, 0, 0x0);
1187 	/* We extract 20 bytes from packet start */
1188 	nlm_setup_l4ctable_odd(nae_base, 7, 0, 15, 15, 5);
1189 }
1190 
1191 void
nlm_enable_hardware_parser_per_port(uint64_t nae_base,int block,int port)1192 nlm_enable_hardware_parser_per_port(uint64_t nae_base, int block, int port)
1193 {
1194 	int hwport = (block * 4) + (port & 0x3);
1195 
1196 	/* program L2 and L3 header extraction for each port */
1197 	/* enable ethernet L2 mode on port */
1198 	nlm_setup_l2type(nae_base, hwport, 0, 0, 0, 0, 0, 1);
1199 
1200 	/* l2proto and ethtype included in l3cam */
1201 	nlm_setup_l3ctable_mask(nae_base, hwport, 1, 0);
1202 }
1203 
1204 void
nlm_prepad_enable(uint64_t nae_base,int size)1205 nlm_prepad_enable(uint64_t nae_base, int size)
1206 {
1207 	uint32_t val;
1208 
1209 	val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
1210 	val |= (1 << 13); /* prepad enable */
1211 	val |= ((size & 0x3) << 22); /* prepad size */
1212 	nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val);
1213 }
1214 
1215 void
nlm_setup_1588_timer(uint64_t nae_base,struct nae_port_config * cfg)1216 nlm_setup_1588_timer(uint64_t nae_base, struct nae_port_config *cfg)
1217 {
1218 	uint32_t hi, lo, val;
1219 
1220 	hi = cfg[0].ieee1588_userval >> 32;
1221 	lo = cfg[0].ieee1588_userval & 0xffffffff;
1222 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_USER_VALUE_HI, hi);
1223 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_USER_VALUE_LO, lo);
1224 
1225 	hi = cfg[0].ieee1588_ptpoff >> 32;
1226 	lo = cfg[0].ieee1588_ptpoff & 0xffffffff;
1227 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_OFFSET_HI, hi);
1228 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_OFFSET_LO, lo);
1229 
1230 	hi = cfg[0].ieee1588_tmr1 >> 32;
1231 	lo = cfg[0].ieee1588_tmr1 & 0xffffffff;
1232 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR1_HI, hi);
1233 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR1_LO, lo);
1234 
1235 	hi = cfg[0].ieee1588_tmr2 >> 32;
1236 	lo = cfg[0].ieee1588_tmr2 & 0xffffffff;
1237 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR2_HI, hi);
1238 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR2_LO, lo);
1239 
1240 	hi = cfg[0].ieee1588_tmr3 >> 32;
1241 	lo = cfg[0].ieee1588_tmr3 & 0xffffffff;
1242 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR3_HI, hi);
1243 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR3_LO, lo);
1244 
1245 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_INTG,
1246 	    cfg[0].ieee1588_inc_intg);
1247 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_NUM,
1248 	    cfg[0].ieee1588_inc_num);
1249 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_DEN,
1250 	    cfg[0].ieee1588_inc_den);
1251 
1252 	val = nlm_read_nae_reg(nae_base, NAE_1588_PTP_CONTROL);
1253 	/* set and clear freq_mul = 1 */
1254 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val | (0x1 << 1));
1255 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val);
1256 	/* set and clear load_user_val = 1 */
1257 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val | (0x1 << 6));
1258 	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val);
1259 }
1260 
1261 void
nlm_mac_enable(uint64_t nae_base,int nblock,int port_type,int port)1262 nlm_mac_enable(uint64_t nae_base, int nblock, int port_type, int port)
1263 {
1264 	uint32_t mac_cfg1, xaui_cfg;
1265 	uint32_t netwk_inf;
1266 	int iface = port & 0x3;
1267 
1268 	switch(port_type) {
1269 	case SGMIIC:
1270 		netwk_inf = nlm_read_nae_reg(nae_base,
1271 		    SGMII_NET_IFACE_CTRL(nblock, iface));
1272 		nlm_write_nae_reg(nae_base,
1273 		    SGMII_NET_IFACE_CTRL(nblock, iface),
1274 		    netwk_inf		|
1275 		    (1 << 2));			/* enable tx */
1276 		mac_cfg1 = nlm_read_nae_reg(nae_base,
1277 		    SGMII_MAC_CONF1(nblock, iface));
1278 		nlm_write_nae_reg(nae_base,
1279 		    SGMII_MAC_CONF1(nblock, iface),
1280 		    mac_cfg1		|
1281 		    (1 << 2)		|	/* rx enable */
1282 		    1);				/* tx enable */
1283 		break;
1284 	case XAUIC:
1285 		xaui_cfg = nlm_read_nae_reg(nae_base,
1286 		    XAUI_CONFIG1(nblock));
1287 		nlm_write_nae_reg(nae_base,
1288 		    XAUI_CONFIG1(nblock),
1289 		    xaui_cfg		|
1290 		    XAUI_CONFIG_TFEN	|
1291 		    XAUI_CONFIG_RFEN);
1292 		break;
1293 	case ILC:
1294 		break;
1295 	}
1296 }
1297 
1298 void
nlm_mac_disable(uint64_t nae_base,int nblock,int port_type,int port)1299 nlm_mac_disable(uint64_t nae_base, int nblock, int port_type, int port)
1300 {
1301 	uint32_t mac_cfg1, xaui_cfg;
1302 	uint32_t netwk_inf;
1303 	int iface = port & 0x3;
1304 
1305 	switch(port_type) {
1306 	case SGMIIC:
1307 		mac_cfg1 = nlm_read_nae_reg(nae_base,
1308 		    SGMII_MAC_CONF1(nblock, iface));
1309 		nlm_write_nae_reg(nae_base,
1310 		    SGMII_MAC_CONF1(nblock, iface),
1311 		    mac_cfg1		&
1312 		    ~((1 << 2)		|	/* rx enable */
1313 		    1));			/* tx enable */
1314 		netwk_inf = nlm_read_nae_reg(nae_base,
1315 		    SGMII_NET_IFACE_CTRL(nblock, iface));
1316 		nlm_write_nae_reg(nae_base,
1317 		    SGMII_NET_IFACE_CTRL(nblock, iface),
1318 		    netwk_inf		&
1319 		    ~(1 << 2));			/* enable tx */
1320 		break;
1321 	case XAUIC:
1322 		xaui_cfg = nlm_read_nae_reg(nae_base,
1323 		    XAUI_CONFIG1(nblock));
1324 		nlm_write_nae_reg(nae_base,
1325 		    XAUI_CONFIG1(nblock),
1326 		    xaui_cfg		&
1327 		    ~(XAUI_CONFIG_TFEN	|
1328 		    XAUI_CONFIG_RFEN));
1329 		break;
1330 	case ILC:
1331 		break;
1332 	}
1333 }
1334 
1335 /*
1336  * Set IOR credits for the ports in ifmask to valmask
1337  */
1338 static void
nlm_nae_set_ior_credit(uint64_t nae_base,uint32_t ifmask,uint32_t valmask)1339 nlm_nae_set_ior_credit(uint64_t nae_base, uint32_t ifmask, uint32_t valmask)
1340 {
1341 	uint32_t tx_config, tx_ior_credit;
1342 
1343 	tx_ior_credit = nlm_read_nae_reg(nae_base, NAE_TX_IORCRDT_INIT);
1344 	tx_ior_credit &= ~ifmask;
1345 	tx_ior_credit |= valmask;
1346 	nlm_write_nae_reg(nae_base, NAE_TX_IORCRDT_INIT, tx_ior_credit);
1347 
1348 	tx_config = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG);
1349 	/* need to toggle these bits for credits to be loaded */
1350 	nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
1351 	    tx_config | (TXINITIORCR(ifmask)));
1352 	nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
1353 	    tx_config & ~(TXINITIORCR(ifmask)));
1354 }
1355 
1356 int
nlm_nae_open_if(uint64_t nae_base,int nblock,int port_type,int port,uint32_t desc_size)1357 nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
1358     int port, uint32_t desc_size)
1359 {
1360 	uint32_t netwk_inf;
1361 	uint32_t mac_cfg1, netior_ctrl3;
1362 	int iface, iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg;
1363 
1364 	switch (port_type) {
1365 	case XAUIC:
1366 		netwk_inf = nlm_read_nae_reg(nae_base,
1367 		    XAUI_NETIOR_XGMAC_CTRL1(nblock));
1368 		netwk_inf |= (1 << NETIOR_XGMAC_STATS_CLR_POS);
1369 		nlm_write_nae_reg(nae_base,
1370 		    XAUI_NETIOR_XGMAC_CTRL1(nblock), netwk_inf);
1371 
1372 		nlm_nae_set_ior_credit(nae_base, 0xf << port, 0xf << port);
1373 		break;
1374 
1375 	case ILC:
1376 		nlm_nae_set_ior_credit(nae_base, 0xff << port, 0xff << port);
1377 		break;
1378 
1379 	case SGMIIC:
1380 		nlm_nae_set_ior_credit(nae_base, 0x1 << port, 0);
1381 
1382 		/*
1383 		 * XXXJC: split this and merge to sgmii.c
1384 		 * some of this is duplicated from there.
1385 		 */
1386 		/* init phy id to access internal PCS */
1387 		iface = port & 0x3;
1388 		iface_ctrl_reg = SGMII_NET_IFACE_CTRL(nblock, iface);
1389 		conf1_reg = SGMII_MAC_CONF1(nblock, iface);
1390 		conf2_reg = SGMII_MAC_CONF2(nblock, iface);
1391 
1392 		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1393 		netwk_inf &= 0x7ffffff;
1394 		netwk_inf |= (port << 27);
1395 		nlm_write_nae_reg(nae_base, iface_ctrl_reg, netwk_inf);
1396 
1397 		/* Sofreset sgmii port - set bit 11 to 0  */
1398 		netwk_inf &= 0xfffff7ff;
1399 		nlm_write_nae_reg(nae_base, iface_ctrl_reg, netwk_inf);
1400 
1401 		/* Reset Gmac */
1402 		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1403 		nlm_write_nae_reg(nae_base, conf1_reg,
1404 		    mac_cfg1	|
1405 		    (1U << 31)	|	/* soft reset */
1406 		    (1 << 2)	|	/* rx enable */
1407 		    (1));		/* tx enable */
1408 
1409 		/* default to 1G */
1410 		nlm_write_nae_reg(nae_base,
1411 		    conf2_reg,
1412 		    (0x7 << 12)	|	/* interface preamble length */
1413 		    (0x2 << 8)	|	/* interface mode */
1414 		    (0x1 << 2)	|	/* pad crc enable */
1415 		    (0x1));		/* full duplex */
1416 
1417 		/* clear gmac reset */
1418 		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1419 		nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(1U << 31));
1420 
1421 		/* clear speed debug bit */
1422 		iface_ctrl3_reg = SGMII_NET_IFACE_CTRL3(nblock, iface);
1423 		netior_ctrl3 = nlm_read_nae_reg(nae_base, iface_ctrl3_reg);
1424 		nlm_write_nae_reg(nae_base, iface_ctrl3_reg,
1425 		    netior_ctrl3 & ~(1 << 6));
1426 
1427 		/* disable TX, RX for now */
1428 		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1429 		nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(0x5));
1430 		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1431 		nlm_write_nae_reg(nae_base, iface_ctrl_reg,
1432 		    netwk_inf & ~(0x1 << 2));
1433 
1434 		/* clear stats counters */
1435 		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1436 		nlm_write_nae_reg(nae_base, iface_ctrl_reg,
1437 		    netwk_inf | (1 << 15));
1438 
1439 		/* enable stats counters */
1440 		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1441 		nlm_write_nae_reg(nae_base, iface_ctrl_reg,
1442 		    (netwk_inf & ~(1 << 15)) | (1 << 16));
1443 
1444 		/* flow control? */
1445 		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1446 		nlm_write_nae_reg(nae_base, conf1_reg,
1447 		    mac_cfg1 | (0x3 << 4));
1448 		break;
1449 	}
1450 
1451 	nlm_nae_init_ingress(nae_base, desc_size);
1452 	nlm_nae_init_egress(nae_base);
1453 
1454 	return (0);
1455 }
1456