1233545Sjchandra/*-
2233545Sjchandra * Copyright (c) 2003-2012 Broadcom Corporation
3233545Sjchandra * All Rights Reserved
4233545Sjchandra *
5233545Sjchandra * Redistribution and use in source and binary forms, with or without
6233545Sjchandra * modification, are permitted provided that the following conditions
7233545Sjchandra * are met:
8233545Sjchandra *
9233545Sjchandra * 1. Redistributions of source code must retain the above copyright
10233545Sjchandra *    notice, this list of conditions and the following disclaimer.
11233545Sjchandra * 2. Redistributions in binary form must reproduce the above copyright
12233545Sjchandra *    notice, this list of conditions and the following disclaimer in
13233545Sjchandra *    the documentation and/or other materials provided with the
14233545Sjchandra *    distribution.
15233545Sjchandra *
16233545Sjchandra * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
17233545Sjchandra * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18233545Sjchandra * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19233545Sjchandra * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
20233545Sjchandra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21233545Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22233545Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23233545Sjchandra * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24233545Sjchandra * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25233545Sjchandra * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26233545Sjchandra * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27233545Sjchandra */
28233545Sjchandra
29233545Sjchandra#include <sys/cdefs.h>
30233545Sjchandra__FBSDID("$FreeBSD$");
31233545Sjchandra#include <sys/types.h>
32233545Sjchandra#include <sys/systm.h>
33233545Sjchandra
34233545Sjchandra#include <mips/nlm/hal/mips-extns.h>
35233545Sjchandra#include <mips/nlm/hal/haldefs.h>
36233545Sjchandra#include <mips/nlm/hal/iomap.h>
37233545Sjchandra#include <mips/nlm/hal/sys.h>
38233545Sjchandra#include <mips/nlm/hal/nae.h>
39233545Sjchandra#include <mips/nlm/hal/mdio.h>
40233545Sjchandra#include <mips/nlm/hal/sgmii.h>
41233545Sjchandra#include <mips/nlm/hal/xaui.h>
42233545Sjchandra
43233545Sjchandra#include <mips/nlm/board.h>
44233545Sjchandra#include <mips/nlm/xlp.h>
45233545Sjchandra
46233545Sjchandravoid
47233545Sjchandranlm_nae_flush_free_fifo(uint64_t nae_base, int nblocks)
48233545Sjchandra{
49233545Sjchandra	uint32_t data, fifo_mask;
50233545Sjchandra
51233545Sjchandra	fifo_mask = (1 << (4 * nblocks)) - 1;
52233545Sjchandra
53233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP, fifo_mask);
54233545Sjchandra	do {
55233545Sjchandra		data = nlm_read_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP);
56233545Sjchandra	} while (data != fifo_mask);
57233545Sjchandra
58233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP, 0);
59233545Sjchandra}
60233545Sjchandra
61233545Sjchandravoid
62255368Sjchandranlm_program_nae_parser_seq_fifo(uint64_t nae_base, int maxports,
63233545Sjchandra    struct nae_port_config *cfg)
64233545Sjchandra{
65233545Sjchandra	uint32_t val;
66255368Sjchandra	int start = 0, size, i;
67233545Sjchandra
68255368Sjchandra	for (i = 0; i < maxports; i++) {
69255368Sjchandra		size = cfg[i].pseq_fifo_size;
70233545Sjchandra		val = (((size & 0x1fff) << 17) |
71233545Sjchandra		    ((start & 0xfff) << 5) |
72255368Sjchandra		    (i & 0x1f));
73233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_PARSER_SEQ_FIFO_CFG, val);
74233545Sjchandra		start += size;
75233545Sjchandra	}
76233545Sjchandra}
77233545Sjchandra
78233545Sjchandravoid
79233545Sjchandranlm_setup_rx_cal_cfg(uint64_t nae_base, int total_num_ports,
80233545Sjchandra    struct nae_port_config *cfg)
81233545Sjchandra{
82233545Sjchandra	int rx_slots = 0, port;
83233545Sjchandra	int cal_len, cal = 0, last_free = 0;
84233545Sjchandra	uint32_t val;
85233545Sjchandra
86233545Sjchandra	for (port = 0; port < total_num_ports; port++) {
87233545Sjchandra		if (cfg[port].rx_slots_reqd)
88233545Sjchandra		    rx_slots += cfg[port].rx_slots_reqd;
89233545Sjchandra		if (rx_slots > MAX_CAL_SLOTS) {
90233545Sjchandra			rx_slots = MAX_CAL_SLOTS;
91233545Sjchandra			break;
92233545Sjchandra		}
93233545Sjchandra	}
94233545Sjchandra
95233545Sjchandra	cal_len = rx_slots - 1;
96233545Sjchandra
97233545Sjchandra	do {
98233545Sjchandra		if (cal >= MAX_CAL_SLOTS)
99233545Sjchandra			break;
100233545Sjchandra		last_free = cal;
101233545Sjchandra		for (port = 0; port < total_num_ports; port++) {
102233545Sjchandra			if (cfg[port].rx_slots_reqd > 0) {
103233545Sjchandra				val = (cal_len << 16) | (port << 8) | cal;
104233545Sjchandra				nlm_write_nae_reg(nae_base,
105233545Sjchandra				    NAE_RX_IF_SLOT_CAL, val);
106233545Sjchandra				cal++;
107233545Sjchandra				cfg[port].rx_slots_reqd--;
108233545Sjchandra			}
109233545Sjchandra		}
110233545Sjchandra		if (last_free == cal)
111233545Sjchandra			break;
112233545Sjchandra	} while (1);
113233545Sjchandra}
114233545Sjchandra
115233545Sjchandravoid
116233545Sjchandranlm_setup_tx_cal_cfg(uint64_t nae_base, int total_num_ports,
117233545Sjchandra    struct nae_port_config *cfg)
118233545Sjchandra{
119233545Sjchandra	int tx_slots = 0, port;
120233545Sjchandra	int cal = 0, last_free = 0;
121233545Sjchandra	uint32_t val;
122233545Sjchandra
123233545Sjchandra	for (port = 0; port < total_num_ports; port++) {
124233545Sjchandra		if (cfg[port].tx_slots_reqd)
125233545Sjchandra			tx_slots += cfg[port].tx_slots_reqd;
126233545Sjchandra		if (tx_slots > MAX_CAL_SLOTS) {
127233545Sjchandra			tx_slots = MAX_CAL_SLOTS;
128233545Sjchandra			break;
129233545Sjchandra		}
130233545Sjchandra	}
131233545Sjchandra
132233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_EGR_NIOR_CAL_LEN_REG, tx_slots - 1);
133233545Sjchandra	do {
134233545Sjchandra		if (cal >= MAX_CAL_SLOTS)
135233545Sjchandra			break;
136233545Sjchandra		last_free = cal;
137233545Sjchandra		for (port = 0; port < total_num_ports; port++) {
138233545Sjchandra			if (cfg[port].tx_slots_reqd > 0) {
139233545Sjchandra				val = (port << 7) | (cal << 1) | 1;
140233545Sjchandra				nlm_write_nae_reg(nae_base,
141233545Sjchandra				    NAE_EGR_NIOR_CRDT_CAL_PROG, val);
142233545Sjchandra				cal++;
143233545Sjchandra				cfg[port].tx_slots_reqd--;
144233545Sjchandra			}
145233545Sjchandra		}
146233545Sjchandra		if (last_free == cal)
147233545Sjchandra			break;
148233545Sjchandra	} while (1);
149233545Sjchandra}
150233545Sjchandra
151233545Sjchandravoid
152233545Sjchandranlm_deflate_frin_fifo_carving(uint64_t nae_base, int total_num_ports)
153233545Sjchandra{
154233545Sjchandra	const int minimum_size = 8;
155233545Sjchandra	uint32_t value;
156233545Sjchandra	int intf, start;
157233545Sjchandra
158233545Sjchandra	for (intf = 0; intf < total_num_ports; intf++) {
159233545Sjchandra		start = minimum_size * intf;
160233545Sjchandra		value = (minimum_size << 20) | (start << 8) | (intf);
161233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_FREE_IN_FIFO_CFG, value);
162233545Sjchandra	}
163233545Sjchandra}
164233545Sjchandra
165233545Sjchandravoid
166233545Sjchandranlm_reset_nae(int node)
167233545Sjchandra{
168233545Sjchandra	uint64_t sysbase;
169233545Sjchandra	uint64_t nae_base;
170233545Sjchandra	uint64_t nae_pcibase;
171233545Sjchandra	uint32_t rx_config;
172233545Sjchandra	uint32_t bar0;
173233545Sjchandra	int reset_bit;
174233545Sjchandra
175233545Sjchandra	sysbase  = nlm_get_sys_regbase(node);
176233545Sjchandra	nae_base = nlm_get_nae_regbase(node);
177233545Sjchandra	nae_pcibase = nlm_get_nae_pcibase(node);
178233545Sjchandra
179233545Sjchandra	bar0 = nlm_read_pci_reg(nae_pcibase, XLP_PCI_CFGREG4);
180233545Sjchandra
181233545Sjchandra#if BYTE_ORDER == LITTLE_ENDIAN
182233545Sjchandra	if (nlm_is_xlp8xx_ax()) {
183233636Sjmallett		uint8_t	val;
184233545Sjchandra		/* membar fixup */
185233545Sjchandra		val = (bar0 >> 24) & 0xff;
186233545Sjchandra		bar0 = (val << 24) | (val << 16) | (val << 8) | val;
187233545Sjchandra	}
188233545Sjchandra#endif
189233545Sjchandra
190233545Sjchandra	if (nlm_is_xlp3xx())
191233545Sjchandra		reset_bit = 6;
192233545Sjchandra	else
193233545Sjchandra		reset_bit = 9;
194233545Sjchandra
195233545Sjchandra	/* Reset NAE */
196233545Sjchandra	nlm_write_sys_reg(sysbase, SYS_RESET, (1 << reset_bit));
197233545Sjchandra
198233545Sjchandra	/* XXXJC - 1s delay here may be too high */
199233545Sjchandra	DELAY(1000000);
200233545Sjchandra	nlm_write_sys_reg(sysbase, SYS_RESET, (0 << reset_bit));
201233545Sjchandra	DELAY(1000000);
202233545Sjchandra
203233545Sjchandra	rx_config = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
204233545Sjchandra	nlm_write_pci_reg(nae_pcibase, XLP_PCI_CFGREG4, bar0);
205233545Sjchandra}
206233545Sjchandra
207233545Sjchandravoid
208233545Sjchandranlm_setup_poe_class_config(uint64_t nae_base, int max_poe_classes,
209233545Sjchandra    int num_contexts, int *poe_cl_tbl)
210233545Sjchandra{
211233545Sjchandra	uint32_t val;
212233545Sjchandra	int i, max_poe_class_ctxt_tbl_sz;
213233545Sjchandra
214233545Sjchandra	max_poe_class_ctxt_tbl_sz = num_contexts/max_poe_classes;
215233545Sjchandra	for (i = 0; i < max_poe_class_ctxt_tbl_sz; i++) {
216233545Sjchandra		val = (poe_cl_tbl[(i/max_poe_classes) & 0x7] << 8) | i;
217233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_POE_CLASS_SETUP_CFG, val);
218233545Sjchandra	}
219233545Sjchandra}
220233545Sjchandra
221233545Sjchandravoid
222233545Sjchandranlm_setup_vfbid_mapping(uint64_t nae_base)
223233545Sjchandra{
224233545Sjchandra	uint32_t val;
225233545Sjchandra	int dest_vc, vfbid;
226233545Sjchandra
227233545Sjchandra	/* 127 is max vfbid */
228233545Sjchandra	for (vfbid = 127; vfbid >= 0; vfbid--) {
229233545Sjchandra		dest_vc = nlm_get_vfbid_mapping(vfbid);
230233545Sjchandra		if (dest_vc < 0)
231233545Sjchandra			continue;
232233545Sjchandra		val = (dest_vc << 16) | (vfbid << 4) | 1;
233233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_VFBID_DESTMAP_CMD, val);
234233545Sjchandra	}
235233545Sjchandra}
236233545Sjchandra
237233545Sjchandravoid
238233545Sjchandranlm_setup_flow_crc_poly(uint64_t nae_base, uint32_t poly)
239233545Sjchandra{
240233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_FLOW_CRC16_POLY_CFG, poly);
241233545Sjchandra}
242233545Sjchandra
243233545Sjchandravoid
244255368Sjchandranlm_setup_iface_fifo_cfg(uint64_t nae_base, int maxports,
245233545Sjchandra    struct nae_port_config *cfg)
246233545Sjchandra{
247233545Sjchandra	uint32_t reg;
248233545Sjchandra	int fifo_xoff_thresh = 12;
249255368Sjchandra	int i, size;
250233545Sjchandra	int cur_iface_start = 0;
251233545Sjchandra
252255368Sjchandra	for (i = 0; i < maxports; i++) {
253255368Sjchandra		size = cfg[i].iface_fifo_size;
254233545Sjchandra		reg = ((fifo_xoff_thresh << 25) |
255233545Sjchandra		    ((size & 0x1ff) << 16) |
256233545Sjchandra		    ((cur_iface_start & 0xff) << 8) |
257255368Sjchandra		    (i & 0x1f));
258233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_IFACE_FIFO_CFG, reg);
259233545Sjchandra		cur_iface_start += size;
260233545Sjchandra	}
261233545Sjchandra}
262233545Sjchandra
263233545Sjchandravoid
264255368Sjchandranlm_setup_rx_base_config(uint64_t nae_base, int maxports,
265233545Sjchandra    struct nae_port_config *cfg)
266233545Sjchandra{
267233545Sjchandra	int base = 0;
268255368Sjchandra	uint32_t val;
269255368Sjchandra	int i;
270233545Sjchandra	int id;
271233545Sjchandra
272255368Sjchandra	for (i = 0; i < (maxports/2); i++) {
273255368Sjchandra		id = 0x12 + i; /* RX_IF_BASE_CONFIG0 */
274233545Sjchandra
275233545Sjchandra		val = (base & 0x3ff);
276255368Sjchandra		base += cfg[(i * 2)].num_channels;
277233545Sjchandra
278233545Sjchandra		val |= ((base & 0x3ff) << 16);
279255368Sjchandra		base += cfg[(i * 2) + 1].num_channels;
280233545Sjchandra
281255368Sjchandra		nlm_write_nae_reg(nae_base, NAE_REG(7, 0, id), val);
282233545Sjchandra	}
283233545Sjchandra}
284233545Sjchandra
285233545Sjchandravoid
286255368Sjchandranlm_setup_rx_buf_config(uint64_t nae_base, int maxports,
287233545Sjchandra    struct nae_port_config *cfg)
288233545Sjchandra{
289233545Sjchandra	uint32_t val;
290255368Sjchandra	int i, sz, k;
291233545Sjchandra	int context = 0;
292233545Sjchandra	int base = 0;
293233545Sjchandra
294255368Sjchandra	for (i = 0; i < maxports; i++) {
295255368Sjchandra		if (cfg[i].type == UNKNOWN)
296255368Sjchandra			continue;
297255368Sjchandra		for (k = 0; k < cfg[i].num_channels; k++) {
298233545Sjchandra			/* write index (context num) */
299233545Sjchandra			nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH_ADDR,
300233545Sjchandra			    (context+k));
301233545Sjchandra
302233545Sjchandra			/* write value (rx buf sizes) */
303255368Sjchandra			sz = cfg[i].rxbuf_size;
304233545Sjchandra			val = 0x80000000 | ((base << 2) & 0x3fff); /* base */
305233545Sjchandra			val |= (((sz << 2)  & 0x3fff) << 16); /* size */
306233545Sjchandra
307233545Sjchandra			nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH, val);
308233545Sjchandra			nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH,
309233545Sjchandra			    (0x7fffffff & val));
310233545Sjchandra			base += sz;
311233545Sjchandra		}
312255368Sjchandra		context += cfg[i].num_channels;
313233545Sjchandra	}
314233545Sjchandra}
315233545Sjchandra
316233545Sjchandravoid
317255368Sjchandranlm_setup_freein_fifo_cfg(uint64_t nae_base, struct nae_port_config *cfg)
318233545Sjchandra{
319255368Sjchandra	int size, i;
320233545Sjchandra	uint32_t reg;
321255368Sjchandra	int start = 0, maxbufpool;
322233545Sjchandra
323255368Sjchandra	if (nlm_is_xlp8xx())
324255368Sjchandra		maxbufpool = MAX_FREE_FIFO_POOL_8XX;
325255368Sjchandra	else
326255368Sjchandra		maxbufpool = MAX_FREE_FIFO_POOL_3XX;
327255368Sjchandra	for (i = 0; i < maxbufpool; i++) {
328233545Sjchandra		/* Each entry represents 2 descs; hence division by 2 */
329255368Sjchandra		size = (cfg[i].num_free_descs / 2);
330233545Sjchandra		if (size == 0)
331233545Sjchandra			size = 8;
332233545Sjchandra		reg = ((size  & 0x3ff ) << 20) | /* fcSize */
333233545Sjchandra		    ((start & 0x1ff)  << 8) | /* fcStart */
334255368Sjchandra		    (i & 0x1f);
335233545Sjchandra
336233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_FREE_IN_FIFO_CFG, reg);
337233545Sjchandra		start += size;
338233545Sjchandra	}
339233545Sjchandra}
340233545Sjchandra
341233545Sjchandra/* XXX function name */
342233545Sjchandraint
343233545Sjchandranlm_get_flow_mask(int num_ports)
344233545Sjchandra{
345233545Sjchandra	const int max_bits = 5; /* upto 32 ports */
346233545Sjchandra	int i;
347233545Sjchandra
348233545Sjchandra	/* Compute the number of bits to needed to
349233545Sjchandra	 * represent all the ports */
350233545Sjchandra	for (i = 0; i < max_bits; i++) {
351233545Sjchandra		if (num_ports <= (2 << i))
352233545Sjchandra			return (i + 1);
353233545Sjchandra	}
354233545Sjchandra	return (max_bits);
355233545Sjchandra}
356233545Sjchandra
357233545Sjchandravoid
358233545Sjchandranlm_program_flow_cfg(uint64_t nae_base, int port,
359233545Sjchandra    uint32_t cur_flow_base, uint32_t flow_mask)
360233545Sjchandra{
361233545Sjchandra	uint32_t val;
362233545Sjchandra
363233545Sjchandra	val = (cur_flow_base << 16) | port;
364233545Sjchandra	val |= ((flow_mask & 0x1f) << 8);
365233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_FLOW_BASEMASK_CFG, val);
366233545Sjchandra}
367233545Sjchandra
368233545Sjchandravoid
369233545Sjchandraxlp_ax_nae_lane_reset_txpll(uint64_t nae_base, int block, int lane_ctrl,
370233545Sjchandra    int mode)
371233545Sjchandra{
372233545Sjchandra	uint32_t val = 0, saved_data;
373233545Sjchandra	int rext_sel = 0;
374233545Sjchandra
375233545Sjchandra	val = PHY_LANE_CTRL_RST |
376233545Sjchandra	    PHY_LANE_CTRL_PWRDOWN |
377233545Sjchandra	    (mode << PHY_LANE_CTRL_PHYMODE_POS);
378233545Sjchandra
379233545Sjchandra	/* set comma bypass for XAUI */
380233545Sjchandra	if (mode != PHYMODE_SGMII)
381233545Sjchandra		val |= PHY_LANE_CTRL_BPC_XAUI;
382233545Sjchandra
383233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl), val);
384233545Sjchandra
385233545Sjchandra	if (lane_ctrl != 4) {
386233545Sjchandra		rext_sel = (1 << 23);
387233545Sjchandra		if (mode != PHYMODE_SGMII)
388233545Sjchandra			rext_sel |= PHY_LANE_CTRL_BPC_XAUI;
389233545Sjchandra
390233545Sjchandra		val = nlm_read_nae_reg(nae_base,
391233545Sjchandra		    NAE_REG(block, PHY, lane_ctrl));
392233545Sjchandra		val &= ~PHY_LANE_CTRL_RST;
393233545Sjchandra		val |= rext_sel;
394233545Sjchandra
395233545Sjchandra		/* Resetting PMA for non-zero lanes */
396233545Sjchandra		nlm_write_nae_reg(nae_base,
397233545Sjchandra		    NAE_REG(block, PHY, lane_ctrl), val);
398233545Sjchandra
399233545Sjchandra		DELAY(20000);	/* 20 ms delay, XXXJC: needed? */
400233545Sjchandra
401233545Sjchandra		val |= PHY_LANE_CTRL_RST;
402233545Sjchandra		nlm_write_nae_reg(nae_base,
403233545Sjchandra		    NAE_REG(block, PHY, lane_ctrl), val);
404233545Sjchandra
405233545Sjchandra		val = 0;
406233545Sjchandra	}
407233545Sjchandra
408233545Sjchandra	/* Come out of reset for TXPLL */
409233545Sjchandra	saved_data = nlm_read_nae_reg(nae_base,
410233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl)) & 0xFFC00000;
411233545Sjchandra
412233545Sjchandra	nlm_write_nae_reg(nae_base,
413233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl),
414233545Sjchandra	    (0x66 << PHY_LANE_CTRL_ADDR_POS)
415233545Sjchandra	    | PHY_LANE_CTRL_CMD_READ
416233545Sjchandra	    | PHY_LANE_CTRL_CMD_START
417233545Sjchandra	    | PHY_LANE_CTRL_RST
418233545Sjchandra	    | rext_sel
419233545Sjchandra	    | val );
420233545Sjchandra
421233545Sjchandra	while (((val = nlm_read_nae_reg(nae_base,
422233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl))) &
423233545Sjchandra	    PHY_LANE_CTRL_CMD_PENDING));
424233545Sjchandra
425233545Sjchandra	val &= 0xFF;
426233545Sjchandra	/* set bit[4] to 0 */
427233545Sjchandra	val &= ~(1 << 4);
428233545Sjchandra	nlm_write_nae_reg(nae_base,
429233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl),
430233545Sjchandra	    (0x66 << PHY_LANE_CTRL_ADDR_POS)
431233545Sjchandra	    | PHY_LANE_CTRL_CMD_WRITE
432233545Sjchandra	    | PHY_LANE_CTRL_CMD_START
433233545Sjchandra	    | (0x0 << 19) /* (0x4 << 19) */
434233545Sjchandra	    | rext_sel
435233545Sjchandra	    | saved_data
436233545Sjchandra	    | val );
437233545Sjchandra
438233545Sjchandra	/* re-do */
439233545Sjchandra	nlm_write_nae_reg(nae_base,
440233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl),
441233545Sjchandra	    (0x66 << PHY_LANE_CTRL_ADDR_POS)
442233545Sjchandra	    | PHY_LANE_CTRL_CMD_WRITE
443233545Sjchandra	    | PHY_LANE_CTRL_CMD_START
444233545Sjchandra	    | (0x0 << 19) /* (0x4 << 19) */
445233545Sjchandra	    | rext_sel
446233545Sjchandra	    | saved_data
447233545Sjchandra	    | val );
448233545Sjchandra
449233545Sjchandra	while (!((val = nlm_read_nae_reg(nae_base,
450233545Sjchandra	    NAE_REG(block, PHY, (lane_ctrl - PHY_LANE_0_CTRL)))) &
451233545Sjchandra	    PHY_LANE_STAT_PCR));
452233545Sjchandra
453233545Sjchandra	/* Clear the Power Down bit */
454233545Sjchandra	val = nlm_read_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl));
455233545Sjchandra	val &= ~((1 << 29) | (0x7ffff));
456233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl),
457233545Sjchandra	    (rext_sel | val));
458233545Sjchandra}
459233545Sjchandra
460233545Sjchandravoid
461233545Sjchandraxlp_nae_lane_reset_txpll(uint64_t nae_base, int block, int lane_ctrl,
462233545Sjchandra    int mode)
463233545Sjchandra{
464233545Sjchandra	uint32_t val = 0;
465233545Sjchandra	int rext_sel = 0;
466233545Sjchandra
467233545Sjchandra	if (lane_ctrl != 4)
468233545Sjchandra		rext_sel = (1 << 23);
469233545Sjchandra
470233545Sjchandra	val = nlm_read_nae_reg(nae_base,
471233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl));
472233545Sjchandra
473233545Sjchandra	/* set comma bypass for XAUI */
474233545Sjchandra	if (mode != PHYMODE_SGMII)
475233545Sjchandra		val |= PHY_LANE_CTRL_BPC_XAUI;
476233545Sjchandra	val |= 0x100000;
477233545Sjchandra	val |= (mode << PHY_LANE_CTRL_PHYMODE_POS);
478233545Sjchandra	val &= ~(0x20000);
479233545Sjchandra	nlm_write_nae_reg(nae_base,
480233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl), val);
481233545Sjchandra
482233545Sjchandra	val = nlm_read_nae_reg(nae_base,
483233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl));
484233545Sjchandra	val |= 0x40000000;
485233545Sjchandra	nlm_write_nae_reg(nae_base,
486233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl), val);
487233545Sjchandra
488233545Sjchandra	/* clear the power down bit */
489233545Sjchandra	val = nlm_read_nae_reg(nae_base,
490233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl));
491233545Sjchandra	val &= ~( (1 << 29) | (0x7ffff));
492233545Sjchandra	nlm_write_nae_reg(nae_base,
493233545Sjchandra	    NAE_REG(block, PHY, lane_ctrl), rext_sel | val);
494233545Sjchandra}
495233545Sjchandra
496233545Sjchandravoid
497233545Sjchandraxlp_nae_config_lane_gmac(uint64_t nae_base, int cplx_mask)
498233545Sjchandra{
499233545Sjchandra	int block, lane_ctrl;
500233545Sjchandra	int cplx_lane_enable;
501233545Sjchandra	int lane_enable = 0;
502233545Sjchandra
503233545Sjchandra	cplx_lane_enable = LM_SGMII |
504233545Sjchandra	    (LM_SGMII << 4) |
505233545Sjchandra	    (LM_SGMII << 8) |
506233545Sjchandra	    (LM_SGMII << 12);
507233545Sjchandra
508233545Sjchandra	/*  Lane mode progamming */
509233545Sjchandra	block = 7;
510233545Sjchandra
511233545Sjchandra	/* Complexes 0, 1 */
512233545Sjchandra	if (cplx_mask & 0x1)
513233545Sjchandra		lane_enable |= cplx_lane_enable;
514233545Sjchandra
515233545Sjchandra	if (cplx_mask & 0x2)
516233545Sjchandra		lane_enable |= (cplx_lane_enable << 16);
517233545Sjchandra
518233545Sjchandra	if (lane_enable) {
519233545Sjchandra		nlm_write_nae_reg(nae_base,
520233545Sjchandra		    NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1),
521233545Sjchandra		    lane_enable);
522233545Sjchandra		lane_enable = 0;
523233545Sjchandra	}
524233545Sjchandra	/* Complexes 2 3 */
525233545Sjchandra	if (cplx_mask & 0x4)
526233545Sjchandra		lane_enable |= cplx_lane_enable;
527233545Sjchandra
528233545Sjchandra	if (cplx_mask & 0x8)
529233545Sjchandra		lane_enable |= (cplx_lane_enable << 16);
530233545Sjchandra
531233545Sjchandra	nlm_write_nae_reg(nae_base,
532233545Sjchandra	    NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3),
533233545Sjchandra	    lane_enable);
534233545Sjchandra
535233545Sjchandra	/* complex 4 */
536233545Sjchandra	/* XXXJC : fix duplicate code */
537233545Sjchandra	if (cplx_mask & 0x10) {
538233545Sjchandra		nlm_write_nae_reg(nae_base,
539233545Sjchandra		    NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_4),
540233545Sjchandra		    ((LM_SGMII << 4) | LM_SGMII));
541233545Sjchandra		for (lane_ctrl = PHY_LANE_0_CTRL;
542233545Sjchandra		    lane_ctrl <= PHY_LANE_1_CTRL; lane_ctrl++) {
543233545Sjchandra			if (!nlm_is_xlp8xx_ax())
544233545Sjchandra				xlp_nae_lane_reset_txpll(nae_base,
545233545Sjchandra				    4, lane_ctrl, PHYMODE_SGMII);
546233545Sjchandra			else
547233545Sjchandra				xlp_ax_nae_lane_reset_txpll(nae_base, 4,
548233545Sjchandra				    lane_ctrl, PHYMODE_SGMII);
549233545Sjchandra		}
550233545Sjchandra	}
551233545Sjchandra
552233545Sjchandra	for (block = 0; block < 4; block++) {
553233545Sjchandra		if ((cplx_mask & (1 << block)) == 0)
554233545Sjchandra			continue;
555233545Sjchandra
556233545Sjchandra		for (lane_ctrl = PHY_LANE_0_CTRL;
557233545Sjchandra		    lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) {
558233545Sjchandra			if (!nlm_is_xlp8xx_ax())
559233545Sjchandra				xlp_nae_lane_reset_txpll(nae_base,
560233545Sjchandra				    block, lane_ctrl, PHYMODE_SGMII);
561233545Sjchandra			else
562233545Sjchandra				xlp_ax_nae_lane_reset_txpll(nae_base, block,
563233545Sjchandra				    lane_ctrl, PHYMODE_SGMII);
564233545Sjchandra		}
565233545Sjchandra	}
566233545Sjchandra}
567233545Sjchandra
568233545Sjchandravoid
569233545Sjchandraconfig_egress_fifo_carvings(uint64_t nae_base, int hwport, int start_ctxt,
570233545Sjchandra    int num_ctxts, int max_ctxts, struct nae_port_config *cfg)
571233545Sjchandra{
572233545Sjchandra	static uint32_t cur_start[6] = {0, 0, 0, 0, 0, 0};
573233545Sjchandra	uint32_t data = 0;
574233545Sjchandra	uint32_t start = 0, size, offset;
575233545Sjchandra	int i, limit;
576233545Sjchandra
577233545Sjchandra	limit = start_ctxt + num_ctxts;
578233545Sjchandra	/* Stage 2 FIFO */
579233545Sjchandra	start = cur_start[0];
580233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
581233545Sjchandra		size = cfg[hwport].stg2_fifo_size / max_ctxts;
582233545Sjchandra		if (size)
583233545Sjchandra			offset = size - 1;
584233545Sjchandra		else
585233545Sjchandra			offset = size;
586233545Sjchandra		if (offset > cfg[hwport].max_stg2_offset)
587233545Sjchandra			offset = cfg[hwport].max_stg2_offset;
588233545Sjchandra		data = offset << 23  |
589233545Sjchandra		    start << 11 |
590233545Sjchandra		    i << 1      |
591233545Sjchandra		    1;
592233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_STG2_PMEM_PROG, data);
593233545Sjchandra		start += size;
594233545Sjchandra	}
595233545Sjchandra	cur_start[0] = start;
596233545Sjchandra
597233545Sjchandra	/* EH FIFO */
598233545Sjchandra	start  = cur_start[1];
599233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
600233545Sjchandra		size = cfg[hwport].eh_fifo_size / max_ctxts;
601233545Sjchandra		if (size)
602233545Sjchandra			offset = size - 1;
603233545Sjchandra		else
604233545Sjchandra			offset = size ;
605233545Sjchandra		if (offset > cfg[hwport].max_eh_offset)
606233545Sjchandra		    offset = cfg[hwport].max_eh_offset;
607233545Sjchandra		data = offset << 23  |
608233545Sjchandra		    start << 11 |
609233545Sjchandra		    i << 1      |
610233545Sjchandra		    1;
611233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_EH_PMEM_PROG, data);
612233545Sjchandra		start += size;
613233545Sjchandra	}
614233545Sjchandra	cur_start[1] = start;
615233545Sjchandra
616233545Sjchandra	/* FROUT FIFO */
617233545Sjchandra	start  = cur_start[2];
618233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
619233545Sjchandra		size = cfg[hwport].frout_fifo_size / max_ctxts;
620233545Sjchandra		if (size)
621233545Sjchandra			offset = size - 1;
622233545Sjchandra		else
623233545Sjchandra			offset = size ;
624233545Sjchandra		if (offset > cfg[hwport].max_frout_offset)
625233545Sjchandra			offset = cfg[hwport].max_frout_offset;
626233545Sjchandra		data = offset << 23  |
627233545Sjchandra		    start << 11 |
628233545Sjchandra		    i << 1      |
629233545Sjchandra		    1;
630233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_FREE_PMEM_PROG, data);
631233545Sjchandra		start += size;
632233545Sjchandra	}
633233545Sjchandra	cur_start[2] = start;
634233545Sjchandra
635233545Sjchandra	/* MS FIFO */
636233545Sjchandra	start = cur_start[3];
637233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
638233545Sjchandra		size = cfg[hwport].ms_fifo_size / max_ctxts;
639233545Sjchandra		if (size)
640233545Sjchandra			offset = size - 1;
641233545Sjchandra		else
642233545Sjchandra			offset = size ;
643233545Sjchandra		if (offset > cfg[hwport].max_ms_offset)
644233545Sjchandra			offset = cfg[hwport].max_ms_offset;
645233545Sjchandra		data = offset << 22  |	/* FIXME in PRM */
646233545Sjchandra		    start << 11 |
647233545Sjchandra		    i << 1      |
648233545Sjchandra		    1;
649233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_STR_PMEM_CMD, data);
650233545Sjchandra		start += size;
651233545Sjchandra	}
652233545Sjchandra	cur_start[3] = start;
653233545Sjchandra
654233545Sjchandra	/* PKT FIFO */
655233545Sjchandra	start  = cur_start[4];
656233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
657233545Sjchandra		size = cfg[hwport].pkt_fifo_size / max_ctxts;
658233545Sjchandra		if (size)
659233545Sjchandra			offset = size - 1;
660233545Sjchandra		else
661233545Sjchandra			offset = size ;
662233545Sjchandra		if (offset > cfg[hwport].max_pmem_offset)
663233545Sjchandra			offset = cfg[hwport].max_pmem_offset;
664233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_TX_PKT_PMEM_CMD1, offset);
665233545Sjchandra
666233545Sjchandra		data = start << 11	|
667233545Sjchandra		    i << 1		|
668233545Sjchandra		    1;
669233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_TX_PKT_PMEM_CMD0, data);
670233545Sjchandra		start += size;
671233545Sjchandra	}
672233545Sjchandra	cur_start[4] = start;
673233545Sjchandra
674233545Sjchandra	/* PKT LEN FIFO */
675233545Sjchandra	start  = cur_start[5];
676233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
677233545Sjchandra		size = cfg[hwport].pktlen_fifo_size / max_ctxts;
678233545Sjchandra		if (size)
679233545Sjchandra			offset = size - 1;
680233545Sjchandra		else
681233545Sjchandra			offset = size ;
682233545Sjchandra		data = offset  << 22	|
683233545Sjchandra		    start << 11		|
684233545Sjchandra		    i << 1		|
685233545Sjchandra		    1;
686233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_TX_PKTLEN_PMEM_CMD, data);
687233545Sjchandra		start += size;
688233545Sjchandra	}
689233545Sjchandra	cur_start[5] = start;
690233545Sjchandra}
691233545Sjchandra
692233545Sjchandravoid
693233545Sjchandraconfig_egress_fifo_credits(uint64_t nae_base, int hwport, int start_ctxt,
694233545Sjchandra    int num_ctxts, int max_ctxts, struct nae_port_config *cfg)
695233545Sjchandra{
696233545Sjchandra	uint32_t data, credit, max_credit;
697233545Sjchandra	int i, limit;
698233545Sjchandra
699233545Sjchandra	limit = start_ctxt + num_ctxts;
700233545Sjchandra	/* Stage1 -> Stage2 */
701233545Sjchandra	max_credit = cfg[hwport].max_stg2_offset + 1;
702233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
703233545Sjchandra		credit = cfg[hwport].stg1_2_credit / max_ctxts;
704233545Sjchandra		if (credit > max_credit)
705233545Sjchandra		    credit = max_credit;
706233545Sjchandra		data = credit << 16	|
707233545Sjchandra		    i << 4		|
708233545Sjchandra		    1;
709233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_STG1_STG2CRDT_CMD, data);
710233545Sjchandra	}
711233545Sjchandra
712233545Sjchandra	/* Stage2 -> EH */
713233545Sjchandra	max_credit = cfg[hwport].max_eh_offset + 1;
714233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
715233545Sjchandra		credit = cfg[hwport].stg2_eh_credit / max_ctxts;
716233545Sjchandra		if (credit > max_credit)
717233545Sjchandra			credit = max_credit;
718233545Sjchandra		data = credit << 16	|
719233545Sjchandra		    i << 4		|
720233545Sjchandra		    1;
721233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_STG2_EHCRDT_CMD, data);
722233545Sjchandra	}
723233545Sjchandra
724233545Sjchandra	/* Stage2 -> Frout */
725233545Sjchandra	max_credit = cfg[hwport].max_frout_offset + 1;
726233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
727233545Sjchandra		credit = cfg[hwport].stg2_frout_credit / max_ctxts;
728233545Sjchandra		if (credit > max_credit)
729233545Sjchandra			credit = max_credit;
730233545Sjchandra		data = credit << 16	|
731233545Sjchandra		    i << 4		|
732233545Sjchandra		    1;
733233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_EH_FREECRDT_CMD, data);
734233545Sjchandra	}
735233545Sjchandra
736233545Sjchandra	/* Stage2 -> MS */
737233545Sjchandra	max_credit = cfg[hwport].max_ms_offset + 1;
738233545Sjchandra	for (i = start_ctxt; i < limit; i++) {
739233545Sjchandra		credit = cfg[hwport].stg2_ms_credit / max_ctxts;
740233545Sjchandra		if (credit > max_credit)
741233545Sjchandra			credit = max_credit;
742233545Sjchandra		data = credit << 16	|
743233545Sjchandra		    i << 4		|
744233545Sjchandra		    1;
745233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_STG2_STRCRDT_CMD, data);
746233545Sjchandra	}
747233545Sjchandra}
748233545Sjchandra
749233545Sjchandravoid
750233545Sjchandranlm_config_freein_fifo_uniq_cfg(uint64_t nae_base, int port,
751233545Sjchandra    int nblock_free_desc)
752233545Sjchandra{
753233545Sjchandra	uint32_t val;
754233545Sjchandra	int size_in_clines;
755233545Sjchandra
756233545Sjchandra	size_in_clines = (nblock_free_desc / NAE_CACHELINE_SIZE);
757233545Sjchandra	val = (size_in_clines << 8) | (port & 0x1f);
758233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_FREEIN_FIFO_UNIQ_SZ_CFG, val);
759233545Sjchandra}
760233545Sjchandra
761233545Sjchandra/* XXXJC: redundant, see ucore_spray_config() */
762233545Sjchandravoid
763233545Sjchandranlm_config_ucore_iface_mask_cfg(uint64_t nae_base, int port,
764233545Sjchandra    int nblock_ucore_mask)
765233545Sjchandra{
766233545Sjchandra	uint32_t val;
767233545Sjchandra
768233545Sjchandra	val = ( 0x1U << 31) | ((nblock_ucore_mask & 0xffff) << 8) |
769233545Sjchandra	    (port & 0x1f);
770233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_UCORE_IFACEMASK_CFG, val);
771233545Sjchandra}
772233545Sjchandra
773233545Sjchandraint
774233545Sjchandranlm_nae_init_netior(uint64_t nae_base, int nblocks)
775233545Sjchandra{
776233545Sjchandra	uint32_t ctrl1, ctrl2, ctrl3;
777233545Sjchandra
778233545Sjchandra	if (nblocks == 5)
779233545Sjchandra		ctrl3 = 0x07 << 18;
780233545Sjchandra	else
781233545Sjchandra		ctrl3 = 0;
782233545Sjchandra
783233545Sjchandra	switch (nblocks) {
784233545Sjchandra	case 2:
785233545Sjchandra		ctrl1 = 0xff;
786233545Sjchandra		ctrl2 = 0x0707;
787233545Sjchandra		break;
788233545Sjchandra	case 4:
789233545Sjchandra	case 5:
790233545Sjchandra		ctrl1 = 0xfffff;
791233545Sjchandra		ctrl2 = 0x07070707;
792233545Sjchandra		break;
793233545Sjchandra	default:
794233545Sjchandra		printf("WARNING: unsupported blocks %d\n", nblocks);
795233545Sjchandra		return (-1);
796233545Sjchandra	}
797233545Sjchandra
798233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_LANE_CFG_SOFTRESET, 0);
799233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL3, ctrl3);
800233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL2, ctrl2);
801233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL1, ctrl1);
802233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL1, 0x0);
803233545Sjchandra	return (0);
804233545Sjchandra}
805233545Sjchandra
806233545Sjchandravoid
807233545Sjchandranlm_nae_init_ingress(uint64_t nae_base, uint32_t desc_size)
808233545Sjchandra{
809233545Sjchandra	uint32_t rx_cfg;
810233545Sjchandra	uint32_t parser_threshold = 384;
811233545Sjchandra
812233545Sjchandra	rx_cfg = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
813233545Sjchandra	rx_cfg &= ~(0x3 << 1);		/* reset max message size */
814233545Sjchandra	rx_cfg &= ~(0xff << 4);		/* clear freein desc cluster size */
815233545Sjchandra	rx_cfg &= ~(0x3f << 24);	/* reset rx status mask */ /*XXX: why not 7f */
816233545Sjchandra
817233545Sjchandra	rx_cfg |= 1;			/* rx enable */
818233545Sjchandra	rx_cfg |= (0x0 << 1);		/* max message size */
819233545Sjchandra	rx_cfg |= (0x43 & 0x7f) << 24;	/* rx status mask */
820233545Sjchandra	rx_cfg |= ((desc_size / 64) & 0xff) << 4; /* freein desc cluster size */
821233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, rx_cfg);
822233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_PARSER_CONFIG,
823233545Sjchandra	    (parser_threshold & 0x3ff) |
824233545Sjchandra	    (((parser_threshold / desc_size) + 1) & 0xff) << 12 |
825233545Sjchandra	    (((parser_threshold / 64) % desc_size) & 0xff) << 20);
826233545Sjchandra
827233545Sjchandra	/*nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_THRESH, 33);*/
828233545Sjchandra}
829233545Sjchandra
830233545Sjchandravoid
831233545Sjchandranlm_nae_init_egress(uint64_t nae_base)
832233545Sjchandra{
833233545Sjchandra	uint32_t tx_cfg;
834233545Sjchandra
835233545Sjchandra	tx_cfg = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG);
836233545Sjchandra	if (!nlm_is_xlp8xx_ax()) {
837233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
838233545Sjchandra		    tx_cfg	|
839233545Sjchandra		    0x1		|	/* tx enable */
840233545Sjchandra		    0x2		|	/* tx ace */
841233545Sjchandra		    0x4		|	/* tx compatible */
842233545Sjchandra		    (1 << 3));
843233545Sjchandra	} else {
844233545Sjchandra		nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
845233545Sjchandra		    tx_cfg	|
846233545Sjchandra		    0x1		|	/* tx enable */
847233545Sjchandra		    0x2);		/* tx ace */
848233545Sjchandra	}
849233545Sjchandra}
850233545Sjchandra
851233545Sjchandrauint32_t
852233545Sjchandraucore_spray_config(uint32_t interface, uint32_t ucore_mask, int cmd)
853233545Sjchandra{
854233545Sjchandra	return ((cmd & 0x1) << 31) | ((ucore_mask & 0xffff) << 8) |
855233545Sjchandra	    (interface & 0x1f);
856233545Sjchandra}
857233545Sjchandra
858233545Sjchandravoid
859233545Sjchandranlm_nae_init_ucore(uint64_t nae_base, int if_num, u_int ucore_mask)
860233545Sjchandra{
861233545Sjchandra	uint32_t ucfg;
862233545Sjchandra
863233545Sjchandra	ucfg = ucore_spray_config(if_num, ucore_mask, 1); /* 1 : write */
864233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_UCORE_IFACEMASK_CFG, ucfg);
865233545Sjchandra}
866233545Sjchandra
867233545Sjchandrauint64_t
868233545Sjchandranae_tx_desc(u_int type, u_int rdex, u_int fbid, u_int len, uint64_t addr)
869233545Sjchandra{
870233545Sjchandra	return ((uint64_t)type  << 62) |
871233545Sjchandra		((uint64_t)rdex << 61) |
872233545Sjchandra		((uint64_t)fbid << 54) |
873233545Sjchandra		((uint64_t)len  << 40) | addr;
874233545Sjchandra}
875233545Sjchandra
876233545Sjchandravoid
877233545Sjchandranlm_setup_l2type(uint64_t nae_base, int hwport, uint32_t l2extlen,
878233545Sjchandra    uint32_t l2extoff, uint32_t extra_hdrsize, uint32_t proto_offset,
879233545Sjchandra    uint32_t fixed_hdroff, uint32_t l2proto)
880233545Sjchandra{
881233545Sjchandra	uint32_t val;
882233545Sjchandra
883233545Sjchandra	val = ((l2extlen & 0x3f) << 26)		|
884233545Sjchandra	    ((l2extoff & 0x3f) << 20)		|
885233545Sjchandra	    ((extra_hdrsize & 0x3f) << 14)	|
886233545Sjchandra	    ((proto_offset & 0x3f) << 8)	|
887233545Sjchandra	    ((fixed_hdroff & 0x3f) << 2)	|
888233545Sjchandra	    (l2proto & 0x3);
889233545Sjchandra	nlm_write_nae_reg(nae_base, (NAE_L2_TYPE_PORT0 + hwport), val);
890233545Sjchandra}
891233545Sjchandra
892233545Sjchandravoid
893233545Sjchandranlm_setup_l3ctable_mask(uint64_t nae_base, int hwport, uint32_t ptmask,
894233545Sjchandra    uint32_t l3portmask)
895233545Sjchandra{
896233545Sjchandra	uint32_t val;
897233545Sjchandra
898233545Sjchandra	val = ((ptmask & 0x1) << 6)	|
899233545Sjchandra	    ((l3portmask & 0x1) << 5)	|
900233545Sjchandra	    (hwport & 0x1f);
901233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_L3_CTABLE_MASK0, val);
902233545Sjchandra}
903233545Sjchandra
904233545Sjchandravoid
905233545Sjchandranlm_setup_l3ctable_even(uint64_t nae_base, int entry, uint32_t l3hdroff,
906233545Sjchandra    uint32_t ipcsum_en, uint32_t l4protooff,
907233545Sjchandra    uint32_t l2proto, uint32_t eth_type)
908233545Sjchandra{
909233545Sjchandra	uint32_t val;
910233545Sjchandra
911233545Sjchandra	val = ((l3hdroff & 0x3f) << 26)	|
912233545Sjchandra	    ((l4protooff & 0x3f) << 20)	|
913233545Sjchandra	    ((ipcsum_en & 0x1) << 18)	|
914233545Sjchandra	    ((l2proto & 0x3) << 16)	|
915233545Sjchandra	    (eth_type & 0xffff);
916233545Sjchandra	nlm_write_nae_reg(nae_base, (NAE_L3CTABLE0 + (entry * 2)), val);
917233545Sjchandra}
918233545Sjchandra
919233545Sjchandravoid
920233545Sjchandranlm_setup_l3ctable_odd(uint64_t nae_base, int entry, uint32_t l3off0,
921233545Sjchandra    uint32_t l3len0, uint32_t l3off1, uint32_t l3len1,
922233545Sjchandra    uint32_t l3off2, uint32_t l3len2)
923233545Sjchandra{
924233545Sjchandra	uint32_t val;
925233545Sjchandra
926233545Sjchandra	val = ((l3off0 & 0x3f) << 26)	|
927233545Sjchandra	    ((l3len0 & 0x1f) << 21)	|
928233545Sjchandra	    ((l3off1 & 0x3f) << 15)	|
929233545Sjchandra	    ((l3len1 & 0x1f) << 10)	|
930233545Sjchandra	    ((l3off2 & 0x3f) << 4)	|
931233545Sjchandra	    (l3len2 & 0xf);
932233545Sjchandra	nlm_write_nae_reg(nae_base, (NAE_L3CTABLE0 + ((entry * 2) + 1)), val);
933233545Sjchandra}
934233545Sjchandra
935233545Sjchandravoid
936233545Sjchandranlm_setup_l4ctable_even(uint64_t nae_base, int entry, uint32_t im,
937233545Sjchandra    uint32_t l3cm, uint32_t l4pm, uint32_t port,
938233545Sjchandra    uint32_t l3camaddr, uint32_t l4proto)
939233545Sjchandra{
940233545Sjchandra	uint32_t val;
941233545Sjchandra
942233545Sjchandra	val = ((im & 0x1) << 19)	|
943233545Sjchandra	    ((l3cm & 0x1) << 18)	|
944233545Sjchandra	    ((l4pm & 0x1) << 17)	|
945233545Sjchandra	    ((port & 0x1f) << 12)	|
946233545Sjchandra	    ((l3camaddr & 0xf) << 8)	|
947233545Sjchandra	    (l4proto & 0xff);
948233545Sjchandra	nlm_write_nae_reg(nae_base, (NAE_L4CTABLE0 + (entry * 2)), val);
949233545Sjchandra}
950233545Sjchandra
951233545Sjchandravoid
952233545Sjchandranlm_setup_l4ctable_odd(uint64_t nae_base, int entry, uint32_t l4off0,
953233545Sjchandra    uint32_t l4len0, uint32_t l4off1, uint32_t l4len1)
954233545Sjchandra{
955233545Sjchandra	uint32_t val;
956233545Sjchandra
957233545Sjchandra	val = ((l4off0 & 0x3f) << 21)	|
958233545Sjchandra	    ((l4len0 & 0xf) << 17)	|
959233545Sjchandra	    ((l4off1 & 0x3f) << 11)	|
960233545Sjchandra	    (l4len1 & 0xf);
961233545Sjchandra	nlm_write_nae_reg(nae_base, (NAE_L4CTABLE0 + ((entry * 2) + 1)), val);
962233545Sjchandra}
963233545Sjchandra
964233545Sjchandravoid
965233545Sjchandranlm_enable_hardware_parser(uint64_t nae_base)
966233545Sjchandra{
967233545Sjchandra	uint32_t val;
968233545Sjchandra
969233545Sjchandra	val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
970233545Sjchandra	val |= (1 << 12); /* hardware parser enable */
971233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val);
972233545Sjchandra
973233545Sjchandra	/***********************************************
974233545Sjchandra	 * program L3 CAM table
975233545Sjchandra	 ***********************************************/
976233545Sjchandra
977233545Sjchandra	/*
978233545Sjchandra	 *  entry-0 is ipv4 MPLS type 1 label
979233545Sjchandra	 */
980233545Sjchandra	 /* l3hdroff = 4 bytes, ether_type = 0x8847 for MPLS_type1 */
981233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 0, 4, 1, 9, 1, 0x8847);
982233545Sjchandra	/* l3off0 (8 bytes) -> l3len0 (1 byte) := ip proto
983233545Sjchandra	 * l3off1 (12 bytes) -> l3len1 (4 bytes) := src ip
984233545Sjchandra	 * l3off2 (16 bytes) -> l3len2 (4 bytes) := dst ip
985233545Sjchandra	 */
986233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 0, 9, 1, 12, 4, 16, 4);
987233545Sjchandra
988233545Sjchandra	/*
989233545Sjchandra	 * entry-1 is for ethernet IPv4 packets
990233545Sjchandra	 */
991233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 1, 0, 1, 9, 1, 0x0800);
992233545Sjchandra	/* l3off0 (8 bytes) -> l3len0 (1 byte) := ip proto
993233545Sjchandra	 * l3off1 (12 bytes) -> l3len1 (4 bytes) := src ip
994233545Sjchandra	 * l3off2 (16 bytes) -> l3len2 (4 bytes) := dst ip
995233545Sjchandra	 */
996233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 1, 9, 1, 12, 4, 16, 4);
997233545Sjchandra
998233545Sjchandra	/*
999233545Sjchandra	 * entry-2 is for ethernet IPv6 packets
1000233545Sjchandra	 */
1001233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 2, 0, 1, 6, 1, 0x86dd);
1002233545Sjchandra	/* l3off0 (6 bytes) -> l3len0 (1 byte) := next header (ip proto)
1003233545Sjchandra	 * l3off1 (8 bytes) -> l3len1 (16 bytes) := src ip
1004233545Sjchandra	 * l3off2 (24 bytes) -> l3len2 (16 bytes) := dst ip
1005233545Sjchandra	 */
1006233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 2, 6, 1, 8, 16, 24, 16);
1007233545Sjchandra
1008233545Sjchandra	/*
1009233545Sjchandra	 * entry-3 is for ethernet ARP packets
1010233545Sjchandra	 */
1011233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 3, 0, 0, 9, 1, 0x0806);
1012233545Sjchandra	/* extract 30 bytes from packet start */
1013233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 3, 0, 30, 0, 0, 0, 0);
1014233545Sjchandra
1015233545Sjchandra	/*
1016233545Sjchandra	 * entry-4 is for ethernet FCoE packets
1017233545Sjchandra	 */
1018233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 4, 0, 0, 9, 1, 0x8906);
1019233545Sjchandra	/* FCoE packet consists of 4 byte start-of-frame,
1020233545Sjchandra	 * and 24 bytes of frame header, followed by
1021233545Sjchandra	 * 64 bytes of optional-header (ESP, network..),
1022233545Sjchandra	 * 2048 bytes of payload, 36 bytes of optional
1023233545Sjchandra	 * "fill bytes" or ESP trailer, 4 bytes of CRC,
1024233545Sjchandra	 * and 4 bytes of end-of-frame
1025233545Sjchandra	 * We extract the first 4 + 24 = 28 bytes
1026233545Sjchandra	 */
1027233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 4, 0, 28, 0, 0, 0, 0);
1028233545Sjchandra
1029233545Sjchandra	/*
1030233545Sjchandra	 * entry-5 is for vlan tagged frames (0x8100)
1031233545Sjchandra	 */
1032233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 5, 0, 0, 9, 1, 0x8100);
1033233545Sjchandra	/* we extract 31 bytes from the payload */
1034233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 5, 0, 31, 0, 0, 0, 0);
1035233545Sjchandra
1036233545Sjchandra	/*
1037233545Sjchandra	 * entry-6 is for ieee 802.1ad provider bridging
1038233545Sjchandra	 * tagged frames (0x88a8)
1039233545Sjchandra	 */
1040233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 6, 0, 0, 9, 1, 0x88a8);
1041233545Sjchandra	/* we extract 31 bytes from the payload */
1042233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 6, 0, 31, 0, 0, 0, 0);
1043233545Sjchandra
1044233545Sjchandra	/*
1045233545Sjchandra	 * entry-7 is for Cisco's Q-in-Q tagged frames (0x9100)
1046233545Sjchandra	 */
1047233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 7, 0, 0, 9, 1, 0x9100);
1048233545Sjchandra	/* we extract 31 bytes from the payload */
1049233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 7, 0, 31, 0, 0, 0, 0);
1050233545Sjchandra
1051233545Sjchandra	/*
1052233545Sjchandra	 * entry-8 is for Ethernet Jumbo frames (0x8870)
1053233545Sjchandra	 */
1054233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 8, 0, 0, 9, 1, 0x8870);
1055233545Sjchandra	/* we extract 31 bytes from the payload */
1056233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 8, 0, 31, 0, 0, 0, 0);
1057233545Sjchandra
1058233545Sjchandra	/*
1059233545Sjchandra	 * entry-9 is for MPLS Multicast frames (0x8848)
1060233545Sjchandra	 */
1061233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 9, 0, 0, 9, 1, 0x8848);
1062233545Sjchandra	/* we extract 31 bytes from the payload */
1063233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 9, 0, 31, 0, 0, 0, 0);
1064233545Sjchandra
1065233545Sjchandra	/*
1066233545Sjchandra	 * entry-10 is for IEEE 802.1ae MAC Security frames (0x88e5)
1067233545Sjchandra	 */
1068233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 10, 0, 0, 9, 1, 0x88e5);
1069233545Sjchandra	/* we extract 31 bytes from the payload */
1070233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 10, 0, 31, 0, 0, 0, 0);
1071233545Sjchandra
1072233545Sjchandra	/*
1073233545Sjchandra	 * entry-11 is for PTP frames (0x88f7)
1074233545Sjchandra	 */
1075233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 11, 0, 0, 9, 1, 0x88f7);
1076233545Sjchandra	/* PTP messages can be sent as UDP messages over
1077233545Sjchandra	 * IPv4 or IPv6; and as a raw ethernet message
1078233545Sjchandra	 * with ethertype 0x88f7. The message contents
1079233545Sjchandra	 * are the same for UDP or ethernet based encapsulations
1080233545Sjchandra	 * The header is 34 bytes long, and we extract
1081233545Sjchandra	 * it all out.
1082233545Sjchandra	 */
1083233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 11, 0, 31, 31, 2, 0, 0);
1084233545Sjchandra
1085233545Sjchandra	/*
1086233545Sjchandra	 * entry-12 is for ethernet Link Control Protocol (LCP)
1087233545Sjchandra	 * used with PPPoE
1088233545Sjchandra	 */
1089233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 12, 0, 0, 9, 1, 0xc021);
1090233545Sjchandra	/* LCP packet consists of 1 byte of code, 1 byte of
1091233545Sjchandra	 * identifier and two bytes of length followed by
1092233545Sjchandra	 * data (upto length bytes).
1093233545Sjchandra	 * We extract 4 bytes from start of packet
1094233545Sjchandra	 */
1095233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 12, 0, 4, 0, 0, 0, 0);
1096233545Sjchandra
1097233545Sjchandra	/*
1098233545Sjchandra	 * entry-13 is for ethernet Link Quality Report (0xc025)
1099233545Sjchandra	 * used with PPPoE
1100233545Sjchandra	 */
1101233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 13, 0, 0, 9, 1, 0xc025);
1102233545Sjchandra	/* We extract 31 bytes from packet start */
1103233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 13, 0, 31, 0, 0, 0, 0);
1104233545Sjchandra
1105233545Sjchandra	/*
1106233545Sjchandra	 * entry-14 is for PPPoE Session (0x8864)
1107233545Sjchandra	 */
1108233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 14, 0, 0, 9, 1, 0x8864);
1109233545Sjchandra	/* We extract 31 bytes from packet start */
1110233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 14, 0, 31, 0, 0, 0, 0);
1111233545Sjchandra
1112233545Sjchandra	/*
1113233545Sjchandra	 * entry-15 - default entry
1114233545Sjchandra	 */
1115233545Sjchandra	nlm_setup_l3ctable_even(nae_base, 15, 0, 0, 0, 0, 0x0000);
1116233545Sjchandra	/* We extract 31 bytes from packet start */
1117233545Sjchandra	nlm_setup_l3ctable_odd(nae_base, 15, 0, 31, 0, 0, 0, 0);
1118233545Sjchandra
1119233545Sjchandra	/***********************************************
1120233545Sjchandra	 * program L4 CAM table
1121233545Sjchandra	 ***********************************************/
1122233545Sjchandra
1123233545Sjchandra	/*
1124233545Sjchandra	 * entry-0 - tcp packets (0x6)
1125233545Sjchandra	 */
1126233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 0, 0, 0, 1, 0, 0, 0x6);
1127233545Sjchandra	/* tcp header is 20 bytes without tcp options
1128233545Sjchandra	 * We extract 20 bytes from tcp start */
1129233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 0, 0, 15, 15, 5);
1130233545Sjchandra
1131233545Sjchandra	/*
1132233545Sjchandra	 * entry-1 - udp packets (0x11)
1133233545Sjchandra	 */
1134233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 1, 0, 0, 1, 0, 0, 0x11);
1135233545Sjchandra	/* udp header is 8 bytes in size.
1136233545Sjchandra	 * We extract 8 bytes from udp start */
1137233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 1, 0, 8, 0, 0);
1138233545Sjchandra
1139233545Sjchandra	/*
1140233545Sjchandra	 * entry-2 - sctp packets (0x84)
1141233545Sjchandra	 */
1142233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 2, 0, 0, 1, 0, 0, 0x84);
1143233545Sjchandra	/* sctp packets have a 12 byte generic header
1144233545Sjchandra	 * and various chunks.
1145233545Sjchandra	 * We extract 12 bytes from sctp start */
1146233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 2, 0, 12, 0, 0);
1147233545Sjchandra
1148233545Sjchandra	/*
1149233545Sjchandra	 * entry-3 - RDP packets (0x1b)
1150233545Sjchandra	 */
1151233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 3, 0, 0, 1, 0, 0, 0x1b);
1152233545Sjchandra	/* RDP packets have 18 bytes of generic header
1153233545Sjchandra	 * before variable header starts.
1154233545Sjchandra	 * We extract 18 bytes from rdp start */
1155233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 3, 0, 15, 15, 3);
1156233545Sjchandra
1157233545Sjchandra	/*
1158233545Sjchandra	 * entry-4 - DCCP packets (0x21)
1159233545Sjchandra	 */
1160233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 4, 0, 0, 1, 0, 0, 0x21);
1161233545Sjchandra	/* DCCP has two types of generic headers of
1162233545Sjchandra	 * sizes 16 bytes and 12 bytes if X = 1.
1163233545Sjchandra	 * We extract 16 bytes from dccp start */
1164233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 4, 0, 15, 15, 1);
1165233545Sjchandra
1166233545Sjchandra	/*
1167233545Sjchandra	 * entry-5 - ipv6 encapsulated in ipv4 packets (0x29)
1168233545Sjchandra	 */
1169233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 5, 0, 0, 1, 0, 0, 0x29);
1170233545Sjchandra	/* ipv4 header is 20 bytes excluding IP options.
1171233545Sjchandra	 * We extract 20 bytes from IPv4 start */
1172233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 5, 0, 15, 15, 5);
1173233545Sjchandra
1174233545Sjchandra	/*
1175233545Sjchandra	 * entry-6 - ip in ip encapsulation packets (0x04)
1176233545Sjchandra	 */
1177233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 6, 0, 0, 1, 0, 0, 0x04);
1178233545Sjchandra	/* ipv4 header is 20 bytes excluding IP options.
1179233545Sjchandra	 * We extract 20 bytes from ipv4 start */
1180233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 6, 0, 15, 15, 5);
1181233545Sjchandra
1182233545Sjchandra	/*
1183233545Sjchandra	 * entry-7 - default entry (0x0)
1184233545Sjchandra	 */
1185233545Sjchandra	nlm_setup_l4ctable_even(nae_base, 7, 0, 0, 1, 0, 0, 0x0);
1186233545Sjchandra	/* We extract 20 bytes from packet start */
1187233545Sjchandra	nlm_setup_l4ctable_odd(nae_base, 7, 0, 15, 15, 5);
1188233545Sjchandra}
1189233545Sjchandra
1190233545Sjchandravoid
1191233545Sjchandranlm_enable_hardware_parser_per_port(uint64_t nae_base, int block, int port)
1192233545Sjchandra{
1193233545Sjchandra	int hwport = (block * 4) + (port & 0x3);
1194233545Sjchandra
1195233545Sjchandra	/* program L2 and L3 header extraction for each port */
1196233545Sjchandra	/* enable ethernet L2 mode on port */
1197233545Sjchandra	nlm_setup_l2type(nae_base, hwport, 0, 0, 0, 0, 0, 1);
1198233545Sjchandra
1199233545Sjchandra	/* l2proto and ethtype included in l3cam */
1200233545Sjchandra	nlm_setup_l3ctable_mask(nae_base, hwport, 1, 0);
1201233545Sjchandra}
1202233545Sjchandra
1203233545Sjchandravoid
1204233545Sjchandranlm_prepad_enable(uint64_t nae_base, int size)
1205233545Sjchandra{
1206233545Sjchandra	uint32_t val;
1207233545Sjchandra
1208233545Sjchandra	val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG);
1209233545Sjchandra	val |= (1 << 13); /* prepad enable */
1210233545Sjchandra	val |= ((size & 0x3) << 22); /* prepad size */
1211233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val);
1212233545Sjchandra}
1213233545Sjchandra
1214233545Sjchandravoid
1215233545Sjchandranlm_setup_1588_timer(uint64_t nae_base, struct nae_port_config *cfg)
1216233545Sjchandra{
1217233545Sjchandra	uint32_t hi, lo, val;
1218233545Sjchandra
1219233545Sjchandra	hi = cfg[0].ieee1588_userval >> 32;
1220233545Sjchandra	lo = cfg[0].ieee1588_userval & 0xffffffff;
1221233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_USER_VALUE_HI, hi);
1222233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_USER_VALUE_LO, lo);
1223233545Sjchandra
1224233545Sjchandra	hi = cfg[0].ieee1588_ptpoff >> 32;
1225233545Sjchandra	lo = cfg[0].ieee1588_ptpoff & 0xffffffff;
1226233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_OFFSET_HI, hi);
1227233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_OFFSET_LO, lo);
1228233545Sjchandra
1229233545Sjchandra	hi = cfg[0].ieee1588_tmr1 >> 32;
1230233545Sjchandra	lo = cfg[0].ieee1588_tmr1 & 0xffffffff;
1231233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR1_HI, hi);
1232233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR1_LO, lo);
1233233545Sjchandra
1234233545Sjchandra	hi = cfg[0].ieee1588_tmr2 >> 32;
1235233545Sjchandra	lo = cfg[0].ieee1588_tmr2 & 0xffffffff;
1236233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR2_HI, hi);
1237233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR2_LO, lo);
1238233545Sjchandra
1239233545Sjchandra	hi = cfg[0].ieee1588_tmr3 >> 32;
1240233545Sjchandra	lo = cfg[0].ieee1588_tmr3 & 0xffffffff;
1241233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR3_HI, hi);
1242233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR3_LO, lo);
1243233545Sjchandra
1244233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_INTG,
1245233545Sjchandra	    cfg[0].ieee1588_inc_intg);
1246233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_NUM,
1247233545Sjchandra	    cfg[0].ieee1588_inc_num);
1248233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_DEN,
1249233545Sjchandra	    cfg[0].ieee1588_inc_den);
1250233545Sjchandra
1251233545Sjchandra	val = nlm_read_nae_reg(nae_base, NAE_1588_PTP_CONTROL);
1252233545Sjchandra	/* set and clear freq_mul = 1 */
1253233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val | (0x1 << 1));
1254233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val);
1255233545Sjchandra	/* set and clear load_user_val = 1 */
1256233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val | (0x1 << 6));
1257233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val);
1258233545Sjchandra}
1259233545Sjchandra
1260233545Sjchandravoid
1261233545Sjchandranlm_mac_enable(uint64_t nae_base, int nblock, int port_type, int port)
1262233545Sjchandra{
1263233545Sjchandra	uint32_t mac_cfg1, xaui_cfg;
1264233545Sjchandra	uint32_t netwk_inf;
1265233545Sjchandra	int iface = port & 0x3;
1266233545Sjchandra
1267233545Sjchandra	switch(port_type) {
1268233545Sjchandra	case SGMIIC:
1269233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base,
1270233545Sjchandra		    SGMII_NET_IFACE_CTRL(nblock, iface));
1271233545Sjchandra		nlm_write_nae_reg(nae_base,
1272233545Sjchandra		    SGMII_NET_IFACE_CTRL(nblock, iface),
1273233545Sjchandra		    netwk_inf		|
1274233545Sjchandra		    (1 << 2));			/* enable tx */
1275233545Sjchandra		mac_cfg1 = nlm_read_nae_reg(nae_base,
1276233545Sjchandra		    SGMII_MAC_CONF1(nblock, iface));
1277233545Sjchandra		nlm_write_nae_reg(nae_base,
1278233545Sjchandra		    SGMII_MAC_CONF1(nblock, iface),
1279233545Sjchandra		    mac_cfg1		|
1280233545Sjchandra		    (1 << 2)		|	/* rx enable */
1281233545Sjchandra		    1);				/* tx enable */
1282233545Sjchandra		break;
1283233545Sjchandra	case XAUIC:
1284233545Sjchandra		xaui_cfg = nlm_read_nae_reg(nae_base,
1285233545Sjchandra		    XAUI_CONFIG1(nblock));
1286233545Sjchandra		nlm_write_nae_reg(nae_base,
1287233545Sjchandra		    XAUI_CONFIG1(nblock),
1288233545Sjchandra		    xaui_cfg		|
1289233545Sjchandra		    XAUI_CONFIG_TFEN	|
1290233545Sjchandra		    XAUI_CONFIG_RFEN);
1291233545Sjchandra		break;
1292233545Sjchandra	case ILC:
1293233545Sjchandra		break;
1294233545Sjchandra	}
1295233545Sjchandra}
1296233545Sjchandra
1297233545Sjchandravoid
1298233545Sjchandranlm_mac_disable(uint64_t nae_base, int nblock, int port_type, int port)
1299233545Sjchandra{
1300233545Sjchandra	uint32_t mac_cfg1, xaui_cfg;
1301233545Sjchandra	uint32_t netwk_inf;
1302233545Sjchandra	int iface = port & 0x3;
1303233545Sjchandra
1304233545Sjchandra	switch(port_type) {
1305233545Sjchandra	case SGMIIC:
1306233545Sjchandra		mac_cfg1 = nlm_read_nae_reg(nae_base,
1307233545Sjchandra		    SGMII_MAC_CONF1(nblock, iface));
1308233545Sjchandra		nlm_write_nae_reg(nae_base,
1309233545Sjchandra		    SGMII_MAC_CONF1(nblock, iface),
1310233545Sjchandra		    mac_cfg1		&
1311233545Sjchandra		    ~((1 << 2)		|	/* rx enable */
1312233545Sjchandra		    1));			/* tx enable */
1313233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base,
1314233545Sjchandra		    SGMII_NET_IFACE_CTRL(nblock, iface));
1315233545Sjchandra		nlm_write_nae_reg(nae_base,
1316233545Sjchandra		    SGMII_NET_IFACE_CTRL(nblock, iface),
1317233545Sjchandra		    netwk_inf		&
1318233545Sjchandra		    ~(1 << 2));			/* enable tx */
1319233545Sjchandra		break;
1320233545Sjchandra	case XAUIC:
1321233545Sjchandra		xaui_cfg = nlm_read_nae_reg(nae_base,
1322233545Sjchandra		    XAUI_CONFIG1(nblock));
1323233545Sjchandra		nlm_write_nae_reg(nae_base,
1324233545Sjchandra		    XAUI_CONFIG1(nblock),
1325233545Sjchandra		    xaui_cfg		&
1326233545Sjchandra		    ~(XAUI_CONFIG_TFEN	|
1327233545Sjchandra		    XAUI_CONFIG_RFEN));
1328233545Sjchandra		break;
1329233545Sjchandra	case ILC:
1330233545Sjchandra		break;
1331233545Sjchandra	}
1332233545Sjchandra}
1333233545Sjchandra
1334233545Sjchandra/*
1335233545Sjchandra * Set IOR credits for the ports in ifmask to valmask
1336233545Sjchandra */
1337233545Sjchandrastatic void
1338233545Sjchandranlm_nae_set_ior_credit(uint64_t nae_base, uint32_t ifmask, uint32_t valmask)
1339233545Sjchandra{
1340233545Sjchandra	uint32_t tx_config, tx_ior_credit;
1341233545Sjchandra
1342233545Sjchandra	tx_ior_credit = nlm_read_nae_reg(nae_base, NAE_TX_IORCRDT_INIT);
1343233545Sjchandra	tx_ior_credit &= ~ifmask;
1344233545Sjchandra	tx_ior_credit |= valmask;
1345233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_TX_IORCRDT_INIT, tx_ior_credit);
1346233545Sjchandra
1347233545Sjchandra	tx_config = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG);
1348233545Sjchandra	/* need to toggle these bits for credits to be loaded */
1349233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
1350233545Sjchandra	    tx_config | (TXINITIORCR(ifmask)));
1351233545Sjchandra	nlm_write_nae_reg(nae_base, NAE_TX_CONFIG,
1352233545Sjchandra	    tx_config & ~(TXINITIORCR(ifmask)));
1353233545Sjchandra}
1354233545Sjchandra
1355233545Sjchandraint
1356233545Sjchandranlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
1357233545Sjchandra    int port, uint32_t desc_size)
1358233545Sjchandra{
1359233545Sjchandra	uint32_t netwk_inf;
1360245880Sjchandra	uint32_t mac_cfg1, netior_ctrl3;
1361245880Sjchandra	int iface, iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg;
1362233545Sjchandra
1363233545Sjchandra	switch (port_type) {
1364233545Sjchandra	case XAUIC:
1365233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base,
1366233545Sjchandra		    XAUI_NETIOR_XGMAC_CTRL1(nblock));
1367233545Sjchandra		netwk_inf |= (1 << NETIOR_XGMAC_STATS_CLR_POS);
1368233545Sjchandra		nlm_write_nae_reg(nae_base,
1369233545Sjchandra		    XAUI_NETIOR_XGMAC_CTRL1(nblock), netwk_inf);
1370233545Sjchandra
1371233545Sjchandra		nlm_nae_set_ior_credit(nae_base, 0xf << port, 0xf << port);
1372233545Sjchandra		break;
1373233545Sjchandra
1374233545Sjchandra	case ILC:
1375233545Sjchandra		nlm_nae_set_ior_credit(nae_base, 0xff << port, 0xff << port);
1376233545Sjchandra		break;
1377233545Sjchandra
1378233545Sjchandra	case SGMIIC:
1379233545Sjchandra		nlm_nae_set_ior_credit(nae_base, 0x1 << port, 0);
1380233545Sjchandra
1381233545Sjchandra		/*
1382233545Sjchandra		 * XXXJC: split this and merge to sgmii.c
1383233545Sjchandra		 * some of this is duplicated from there.
1384233545Sjchandra		 */
1385233545Sjchandra		/* init phy id to access internal PCS */
1386233545Sjchandra		iface = port & 0x3;
1387233545Sjchandra		iface_ctrl_reg = SGMII_NET_IFACE_CTRL(nblock, iface);
1388233545Sjchandra		conf1_reg = SGMII_MAC_CONF1(nblock, iface);
1389233545Sjchandra		conf2_reg = SGMII_MAC_CONF2(nblock, iface);
1390233545Sjchandra
1391233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1392233545Sjchandra		netwk_inf &= 0x7ffffff;
1393233545Sjchandra		netwk_inf |= (port << 27);
1394233545Sjchandra		nlm_write_nae_reg(nae_base, iface_ctrl_reg, netwk_inf);
1395233545Sjchandra
1396233545Sjchandra		/* Sofreset sgmii port - set bit 11 to 0  */
1397233545Sjchandra		netwk_inf &= 0xfffff7ff;
1398233545Sjchandra		nlm_write_nae_reg(nae_base, iface_ctrl_reg, netwk_inf);
1399233545Sjchandra
1400233545Sjchandra		/* Reset Gmac */
1401233545Sjchandra		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1402233545Sjchandra		nlm_write_nae_reg(nae_base, conf1_reg,
1403233545Sjchandra		    mac_cfg1	|
1404261455Seadler		    (1U << 31)	|	/* soft reset */
1405233545Sjchandra		    (1 << 2)	|	/* rx enable */
1406233545Sjchandra		    (1));		/* tx enable */
1407233545Sjchandra
1408233545Sjchandra		/* default to 1G */
1409233545Sjchandra		nlm_write_nae_reg(nae_base,
1410233545Sjchandra		    conf2_reg,
1411233545Sjchandra		    (0x7 << 12)	|	/* interface preamble length */
1412233545Sjchandra		    (0x2 << 8)	|	/* interface mode */
1413233545Sjchandra		    (0x1 << 2)	|	/* pad crc enable */
1414233545Sjchandra		    (0x1));		/* full duplex */
1415233545Sjchandra
1416233545Sjchandra		/* clear gmac reset */
1417233545Sjchandra		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1418261455Seadler		nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(1U << 31));
1419245880Sjchandra
1420233545Sjchandra		/* clear speed debug bit */
1421233545Sjchandra		iface_ctrl3_reg = SGMII_NET_IFACE_CTRL3(nblock, iface);
1422233545Sjchandra		netior_ctrl3 = nlm_read_nae_reg(nae_base, iface_ctrl3_reg);
1423233545Sjchandra		nlm_write_nae_reg(nae_base, iface_ctrl3_reg,
1424233545Sjchandra		    netior_ctrl3 & ~(1 << 6));
1425233545Sjchandra
1426233545Sjchandra		/* disable TX, RX for now */
1427233545Sjchandra		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1428233545Sjchandra		nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(0x5));
1429233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1430233545Sjchandra		nlm_write_nae_reg(nae_base, iface_ctrl_reg,
1431233545Sjchandra		    netwk_inf & ~(0x1 << 2));
1432233545Sjchandra
1433233545Sjchandra		/* clear stats counters */
1434233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1435233545Sjchandra		nlm_write_nae_reg(nae_base, iface_ctrl_reg,
1436233545Sjchandra		    netwk_inf | (1 << 15));
1437245880Sjchandra
1438233545Sjchandra		/* enable stats counters */
1439233545Sjchandra		netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
1440233545Sjchandra		nlm_write_nae_reg(nae_base, iface_ctrl_reg,
1441233545Sjchandra		    (netwk_inf & ~(1 << 15)) | (1 << 16));
1442245880Sjchandra
1443245880Sjchandra		/* flow control? */
1444233545Sjchandra		mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
1445233545Sjchandra		nlm_write_nae_reg(nae_base, conf1_reg,
1446233545Sjchandra		    mac_cfg1 | (0x3 << 4));
1447245880Sjchandra 		break;
1448233545Sjchandra	}
1449233545Sjchandra
1450233545Sjchandra	nlm_nae_init_ingress(nae_base, desc_size);
1451233545Sjchandra	nlm_nae_init_egress(nae_base);
1452233545Sjchandra
1453233545Sjchandra	return (0);
1454233545Sjchandra}
1455