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