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