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