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