diff options
author | jchandra <jchandra@FreeBSD.org> | 2012-03-27 14:05:12 +0000 |
---|---|---|
committer | jchandra <jchandra@FreeBSD.org> | 2012-03-27 14:05:12 +0000 |
commit | 2f1011004558a0b27cd95f1374185e37450b80e3 (patch) | |
tree | ae659c962d005114389e060c8a8057ddfcad9afd /sys/mips | |
parent | 961cc7f6b46bf3162f967f3b4ff8a1d0dce295b1 (diff) | |
download | FreeBSD-src-2f1011004558a0b27cd95f1374185e37450b80e3.zip FreeBSD-src-2f1011004558a0b27cd95f1374185e37450b80e3.tar.gz |
xlpge : driver for XLP network accelerator
Features:
- network driver for the four 10G interfaces and two management ports
on XLP 8xx.
- Support 4xx and 3xx variants of the processor.
- Source code and firmware building for the 16 mips32r2 micro-code engines
in the Network Accelerator.
- Basic initialization code for Packet ordering Engine.
Submitted by: Prabhath Raman (prabhath at netlogicmicro com)
[refactored and fixed up for style by jchandra]
Diffstat (limited to 'sys/mips')
-rw-r--r-- | sys/mips/conf/std.XLP | 1 | ||||
-rw-r--r-- | sys/mips/nlm/board.c | 390 | ||||
-rw-r--r-- | sys/mips/nlm/board.h | 73 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/mdio.c | 301 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/nae.c | 1536 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/sgmii.c | 216 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/ucore/crt0_basic.S | 66 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/ucore/ld.ucore.S | 162 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/ucore/ucore.h | 356 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/ucore/ucore_app.c | 58 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/xaui.c | 251 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/xlpge.c | 1574 | ||||
-rw-r--r-- | sys/mips/nlm/dev/net/xlpge.h | 135 | ||||
-rw-r--r-- | sys/mips/nlm/files.xlp | 17 | ||||
-rw-r--r-- | sys/mips/nlm/hal/interlaken.h | 70 | ||||
-rw-r--r-- | sys/mips/nlm/hal/iomap.h | 2 | ||||
-rw-r--r-- | sys/mips/nlm/hal/mdio.h | 104 | ||||
-rw-r--r-- | sys/mips/nlm/hal/nae.h | 646 | ||||
-rw-r--r-- | sys/mips/nlm/hal/poe.h | 352 | ||||
-rw-r--r-- | sys/mips/nlm/hal/sgmii.h | 217 | ||||
-rw-r--r-- | sys/mips/nlm/hal/ucore_loader.h | 141 | ||||
-rw-r--r-- | sys/mips/nlm/hal/xaui.h | 193 | ||||
-rw-r--r-- | sys/mips/nlm/msgring.h | 7 |
23 files changed, 6861 insertions, 7 deletions
diff --git a/sys/mips/conf/std.XLP b/sys/mips/conf/std.XLP index 2d867c2..188a2f9 100644 --- a/sys/mips/conf/std.XLP +++ b/sys/mips/conf/std.XLP @@ -71,6 +71,7 @@ device bpf # Network device miibus device ether +device xlpge #device re device msk device em diff --git a/sys/mips/nlm/board.c b/sys/mips/nlm/board.c index c84ea33..b4b0439 100644 --- a/sys/mips/nlm/board.c +++ b/sys/mips/nlm/board.c @@ -44,16 +44,289 @@ __FBSDID("$FreeBSD$"); #include <mips/nlm/hal/fmn.h> #include <mips/nlm/hal/pic.h> #include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/nae.h> #include <mips/nlm/hal/uart.h> +#include <mips/nlm/hal/poe.h> #include <mips/nlm/xlp.h> #include <mips/nlm/board.h> +#include <mips/nlm/msgring.h> static uint8_t board_eeprom_buf[EEPROM_SIZE]; static int board_eeprom_set; struct xlp_board_info xlp_board_info; +struct vfbid_tbl { + int vfbid; + int dest_vc; +}; + +/* XXXJC : this should be derived from msg thread mask */ +static struct vfbid_tbl nlm_vfbid[] = { + /* NULL FBID should map to cpu0 to detect NAE send msg errors */ + {127, 0}, /* NAE <-> NAE mappings */ + {51, 1019}, {50, 1018}, {49, 1017}, {48, 1016}, + {47, 1015}, {46, 1014}, {45, 1013}, {44, 1012}, + {43, 1011}, {42, 1010}, {41, 1009}, {40, 1008}, + {39, 1007}, {38, 1006}, {37, 1005}, {36, 1004}, + {35, 1003}, {34, 1002}, {33, 1001}, {32, 1000}, + /* NAE <-> CPU mappings, freeback got to vc 3 of each thread */ + {31, 127}, {30, 123}, {29, 119}, {28, 115}, + {27, 111}, {26, 107}, {25, 103}, {24, 99}, + {23, 95}, {22, 91}, {21, 87}, {20, 83}, + {19, 79}, {18, 75}, {17, 71}, {16, 67}, + {15, 63}, {14, 59}, {13, 55}, {12, 51}, + {11, 47}, {10, 43}, { 9, 39}, { 8, 35}, + { 7, 31}, { 6, 27}, { 5, 23}, { 4, 19}, + { 3, 15}, { 2, 11}, { 1, 7}, { 0, 3}, +}; + +static struct vfbid_tbl nlm3xx_vfbid[] = { + /* NULL FBID should map to cpu0 to detect NAE send msg errors */ + {127, 0}, /* NAE <-> NAE mappings */ + {39, 503}, {38, 502}, {37, 501}, {36, 500}, + {35, 499}, {34, 498}, {33, 497}, {32, 496}, + /* NAE <-> CPU mappings, freeback got to vc 3 of each thread */ + {31, 127}, {30, 123}, {29, 119}, {28, 115}, + {27, 111}, {26, 107}, {25, 103}, {24, 99}, + {23, 95}, {22, 91}, {21, 87}, {20, 83}, + {19, 79}, {18, 75}, {17, 71}, {16, 67}, + {15, 63}, {14, 59}, {13, 55}, {12, 51}, + {11, 47}, {10, 43}, { 9, 39}, { 8, 35}, + { 7, 31}, { 6, 27}, { 5, 23}, { 4, 19}, + { 3, 15}, { 2, 11}, { 1, 7}, { 0, 3}, +}; + +int +nlm_get_vfbid_mapping(int vfbid) +{ + int i, nentries; + struct vfbid_tbl *p; + + if (nlm_is_xlp3xx()) { + nentries = sizeof(nlm3xx_vfbid)/sizeof(struct vfbid_tbl); + p = nlm3xx_vfbid; + } else { + nentries = sizeof(nlm_vfbid)/sizeof(struct vfbid_tbl); + p = nlm_vfbid; + } + + for (i = 0; i < nentries; i++) { + if (p[i].vfbid == vfbid) + return (p[i].dest_vc); + } + + return (-1); +} + +int +nlm_get_poe_distvec(int vec, uint32_t *distvec) +{ + + if (vec != 0) + return (-1); /* we support just vec 0 */ + nlm_calc_poe_distvec(xlp_msg_thread_mask, 0, 0, 0, + 0x1 << XLPGE_RX_VC, distvec); + return (0); +} + +/* + * All our knowledge of chip and board that cannot be detected by probing + * at run-time goes here + */ + +void +xlpge_get_macaddr(uint8_t *macaddr) +{ + + if (board_eeprom_set == 0) { + /* No luck, take some reasonable value */ + macaddr[0] = 0x00; macaddr[1] = 0x0f; macaddr[2] = 0x30; + macaddr[3] = 0x20; macaddr[4] = 0x0d; macaddr[5] = 0x5b; + } else + memcpy(macaddr, &board_eeprom_buf[EEPROM_MACADDR_OFFSET], + ETHER_ADDR_LEN); +} + +static void +nlm_setup_port_defaults(struct xlp_port_ivars *p) +{ + p->loopback_mode = 0; + p->num_channels = 1; + p->free_desc_sizes = 2048; + p->vlan_pri_en = 0; + p->hw_parser_en = 1; + p->ieee1588_userval = 0; + p->ieee1588_ptpoff = 0; + p->ieee1588_tmr1 = 0; + p->ieee1588_tmr2 = 0; + p->ieee1588_tmr3 = 0; + p->ieee1588_inc_intg = 0; + p->ieee1588_inc_den = 1; + p->ieee1588_inc_num = 1; + + if (nlm_is_xlp3xx()) { + p->stg2_fifo_size = XLP3XX_STG2_FIFO_SZ; + p->eh_fifo_size = XLP3XX_EH_FIFO_SZ; + p->frout_fifo_size = XLP3XX_FROUT_FIFO_SZ; + p->ms_fifo_size = XLP3XX_MS_FIFO_SZ; + p->pkt_fifo_size = XLP3XX_PKT_FIFO_SZ; + p->pktlen_fifo_size = XLP3XX_PKTLEN_FIFO_SZ; + p->max_stg2_offset = XLP3XX_MAX_STG2_OFFSET; + p->max_eh_offset = XLP3XX_MAX_EH_OFFSET; + p->max_frout_offset = XLP3XX_MAX_FREE_OUT_OFFSET; + p->max_ms_offset = XLP3XX_MAX_MS_OFFSET; + p->max_pmem_offset = XLP3XX_MAX_PMEM_OFFSET; + p->stg1_2_credit = XLP3XX_STG1_2_CREDIT; + p->stg2_eh_credit = XLP3XX_STG2_EH_CREDIT; + p->stg2_frout_credit = XLP3XX_STG2_FROUT_CREDIT; + p->stg2_ms_credit = XLP3XX_STG2_MS_CREDIT; + } else { + p->stg2_fifo_size = XLP8XX_STG2_FIFO_SZ; + p->eh_fifo_size = XLP8XX_EH_FIFO_SZ; + p->frout_fifo_size = XLP8XX_FROUT_FIFO_SZ; + p->ms_fifo_size = XLP8XX_MS_FIFO_SZ; + p->pkt_fifo_size = XLP8XX_PKT_FIFO_SZ; + p->pktlen_fifo_size = XLP8XX_PKTLEN_FIFO_SZ; + p->max_stg2_offset = XLP8XX_MAX_STG2_OFFSET; + p->max_eh_offset = XLP8XX_MAX_EH_OFFSET; + p->max_frout_offset = XLP8XX_MAX_FREE_OUT_OFFSET; + p->max_ms_offset = XLP8XX_MAX_MS_OFFSET; + p->max_pmem_offset = XLP8XX_MAX_PMEM_OFFSET; + p->stg1_2_credit = XLP8XX_STG1_2_CREDIT; + p->stg2_eh_credit = XLP8XX_STG2_EH_CREDIT; + p->stg2_frout_credit = XLP8XX_STG2_FROUT_CREDIT; + p->stg2_ms_credit = XLP8XX_STG2_MS_CREDIT; + } + + switch (p->type) { + case SGMIIC: + p->num_free_descs = 52; + p->iface_fifo_size = 13; + p->rxbuf_size = 128; + p->rx_slots_reqd = SGMII_CAL_SLOTS; + p->tx_slots_reqd = SGMII_CAL_SLOTS; + if (nlm_is_xlp3xx()) + p->pseq_fifo_size = 30; + else + p->pseq_fifo_size = 62; + break; + case ILC: + p->num_free_descs = 150; + p->rxbuf_size = 944; + p->rx_slots_reqd = IL8_CAL_SLOTS; + p->tx_slots_reqd = IL8_CAL_SLOTS; + p->pseq_fifo_size = 225; + p->iface_fifo_size = 55; + break; + case XAUIC: + default: + p->num_free_descs = 150; + p->rxbuf_size = 944; + p->rx_slots_reqd = XAUI_CAL_SLOTS; + p->tx_slots_reqd = XAUI_CAL_SLOTS; + if (nlm_is_xlp3xx()) { + p->pseq_fifo_size = 120; + p->iface_fifo_size = 52; + } else { + p->pseq_fifo_size = 225; + p->iface_fifo_size = 55; + } + break; + } +} + +/* XLP 8XX evaluation boards have the following phy-addr + * assignment. There are two external mdio buses in XLP -- + * bus 0 and bus 1. The management ports (16 and 17) are + * on mdio bus 0 while blocks/complexes[0 to 3] are all + * on mdio bus 1. The phy_addr on bus 0 (mgmt ports 16 + * and 17) match the port numbers. + * These are the details: + * block port phy_addr mdio_bus + * ==================================== + * 0 0 4 1 + * 0 1 7 1 + * 0 2 6 1 + * 0 3 5 1 + * 1 0 8 1 + * 1 1 11 1 + * 1 2 10 1 + * 1 3 9 1 + * 2 0 0 1 + * 2 1 3 1 + * 2 2 2 1 + * 2 3 1 1 + * 3 0 12 1 + * 3 1 15 1 + * 3 2 14 1 + * 3 3 13 1 + * + * 4 0 16 0 + * 4 1 17 0 + * + * The XLP 3XX evaluation boards have the following phy-addr + * assignments. + * block port phy_addr mdio_bus + * ==================================== + * 0 0 4 0 + * 0 1 7 0 + * 0 2 6 0 + * 0 3 5 0 + * 1 0 8 0 + * 1 1 11 0 + * 1 2 10 0 + * 1 3 9 0 + */ +static void +nlm_board_get_phyaddr(int block, int port, int *mdio, int *phyaddr) +{ + + /* XXXJC: this is a board feature, check for chip not proper */ + if (nlm_is_xlp3xx() || (nlm_is_xlp8xx() && block == 4)) + *mdio = 0; + else + *mdio = 1; + + switch (block) { + case 0: switch (port) { + case 0: *phyaddr = 4; break; + case 1: *phyaddr = 7; break; + case 2: *phyaddr = 6; break; + case 3: *phyaddr = 5; break; + } + break; + case 1: switch (port) { + case 0: *phyaddr = 8; break; + case 1: *phyaddr = 11; break; + case 2: *phyaddr = 10; break; + case 3: *phyaddr = 9; break; + } + break; + case 2: switch (port) { + case 0: *phyaddr = 0; break; + case 1: *phyaddr = 3; break; + case 2: *phyaddr = 2; break; + case 3: *phyaddr = 1; break; + } + break; + case 3: switch (port) { + case 0: *phyaddr = 12; break; + case 1: *phyaddr = 15; break; + case 2: *phyaddr = 14; break; + case 3: *phyaddr = 13; break; + } + break; + case 4: switch (port) { /* management SGMII */ + case 0: *phyaddr = 16; break; + case 1: *phyaddr = 17; break; + } + break; + } +} + + static void nlm_print_processor_info(void) { @@ -105,12 +378,17 @@ static int nlm_setup_xlp_board(void) { struct xlp_board_info *boardp; - int rv; + struct xlp_node_info *nodep; + struct xlp_nae_ivars *naep; + struct xlp_block_ivars *blockp; + struct xlp_port_ivars *portp; + uint64_t cpldbase, nae_pcibase; + int node, block, port, rv, dbtype, usecpld; uint8_t *b; /* start with a clean slate */ boardp = &xlp_board_info; - memset(boardp, 0, sizeof(*boardp)); + memset(boardp, 0, sizeof(xlp_board_info)); boardp->nodemask = 0x1; /* only node 0 */ nlm_print_processor_info(); @@ -129,6 +407,114 @@ nlm_setup_xlp_board(void) printf("Board Info: Error on EEPROM read (i2c@%d %#X).\n", EEPROM_I2CBUS, EEPROM_I2CADDR); + + /* XXXJC: check for boards with right CPLD, for now + * 4xx PCI cards don't have CPLD with daughter + * card info */ + usecpld = !nlm_is_xlp4xx(); + + for (node = 0; node < XLP_MAX_NODES; node++) { + if ((boardp->nodemask & (1 << node)) == 0) + continue; + nae_pcibase = nlm_get_nae_pcibase(node); + nodep = &boardp->nodes[node]; + naep = &nodep->nae_ivars; + naep->node = node; + + naep->nblocks = nae_num_complex(nae_pcibase); + /* 3xx chips lie shamelessly about this */ + if (nlm_is_xlp3xx()) + naep->nblocks = naep->nblocks - 1; + naep->blockmask = (1 << naep->nblocks) - 1; /* XXXJC: redundant */ + naep->xauimask = 0x0; /* set this based on daughter card */ + naep->sgmiimask = 0x0; /* set this based on daughter card */ + + /* frequency at which network block runs */ + naep->freq = 500; + + /* CRC16 polynomial used for flow table generation */ + naep->flow_crc_poly = 0xffff; + naep->hw_parser_en = 1; + naep->prepad_en = 1; + naep->prepad_size = 3; /* size in 16 byte units */ + + naep->ieee_1588_en = 1; + cpldbase = nlm_board_cpld_base(node, XLP_EVB_CPLD_CHIPSELECT); + + for (block = 0; block < naep->nblocks; block++) { + blockp = &naep->block_ivars[block]; + blockp->block = block; + if (usecpld) + dbtype = nlm_board_cpld_dboard_type(cpldbase, + block); + else + dbtype = DCARD_XAUI; /* default XAUI */ + + if (block == 4) { + /* management block 4 on 8xx */ + blockp->type = SGMIIC; + blockp->portmask = 0x3; + naep->sgmiimask |= (1 << block); + } else { + switch (dbtype) { + case DCARD_ILAKEN: + blockp->type = ILC; + blockp->portmask = 0x1; + naep->xauimask |= (1 << block); + break; + case DCARD_SGMII: + blockp->type = SGMIIC; + blockp->portmask = 0xf; + naep->sgmiimask |= (1 << block); + break; + case DCARD_XAUI: + default: + blockp->type = XAUIC; + blockp->portmask = 0x1; + naep->xauimask |= (1 << block); + break; + } + } + for (port = 0; port < PORTS_PER_CMPLX; port++) { + if ((blockp->portmask & (1 << port)) == 0) + continue; + portp = &blockp->port_ivars[port]; + nlm_board_get_phyaddr(block, port, + &portp->mdio_bus, &portp->phy_addr); + portp->port = port; + portp->block = block; + portp->node = node; + portp->type = blockp->type; + nlm_setup_port_defaults(portp); + } + } + } + + /* pretty print network config */ + printf("Network config"); + if (usecpld) + printf("(from CPLD@%d):\n", XLP_EVB_CPLD_CHIPSELECT); + else + printf("(defaults):\n"); + for (node = 0; node < XLP_MAX_NODES; node++) { + if ((boardp->nodemask & (1 << node)) == 0) + continue; + nodep = &boardp->nodes[node]; + naep = &nodep->nae_ivars; + printf(" NAE@%d Blocks: ", node); + for (block = 0; block < naep->nblocks; block++) { + char *s = "???"; + + blockp = &naep->block_ivars[block]; + switch (blockp->type) { + case SGMIIC : s = "SGMII"; break; + case XAUIC : s = "XAUI"; break; + case ILC : s = "IL"; break; + } + printf(" [%d %s]", block, s); + } + printf("\n"); + } return (0); } diff --git a/sys/mips/nlm/board.h b/sys/mips/nlm/board.h index 3a2ae24..4ef4b37 100644 --- a/sys/mips/nlm/board.h +++ b/sys/mips/nlm/board.h @@ -32,9 +32,8 @@ #ifndef __NLM_BOARD_H__ #define __NLM_BOARD_H__ -#define XLP_NAE_NBLOCKS 5 -#define XLP_NAE_NPORTS 4 -#define XLP_I2C_MAXDEVICES 8 +#define XLP_NAE_NBLOCKS 5 +#define XLP_NAE_NPORTS 4 /* * EVP board EEPROM info @@ -44,13 +43,62 @@ #define EEPROM_SIZE 48 #define EEPROM_MACADDR_OFFSET 2 +/* + * EVP board CPLD chip select and daughter card info field + */ +#define XLP_EVB_CPLD_CHIPSELECT 2 + +#define DCARD_ILAKEN 0x0 +#define DCARD_SGMII 0x1 +#define DCARD_XAUI 0x2 +#define DCARD_NOT_PRSNT 0x3 + #if !defined(LOCORE) && !defined(__ASSEMBLY__) +/* + * NAE configuration + */ struct xlp_port_ivars { int port; int block; + int node; int type; int phy_addr; + int mdio_bus; + int loopback_mode; + int num_channels; + int free_desc_sizes; + int num_free_descs; + int pseq_fifo_size; + int iface_fifo_size; + int rxbuf_size; + int rx_slots_reqd; + int tx_slots_reqd; + int vlan_pri_en; + int stg2_fifo_size; + int eh_fifo_size; + int frout_fifo_size; + int ms_fifo_size; + int pkt_fifo_size; + int pktlen_fifo_size; + int max_stg2_offset; + int max_eh_offset; + int max_frout_offset; + int max_ms_offset; + int max_pmem_offset; + int stg1_2_credit; + int stg2_eh_credit; + int stg2_frout_credit; + int stg2_ms_credit; + int hw_parser_en; + u_int ieee1588_inc_intg; + u_int ieee1588_inc_den; + u_int ieee1588_inc_num; + uint64_t ieee1588_userval; + uint64_t ieee1588_ptpoff; + uint64_t ieee1588_tmr1; + uint64_t ieee1588_tmr2; + uint64_t ieee1588_tmr3; }; struct xlp_block_ivars { @@ -62,7 +110,16 @@ struct xlp_block_ivars { struct xlp_nae_ivars { int node; + int nblocks; u_int blockmask; + u_int xauimask; + u_int sgmiimask; + int freq; + u_int flow_crc_poly; + u_int hw_parser_en; + u_int prepad_en; + u_int prepad_size; /* size in 16 byte units */ + u_int ieee_1588_en; struct xlp_block_ivars block_ivars[XLP_NAE_NBLOCKS]; }; @@ -73,8 +130,16 @@ struct xlp_board_info { } nodes[XLP_MAX_NODES]; }; +extern struct xlp_board_info xlp_board_info; + +/* Network configuration */ +int nlm_get_vfbid_mapping(int); +int nlm_get_poe_distvec(int vec, uint32_t *distvec); +void xlpge_get_macaddr(uint8_t *macaddr); + int nlm_board_info_setup(void); +/* EEPROM & CPLD */ int nlm_board_eeprom_read(int node, int i2cbus, int addr, int offs, uint8_t *buf,int sz); uint64_t nlm_board_cpld_base(int node, int chipselect); @@ -82,6 +147,6 @@ int nlm_board_cpld_majorversion(uint64_t cpldbase); int nlm_board_cpld_minorversion(uint64_t cpldbase); void nlm_board_cpld_reset(uint64_t cpldbase); int nlm_board_cpld_dboard_type(uint64_t cpldbase, int slot); -#endif #endif +#endif diff --git a/sys/mips/nlm/dev/net/mdio.c b/sys/mips/nlm/dev/net/mdio.c new file mode 100644 index 0000000..362312f --- /dev/null +++ b/sys/mips/nlm/dev/net/mdio.c @@ -0,0 +1,301 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/systm.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/haldefs.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/nae.h> +#include <mips/nlm/hal/mdio.h> + +/* Internal MDIO READ/WRITE Routines */ +int +nlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block, + int intf_type, int phyaddr, int regidx) +{ + uint32_t mdio_ld_cmd; + uint32_t ctrlval; + + ctrlval = INT_MDIO_CTRL_SMP | + (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | + (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | + (2 << INT_MDIO_CTRL_OP_POS) | + (1 << INT_MDIO_CTRL_ST_POS) | + (7 << INT_MDIO_CTRL_XDIV_POS) | + (2 << INT_MDIO_CTRL_TA_POS) | + (2 << INT_MDIO_CTRL_MIIM_POS) | + (1 << INT_MDIO_CTRL_MCDIV_POS); + + mdio_ld_cmd = nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); + if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), + (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); + } + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + ctrlval); + + /* Toggle Load Cmd Bit */ + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); + + /* poll master busy bit until it is not busy */ + while(nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & + INT_MDIO_STAT_MBSY) { + } + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + ctrlval); + + /* Read the data back */ + return nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))); +} + +/* Internal MDIO WRITE Routines */ +int +nlm_int_gmac_mdio_write(uint64_t nae_base, int bus, int block, + int intf_type, int phyaddr, int regidx, uint16_t val) +{ + uint32_t mdio_ld_cmd; + uint32_t ctrlval; + + ctrlval = INT_MDIO_CTRL_SMP | + (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | + (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | + (1 << INT_MDIO_CTRL_OP_POS) | + (1 << INT_MDIO_CTRL_ST_POS) | + (7 << INT_MDIO_CTRL_XDIV_POS) | + (2 << INT_MDIO_CTRL_TA_POS) | + (1 << INT_MDIO_CTRL_MIIM_POS) | + (1 << INT_MDIO_CTRL_MCDIV_POS); + + mdio_ld_cmd = nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); + if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), + (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); + } + + /* load data into ctrl data reg */ + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL_DATA + bus * 4)), + val); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + ctrlval); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); + + /* poll master busy bit until it is not busy */ + while(nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & + INT_MDIO_STAT_MBSY) { + } + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + ctrlval); + + return (0); +} + +int +nlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block, + int intf_type) +{ + uint32_t val; + + val = (7 << INT_MDIO_CTRL_XDIV_POS) | + (1 << INT_MDIO_CTRL_MCDIV_POS); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + val | INT_MDIO_CTRL_RST); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), + val); + + return (0); +} + +/* + * nae_gmac_mdio_read - Read sgmii phy register + * + * Input parameters: + * bus - bus number, nae has two external gmac bus: 0 and 1 + * phyaddr - PHY's address + * regidx - index of register to read + * + * Return value: + * value read (16 bits), or 0xffffffff if an error occurred. + */ +int +nlm_gmac_mdio_read(uint64_t nae_base, int bus, int block, + int intf_type, int phyaddr, int regidx) +{ + uint32_t mdio_ld_cmd; + uint32_t val; + + val = EXT_G_MDIO_CMD_SP | + (phyaddr << EXT_G_MDIO_PHYADDR_POS) | + (regidx << EXT_G_MDIO_REGADDR_POS) | + EXT_G_MDIO_DIV; + + mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, + (EXT_G0_MDIO_CTRL + bus * 4))); + if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); + while(nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, + (EXT_G0_MDIO_RD_STAT + bus * 4))) & + EXT_G_MDIO_STAT_MBSY); + } + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + val); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + val | (1<<18)); + + /* poll master busy bit until it is not busy */ + while(nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) & + EXT_G_MDIO_STAT_MBSY); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + val); + + /* Read the data back */ + return nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))); +} + +/* + * nae_gmac_mdio_write -Write sgmac mii PHY register. + * + * Input parameters: + * bus - bus number, nae has two external gmac bus: 0 and 1 + * phyaddr - PHY to use + * regidx - register within the PHY + * val - data to write to register + * + * Return value: + * 0 - success + */ +int +nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, + int intf_type, int phyaddr, int regidx, uint16_t val) +{ + uint32_t mdio_ld_cmd; + uint32_t ctrlval; + + ctrlval = EXT_G_MDIO_CMD_SP | + (phyaddr << EXT_G_MDIO_PHYADDR_POS) | + (regidx << EXT_G_MDIO_REGADDR_POS) | + EXT_G_MDIO_DIV; + + mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, + (EXT_G0_MDIO_CTRL + bus * 4))); + if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); + while(nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, + (EXT_G0_MDIO_RD_STAT + bus * 4))) & + EXT_G_MDIO_STAT_MBSY); + } + + /* load data into ctrl data reg */ + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)), + val); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + ctrlval); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + ctrlval | EXT_G_MDIO_CMD_LCD); + + /* poll master busy bit until it is not busy */ + while(nlm_read_nae_reg(nae_base, + NAE_REG(block, intf_type, + (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + ctrlval); + + return (0); +} + +/* + * nae_gmac_mdio_reset -Reset sgmii mdio module. + * + * Input parameters: + * bus - bus number, nae has two external gmac bus: 0 and 1 + * + * Return value: + * 0 - success + */ +int +nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block, + int intf_type) +{ + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + EXT_G_MDIO_MMRST | EXT_G_MDIO_DIV); + nlm_write_nae_reg(nae_base, + NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), + EXT_G_MDIO_DIV); + return (0); +} diff --git a/sys/mips/nlm/dev/net/nae.c b/sys/mips/nlm/dev/net/nae.c new file mode 100644 index 0000000..8b02b03 --- /dev/null +++ b/sys/mips/nlm/dev/net/nae.c @@ -0,0 +1,1536 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/systm.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/haldefs.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/nae.h> +#include <mips/nlm/hal/mdio.h> +#include <mips/nlm/hal/sgmii.h> +#include <mips/nlm/hal/xaui.h> + +#include <mips/nlm/board.h> +#include <mips/nlm/xlp.h> + +void +nlm_nae_flush_free_fifo(uint64_t nae_base, int nblocks) +{ + uint32_t data, fifo_mask; + + fifo_mask = (1 << (4 * nblocks)) - 1; + + nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP, fifo_mask); + do { + data = nlm_read_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP); + } while (data != fifo_mask); + + nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_POP, 0); +} + +void +nlm_program_nae_parser_seq_fifo(uint64_t nae_base, int nblock, + struct nae_port_config *cfg) +{ + uint32_t val; + int start = 0, size, i, j; + + for (i = 0; i < nblock; i++) { + for (j = 0; j < PORTS_PER_CMPLX; j++) { + if ((i == 4) && (j > 1)) + size = 0; + else + size = cfg[(i*4)+j].pseq_fifo_size; + start += size; + } + } + + for (j = 0; j < PORTS_PER_CMPLX; j++) { + if ((i == 4) && (j > 1)) + size = 0; + else + size = cfg[(i*4)+j].pseq_fifo_size; + + val = (((size & 0x1fff) << 17) | + ((start & 0xfff) << 5) | + (((i * 4) + j) & 0x1f)); + nlm_write_nae_reg(nae_base, NAE_PARSER_SEQ_FIFO_CFG, val); + start += size; + } +} + +void +nlm_setup_rx_cal_cfg(uint64_t nae_base, int total_num_ports, + struct nae_port_config *cfg) +{ + int rx_slots = 0, port; + int cal_len, cal = 0, last_free = 0; + uint32_t val; + + for (port = 0; port < total_num_ports; port++) { + if (cfg[port].rx_slots_reqd) + rx_slots += cfg[port].rx_slots_reqd; + if (rx_slots > MAX_CAL_SLOTS) { + rx_slots = MAX_CAL_SLOTS; + break; + } + } + + cal_len = rx_slots - 1; + + do { + if (cal >= MAX_CAL_SLOTS) + break; + last_free = cal; + for (port = 0; port < total_num_ports; port++) { + if (cfg[port].rx_slots_reqd > 0) { + val = (cal_len << 16) | (port << 8) | cal; + nlm_write_nae_reg(nae_base, + NAE_RX_IF_SLOT_CAL, val); + cal++; + cfg[port].rx_slots_reqd--; + } + } + if (last_free == cal) + break; + } while (1); +} + +void +nlm_setup_tx_cal_cfg(uint64_t nae_base, int total_num_ports, + struct nae_port_config *cfg) +{ + int tx_slots = 0, port; + int cal = 0, last_free = 0; + uint32_t val; + + for (port = 0; port < total_num_ports; port++) { + if (cfg[port].tx_slots_reqd) + tx_slots += cfg[port].tx_slots_reqd; + if (tx_slots > MAX_CAL_SLOTS) { + tx_slots = MAX_CAL_SLOTS; + break; + } + } + + nlm_write_nae_reg(nae_base, NAE_EGR_NIOR_CAL_LEN_REG, tx_slots - 1); + do { + if (cal >= MAX_CAL_SLOTS) + break; + last_free = cal; + for (port = 0; port < total_num_ports; port++) { + if (cfg[port].tx_slots_reqd > 0) { + val = (port << 7) | (cal << 1) | 1; + nlm_write_nae_reg(nae_base, + NAE_EGR_NIOR_CRDT_CAL_PROG, val); + cal++; + cfg[port].tx_slots_reqd--; + } + } + if (last_free == cal) + break; + } while (1); +} + +void +nlm_deflate_frin_fifo_carving(uint64_t nae_base, int total_num_ports) +{ + const int minimum_size = 8; + uint32_t value; + int intf, start; + + for (intf = 0; intf < total_num_ports; intf++) { + start = minimum_size * intf; + value = (minimum_size << 20) | (start << 8) | (intf); + nlm_write_nae_reg(nae_base, NAE_FREE_IN_FIFO_CFG, value); + } +} + +void +nlm_reset_nae(int node) +{ + uint64_t sysbase; + uint64_t nae_base; + uint64_t nae_pcibase; + uint32_t rx_config; + uint32_t bar0; + int reset_bit; + + sysbase = nlm_get_sys_regbase(node); + nae_base = nlm_get_nae_regbase(node); + nae_pcibase = nlm_get_nae_pcibase(node); + + bar0 = nlm_read_pci_reg(nae_pcibase, XLP_PCI_CFGREG4); + +#if BYTE_ORDER == LITTLE_ENDIAN + if (nlm_is_xlp8xx_ax()) { + uchar_t val; + /* membar fixup */ + val = (bar0 >> 24) & 0xff; + bar0 = (val << 24) | (val << 16) | (val << 8) | val; + } +#endif + + if (nlm_is_xlp3xx()) + reset_bit = 6; + else + reset_bit = 9; + + /* Reset NAE */ + nlm_write_sys_reg(sysbase, SYS_RESET, (1 << reset_bit)); + + /* XXXJC - 1s delay here may be too high */ + DELAY(1000000); + nlm_write_sys_reg(sysbase, SYS_RESET, (0 << reset_bit)); + DELAY(1000000); + + rx_config = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG); + nlm_write_pci_reg(nae_pcibase, XLP_PCI_CFGREG4, bar0); +} + +void +nlm_setup_poe_class_config(uint64_t nae_base, int max_poe_classes, + int num_contexts, int *poe_cl_tbl) +{ + uint32_t val; + int i, max_poe_class_ctxt_tbl_sz; + + max_poe_class_ctxt_tbl_sz = num_contexts/max_poe_classes; + for (i = 0; i < max_poe_class_ctxt_tbl_sz; i++) { + val = (poe_cl_tbl[(i/max_poe_classes) & 0x7] << 8) | i; + nlm_write_nae_reg(nae_base, NAE_POE_CLASS_SETUP_CFG, val); + } +} + +void +nlm_setup_vfbid_mapping(uint64_t nae_base) +{ + uint32_t val; + int dest_vc, vfbid; + + /* 127 is max vfbid */ + for (vfbid = 127; vfbid >= 0; vfbid--) { + dest_vc = nlm_get_vfbid_mapping(vfbid); + if (dest_vc < 0) + continue; + val = (dest_vc << 16) | (vfbid << 4) | 1; + nlm_write_nae_reg(nae_base, NAE_VFBID_DESTMAP_CMD, val); + } +} + +void +nlm_setup_flow_crc_poly(uint64_t nae_base, uint32_t poly) +{ + nlm_write_nae_reg(nae_base, NAE_FLOW_CRC16_POLY_CFG, poly); +} + +void +nlm_setup_iface_fifo_cfg(uint64_t nae_base, int nblock, + struct nae_port_config *cfg) +{ + uint32_t reg; + int fifo_xoff_thresh = 12; + int i, size, j; + int cur_iface_start = 0; + + for (i = 0; i < nblock; i++) { + for (j = 0; j < PORTS_PER_CMPLX; j++) { + if ((i == 4) && (j > 1)) + size = 0; + else + size = cfg[(i*4)+j].iface_fifo_size; + cur_iface_start += size; + } + } + + for (j = 0; j < PORTS_PER_CMPLX; j++) { + if ((i == 4) && (j > 1)) + size = 0; + else + size = cfg[(i*4)+j].iface_fifo_size; + reg = ((fifo_xoff_thresh << 25) | + ((size & 0x1ff) << 16) | + ((cur_iface_start & 0xff) << 8) | + (((i * 4) + j) & 0x1f)); + nlm_write_nae_reg(nae_base, NAE_IFACE_FIFO_CFG, reg); + cur_iface_start += size; + } +} + +void +nlm_setup_rx_base_config(uint64_t nae_base, int nblock, + struct nae_port_config *cfg) +{ + uint32_t val, nc; + int base = 0; + int i, j; + int id; + + for (i = 0; i < nblock; i++) { + for (j = 0; j < (PORTS_PER_CMPLX/2); j++) { + base += cfg[(i*4)+(2*j)].num_channels; + base += cfg[(i*4)+(2*j + 1)].num_channels; + } + } + + id = 0x12 + (i * 2); /* RX_IF_BASE_CONFIG0 */ + + for (j = 0; j < (PORTS_PER_CMPLX/2); j++) { + val = (base & 0x3ff); + nc = cfg[(i*4)+(2*j)].num_channels; + base += nc; + + val |= ((base & 0x3ff) << 16); + nc = cfg[(i*4)+(2*j + 1)].num_channels; + base += nc; + + nlm_write_nae_reg(nae_base, NAE_REG(7, 0, (id+j)), val); + } +} + +void +nlm_setup_rx_buf_config(uint64_t nae_base, int nblock, + struct nae_port_config *cfg) +{ + uint32_t val; + int i, sz, j, k; + int context = 0; + int base = 0; + int nc = 0; + + for (i = 0; i < nblock; i++) { + for (j = 0; j < PORTS_PER_CMPLX; j++) { + if ((i == 4) && (j > 1)) + nc = 0; + else + nc = cfg[(i*4)+j].num_channels; + for (k = 0; k < nc; k++) { + sz = cfg[(i*4)+j].rxbuf_size; + base += sz; + } + context += nc; + } + } + + for (j = 0; j < PORTS_PER_CMPLX; j++) { + if ((i == 4) && (j > 1)) + nc = 0; + else + nc = cfg[(i*4)+j].num_channels; + for (k = 0; k < nc; k++) { + /* write index (context num) */ + nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH_ADDR, + (context+k)); + + /* write value (rx buf sizes) */ + sz = cfg[(i*4)+j].rxbuf_size; + val = 0x80000000 | ((base << 2) & 0x3fff); /* base */ + val |= (((sz << 2) & 0x3fff) << 16); /* size */ + + nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH, val); + nlm_write_nae_reg(nae_base, NAE_RXBUF_BASE_DPTH, + (0x7fffffff & val)); + base += sz; + } + context += nc; + } +} + +void +nlm_setup_freein_fifo_cfg(uint64_t nae_base, int nblock, + struct nae_port_config *cfg) +{ + int size, i, cp = 0; + uint32_t reg; + int start = 0; + + for (cp = 0 ; cp < nblock; cp++ ) { + for (i = 0; i < PORTS_PER_CMPLX; i++) { /* 4 interfaces */ + if ((cp == 4) && (i > 1)) + size = 0; + else { + /* Each entry represents 2 descs; hence division by 2 */ + size = cfg[(cp*4)+i].num_free_descs / 2; + } + if (size == 0) + size = 8; + start += size; + } + } + + for (i = 0; i < PORTS_PER_CMPLX; i++) { /* 4 interfaces */ + if ((cp == 4) && (i > 1)) + size = 0; + else { + /* Each entry represents 2 descs; hence division by 2 */ + size = cfg[(cp*4)+i].num_free_descs / 2; + } + /* Each entry represents 2 descs; hence division by 2 */ + if (size == 0) + size = 8; + + reg = ((size & 0x3ff ) << 20) | /* fcSize */ + ((start & 0x1ff) << 8) | /* fcStart */ + (((cp * 4) + i) & 0x1f); + + nlm_write_nae_reg(nae_base, NAE_FREE_IN_FIFO_CFG, reg); + start += size; + } +} + +/* XXX function name */ +int +nlm_get_flow_mask(int num_ports) +{ + const int max_bits = 5; /* upto 32 ports */ + int i; + + /* Compute the number of bits to needed to + * represent all the ports */ + for (i = 0; i < max_bits; i++) { + if (num_ports <= (2 << i)) + return (i + 1); + } + return (max_bits); +} + +void +nlm_program_flow_cfg(uint64_t nae_base, int port, + uint32_t cur_flow_base, uint32_t flow_mask) +{ + uint32_t val; + + val = (cur_flow_base << 16) | port; + val |= ((flow_mask & 0x1f) << 8); + nlm_write_nae_reg(nae_base, NAE_FLOW_BASEMASK_CFG, val); +} + +void +xlp_ax_nae_lane_reset_txpll(uint64_t nae_base, int block, int lane_ctrl, + int mode) +{ + uint32_t val = 0, saved_data; + int rext_sel = 0; + + val = PHY_LANE_CTRL_RST | + PHY_LANE_CTRL_PWRDOWN | + (mode << PHY_LANE_CTRL_PHYMODE_POS); + + /* set comma bypass for XAUI */ + if (mode != PHYMODE_SGMII) + val |= PHY_LANE_CTRL_BPC_XAUI; + + nlm_write_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl), val); + + if (lane_ctrl != 4) { + rext_sel = (1 << 23); + if (mode != PHYMODE_SGMII) + rext_sel |= PHY_LANE_CTRL_BPC_XAUI; + + val = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl)); + val &= ~PHY_LANE_CTRL_RST; + val |= rext_sel; + + /* Resetting PMA for non-zero lanes */ + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), val); + + DELAY(20000); /* 20 ms delay, XXXJC: needed? */ + + val |= PHY_LANE_CTRL_RST; + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), val); + + val = 0; + } + + /* Come out of reset for TXPLL */ + saved_data = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl)) & 0xFFC00000; + + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), + (0x66 << PHY_LANE_CTRL_ADDR_POS) + | PHY_LANE_CTRL_CMD_READ + | PHY_LANE_CTRL_CMD_START + | PHY_LANE_CTRL_RST + | rext_sel + | val ); + + while (((val = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl))) & + PHY_LANE_CTRL_CMD_PENDING)); + + val &= 0xFF; + /* set bit[4] to 0 */ + val &= ~(1 << 4); + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), + (0x66 << PHY_LANE_CTRL_ADDR_POS) + | PHY_LANE_CTRL_CMD_WRITE + | PHY_LANE_CTRL_CMD_START + | (0x0 << 19) /* (0x4 << 19) */ + | rext_sel + | saved_data + | val ); + + /* re-do */ + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), + (0x66 << PHY_LANE_CTRL_ADDR_POS) + | PHY_LANE_CTRL_CMD_WRITE + | PHY_LANE_CTRL_CMD_START + | (0x0 << 19) /* (0x4 << 19) */ + | rext_sel + | saved_data + | val ); + + while (!((val = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, (lane_ctrl - PHY_LANE_0_CTRL)))) & + PHY_LANE_STAT_PCR)); + + /* Clear the Power Down bit */ + val = nlm_read_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl)); + val &= ~((1 << 29) | (0x7ffff)); + nlm_write_nae_reg(nae_base, NAE_REG(block, PHY, lane_ctrl), + (rext_sel | val)); +} + +void +xlp_nae_lane_reset_txpll(uint64_t nae_base, int block, int lane_ctrl, + int mode) +{ + uint32_t val = 0; + int rext_sel = 0; + + if (lane_ctrl != 4) + rext_sel = (1 << 23); + + val = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl)); + + /* set comma bypass for XAUI */ + if (mode != PHYMODE_SGMII) + val |= PHY_LANE_CTRL_BPC_XAUI; + val |= 0x100000; + val |= (mode << PHY_LANE_CTRL_PHYMODE_POS); + val &= ~(0x20000); + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), val); + + val = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl)); + val |= 0x40000000; + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), val); + + /* clear the power down bit */ + val = nlm_read_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl)); + val &= ~( (1 << 29) | (0x7ffff)); + nlm_write_nae_reg(nae_base, + NAE_REG(block, PHY, lane_ctrl), rext_sel | val); +} + +void +xlp_nae_config_lane_gmac(uint64_t nae_base, int cplx_mask) +{ + int block, lane_ctrl; + int cplx_lane_enable; + int lane_enable = 0; + + cplx_lane_enable = LM_SGMII | + (LM_SGMII << 4) | + (LM_SGMII << 8) | + (LM_SGMII << 12); + + /* Lane mode progamming */ + block = 7; + + /* Complexes 0, 1 */ + if (cplx_mask & 0x1) + lane_enable |= cplx_lane_enable; + + if (cplx_mask & 0x2) + lane_enable |= (cplx_lane_enable << 16); + + if (lane_enable) { + nlm_write_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1), + lane_enable); + lane_enable = 0; + } + /* Complexes 2 3 */ + if (cplx_mask & 0x4) + lane_enable |= cplx_lane_enable; + + if (cplx_mask & 0x8) + lane_enable |= (cplx_lane_enable << 16); + + nlm_write_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3), + lane_enable); + + /* complex 4 */ + /* XXXJC : fix duplicate code */ + if (cplx_mask & 0x10) { + nlm_write_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_4), + ((LM_SGMII << 4) | LM_SGMII)); + for (lane_ctrl = PHY_LANE_0_CTRL; + lane_ctrl <= PHY_LANE_1_CTRL; lane_ctrl++) { + if (!nlm_is_xlp8xx_ax()) + xlp_nae_lane_reset_txpll(nae_base, + 4, lane_ctrl, PHYMODE_SGMII); + else + xlp_ax_nae_lane_reset_txpll(nae_base, 4, + lane_ctrl, PHYMODE_SGMII); + } + } + + for (block = 0; block < 4; block++) { + if ((cplx_mask & (1 << block)) == 0) + continue; + + for (lane_ctrl = PHY_LANE_0_CTRL; + lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { + if (!nlm_is_xlp8xx_ax()) + xlp_nae_lane_reset_txpll(nae_base, + block, lane_ctrl, PHYMODE_SGMII); + else + xlp_ax_nae_lane_reset_txpll(nae_base, block, + lane_ctrl, PHYMODE_SGMII); + } + } +} + +void +config_egress_fifo_carvings(uint64_t nae_base, int hwport, int start_ctxt, + int num_ctxts, int max_ctxts, struct nae_port_config *cfg) +{ + static uint32_t cur_start[6] = {0, 0, 0, 0, 0, 0}; + uint32_t data = 0; + uint32_t start = 0, size, offset; + int i, limit; + + limit = start_ctxt + num_ctxts; + /* Stage 2 FIFO */ + start = cur_start[0]; + for (i = start_ctxt; i < limit; i++) { + size = cfg[hwport].stg2_fifo_size / max_ctxts; + if (size) + offset = size - 1; + else + offset = size; + if (offset > cfg[hwport].max_stg2_offset) + offset = cfg[hwport].max_stg2_offset; + data = offset << 23 | + start << 11 | + i << 1 | + 1; + nlm_write_nae_reg(nae_base, NAE_STG2_PMEM_PROG, data); + start += size; + } + cur_start[0] = start; + + /* EH FIFO */ + start = cur_start[1]; + for (i = start_ctxt; i < limit; i++) { + size = cfg[hwport].eh_fifo_size / max_ctxts; + if (size) + offset = size - 1; + else + offset = size ; + if (offset > cfg[hwport].max_eh_offset) + offset = cfg[hwport].max_eh_offset; + data = offset << 23 | + start << 11 | + i << 1 | + 1; + nlm_write_nae_reg(nae_base, NAE_EH_PMEM_PROG, data); + start += size; + } + cur_start[1] = start; + + /* FROUT FIFO */ + start = cur_start[2]; + for (i = start_ctxt; i < limit; i++) { + size = cfg[hwport].frout_fifo_size / max_ctxts; + if (size) + offset = size - 1; + else + offset = size ; + if (offset > cfg[hwport].max_frout_offset) + offset = cfg[hwport].max_frout_offset; + data = offset << 23 | + start << 11 | + i << 1 | + 1; + nlm_write_nae_reg(nae_base, NAE_FREE_PMEM_PROG, data); + start += size; + } + cur_start[2] = start; + + /* MS FIFO */ + start = cur_start[3]; + for (i = start_ctxt; i < limit; i++) { + size = cfg[hwport].ms_fifo_size / max_ctxts; + if (size) + offset = size - 1; + else + offset = size ; + if (offset > cfg[hwport].max_ms_offset) + offset = cfg[hwport].max_ms_offset; + data = offset << 22 | /* FIXME in PRM */ + start << 11 | + i << 1 | + 1; + nlm_write_nae_reg(nae_base, NAE_STR_PMEM_CMD, data); + start += size; + } + cur_start[3] = start; + + /* PKT FIFO */ + start = cur_start[4]; + for (i = start_ctxt; i < limit; i++) { + size = cfg[hwport].pkt_fifo_size / max_ctxts; + if (size) + offset = size - 1; + else + offset = size ; + if (offset > cfg[hwport].max_pmem_offset) + offset = cfg[hwport].max_pmem_offset; + nlm_write_nae_reg(nae_base, NAE_TX_PKT_PMEM_CMD1, offset); + + data = start << 11 | + i << 1 | + 1; + nlm_write_nae_reg(nae_base, NAE_TX_PKT_PMEM_CMD0, data); + start += size; + } + cur_start[4] = start; + + /* PKT LEN FIFO */ + start = cur_start[5]; + for (i = start_ctxt; i < limit; i++) { + size = cfg[hwport].pktlen_fifo_size / max_ctxts; + if (size) + offset = size - 1; + else + offset = size ; + data = offset << 22 | + start << 11 | + i << 1 | + 1; + nlm_write_nae_reg(nae_base, NAE_TX_PKTLEN_PMEM_CMD, data); + start += size; + } + cur_start[5] = start; +} + +void +config_egress_fifo_credits(uint64_t nae_base, int hwport, int start_ctxt, + int num_ctxts, int max_ctxts, struct nae_port_config *cfg) +{ + uint32_t data, credit, max_credit; + int i, limit; + + limit = start_ctxt + num_ctxts; + /* Stage1 -> Stage2 */ + max_credit = cfg[hwport].max_stg2_offset + 1; + for (i = start_ctxt; i < limit; i++) { + credit = cfg[hwport].stg1_2_credit / max_ctxts; + if (credit > max_credit) + credit = max_credit; + data = credit << 16 | + i << 4 | + 1; + nlm_write_nae_reg(nae_base, NAE_STG1_STG2CRDT_CMD, data); + } + + /* Stage2 -> EH */ + max_credit = cfg[hwport].max_eh_offset + 1; + for (i = start_ctxt; i < limit; i++) { + credit = cfg[hwport].stg2_eh_credit / max_ctxts; + if (credit > max_credit) + credit = max_credit; + data = credit << 16 | + i << 4 | + 1; + nlm_write_nae_reg(nae_base, NAE_STG2_EHCRDT_CMD, data); + } + + /* Stage2 -> Frout */ + max_credit = cfg[hwport].max_frout_offset + 1; + for (i = start_ctxt; i < limit; i++) { + credit = cfg[hwport].stg2_frout_credit / max_ctxts; + if (credit > max_credit) + credit = max_credit; + data = credit << 16 | + i << 4 | + 1; + nlm_write_nae_reg(nae_base, NAE_EH_FREECRDT_CMD, data); + } + + /* Stage2 -> MS */ + max_credit = cfg[hwport].max_ms_offset + 1; + for (i = start_ctxt; i < limit; i++) { + credit = cfg[hwport].stg2_ms_credit / max_ctxts; + if (credit > max_credit) + credit = max_credit; + data = credit << 16 | + i << 4 | + 1; + nlm_write_nae_reg(nae_base, NAE_STG2_STRCRDT_CMD, data); + } +} + +void +nlm_config_freein_fifo_uniq_cfg(uint64_t nae_base, int port, + int nblock_free_desc) +{ + uint32_t val; + int size_in_clines; + + size_in_clines = (nblock_free_desc / NAE_CACHELINE_SIZE); + val = (size_in_clines << 8) | (port & 0x1f); + nlm_write_nae_reg(nae_base, NAE_FREEIN_FIFO_UNIQ_SZ_CFG, val); +} + +/* XXXJC: redundant, see ucore_spray_config() */ +void +nlm_config_ucore_iface_mask_cfg(uint64_t nae_base, int port, + int nblock_ucore_mask) +{ + uint32_t val; + + val = ( 0x1U << 31) | ((nblock_ucore_mask & 0xffff) << 8) | + (port & 0x1f); + nlm_write_nae_reg(nae_base, NAE_UCORE_IFACEMASK_CFG, val); +} + +int +nlm_nae_init_netior(uint64_t nae_base, int nblocks) +{ + uint32_t ctrl1, ctrl2, ctrl3; + + if (nblocks == 5) + ctrl3 = 0x07 << 18; + else + ctrl3 = 0; + + switch (nblocks) { + case 2: + ctrl1 = 0xff; + ctrl2 = 0x0707; + break; + case 4: + case 5: + ctrl1 = 0xfffff; + ctrl2 = 0x07070707; + break; + default: + printf("WARNING: unsupported blocks %d\n", nblocks); + return (-1); + } + + nlm_write_nae_reg(nae_base, NAE_LANE_CFG_SOFTRESET, 0); + nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL3, ctrl3); + nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL2, ctrl2); + nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL1, ctrl1); + nlm_write_nae_reg(nae_base, NAE_NETIOR_MISC_CTRL1, 0x0); + return (0); +} + +void +nlm_nae_init_ingress(uint64_t nae_base, uint32_t desc_size) +{ + uint32_t rx_cfg; + uint32_t parser_threshold = 384; + + rx_cfg = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG); + rx_cfg &= ~(0x3 << 1); /* reset max message size */ + rx_cfg &= ~(0xff << 4); /* clear freein desc cluster size */ + rx_cfg &= ~(0x3f << 24); /* reset rx status mask */ /*XXX: why not 7f */ + + rx_cfg |= 1; /* rx enable */ + rx_cfg |= (0x0 << 1); /* max message size */ + rx_cfg |= (0x43 & 0x7f) << 24; /* rx status mask */ + rx_cfg |= ((desc_size / 64) & 0xff) << 4; /* freein desc cluster size */ + nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, rx_cfg); + nlm_write_nae_reg(nae_base, NAE_PARSER_CONFIG, + (parser_threshold & 0x3ff) | + (((parser_threshold / desc_size) + 1) & 0xff) << 12 | + (((parser_threshold / 64) % desc_size) & 0xff) << 20); + + /*nlm_write_nae_reg(nae_base, NAE_RX_FREE_FIFO_THRESH, 33);*/ +} + +void +nlm_nae_init_egress(uint64_t nae_base) +{ + uint32_t tx_cfg; + + tx_cfg = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG); + if (!nlm_is_xlp8xx_ax()) { + nlm_write_nae_reg(nae_base, NAE_TX_CONFIG, + tx_cfg | + 0x1 | /* tx enable */ + 0x2 | /* tx ace */ + 0x4 | /* tx compatible */ + (1 << 3)); + } else { + nlm_write_nae_reg(nae_base, NAE_TX_CONFIG, + tx_cfg | + 0x1 | /* tx enable */ + 0x2); /* tx ace */ + } +} + +uint32_t +ucore_spray_config(uint32_t interface, uint32_t ucore_mask, int cmd) +{ + return ((cmd & 0x1) << 31) | ((ucore_mask & 0xffff) << 8) | + (interface & 0x1f); +} + +void +nlm_nae_init_ucore(uint64_t nae_base, int if_num, u_int ucore_mask) +{ + uint32_t ucfg; + + ucfg = ucore_spray_config(if_num, ucore_mask, 1); /* 1 : write */ + nlm_write_nae_reg(nae_base, NAE_UCORE_IFACEMASK_CFG, ucfg); +} + +uint64_t +nae_tx_desc(u_int type, u_int rdex, u_int fbid, u_int len, uint64_t addr) +{ + return ((uint64_t)type << 62) | + ((uint64_t)rdex << 61) | + ((uint64_t)fbid << 54) | + ((uint64_t)len << 40) | addr; +} + +void +nlm_setup_l2type(uint64_t nae_base, int hwport, uint32_t l2extlen, + uint32_t l2extoff, uint32_t extra_hdrsize, uint32_t proto_offset, + uint32_t fixed_hdroff, uint32_t l2proto) +{ + uint32_t val; + + val = ((l2extlen & 0x3f) << 26) | + ((l2extoff & 0x3f) << 20) | + ((extra_hdrsize & 0x3f) << 14) | + ((proto_offset & 0x3f) << 8) | + ((fixed_hdroff & 0x3f) << 2) | + (l2proto & 0x3); + nlm_write_nae_reg(nae_base, (NAE_L2_TYPE_PORT0 + hwport), val); +} + +void +nlm_setup_l3ctable_mask(uint64_t nae_base, int hwport, uint32_t ptmask, + uint32_t l3portmask) +{ + uint32_t val; + + val = ((ptmask & 0x1) << 6) | + ((l3portmask & 0x1) << 5) | + (hwport & 0x1f); + nlm_write_nae_reg(nae_base, NAE_L3_CTABLE_MASK0, val); +} + +void +nlm_setup_l3ctable_even(uint64_t nae_base, int entry, uint32_t l3hdroff, + uint32_t ipcsum_en, uint32_t l4protooff, + uint32_t l2proto, uint32_t eth_type) +{ + uint32_t val; + + val = ((l3hdroff & 0x3f) << 26) | + ((l4protooff & 0x3f) << 20) | + ((ipcsum_en & 0x1) << 18) | + ((l2proto & 0x3) << 16) | + (eth_type & 0xffff); + nlm_write_nae_reg(nae_base, (NAE_L3CTABLE0 + (entry * 2)), val); +} + +void +nlm_setup_l3ctable_odd(uint64_t nae_base, int entry, uint32_t l3off0, + uint32_t l3len0, uint32_t l3off1, uint32_t l3len1, + uint32_t l3off2, uint32_t l3len2) +{ + uint32_t val; + + val = ((l3off0 & 0x3f) << 26) | + ((l3len0 & 0x1f) << 21) | + ((l3off1 & 0x3f) << 15) | + ((l3len1 & 0x1f) << 10) | + ((l3off2 & 0x3f) << 4) | + (l3len2 & 0xf); + nlm_write_nae_reg(nae_base, (NAE_L3CTABLE0 + ((entry * 2) + 1)), val); +} + +void +nlm_setup_l4ctable_even(uint64_t nae_base, int entry, uint32_t im, + uint32_t l3cm, uint32_t l4pm, uint32_t port, + uint32_t l3camaddr, uint32_t l4proto) +{ + uint32_t val; + + val = ((im & 0x1) << 19) | + ((l3cm & 0x1) << 18) | + ((l4pm & 0x1) << 17) | + ((port & 0x1f) << 12) | + ((l3camaddr & 0xf) << 8) | + (l4proto & 0xff); + nlm_write_nae_reg(nae_base, (NAE_L4CTABLE0 + (entry * 2)), val); +} + +void +nlm_setup_l4ctable_odd(uint64_t nae_base, int entry, uint32_t l4off0, + uint32_t l4len0, uint32_t l4off1, uint32_t l4len1) +{ + uint32_t val; + + val = ((l4off0 & 0x3f) << 21) | + ((l4len0 & 0xf) << 17) | + ((l4off1 & 0x3f) << 11) | + (l4len1 & 0xf); + nlm_write_nae_reg(nae_base, (NAE_L4CTABLE0 + ((entry * 2) + 1)), val); +} + +void +nlm_enable_hardware_parser(uint64_t nae_base) +{ + uint32_t val; + + val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG); + val |= (1 << 12); /* hardware parser enable */ + nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val); + + /*********************************************** + * program L3 CAM table + ***********************************************/ + + /* + * entry-0 is ipv4 MPLS type 1 label + */ + /* l3hdroff = 4 bytes, ether_type = 0x8847 for MPLS_type1 */ + nlm_setup_l3ctable_even(nae_base, 0, 4, 1, 9, 1, 0x8847); + /* l3off0 (8 bytes) -> l3len0 (1 byte) := ip proto + * l3off1 (12 bytes) -> l3len1 (4 bytes) := src ip + * l3off2 (16 bytes) -> l3len2 (4 bytes) := dst ip + */ + nlm_setup_l3ctable_odd(nae_base, 0, 9, 1, 12, 4, 16, 4); + + /* + * entry-1 is for ethernet IPv4 packets + */ + nlm_setup_l3ctable_even(nae_base, 1, 0, 1, 9, 1, 0x0800); + /* l3off0 (8 bytes) -> l3len0 (1 byte) := ip proto + * l3off1 (12 bytes) -> l3len1 (4 bytes) := src ip + * l3off2 (16 bytes) -> l3len2 (4 bytes) := dst ip + */ + nlm_setup_l3ctable_odd(nae_base, 1, 9, 1, 12, 4, 16, 4); + + /* + * entry-2 is for ethernet IPv6 packets + */ + nlm_setup_l3ctable_even(nae_base, 2, 0, 1, 6, 1, 0x86dd); + /* l3off0 (6 bytes) -> l3len0 (1 byte) := next header (ip proto) + * l3off1 (8 bytes) -> l3len1 (16 bytes) := src ip + * l3off2 (24 bytes) -> l3len2 (16 bytes) := dst ip + */ + nlm_setup_l3ctable_odd(nae_base, 2, 6, 1, 8, 16, 24, 16); + + /* + * entry-3 is for ethernet ARP packets + */ + nlm_setup_l3ctable_even(nae_base, 3, 0, 0, 9, 1, 0x0806); + /* extract 30 bytes from packet start */ + nlm_setup_l3ctable_odd(nae_base, 3, 0, 30, 0, 0, 0, 0); + + /* + * entry-4 is for ethernet FCoE packets + */ + nlm_setup_l3ctable_even(nae_base, 4, 0, 0, 9, 1, 0x8906); + /* FCoE packet consists of 4 byte start-of-frame, + * and 24 bytes of frame header, followed by + * 64 bytes of optional-header (ESP, network..), + * 2048 bytes of payload, 36 bytes of optional + * "fill bytes" or ESP trailer, 4 bytes of CRC, + * and 4 bytes of end-of-frame + * We extract the first 4 + 24 = 28 bytes + */ + nlm_setup_l3ctable_odd(nae_base, 4, 0, 28, 0, 0, 0, 0); + + /* + * entry-5 is for vlan tagged frames (0x8100) + */ + nlm_setup_l3ctable_even(nae_base, 5, 0, 0, 9, 1, 0x8100); + /* we extract 31 bytes from the payload */ + nlm_setup_l3ctable_odd(nae_base, 5, 0, 31, 0, 0, 0, 0); + + /* + * entry-6 is for ieee 802.1ad provider bridging + * tagged frames (0x88a8) + */ + nlm_setup_l3ctable_even(nae_base, 6, 0, 0, 9, 1, 0x88a8); + /* we extract 31 bytes from the payload */ + nlm_setup_l3ctable_odd(nae_base, 6, 0, 31, 0, 0, 0, 0); + + /* + * entry-7 is for Cisco's Q-in-Q tagged frames (0x9100) + */ + nlm_setup_l3ctable_even(nae_base, 7, 0, 0, 9, 1, 0x9100); + /* we extract 31 bytes from the payload */ + nlm_setup_l3ctable_odd(nae_base, 7, 0, 31, 0, 0, 0, 0); + + /* + * entry-8 is for Ethernet Jumbo frames (0x8870) + */ + nlm_setup_l3ctable_even(nae_base, 8, 0, 0, 9, 1, 0x8870); + /* we extract 31 bytes from the payload */ + nlm_setup_l3ctable_odd(nae_base, 8, 0, 31, 0, 0, 0, 0); + + /* + * entry-9 is for MPLS Multicast frames (0x8848) + */ + nlm_setup_l3ctable_even(nae_base, 9, 0, 0, 9, 1, 0x8848); + /* we extract 31 bytes from the payload */ + nlm_setup_l3ctable_odd(nae_base, 9, 0, 31, 0, 0, 0, 0); + + /* + * entry-10 is for IEEE 802.1ae MAC Security frames (0x88e5) + */ + nlm_setup_l3ctable_even(nae_base, 10, 0, 0, 9, 1, 0x88e5); + /* we extract 31 bytes from the payload */ + nlm_setup_l3ctable_odd(nae_base, 10, 0, 31, 0, 0, 0, 0); + + /* + * entry-11 is for PTP frames (0x88f7) + */ + nlm_setup_l3ctable_even(nae_base, 11, 0, 0, 9, 1, 0x88f7); + /* PTP messages can be sent as UDP messages over + * IPv4 or IPv6; and as a raw ethernet message + * with ethertype 0x88f7. The message contents + * are the same for UDP or ethernet based encapsulations + * The header is 34 bytes long, and we extract + * it all out. + */ + nlm_setup_l3ctable_odd(nae_base, 11, 0, 31, 31, 2, 0, 0); + + /* + * entry-12 is for ethernet Link Control Protocol (LCP) + * used with PPPoE + */ + nlm_setup_l3ctable_even(nae_base, 12, 0, 0, 9, 1, 0xc021); + /* LCP packet consists of 1 byte of code, 1 byte of + * identifier and two bytes of length followed by + * data (upto length bytes). + * We extract 4 bytes from start of packet + */ + nlm_setup_l3ctable_odd(nae_base, 12, 0, 4, 0, 0, 0, 0); + + /* + * entry-13 is for ethernet Link Quality Report (0xc025) + * used with PPPoE + */ + nlm_setup_l3ctable_even(nae_base, 13, 0, 0, 9, 1, 0xc025); + /* We extract 31 bytes from packet start */ + nlm_setup_l3ctable_odd(nae_base, 13, 0, 31, 0, 0, 0, 0); + + /* + * entry-14 is for PPPoE Session (0x8864) + */ + nlm_setup_l3ctable_even(nae_base, 14, 0, 0, 9, 1, 0x8864); + /* We extract 31 bytes from packet start */ + nlm_setup_l3ctable_odd(nae_base, 14, 0, 31, 0, 0, 0, 0); + + /* + * entry-15 - default entry + */ + nlm_setup_l3ctable_even(nae_base, 15, 0, 0, 0, 0, 0x0000); + /* We extract 31 bytes from packet start */ + nlm_setup_l3ctable_odd(nae_base, 15, 0, 31, 0, 0, 0, 0); + + /*********************************************** + * program L4 CAM table + ***********************************************/ + + /* + * entry-0 - tcp packets (0x6) + */ + nlm_setup_l4ctable_even(nae_base, 0, 0, 0, 1, 0, 0, 0x6); + /* tcp header is 20 bytes without tcp options + * We extract 20 bytes from tcp start */ + nlm_setup_l4ctable_odd(nae_base, 0, 0, 15, 15, 5); + + /* + * entry-1 - udp packets (0x11) + */ + nlm_setup_l4ctable_even(nae_base, 1, 0, 0, 1, 0, 0, 0x11); + /* udp header is 8 bytes in size. + * We extract 8 bytes from udp start */ + nlm_setup_l4ctable_odd(nae_base, 1, 0, 8, 0, 0); + + /* + * entry-2 - sctp packets (0x84) + */ + nlm_setup_l4ctable_even(nae_base, 2, 0, 0, 1, 0, 0, 0x84); + /* sctp packets have a 12 byte generic header + * and various chunks. + * We extract 12 bytes from sctp start */ + nlm_setup_l4ctable_odd(nae_base, 2, 0, 12, 0, 0); + + /* + * entry-3 - RDP packets (0x1b) + */ + nlm_setup_l4ctable_even(nae_base, 3, 0, 0, 1, 0, 0, 0x1b); + /* RDP packets have 18 bytes of generic header + * before variable header starts. + * We extract 18 bytes from rdp start */ + nlm_setup_l4ctable_odd(nae_base, 3, 0, 15, 15, 3); + + /* + * entry-4 - DCCP packets (0x21) + */ + nlm_setup_l4ctable_even(nae_base, 4, 0, 0, 1, 0, 0, 0x21); + /* DCCP has two types of generic headers of + * sizes 16 bytes and 12 bytes if X = 1. + * We extract 16 bytes from dccp start */ + nlm_setup_l4ctable_odd(nae_base, 4, 0, 15, 15, 1); + + /* + * entry-5 - ipv6 encapsulated in ipv4 packets (0x29) + */ + nlm_setup_l4ctable_even(nae_base, 5, 0, 0, 1, 0, 0, 0x29); + /* ipv4 header is 20 bytes excluding IP options. + * We extract 20 bytes from IPv4 start */ + nlm_setup_l4ctable_odd(nae_base, 5, 0, 15, 15, 5); + + /* + * entry-6 - ip in ip encapsulation packets (0x04) + */ + nlm_setup_l4ctable_even(nae_base, 6, 0, 0, 1, 0, 0, 0x04); + /* ipv4 header is 20 bytes excluding IP options. + * We extract 20 bytes from ipv4 start */ + nlm_setup_l4ctable_odd(nae_base, 6, 0, 15, 15, 5); + + /* + * entry-7 - default entry (0x0) + */ + nlm_setup_l4ctable_even(nae_base, 7, 0, 0, 1, 0, 0, 0x0); + /* We extract 20 bytes from packet start */ + nlm_setup_l4ctable_odd(nae_base, 7, 0, 15, 15, 5); +} + +void +nlm_enable_hardware_parser_per_port(uint64_t nae_base, int block, int port) +{ + int hwport = (block * 4) + (port & 0x3); + + /* program L2 and L3 header extraction for each port */ + /* enable ethernet L2 mode on port */ + nlm_setup_l2type(nae_base, hwport, 0, 0, 0, 0, 0, 1); + + /* l2proto and ethtype included in l3cam */ + nlm_setup_l3ctable_mask(nae_base, hwport, 1, 0); +} + +void +nlm_prepad_enable(uint64_t nae_base, int size) +{ + uint32_t val; + + val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG); + val |= (1 << 13); /* prepad enable */ + val |= ((size & 0x3) << 22); /* prepad size */ + nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val); +} + +void +nlm_setup_1588_timer(uint64_t nae_base, struct nae_port_config *cfg) +{ + uint32_t hi, lo, val; + + hi = cfg[0].ieee1588_userval >> 32; + lo = cfg[0].ieee1588_userval & 0xffffffff; + nlm_write_nae_reg(nae_base, NAE_1588_PTP_USER_VALUE_HI, hi); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_USER_VALUE_LO, lo); + + hi = cfg[0].ieee1588_ptpoff >> 32; + lo = cfg[0].ieee1588_ptpoff & 0xffffffff; + nlm_write_nae_reg(nae_base, NAE_1588_PTP_OFFSET_HI, hi); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_OFFSET_LO, lo); + + hi = cfg[0].ieee1588_tmr1 >> 32; + lo = cfg[0].ieee1588_tmr1 & 0xffffffff; + nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR1_HI, hi); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR1_LO, lo); + + hi = cfg[0].ieee1588_tmr2 >> 32; + lo = cfg[0].ieee1588_tmr2 & 0xffffffff; + nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR2_HI, hi); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR2_LO, lo); + + hi = cfg[0].ieee1588_tmr3 >> 32; + lo = cfg[0].ieee1588_tmr3 & 0xffffffff; + nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR3_HI, hi); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_TMR3_LO, lo); + + nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_INTG, + cfg[0].ieee1588_inc_intg); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_NUM, + cfg[0].ieee1588_inc_num); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_INC_DEN, + cfg[0].ieee1588_inc_den); + + val = nlm_read_nae_reg(nae_base, NAE_1588_PTP_CONTROL); + /* set and clear freq_mul = 1 */ + nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val | (0x1 << 1)); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val); + /* set and clear load_user_val = 1 */ + nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val | (0x1 << 6)); + nlm_write_nae_reg(nae_base, NAE_1588_PTP_CONTROL, val); +} + +void +nlm_mac_enable(uint64_t nae_base, int nblock, int port_type, int port) +{ + uint32_t mac_cfg1, xaui_cfg; + uint32_t netwk_inf; + int iface = port & 0x3; + + switch(port_type) { + case SGMIIC: + netwk_inf = nlm_read_nae_reg(nae_base, + SGMII_NET_IFACE_CTRL(nblock, iface)); + nlm_write_nae_reg(nae_base, + SGMII_NET_IFACE_CTRL(nblock, iface), + netwk_inf | + (1 << 2)); /* enable tx */ + mac_cfg1 = nlm_read_nae_reg(nae_base, + SGMII_MAC_CONF1(nblock, iface)); + nlm_write_nae_reg(nae_base, + SGMII_MAC_CONF1(nblock, iface), + mac_cfg1 | + (1 << 2) | /* rx enable */ + 1); /* tx enable */ + break; + case XAUIC: + xaui_cfg = nlm_read_nae_reg(nae_base, + XAUI_CONFIG1(nblock)); + nlm_write_nae_reg(nae_base, + XAUI_CONFIG1(nblock), + xaui_cfg | + XAUI_CONFIG_TFEN | + XAUI_CONFIG_RFEN); + break; + case ILC: + break; + } +} + +void +nlm_mac_disable(uint64_t nae_base, int nblock, int port_type, int port) +{ + uint32_t mac_cfg1, xaui_cfg; + uint32_t netwk_inf; + int iface = port & 0x3; + + switch(port_type) { + case SGMIIC: + mac_cfg1 = nlm_read_nae_reg(nae_base, + SGMII_MAC_CONF1(nblock, iface)); + nlm_write_nae_reg(nae_base, + SGMII_MAC_CONF1(nblock, iface), + mac_cfg1 & + ~((1 << 2) | /* rx enable */ + 1)); /* tx enable */ + netwk_inf = nlm_read_nae_reg(nae_base, + SGMII_NET_IFACE_CTRL(nblock, iface)); + nlm_write_nae_reg(nae_base, + SGMII_NET_IFACE_CTRL(nblock, iface), + netwk_inf & + ~(1 << 2)); /* enable tx */ + break; + case XAUIC: + xaui_cfg = nlm_read_nae_reg(nae_base, + XAUI_CONFIG1(nblock)); + nlm_write_nae_reg(nae_base, + XAUI_CONFIG1(nblock), + xaui_cfg & + ~(XAUI_CONFIG_TFEN | + XAUI_CONFIG_RFEN)); + break; + case ILC: + break; + } +} + +/* + * Set IOR credits for the ports in ifmask to valmask + */ +static void +nlm_nae_set_ior_credit(uint64_t nae_base, uint32_t ifmask, uint32_t valmask) +{ + uint32_t tx_config, tx_ior_credit; + + tx_ior_credit = nlm_read_nae_reg(nae_base, NAE_TX_IORCRDT_INIT); + tx_ior_credit &= ~ifmask; + tx_ior_credit |= valmask; + nlm_write_nae_reg(nae_base, NAE_TX_IORCRDT_INIT, tx_ior_credit); + + tx_config = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG); + /* need to toggle these bits for credits to be loaded */ + nlm_write_nae_reg(nae_base, NAE_TX_CONFIG, + tx_config | (TXINITIORCR(ifmask))); + nlm_write_nae_reg(nae_base, NAE_TX_CONFIG, + tx_config & ~(TXINITIORCR(ifmask))); +} + +int +nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type, + int port, uint32_t desc_size) +{ + uint32_t netwk_inf; + uint32_t mac_cfg1, mac_cfg2, netior_ctrl3; + int iface, speed, duplex, ifmode; + int iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg; + + switch (port_type) { + case XAUIC: + netwk_inf = nlm_read_nae_reg(nae_base, + XAUI_NETIOR_XGMAC_CTRL1(nblock)); + netwk_inf |= (1 << NETIOR_XGMAC_STATS_CLR_POS); + nlm_write_nae_reg(nae_base, + XAUI_NETIOR_XGMAC_CTRL1(nblock), netwk_inf); + + nlm_nae_set_ior_credit(nae_base, 0xf << port, 0xf << port); + break; + + case ILC: + nlm_nae_set_ior_credit(nae_base, 0xff << port, 0xff << port); + break; + + case SGMIIC: + nlm_nae_set_ior_credit(nae_base, 0x1 << port, 0); + + /* + * XXXJC: split this and merge to sgmii.c + * some of this is duplicated from there. + */ + /* init phy id to access internal PCS */ + iface = port & 0x3; + iface_ctrl_reg = SGMII_NET_IFACE_CTRL(nblock, iface); + conf1_reg = SGMII_MAC_CONF1(nblock, iface); + conf2_reg = SGMII_MAC_CONF2(nblock, iface); + + netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg); + netwk_inf &= 0x7ffffff; + netwk_inf |= (port << 27); + nlm_write_nae_reg(nae_base, iface_ctrl_reg, netwk_inf); + + /* Sofreset sgmii port - set bit 11 to 0 */ + netwk_inf &= 0xfffff7ff; + nlm_write_nae_reg(nae_base, iface_ctrl_reg, netwk_inf); + + /* Reset Gmac */ + mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg); + nlm_write_nae_reg(nae_base, conf1_reg, + mac_cfg1 | + (1 << 31) | /* soft reset */ + (1 << 2) | /* rx enable */ + (1)); /* tx enable */ + + /* default to 1G */ + nlm_write_nae_reg(nae_base, + conf2_reg, + (0x7 << 12) | /* interface preamble length */ + (0x2 << 8) | /* interface mode */ + (0x1 << 2) | /* pad crc enable */ + (0x1)); /* full duplex */ + + /* clear gmac reset */ + mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg); + nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(1 << 31)); + /* clear speed debug bit */ + iface_ctrl3_reg = SGMII_NET_IFACE_CTRL3(nblock, iface); + netior_ctrl3 = nlm_read_nae_reg(nae_base, iface_ctrl3_reg); + nlm_write_nae_reg(nae_base, iface_ctrl3_reg, + netior_ctrl3 & ~(1 << 6)); + + /* disable TX, RX for now */ + mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg); + nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(0x5)); + netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg); + nlm_write_nae_reg(nae_base, iface_ctrl_reg, + netwk_inf & ~(0x1 << 2)); + + /* setup defaults */ /* XXXJC: take defaults from sc? */ + speed = 2; + duplex = 1; + ifmode = 0x2; + netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg); + netwk_inf &= ~(0x3); + nlm_write_nae_reg(nae_base, iface_ctrl_reg, + netwk_inf | (speed & 0x3)); + mac_cfg2 = nlm_read_nae_reg(nae_base, conf2_reg); + mac_cfg2 &= ~(0x3 << 8); + nlm_write_nae_reg(nae_base, conf2_reg, + mac_cfg2 | + ((ifmode & 0x3) << 8) | /* interface mode */ + (duplex & 0x1)); + + /* clear stats counters */ + netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg); + nlm_write_nae_reg(nae_base, iface_ctrl_reg, + netwk_inf | (1 << 15)); + /* enable stats counters */ + netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg); + nlm_write_nae_reg(nae_base, iface_ctrl_reg, + (netwk_inf & ~(1 << 15)) | (1 << 16)); + mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg); + nlm_write_nae_reg(nae_base, conf1_reg, + mac_cfg1 | (0x3 << 4)); + break; + } + + nlm_nae_init_ingress(nae_base, desc_size); + nlm_nae_init_egress(nae_base); + + return (0); +} diff --git a/sys/mips/nlm/dev/net/sgmii.c b/sys/mips/nlm/dev/net/sgmii.c new file mode 100644 index 0000000..91f5f7a --- /dev/null +++ b/sys/mips/nlm/dev/net/sgmii.c @@ -0,0 +1,216 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/systm.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/haldefs.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/nae.h> +#include <mips/nlm/hal/mdio.h> +#include <mips/nlm/hal/sgmii.h> + +void +nlm_configure_sgmii_interface(uint64_t nae_base, int block, int port, + int mtu, int loopback) +{ + uint32_t data1, data2; + + /* Apply a soft reset */ + data1 = (0x1 << 31); /* soft reset */ + if (loopback) + data1 |= (0x01 << 8); + data1 |= (0x01 << 2); /* Rx enable */ + data1 |= 0x01; /* Tx enable */ + nlm_write_nae_reg(nae_base, NAE_REG(block, port, MAC_CONF1), data1); + + data2 = (0x7 << 12) | /* pre-amble length=7 */ + (0x2 << 8) | /* byteMode */ + 0x1; /* fullDuplex */ + nlm_write_nae_reg(nae_base, NAE_REG(block, port, MAC_CONF2), data2); + + /* Remove a soft reset */ + data1 &= ~(0x01 << 31); + nlm_write_nae_reg(nae_base, NAE_REG(block, port, MAC_CONF1), data1); + + /* setup sgmii max frame length */ + nlm_write_nae_reg(nae_base, SGMII_MAX_FRAME(block, port), mtu); +} + +void +nlm_sgmii_pcs_init(uint64_t nae_base, uint32_t cplx_mask) +{ + /* reset internal MDIO */ + nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG); + + /* reset external MDIO */ + nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG); + nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG); + + xlp_nae_config_lane_gmac(nae_base, cplx_mask); +} + +void +nlm_nae_setup_mac(uint64_t nae_base, int nblock, int iface, int reset, + int rx_en, int tx_en, int speed, int duplex) +{ + uint32_t mac_cfg1, mac_cfg2, netwk_inf; + + mac_cfg1 = nlm_read_nae_reg(nae_base, + SGMII_MAC_CONF1(nblock,iface)); + mac_cfg2 = nlm_read_nae_reg(nae_base, + SGMII_MAC_CONF2(nblock,iface)); + netwk_inf = nlm_read_nae_reg(nae_base, + SGMII_NET_IFACE_CTRL(nblock, iface)); + + mac_cfg1 &= ~(0x1 << 31); /* remove reset */ + mac_cfg1 &= ~(0x1 << 2); /* remove rx */ + mac_cfg1 &= ~(0x1); /* remove tx */ + mac_cfg2 &= ~(0x3 << 8); /* remove interface mode bits */ + mac_cfg2 &= ~(0x1); /* remove duplex */ + netwk_inf &= ~(0x1 << 2); /* remove tx */ + netwk_inf &= ~(0x3); /* remove speed */ + + switch (speed) { + case NLM_SGMII_SPEED_10: + netwk_inf |= 0x0; /* 2.5 Mhz clock for 10 Mbps */ + mac_cfg2 |= (0x1 << 8); /* enable 10/100 Mbps */ + break; + case NLM_SGMII_SPEED_100: + netwk_inf |= 0x1; /* 25 Mhz clock for 100 Mbps */ + mac_cfg2 |= (0x1 << 8); /* enable 10/100 Mbps */ + break; + default: /* make it as 1G */ + netwk_inf |= 0x2; /* 125 Mhz clock for 1G */ + mac_cfg2 |= (0x2 << 8); /* enable 1G */ + break; + } + + if (reset) + mac_cfg1 |= (0x1 << 31); /* set reset */ + + if (rx_en) + mac_cfg1 |= (0x1 << 2); /* set rx */ + + nlm_write_nae_reg(nae_base, + SGMII_NET_IFACE_CTRL(nblock, iface), + netwk_inf); + + if (tx_en) { + mac_cfg1 |= 0x1; /* set tx */ + netwk_inf |= (0x1 << 2); /* set tx */ + } + + switch (duplex) { + case NLM_SGMII_DUPLEX_HALF: + /* duplexity is already set to half duplex */ + break; + default: + mac_cfg2 |= 0x1; /* set full duplex */ + } + + nlm_write_nae_reg(nae_base, SGMII_MAC_CONF1(nblock, iface), mac_cfg1); + nlm_write_nae_reg(nae_base, SGMII_MAC_CONF2(nblock, iface), mac_cfg2); + nlm_write_nae_reg(nae_base, SGMII_NET_IFACE_CTRL(nblock, iface), + netwk_inf); +} + +void +nlm_nae_setup_rx_mode_sgmii(uint64_t base, int nblock, int iface, int port_type, + int broadcast_en, int multicast_en, int pause_en, int promisc_en) +{ + uint32_t val; + + /* bit[17] of vlan_typefilter - allows packet matching in MAC. + * When DA filtering is disabled, this bit and bit[16] should + * be zero. + * bit[16] of vlan_typefilter - Allows hash matching to be used + * for DA filtering. When DA filtering is disabled, this bit and + * bit[17] should be zero. + * Both bits have to be set only if you want to turn on both + * features / modes. + */ + if (promisc_en == 1) { + val = nlm_read_nae_reg(base, + SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface)); + val &= (~(0x3 << 16)); + nlm_write_nae_reg(base, + SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface), val); + } else { + val = nlm_read_nae_reg(base, + SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface)); + val |= (0x1 << 17); + nlm_write_nae_reg(base, + SGMII_NETIOR_VLANTYPE_FILTER(nblock, iface), val); + } + + val = ((broadcast_en & 0x1) << 10) | + ((pause_en & 0x1) << 9) | + ((multicast_en & 0x1) << 8) | + ((promisc_en & 0x1) << 7) | /* unicast_enable - enables promisc mode */ + 1; /* MAC address is always valid */ + + nlm_write_nae_reg(base, SGMII_MAC_FILTER_CONFIG(nblock, iface), val); + +} + +void +nlm_nae_setup_mac_addr_sgmii(uint64_t base, int nblock, int iface, + int port_type, uint8_t *mac_addr) +{ + nlm_write_nae_reg(base, + SGMII_MAC_ADDR0_LO(nblock, iface), + (mac_addr[5] << 24) | + (mac_addr[4] << 16) | + (mac_addr[3] << 8) | + mac_addr[2]); + + nlm_write_nae_reg(base, + SGMII_MAC_ADDR0_HI(nblock, iface), + (mac_addr[1] << 24) | + (mac_addr[0] << 16)); + + nlm_write_nae_reg(base, + SGMII_MAC_ADDR_MASK0_LO(nblock, iface), + 0xffffffff); + nlm_write_nae_reg(base, + SGMII_MAC_ADDR_MASK0_HI(nblock, iface), + 0xffffffff); + + nlm_nae_setup_rx_mode_sgmii(base, nblock, iface, + SGMIIC, + 1, /* broadcast enabled */ + 1, /* multicast enabled */ + 0, /* do not accept pause frames */ + 0 /* promisc mode disabled */ + ); +} diff --git a/sys/mips/nlm/dev/net/ucore/crt0_basic.S b/sys/mips/nlm/dev/net/ucore/crt0_basic.S new file mode 100644 index 0000000..79f8f4b --- /dev/null +++ b/sys/mips/nlm/dev/net/ucore/crt0_basic.S @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <machine/asm.h> + + .text + .align 2 + .globl _start + .ent _start +_start: + .set noreorder + la gp, _gp + .end _start + + .globl __stack + + .ent zerobss +zerobss: + la v0, _fbss + la v1, _end +3: + sw zero, 0(v0) + bltu v0,v1,3b + addiu v0,v0,4 # executed in delay slot + la sp, __stack # set stack pointer + .end zerobss + + .ent init +init: + addiu a1,sp,32 # argv = sp + 32 + addiu a2,sp,40 # envp = sp + 40 + sw zero,(a1) # argv[argc] = 0 + sw zero,(a2) # envp[0] = 0 + jal main # call the program start function + move a0,zero # set argc to 0 +1: b 1b + nop + .end init + diff --git a/sys/mips/nlm/dev/net/ucore/ld.ucore.S b/sys/mips/nlm/dev/net/ucore/ld.ucore.S new file mode 100644 index 0000000..aff83b8 --- /dev/null +++ b/sys/mips/nlm/dev/net/ucore/ld.ucore.S @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +ENTRY(_start) +OUTPUT_FORMAT(elf32-tradbigmips) +__DYNAMIC = 0; + +SECTIONS +{ + . = 0x0; + _loadaddr = . ; + + /* ----------------------------------------- */ + + .text : { + _ftext = . ; + PROVIDE (eprol = .); + _shim_reg = . ; + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + } + .init : { + KEEP(*(.init)) + *(.init) + } + .fini : { + *(.fini) + } + .rel.sdata : { + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + } + PROVIDE (etext = .); + .ctors : + { + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + . = .; + .rodata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + . = . + (0x1000 - .) ; + + /* ----------------------------------------- */ + + . = 0x8000 ; + magicstart = . ; + .magicregs : { + *(.magicregs) + } + magicend = . ; + + /* ----------------------------------------- */ + + . = 0x18000 ; + shmemstart = . ; + .sharedmem : { + *(.sharedmem) + } + shmemend = . ; + + /* ----------------------------------------- */ + + . = 0xFF800 ; + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + } + . = ALIGN(8); + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + . = ALIGN (8); + PROVIDE (edata = .); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(COMMON) + } + _bss_end = . ; + _end = .; + + _gp = . ; + __global = _gp ; + . = ALIGN (8); + + PROVIDE(__stackmarker = .) ; + + . = 0xFFA00 ; + + /* 32 + 4(argc) + 4(argv), aligned to 64 */ + PROVIDE(__stack = . - 64); + + /* ----------------------------------------- */ + + . = 0xFFE00 ; + .pktbuf : { + *(.pktbuf) + } + . = . + (0x100000 - .) ; + + PROVIDE(_endaddr = 0x0 + 0x100000); +} diff --git a/sys/mips/nlm/dev/net/ucore/ucore.h b/sys/mips/nlm/dev/net/ucore/ucore.h new file mode 100644 index 0000000..cd3b6bc --- /dev/null +++ b/sys/mips/nlm/dev/net/ucore/ucore.h @@ -0,0 +1,356 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __NLM_UCORE_H__ +#define __NLM_UCORE_H__ + +/* Microcode registers */ +#define UCORE_OUTBUF_DONE 0x8000 +#define UCORE_RX_PKT_RDY 0x8004 +#define UCORE_RX_PKT_INFO 0x8008 +#define UCORE_CAM0 0x800c +#define UCORE_CAM1 0x8010 +#define UCORE_CAM2 0x8014 +#define UCORE_CAM3 0x8018 +#define UCORE_CAM_RESULT 0x801c +#define UCORE_CSUMINFO 0x8020 +#define UCORE_CRCINFO 0x8024 +#define UCORE_CRCPOS 0x8028 +#define UCORE_FR_FIFOEMPTY 0x802c +#define UCORE_PKT_DISTR 0x8030 + +#define PACKET_MEMORY (0xFFE00) +#define PACKET_DATA_OFFSET (64) +#define SHARED_SCRATCH_MEM 0x18000 + +/* Distribution mode */ +#define VAL_PDM(x) (((x) & 0x7) << 0) + +/* Dest distribution or distribution list */ +#define VAL_DEST(x) (((x) & 0x3ff) << 8) +#define VAL_PDL(x) (((x) & 0xf) << 4) + +/*output buffer done*/ +#define VAL_FSV(x) (x<<19) +#define VAL_FFS(x) (x<<14) + +#define FWD_DEST_ONLY 1 +#define FWD_ENQ_DIST_VEC 2 +#define FWD_ENQ_DEST 3 +#define FWD_DIST_VEC 4 +#define FWD_ENQ_DIST_VEC_SER 6 +#define FWD_ENQ_DEST_SER 7 + +#define USE_HASH_DST (1 << 20) + + +#define NLM_DEFINE_UCORE(name, reg) \ +static __inline__ unsigned int nlm_read_ucore_##name(void) \ +{ \ + unsigned int __rv; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips32\n" \ + "li $8, %1\n" \ + "lw %0, ($8)\n" \ + ".set pop\n" \ + : "=r" (__rv) \ + : "i" (reg) \ + : "$8" \ + ); \ + return __rv; \ +} \ + \ +static __inline__ void nlm_write_ucore_##name(unsigned int val) \ +{ \ + __asm__ __volatile__( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips32\n" \ + "li $8, %1\n" \ + "sw %0, ($8)\n" \ + ".set pop\n" \ + :: "r" (val), "i" (reg) \ + : "$8" \ + ); \ +} struct __hack + + +NLM_DEFINE_UCORE(obufdone, UCORE_OUTBUF_DONE); +NLM_DEFINE_UCORE(rxpktrdy, UCORE_RX_PKT_RDY); +NLM_DEFINE_UCORE(rxpktinfo, UCORE_RX_PKT_INFO); +NLM_DEFINE_UCORE(cam0, UCORE_CAM0); +NLM_DEFINE_UCORE(cam1, UCORE_CAM1); +NLM_DEFINE_UCORE(cam2, UCORE_CAM2); +NLM_DEFINE_UCORE(cam3, UCORE_CAM3); +NLM_DEFINE_UCORE(camresult, UCORE_CAM_RESULT); +NLM_DEFINE_UCORE(csuminfo, UCORE_CSUMINFO); +NLM_DEFINE_UCORE(crcinfo, UCORE_CRCINFO); +NLM_DEFINE_UCORE(crcpos, UCORE_CRCPOS); +NLM_DEFINE_UCORE(freefifo_empty, UCORE_FR_FIFOEMPTY); +NLM_DEFINE_UCORE(pktdistr, UCORE_PKT_DISTR); + +/* + * l3cachelines - number of cache lines to allocate into l3 + * fsv - 0 : use interface-id for selecting the free fifo pool + * 1 : use free fifo pool selected by FFS field + * ffs - selects which free fifo pool to use to take a free fifo + * prepad_en - If this field is set to 1, part or all of the + * 64 byte prepad seen by micro engines, is written + * infront of every packet. + * prepad_ovride - If this field is 1, the ucore system uses + * prepad configuration defined in this register, + * 0 means that it uses the configuration defined + * in NAE RX_CONFIG register + * prepad_size - number of 16 byte words in the 64-byte prepad + * seen by micro engines and dma'ed to memory as + * pkt prepad. This field is meaningful only if + * prepad_en and prepad_ovride is set. + * 0 : 1 word + * 1 : 2 words + * 2 : 3 words + * 3 : 4 words + * prepad[0-3]: writing 0 to this means that the 1st 16 byte offset + * of prepad in micro engine, gets setup as prepad0/1/2/3. + * prepad word. + * 1 : means 2nd 16 byte chunk in prepad0/1/2/3 + * 2 : means 3rd 16 byte chunk in prepad0/1/2/3 + * 3 : means 4rth 16 byte chunk in prepad0/1/2/3 + * pkt_discard - packet will be discarded if this is set to 1 + * rd5 - value (single bit) to be inserted in bit 5, the unclassified + * pkt bit of receive descriptor. If this bit is set, HPRE bit + * should also be set in ucore_rxpktready register + */ +static __inline__ void +nlm_ucore_pkt_done(int l3cachelines, int fsv, int ffs, int prepad_en, + int prepad_ovride, int prepad_size, int prepad0, int prepad1, + int prepad2, int prepad3, int pkt_discard, int rd5) +{ + unsigned int val = 0; + + val |= ((l3cachelines & 0xfff) << 20); + val |= ((fsv & 0x1) << 19); + val |= ((ffs & 0x1f) << 14); + val |= ((prepad_en & 0x1) << 3); + val |= ((prepad_ovride & 0x1) << 2); + val |= ((prepad_size & 0x3) << 12); + val |= ((prepad0 & 0x3) << 4); + val |= ((prepad1 & 0x3) << 6); + val |= ((prepad2 & 0x3) << 8); + val |= ((prepad3 & 0x3) << 10); + val |= ((pkt_discard & 0x1) << 1); + val |= ((rd5 & 0x1) << 0); + + nlm_write_ucore_obufdone(val); +} + +/* Get the class full vector field from POE. + * The POE maintains a threshold for each class. + * A bit in this field will be set corresponding to the class approaching + * class full status. + */ +static __inline__ int +nlm_ucore_get_rxpkt_poeclassfullvec(unsigned int pktrdy) +{ + return ((pktrdy >> 24) & 0xff); +} + +/* This function returns 1 if the hardware parser extraction process + * resulted in an error. Else, returns 0. + */ +static __inline__ int +nlm_ucore_get_rxpkt_hwparsererr(unsigned int pktrdy) +{ + return ((pktrdy >> 23) & 0x1); +} + +/* This function returns the context number assigned to incoming + * packet + */ +static __inline__ int +nlm_ucore_get_rxpkt_context(unsigned int pktrdy) +{ + return ((pktrdy >> 13) & 0x3ff); +} + +/* this function returns the channel number of incoming packet, + * and applies only to interlaken. + */ +static __inline__ int +nlm_ucore_get_rxpkt_channel(unsigned int pktrdy) +{ + return ((pktrdy >> 5) & 0xff); +} + +/* This function returns the interface number on which the pkt + * was received + */ +static __inline__ int +nlm_ucore_get_rxpkt_interface(unsigned int pktrdy) +{ + return (pktrdy & 0x1f); +} + +/* This function returns 1 if end of packet (EOP) is set in + * packet data. + */ +static __inline__ int +nlm_ucore_get_rxpkt_eop(unsigned int rxpkt_info) +{ + return ((rxpkt_info >> 9) & 0x1); +} + +/* This function returns packet length of received pkt */ +static __inline__ int +nlm_ucore_get_rxpktlen(unsigned int rxpkt_info) +{ + return (rxpkt_info & 0x1ff); +} + +/* this function sets up the ucore TCAM keys. */ +static __inline__ void +nlm_ucore_setup_camkey(unsigned int cam_key0, unsigned int cam_key1, + unsigned int cam_key2, unsigned int cam_key3) +{ + nlm_write_ucore_cam0(cam_key0); + nlm_write_ucore_cam1(cam_key1); + nlm_write_ucore_cam2(cam_key2); + nlm_write_ucore_cam3(cam_key3); +} + +/* This function checks if the cam result is valid or not. + * If valid, it returns the result, else it returns 0. + */ +static __inline__ int +nlm_ucore_get_cam_result(unsigned int cam_result) +{ + if (((cam_result >> 15) & 0x1) == 1) /* valid result */ + return (cam_result & 0x3fff); + + return 0; +} + +/* This function sets up the csum in ucore. + * iphdr_start - defines the start of ip header (to check - is this byte + * position???) + * iphdr_len - This field is auto filled by h/w parser if zero, else + * the value defined will be used. + */ +static __inline__ void +nlm_ucore_csum_setup(int iphdr_start, int iphdr_len) +{ + unsigned int val = 0; + + val |= ((iphdr_len & 0xff) << 8); + val |= (iphdr_len & 0xff); + nlm_write_ucore_csuminfo(val); +} + +/* crcpos - position of crc in pkt. If crc position is within startcrc and + * endcrc, zero out these bytes in the packet before computing crc. This + * field is not needed for FCoE. + * cps - If 1, uses the polynomial in RX_CRC_POLY1 of NAE register. + * if 0, uses the polynomial in RX_CRC_POLY0 of NAE register. + * fcoe - If this is 1, crc calculation starts from 'startCRC' and the CRC + * engine ends calculation before the last byte. + * cbm - if 1, enables crc byte mirroring, where bits within a byte will get + * reversed (mirrored) during calculation of crc. + * cfi - If 1, performs a final inversion of crc before comarison is done during + * pkt reception. + * startcrc - This field is always required for both FCoE and SCTP crc. + * endcrc - This information needs to be setup only for SCTP. For FCoE this + * information is provided by hardware. + * valid - if set to 1, CRC status is placed into bit 2 of rx descriptor + * if set to 0, TCP checksum status is placed into bit 2 of rx descriptor + * keysize - defines the number of bytes in the pre-pad that contains the key + */ +static __inline__ void +nlm_ucore_crc_setup(int crcpos, int cps, int cfi, int cbm, int fcoe, + int keysize, int valid, int startcrc, int endcrc) +{ + unsigned int val = 0; + + val |= ((cfi & 0x1) << 20); + val |= ((cbm & 0x1) << 19); + val |= ((fcoe & 0x1) << 18); + val |= ((cps & 0x1) << 16); + val |= (crcpos & 0xffff); + + nlm_write_ucore_crcpos(val); + + val = 0; + val |= ((keysize & 0x3f) << 25); + val |= ((valid & 0x1) << 24); + val |= ((endcrc & 0xffff) << 8); + val |= (startcrc & 0xff); + + nlm_write_ucore_crcinfo(val); +} + +/* This function returns a fifo empty vector, where each bit provides + * the status of a fifo pool, where if the pool is empty the bit gets + * set to 1. + */ +static __inline__ int +nlm_ucore_get_fifoempty(unsigned int fifoempty) +{ + return (fifoempty & 0xfffff); +} + +/* This function controls how POE will distribute the packet. + * pdm - is the packet distribution mode, where + * 0x0 - means packet distribution mode is not used + * 0x1 - means forwarding based on destination only (no enqueue) + * 0x2 - means forwarding based on FID and distr vector (enqueue) + * 0x3 - means forwarding based on dest and FID (enqueue) + * 0x4 - means forwarding based on distr vec (no enqueue) + * 0x6 - means forward based on FID (enqueue), distr vec and serial mode + * 0x7 - means forward based on FID (enqueue), dest and serial mode + * mc3 - If 1, then the 3 most significant bits of distribution list are taken + * from context->class_table + * pdl - poe distribution list + * dest - fixed destination setup + * hash - if 1, use hash based destination + */ +static __inline__ void +nlm_ucore_setup_poepktdistr(int pdm, int mc3, int pdl, int dest, int hash) +{ + unsigned int val = 0; + + val |= ((hash & 0x1) << 20); + val |= ((dest & 0xfff) << 8); + val |= ((pdl & 0xf) << 4); + val |= ((mc3 & 0x1) << 3); + val |= (pdm & 0x7); + + nlm_write_ucore_pktdistr(val); +} + +#endif diff --git a/sys/mips/nlm/dev/net/ucore/ucore_app.c b/sys/mips/nlm/dev/net/ucore/ucore_app.c new file mode 100644 index 0000000..57135e8 --- /dev/null +++ b/sys/mips/nlm/dev/net/ucore/ucore_app.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "ucore.h" + +int main(void) +{ +#if 0 + volatile unsigned int *pkt = + (volatile unsigned int *) (PACKET_MEMORY + PACKET_DATA_OFFSET); + int intf, hw_parser_error, context; +#endif + unsigned int pktrdy; + int num_cachelines = 1518 >> 6; /* pktsize / L3 cacheline size */ + + + /* Spray packets to using distribution vector */ + while (1) { + pktrdy = nlm_read_ucore_rxpktrdy(); +#if 0 + intf = pktrdy & 0x1f; + context = (pktrdy >> 13) & 0x3ff; + hw_parser_error = (pktrdy >> 23) & 0x1; +#endif + nlm_ucore_setup_poepktdistr(FWD_DIST_VEC, 0, 0, 0, 0); + nlm_ucore_pkt_done(num_cachelines, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0); + } + + return (0); +} diff --git a/sys/mips/nlm/dev/net/xaui.c b/sys/mips/nlm/dev/net/xaui.c new file mode 100644 index 0000000..8b4c6a9 --- /dev/null +++ b/sys/mips/nlm/dev/net/xaui.c @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/systm.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/haldefs.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/nae.h> +#include <mips/nlm/hal/mdio.h> +#include <mips/nlm/hal/sgmii.h> +#include <mips/nlm/hal/xaui.h> + +#include <mips/nlm/xlp.h> +void +nlm_xaui_pcs_init(uint64_t nae_base, int xaui_cplx_mask) +{ + int block, lane_ctrl, reg; + int cplx_lane_enable; + int lane_enable = 0; + uint32_t regval; + + cplx_lane_enable = LM_XAUI | + (LM_XAUI << 4) | + (LM_XAUI << 8) | + (LM_XAUI << 12); + + if (xaui_cplx_mask == 0) + return; + + /* write 0x2 to enable SGMII for all lane */ + block = 7; + + if (xaui_cplx_mask & 0x3) { /* Complexes 0, 1 */ + lane_enable = nlm_read_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1)); + if (xaui_cplx_mask & 0x1) { /* Complex 0 */ + lane_enable &= ~(0xFFFF); + lane_enable |= cplx_lane_enable; + } + if (xaui_cplx_mask & 0x2) { /* Complex 1 */ + lane_enable &= ~(0xFFFF<<16); + lane_enable |= (cplx_lane_enable << 16); + } + nlm_write_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1), + lane_enable); + } + lane_enable = 0; + if (xaui_cplx_mask & 0xc) { /* Complexes 2, 3 */ + lane_enable = nlm_read_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3)); + if (xaui_cplx_mask & 0x4) { /* Complex 2 */ + lane_enable &= ~(0xFFFF); + lane_enable |= cplx_lane_enable; + } + if (xaui_cplx_mask & 0x8) { /* Complex 3 */ + lane_enable &= ~(0xFFFF<<16); + lane_enable |= (cplx_lane_enable << 16); + } + nlm_write_nae_reg(nae_base, + NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3), + lane_enable); + } + + /* Bring txpll out of reset */ + for (block = 0; block < 4; block++) { + if ((xaui_cplx_mask & (1 << block)) == 0) + continue; + + for (lane_ctrl = PHY_LANE_0_CTRL; + lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { + if (!nlm_is_xlp8xx_ax()) + xlp_nae_lane_reset_txpll(nae_base, + block, lane_ctrl, PHYMODE_XAUI); + else + xlp_ax_nae_lane_reset_txpll(nae_base, block, + lane_ctrl, PHYMODE_XAUI); + } + } + + /* Wait for Rx & TX clock stable */ + for (block = 0; block < 4; block++) { + if ((xaui_cplx_mask & (1 << block)) == 0) + continue; + + for (lane_ctrl = PHY_LANE_0_CTRL; + lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { + + reg = NAE_REG(block, PHY, lane_ctrl - 4); + /* Wait for TX clock to be set */ + do { + regval = nlm_read_nae_reg(nae_base, reg); + } while ((regval & LANE_TX_CLK) == 0); + + /* Wait for RX clock to be set */ + do { + regval = nlm_read_nae_reg(nae_base, reg); + } while ((regval & LANE_RX_CLK) == 0); + + /* Wait for XAUI Lane fault to be cleared */ + do { + regval = nlm_read_nae_reg(nae_base, reg); + } while ((regval & XAUI_LANE_FAULT) != 0); + } + } +} + +void +nlm_nae_setup_rx_mode_xaui(uint64_t base, int nblock, int iface, int port_type, + int broadcast_en, int multicast_en, int pause_en, int promisc_en) +{ + uint32_t val; + + val = ((broadcast_en & 0x1) << 10) | + ((pause_en & 0x1) << 9) | + ((multicast_en & 0x1) << 8) | + ((promisc_en & 0x1) << 7) | /* unicast_enable - enables promisc mode */ + 1; /* MAC address is always valid */ + + nlm_write_nae_reg(base, XAUI_MAC_FILTER_CFG(nblock), val); +} + +void +nlm_nae_setup_mac_addr_xaui(uint64_t base, int nblock, int iface, + int port_type, unsigned char *mac_addr) +{ + nlm_write_nae_reg(base, + XAUI_MAC_ADDR0_LO(nblock), + (mac_addr[5] << 24) | + (mac_addr[4] << 16) | + (mac_addr[3] << 8) | + mac_addr[2]); + + nlm_write_nae_reg(base, + XAUI_MAC_ADDR0_HI(nblock), + (mac_addr[1] << 24) | + (mac_addr[0] << 16)); + + nlm_write_nae_reg(base, + XAUI_MAC_ADDR_MASK0_LO(nblock), + 0xffffffff); + nlm_write_nae_reg(base, + XAUI_MAC_ADDR_MASK0_HI(nblock), + 0xffffffff); + + nlm_nae_setup_rx_mode_xaui(base, nblock, iface, + XAUIC, + 1, /* broadcast enabled */ + 1, /* multicast enabled */ + 0, /* do not accept pause frames */ + 0 /* promisc mode disabled */ + ); +} + +void +nlm_config_xaui_mtu(uint64_t nae_base, int nblock, + int max_tx_frame_sz, int max_rx_frame_sz) +{ + uint32_t tx_words = max_tx_frame_sz >> 2; /* max_tx_frame_sz / 4 */ + + /* write max frame length */ + nlm_write_nae_reg(nae_base, + XAUI_MAX_FRAME_LEN(nblock), + ((tx_words & 0x3ff) << 16) | (max_rx_frame_sz & 0xffff)); +} + +void +nlm_config_xaui(uint64_t nae_base, int nblock, + int max_tx_frame_sz, int max_rx_frame_sz, int vlan_pri_en) +{ + uint32_t val; + + val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); + val &= ~(0x1 << 11); /* clear soft reset */ + nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); + + val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); + val &= ~(0x3 << 11); /* clear soft reset and hard reset */ + nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); + nlm_write_nae_reg(nae_base, XAUI_CONFIG0(nblock), 0xffffffff); + nlm_write_nae_reg(nae_base, XAUI_CONFIG0(nblock), 0); + + /* Enable tx/rx frame */ + val = 0xF00010A8; + val |= XAUI_CONFIG_LENCHK; + val |= XAUI_CONFIG_GENFCS; + val |= XAUI_CONFIG_PAD_64; + val |= XAUI_CONFIG_TFEN; + val |= XAUI_CONFIG_RFEN; + nlm_write_nae_reg(nae_base, XAUI_CONFIG1(nblock), val); + + /* write max frame length */ + nlm_config_xaui_mtu(nae_base, nblock, max_tx_frame_sz, + max_rx_frame_sz); + + /* set stats counter */ + val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock)); + val |= (0x1 << NETIOR_XGMAC_VLAN_DC_POS); + val |= (0x1 << NETIOR_XGMAC_STATS_EN_POS); + if (vlan_pri_en) { + val |= (0x1 << NETIOR_XGMAC_TX_PFC_EN_POS); + val |= (0x1 << NETIOR_XGMAC_RX_PFC_EN_POS); + val |= (0x1 << NETIOR_XGMAC_TX_PAUSE_POS); + } else { + val &= ~(0x1 << NETIOR_XGMAC_TX_PFC_EN_POS); + val |= (0x1 << NETIOR_XGMAC_TX_PAUSE_POS); + } + nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL1(nblock), val); + /* configure on / off timer */ + if (vlan_pri_en) + val = 0xF1230000; /* PFC mode, offtimer = 0xf123, ontimer = 0 */ + else + val = 0x0000F123; /* link level FC mode, offtimer = 0xf123 */ + nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL2(nblock), val); + + /* set xaui tx threshold */ + val = nlm_read_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL3(nblock)); + val &= ~(0x1f << 10); + val |= ~(15 << 10); + nlm_write_nae_reg(nae_base, XAUI_NETIOR_XGMAC_CTRL3(nblock), val); +} diff --git a/sys/mips/nlm/dev/net/xlpge.c b/sys/mips/nlm/dev/net/xlpge.c new file mode 100644 index 0000000..3af802e --- /dev/null +++ b/sys/mips/nlm/dev/net/xlpge.c @@ -0,0 +1,1574 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/endian.h> +#include <sys/systm.h> +#include <sys/sockio.h> +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/limits.h> +#include <sys/bus.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/socket.h> +#define __RMAN_RESOURCE_VISIBLE +#include <sys/rman.h> +#include <sys/taskqueue.h> + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/bpf.h> +#include <net/if_types.h> +#include <net/if_vlan_var.h> + +#include <dev/pci/pcivar.h> + +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/uma.h> + +#include <machine/reg.h> +#include <machine/cpu.h> +#include <machine/mips_opcode.h> +#include <machine/asm.h> +#include <machine/cpuregs.h> + +#include <machine/param.h> +#include <machine/intr_machdep.h> +#include <machine/clock.h> /* for DELAY */ +#include <machine/bus.h> +#include <machine/resource.h> +#include <mips/nlm/hal/haldefs.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/cop2.h> +#include <mips/nlm/hal/fmn.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/nae.h> +#include <mips/nlm/hal/mdio.h> +#include <mips/nlm/hal/sgmii.h> +#include <mips/nlm/hal/xaui.h> +#include <mips/nlm/hal/poe.h> +#include <ucore_app_bin.h> +#include <mips/nlm/hal/ucore_loader.h> +#include <mips/nlm/xlp.h> +#include <mips/nlm/board.h> +#include <mips/nlm/msgring.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> +#include "miidevs.h" +#include <dev/mii/brgphyreg.h> +#include "miibus_if.h" +#include <sys/sysctl.h> + +#include <mips/nlm/dev/net/xlpge.h> + +/*#define XLP_DRIVER_LOOPBACK*/ + +static struct nae_port_config nae_port_config[64]; + +int poe_cl_tbl[MAX_POE_CLASSES] = { + 0x0, 0x249249, + 0x492492, 0x6db6db, + 0x924924, 0xb6db6d, + 0xdb6db6, 0xffffff +}; + +/* #define DUMP_PACKET */ + +static uint64_t +nlm_paddr_ld(uint64_t paddr) +{ + uint64_t xkaddr = 0x9800000000000000 | paddr; + + return (nlm_load_dword_daddr(xkaddr)); +} + +struct nlm_xlp_portdata ifp_ports[64]; +static uma_zone_t nl_tx_desc_zone; + +/* This implementation will register the following tree of device + * registration: + * pcibus + * | + * xlpnae (1 instance - virtual entity) + * | + * xlpge + * (18 sgmii / 4 xaui / 2 interlaken instances) + * | + * miibus + */ + +static int nlm_xlpnae_probe(device_t); +static int nlm_xlpnae_attach(device_t); +static int nlm_xlpnae_detach(device_t); +static int nlm_xlpnae_suspend(device_t); +static int nlm_xlpnae_resume(device_t); +static int nlm_xlpnae_shutdown(device_t); + +static device_method_t nlm_xlpnae_methods[] = { + /* Methods from the device interface */ + DEVMETHOD(device_probe, nlm_xlpnae_probe), + DEVMETHOD(device_attach, nlm_xlpnae_attach), + DEVMETHOD(device_detach, nlm_xlpnae_detach), + DEVMETHOD(device_suspend, nlm_xlpnae_suspend), + DEVMETHOD(device_resume, nlm_xlpnae_resume), + DEVMETHOD(device_shutdown, nlm_xlpnae_shutdown), + + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + DEVMETHOD_END +}; + +static driver_t nlm_xlpnae_driver = { + "xlpnae", + nlm_xlpnae_methods, + sizeof(struct nlm_xlpnae_softc) +}; + +static devclass_t nlm_xlpnae_devclass; + +static int nlm_xlpge_probe(device_t); +static int nlm_xlpge_attach(device_t); +static int nlm_xlpge_detach(device_t); +static int nlm_xlpge_suspend(device_t); +static int nlm_xlpge_resume(device_t); +static int nlm_xlpge_shutdown(device_t); + +/* mii override functions */ +static int nlm_xlpge_mii_read(struct device *, int, int); +static int nlm_xlpge_mii_write(struct device *, int, int, int); +static void nlm_xlpge_mii_statchg(device_t); + +static device_method_t nlm_xlpge_methods[] = { + /* Methods from the device interface */ + DEVMETHOD(device_probe, nlm_xlpge_probe), + DEVMETHOD(device_attach, nlm_xlpge_attach), + DEVMETHOD(device_detach, nlm_xlpge_detach), + DEVMETHOD(device_suspend, nlm_xlpge_suspend), + DEVMETHOD(device_resume, nlm_xlpge_resume), + DEVMETHOD(device_shutdown, nlm_xlpge_shutdown), + + /* Methods from the nexus bus needed for explicitly + * probing children when driver is loaded as a kernel module + */ + DEVMETHOD(miibus_readreg, nlm_xlpge_mii_read), + DEVMETHOD(miibus_writereg, nlm_xlpge_mii_write), + DEVMETHOD(miibus_statchg, nlm_xlpge_mii_statchg), + + /* Terminate method list */ + DEVMETHOD_END +}; + +static driver_t nlm_xlpge_driver = { + "xlpge", + nlm_xlpge_methods, + sizeof(struct nlm_xlpge_softc) +}; + +static devclass_t nlm_xlpge_devclass; + +DRIVER_MODULE(xlpnae, pci, nlm_xlpnae_driver, nlm_xlpnae_devclass, 0, 0); +DRIVER_MODULE(xlpge, xlpnae, nlm_xlpge_driver, nlm_xlpge_devclass, 0, 0); +DRIVER_MODULE(miibus, xlpge, miibus_driver, miibus_devclass, 0, 0); + +MODULE_DEPEND(pci, xlpnae, 1, 1, 1); +MODULE_DEPEND(xlpnae, xlpge, 1, 1, 1); +MODULE_DEPEND(xlpge, ether, 1, 1, 1); +MODULE_DEPEND(xlpge, miibus, 1, 1, 1); + +#define SGMII_RCV_CONTEXT_WIDTH 8 + +/* prototypes */ +static void nlm_xlpge_msgring_handler(int vc, int size, + int code, int srcid, struct nlm_fmn_msg *msg, void *data); +static void nlm_xlpge_submit_rx_free_desc(struct nlm_xlpge_softc *sc, int num); +static void nlm_xlpge_init(void *addr); +static void nlm_xlpge_port_disable(struct nlm_xlpge_softc *sc); +static void nlm_xlpge_port_enable(struct nlm_xlpge_softc *sc); + +/* globals */ +int dbg_on = 1; +int cntx2port[524]; + +static __inline void +atomic_incr_long(unsigned long *addr) +{ + atomic_add_long(addr, 1); +} + +/* + * xlpnae driver implementation + */ +static int +nlm_xlpnae_probe(device_t dev) +{ + if (pci_get_vendor(dev) != PCI_VENDOR_NETLOGIC || + pci_get_device(dev) != PCI_DEVICE_ID_NLM_NAE) + return (ENXIO); + + return (BUS_PROBE_DEFAULT); +} + +static void +nlm_xlpnae_print_frin_desc_carving(struct nlm_xlpnae_softc *sc) +{ + int intf; + uint32_t value; + int start, size; + + /* XXXJC: use max_ports instead of 20 ? */ + for (intf = 0; intf < 20; intf++) { + nlm_write_nae_reg(sc->base, NAE_FREE_IN_FIFO_CFG, + (0x80000000 | intf)); + value = nlm_read_nae_reg(sc->base, NAE_FREE_IN_FIFO_CFG); + size = 2 * ((value >> 20) & 0x3ff); + start = 2 * ((value >> 8) & 0x1ff); + } +} + +static void +nlm_config_egress(struct nlm_xlpnae_softc *sc, int nblock, + int context_base, int hwport, int max_channels) +{ + int offset, num_channels; + uint32_t data; + + num_channels = sc->portcfg[hwport].num_channels; + + data = (2048 << 12) | (hwport << 4) | 1; + nlm_write_nae_reg(sc->base, NAE_TX_IF_BURSTMAX_CMD, data); + + data = ((context_base + num_channels - 1) << 22) | + (context_base << 12) | (hwport << 4) | 1; + nlm_write_nae_reg(sc->base, NAE_TX_DDR_ACTVLIST_CMD, data); + + config_egress_fifo_carvings(sc->base, hwport, + context_base, num_channels, max_channels, sc->portcfg); + config_egress_fifo_credits(sc->base, hwport, + context_base, num_channels, max_channels, sc->portcfg); + + data = nlm_read_nae_reg(sc->base, NAE_DMA_TX_CREDIT_TH); + data |= (1 << 25) | (1 << 24); + nlm_write_nae_reg(sc->base, NAE_DMA_TX_CREDIT_TH, data); + + for (offset = 0; offset < num_channels; offset++) { + nlm_write_nae_reg(sc->base, NAE_TX_SCHED_MAP_CMD1, + NAE_DRR_QUANTA); + data = (hwport << 15) | ((context_base + offset) << 5); + if (sc->cmplx_type[nblock] == ILC) + data |= (offset << 20); + nlm_write_nae_reg(sc->base, NAE_TX_SCHED_MAP_CMD0, data | 1); + nlm_write_nae_reg(sc->base, NAE_TX_SCHED_MAP_CMD0, data); + } +} + +static int +xlpnae_get_maxchannels(struct nlm_xlpnae_softc *sc) +{ + int maxchans = 0; + int i, j, port = 0; + + for (i = 0; i < sc->nblocks; i++) { + switch (sc->cmplx_type[i]) { + case SGMIIC: + for (j = 0; j < 4; j++) { /* 4 ports */ + if ((i == 4) && (j > 1)) + continue; + maxchans += sc->portcfg[port].num_channels; + port++; + } + break; + case XAUIC: + maxchans += sc->portcfg[port].num_channels; + port += 4; + break; + case ILC: + if (((i%2) == 0) && (i != 4)) { + maxchans += sc->portcfg[port].num_channels; + port += 4; + break; + } + } + } + + return (maxchans); +} + +static void +nlm_setup_interface(struct nlm_xlpnae_softc *sc, int nblock, + int port, uint32_t cur_flow_base, uint32_t flow_mask, + int max_channels, int context) +{ + uint64_t nae_base = sc->base; + int mtu = 1536; /* XXXJC: don't hard code */ + uint32_t ucore_mask; + + if (sc->cmplx_type[nblock] == XAUIC) + nlm_config_xaui(nae_base, nblock, mtu, + mtu, sc->portcfg[port].vlan_pri_en); + nlm_config_freein_fifo_uniq_cfg(nae_base, + port, sc->portcfg[port].free_desc_sizes); + nlm_config_ucore_iface_mask_cfg(nae_base, + port, sc->portcfg[port].ucore_mask); + + nlm_program_flow_cfg(nae_base, port, cur_flow_base, flow_mask); + + if (sc->cmplx_type[nblock] == SGMIIC) + nlm_configure_sgmii_interface(nae_base, nblock, port, mtu, 0); + + nlm_config_egress(sc, nblock, context, port, max_channels); + + nlm_nae_init_netior(nae_base, sc->nblocks); + nlm_nae_open_if(nae_base, nblock, sc->cmplx_type[nblock], port, + sc->portcfg[port].free_desc_sizes); + + /* XXXJC: check mask calculation */ + ucore_mask = (1 << sc->nucores) - 1; + nlm_nae_init_ucore(nae_base, port, ucore_mask); +} + +static void +nlm_setup_interfaces(struct nlm_xlpnae_softc *sc) +{ + uint64_t nae_base; + uint32_t cur_slot, cur_slot_base; + uint32_t cur_flow_base, port, flow_mask; + int max_channels; + int i, j, context; + + cur_slot = 0; + cur_slot_base = 0; + cur_flow_base = 0; + nae_base = sc->base; + flow_mask = nlm_get_flow_mask(sc->total_num_ports); + /* calculate max_channels */ + max_channels = xlpnae_get_maxchannels(sc); + + port = 0; + context = 0; + for (i = 0; i < sc->nblocks; i++) { + switch (sc->cmplx_type[i]) { + case SGMIIC: + for (j = 0; j < 4; j++) { /* 4 ports */ + if ((i == 4) && (j > 1)) + continue; + nlm_setup_interface(sc, i, port, + cur_flow_base, flow_mask, + max_channels, context); + cur_flow_base += sc->per_port_num_flows; + context += sc->portcfg[port].num_channels; + port++; + } + break; + case XAUIC: + nlm_setup_interface(sc, i, port, cur_flow_base, + flow_mask, max_channels, context); + cur_flow_base += sc->per_port_num_flows; + context += sc->portcfg[port].num_channels; + port += 4; + break; + case ILC: + if (((i%2) == 0) && (i != 4)) { + nlm_setup_interface(sc, i, port, + cur_flow_base, flow_mask, + max_channels, context); + cur_flow_base += sc->per_port_num_flows; + context += sc->portcfg[port].num_channels; + port += 4; + } + break; + } + cur_slot_base++; + } +} + +static void +nlm_xlpnae_init(int node, struct nlm_xlpnae_softc *sc) +{ + uint64_t nae_base; + uint32_t ucoremask = 0; + uint32_t val; + int i; + + nae_base = sc->base; + + nlm_nae_flush_free_fifo(nae_base, sc->nblocks); + nlm_deflate_frin_fifo_carving(nae_base, sc->max_ports); + nlm_reset_nae(node); + + for (i = 0; i < sc->nucores; i++) /* XXXJC: code repeated below */ + ucoremask |= (0x1 << i); + printf("Loading 0x%x ucores with microcode\n", ucoremask); + nlm_ucore_load_all(nae_base, ucoremask, 1); + + val = nlm_set_device_frequency(node, DFS_DEVICE_NAE, sc->freq); + printf("Setup NAE frequency to %dMHz\n", val); + + printf("Initialze SGMII PCS for blocks 0x%x\n", sc->sgmiimask); + nlm_sgmii_pcs_init(nae_base, sc->sgmiimask); + + printf("Initialze XAUI PCS for blocks 0x%x\n", sc->xauimask); + nlm_xaui_pcs_init(nae_base, sc->xauimask); + + /* clear NETIOR soft reset */ + nlm_write_nae_reg(nae_base, NAE_LANE_CFG_SOFTRESET, 0x0); + + /* Disable RX enable bit in RX_CONFIG */ + val = nlm_read_nae_reg(nae_base, NAE_RX_CONFIG); + val &= 0xfffffffe; + nlm_write_nae_reg(nae_base, NAE_RX_CONFIG, val); + + if (nlm_is_xlp8xx_ax() == 0) { + val = nlm_read_nae_reg(nae_base, NAE_TX_CONFIG); + val &= ~(1 << 3); + nlm_write_nae_reg(nae_base, NAE_TX_CONFIG, val); + } + + nlm_setup_poe_class_config(nae_base, MAX_POE_CLASSES, + sc->ncontexts, poe_cl_tbl); + + nlm_setup_vfbid_mapping(nae_base); + + nlm_setup_flow_crc_poly(nae_base, sc->flow_crc_poly); + + nlm_setup_rx_cal_cfg(nae_base, sc->max_ports, sc->portcfg); + /* note: xlp8xx Ax does not have Tx Calendering */ + if (!nlm_is_xlp8xx_ax()) + nlm_setup_tx_cal_cfg(nae_base, sc->max_ports, sc->portcfg); + + nlm_setup_interfaces(sc); + nlm_config_poe(sc->poe_base, sc->poedv_base); + + nlm_xlpnae_print_frin_desc_carving(sc); + + if (sc->hw_parser_en) + nlm_enable_hardware_parser(nae_base); + + if (sc->prepad_en) + nlm_prepad_enable(nae_base, sc->prepad_size); + + if (sc->ieee_1588_en) + nlm_setup_1588_timer(sc->base, sc->portcfg); +} + +static void +nlm_xlpnae_update_pde(void *dummy __unused) +{ + struct nlm_xlpnae_softc *sc; + uint32_t dv[NUM_WORDS_PER_DV]; + device_t dev; + int vec; + + dev = devclass_get_device(devclass_find("xlpnae"), 0); + sc = device_get_softc(dev); + + nlm_write_poe_reg(sc->poe_base, POE_DISTR_EN, 0); + for (vec = 0; vec < NUM_DIST_VEC; vec++) { + if (nlm_get_poe_distvec(vec, dv) != 0) + continue; + + nlm_write_poe_distvec(sc->poedv_base, vec, dv); + } + nlm_write_poe_reg(sc->poe_base, POE_DISTR_EN, 1); +} + +SYSINIT(nlm_xlpnae_update_pde, SI_SUB_SMP, SI_ORDER_ANY, + nlm_xlpnae_update_pde, NULL); + +/* configuration common for sgmii, xaui, ilaken goes here */ +static void +nlm_setup_portcfg(struct nlm_xlpnae_softc *sc, struct xlp_nae_ivars *naep, + int block, int port) +{ + int i; + uint32_t ucore_mask = 0; + struct xlp_block_ivars *bp; + struct xlp_port_ivars *p; + + bp = &(naep->block_ivars[block]); + p = &(bp->port_ivars[port & 0x3]); + + sc->portcfg[port].loopback_mode = p->loopback_mode; + sc->portcfg[port].num_channels = p->num_channels; + if (p->free_desc_sizes != MCLBYTES) { + printf("[%d, %d] Error: free_desc_sizes %d != %d\n", + block, port, p->free_desc_sizes, MCLBYTES); + return; + } + sc->portcfg[port].free_desc_sizes = p->free_desc_sizes; + for (i = 0; i < sc->nucores; i++) /* XXXJC: configure this */ + ucore_mask |= (0x1 << i); + sc->portcfg[port].ucore_mask = ucore_mask; + sc->portcfg[port].vlan_pri_en = p->vlan_pri_en; + sc->portcfg[port].num_free_descs = p->num_free_descs; + sc->portcfg[port].iface_fifo_size = p->iface_fifo_size; + sc->portcfg[port].rxbuf_size = p->rxbuf_size; + sc->portcfg[port].rx_slots_reqd = p->rx_slots_reqd; + sc->portcfg[port].tx_slots_reqd = p->tx_slots_reqd; + sc->portcfg[port].pseq_fifo_size = p->pseq_fifo_size; + + sc->portcfg[port].stg2_fifo_size = p->stg2_fifo_size; + sc->portcfg[port].eh_fifo_size = p->eh_fifo_size; + sc->portcfg[port].frout_fifo_size = p->frout_fifo_size; + sc->portcfg[port].ms_fifo_size = p->ms_fifo_size; + sc->portcfg[port].pkt_fifo_size = p->pkt_fifo_size; + sc->portcfg[port].pktlen_fifo_size = p->pktlen_fifo_size; + sc->portcfg[port].max_stg2_offset = p->max_stg2_offset; + sc->portcfg[port].max_eh_offset = p->max_eh_offset; + sc->portcfg[port].max_frout_offset = p->max_frout_offset; + sc->portcfg[port].max_ms_offset = p->max_ms_offset; + sc->portcfg[port].max_pmem_offset = p->max_pmem_offset; + sc->portcfg[port].stg1_2_credit = p->stg1_2_credit; + sc->portcfg[port].stg2_eh_credit = p->stg2_eh_credit; + sc->portcfg[port].stg2_frout_credit = p->stg2_frout_credit; + sc->portcfg[port].stg2_ms_credit = p->stg2_ms_credit; + sc->portcfg[port].ieee1588_inc_intg = p->ieee1588_inc_intg; + sc->portcfg[port].ieee1588_inc_den = p->ieee1588_inc_den; + sc->portcfg[port].ieee1588_inc_num = p->ieee1588_inc_num; + sc->portcfg[port].ieee1588_userval = p->ieee1588_userval; + sc->portcfg[port].ieee1588_ptpoff = p->ieee1588_ptpoff; + sc->portcfg[port].ieee1588_tmr1 = p->ieee1588_tmr1; + sc->portcfg[port].ieee1588_tmr2 = p->ieee1588_tmr2; + sc->portcfg[port].ieee1588_tmr3 = p->ieee1588_tmr3; + + sc->total_free_desc += sc->portcfg[port].free_desc_sizes; + sc->total_num_ports++; +} + +static int +nlm_xlpnae_attach(device_t dev) +{ + struct xlp_nae_ivars *nae_ivars; + struct nlm_xlpnae_softc *sc; + device_t tmpd; + uint32_t dv[NUM_WORDS_PER_DV]; + int port, i, j, n, nchan, nblock, node, qstart, qnum; + int offset, context, txq_base, rxvcbase; + uint64_t poe_pcibase, nae_pcibase; + + node = pci_get_slot(dev) / 8; + nae_ivars = &xlp_board_info.nodes[node].nae_ivars; + + sc = device_get_softc(dev); + sc->xlpnae_dev = dev; + sc->node = nae_ivars->node; + sc->base = nlm_get_nae_regbase(sc->node); + sc->poe_base = nlm_get_poe_regbase(sc->node); + sc->poedv_base = nlm_get_poedv_regbase(sc->node); + sc->portcfg = nae_port_config; + sc->xauimask = nae_ivars->xauimask; + sc->sgmiimask = nae_ivars->sgmiimask; + sc->nblocks = nae_ivars->nblocks; + sc->freq = nae_ivars->freq; + + /* flow table generation is done by CRC16 polynomial */ + sc->flow_crc_poly = nae_ivars->flow_crc_poly; + + sc->hw_parser_en = nae_ivars->hw_parser_en; + sc->prepad_en = nae_ivars->prepad_en; + sc->prepad_size = nae_ivars->prepad_size; + sc->ieee_1588_en = nae_ivars->ieee_1588_en; + + nae_pcibase = nlm_get_nae_pcibase(sc->node); + sc->ncontexts = nlm_read_reg(nae_pcibase, XLP_PCI_DEVINFO_REG5); + sc->nucores = nlm_num_uengines(nae_pcibase); + + /* Initialize the 1st four complexes from board config */ + for (nblock = 0; nblock < sc->nblocks; nblock++) + sc->cmplx_type[nblock] = nae_ivars->block_ivars[nblock].type; + + for (i = 0; i < sc->ncontexts; i++) + cntx2port[i] = 18; /* 18 is an invalid port */ + + if (sc->nblocks == 5) + sc->max_ports = 18; /* 8xx has a block 4 with 2 ports */ + else + sc->max_ports = sc->nblocks * PORTS_PER_CMPLX; + + /* + * Now setup all internal fifo carvings based on + * total number of ports in the system + */ + sc->total_free_desc = 0; + sc->total_num_ports = 0; + port = 0; + context = 0; + txq_base = nlm_qidstart(nae_pcibase); + rxvcbase = txq_base + sc->ncontexts; + for (i = 0; i < sc->nblocks; i++) { + /* only 2 SGMII ports in last complex */ + n = (sc->cmplx_type[i] == SGMIIC && i == 4) ? 2 : 4; + for (j = 0; j < n; j++, port++) { + if (sc->cmplx_type[i] == XAUIC && j != 0) + continue; + if (sc->cmplx_type[i] == ILC && + (i != 0 || i != 2 || j != 0)) + continue; + nlm_setup_portcfg(sc, nae_ivars, i, port); + nchan = sc->portcfg[port].num_channels; + for (offset = 0; offset < nchan; offset++) + cntx2port[context + offset] = port; + sc->portcfg[port].txq = txq_base + context; + sc->portcfg[port].rxfreeq = rxvcbase + port; + context += nchan; + } + } + + poe_pcibase = nlm_get_poe_pcibase(sc->node); + sc->per_port_num_flows = + nlm_poe_max_flows(poe_pcibase) / sc->total_num_ports; + + /* zone for P2P descriptors */ + nl_tx_desc_zone = uma_zcreate("NL Tx Desc", + sizeof(struct xlpge_tx_desc), NULL, NULL, NULL, NULL, + NAE_CACHELINE_SIZE, 0); + + /* NAE FMN messages have CMS src station id's in the + * range of qstart to qnum. + */ + qstart = nlm_qidstart(nae_pcibase); + qnum = nlm_qnum(nae_pcibase); + if (register_msgring_handler(qstart, qstart + qnum - 1, + nlm_xlpge_msgring_handler, sc)) { + panic("Couldn't register NAE msgring handler\n"); + } + + /* POE FMN messages have CMS src station id's in the + * range of qstart to qnum. + */ + qstart = nlm_qidstart(poe_pcibase); + qnum = nlm_qnum(poe_pcibase); + if (register_msgring_handler(qstart, qstart + qnum - 1, + nlm_xlpge_msgring_handler, sc)) { + panic("Couldn't register POE msgring handler\n"); + } + + nlm_xlpnae_init(node, sc); + + for (i = 0; i < sc->nblocks; i++) { + char desc[32]; + struct xlp_block_ivars *bv; + + if ((nae_ivars->blockmask & (1 << i)) == 0) + continue; + bv = &nae_ivars->block_ivars[i]; + for (j = 0; j < PORTS_PER_CMPLX; j++) { + int port = i * 4 + j; + + if ((bv->portmask & (1 << j)) == 0) + continue; + tmpd = device_add_child(dev, "xlpge", port); + device_set_ivars(tmpd, &(bv->port_ivars[j])); + sprintf(desc, "XLP NAE Port %d,%d", i, j); + device_set_desc_copy(tmpd, desc); + } + + nlm_setup_iface_fifo_cfg(sc->base, i, sc->portcfg); + nlm_setup_rx_base_config(sc->base, i, sc->portcfg); + nlm_setup_rx_buf_config(sc->base, i, sc->portcfg); + nlm_setup_freein_fifo_cfg(sc->base, i, sc->portcfg); + nlm_program_nae_parser_seq_fifo(sc->base, i, sc->portcfg); + } + + bus_generic_probe(dev); + bus_generic_attach(dev); + + /* + * Enable only boot cpu at this point, full distribution comes + * only after SMP is started + */ + nlm_write_poe_reg(sc->poe_base, POE_DISTR_EN, 0); + nlm_calc_poe_distvec(0x1, 0, 0, 0, 0x1 << XLPGE_RX_VC, dv); + nlm_write_poe_distvec(sc->poedv_base, 0, dv); + nlm_write_poe_reg(sc->poe_base, POE_DISTR_EN, 1); + + return (0); +} + +static int +nlm_xlpnae_detach(device_t dev) +{ + /* TODO - free zone here */ + return (0); +} + +static int +nlm_xlpnae_suspend(device_t dev) +{ + return (0); +} + +static int +nlm_xlpnae_resume(device_t dev) +{ + return (0); +} + +static int +nlm_xlpnae_shutdown(device_t dev) +{ + return (0); +} + +/* + * xlpge driver implementation + */ + +static void +nlm_xlpge_mac_set_rx_mode(struct nlm_xlpge_softc *sc) +{ + if (sc->if_flags & IFF_PROMISC) { + if (sc->type == SGMIIC) + nlm_nae_setup_rx_mode_sgmii(sc->base_addr, + sc->block, sc->port, sc->type, 1 /* broadcast */, + 1/* multicast */, 0 /* pause */, 1 /* promisc */); + else + nlm_nae_setup_rx_mode_xaui(sc->base_addr, + sc->block, sc->port, sc->type, 1 /* broadcast */, + 1/* multicast */, 0 /* pause */, 1 /* promisc */); + } else { + if (sc->type == SGMIIC) + nlm_nae_setup_rx_mode_sgmii(sc->base_addr, + sc->block, sc->port, sc->type, 1 /* broadcast */, + 1/* multicast */, 0 /* pause */, 0 /* promisc */); + else + nlm_nae_setup_rx_mode_xaui(sc->base_addr, + sc->block, sc->port, sc->type, 1 /* broadcast */, + 1/* multicast */, 0 /* pause */, 0 /* promisc */); + } +} + +static int +nlm_xlpge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct mii_data *mii; + struct nlm_xlpge_softc *sc; + struct ifreq *ifr; + int error; + + sc = ifp->if_softc; + error = 0; + ifr = (struct ifreq *)data; + + switch (command) { + case SIOCSIFFLAGS: + XLPGE_LOCK(sc); + sc->if_flags = ifp->if_flags; + if (ifp->if_flags & IFF_UP) { + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + nlm_xlpge_init(sc); + nlm_xlpge_mac_set_rx_mode(sc); + nlm_xlpge_port_enable(sc); + sc->link = NLM_LINK_UP; + } else { + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + nlm_xlpge_port_disable(sc); + sc->link = NLM_LINK_DOWN; + } + XLPGE_UNLOCK(sc); + error = 0; + break; + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + if (sc->mii_bus != NULL) { + mii = device_get_softc(sc->mii_bus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, + command); + } + break; + default: + error = ether_ioctl(ifp, command, data); + break; + } + + return (error); +} + +static int +xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain) +{ + struct nlm_fmn_msg msg; + struct xlpge_tx_desc *p2p; + struct nlm_xlpge_softc *sc; + struct mbuf *m; + vm_paddr_t paddr; + int fbid, dst, pos, err; + int ret = 0, tx_msgstatus, retries; + + err = 0; + if (mbuf_chain == NULL) + return (0); + + sc = ifp->if_softc; + p2p = NULL; + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || + ifp->if_drv_flags & IFF_DRV_OACTIVE) { + err = ENXIO; + goto fail; + } + + /* free a few in coming messages on the fb vc */ + xlp_handle_msg_vc(1 << XLPGE_FB_VC, 2); + + /* vfb id table is setup to map cpu to vc 3 of the cpu */ + fbid = nlm_cpuid(); + dst = sc->txq; + + pos = 0; + p2p = uma_zalloc(nl_tx_desc_zone, M_NOWAIT); + if (p2p == NULL) { + printf("alloc fail\n"); + err = ENOBUFS; + goto fail; + } + + for (m = mbuf_chain; m != NULL; m = m->m_next) { + vm_offset_t buf = (vm_offset_t) m->m_data; + int len = m->m_len; + int frag_sz; + + /*printf("m_data = %p len %d\n", m->m_data, len); */ + while (len) { + if (pos == XLP_NTXFRAGS - 3) { + device_printf(sc->xlpge_dev, + "packet defrag %d\n", + m_length(mbuf_chain, NULL)); + err = ENOBUFS; /* TODO fix error */ + goto fail; + } + paddr = vtophys(buf); + frag_sz = PAGE_SIZE - (buf & PAGE_MASK); + if (len < frag_sz) + frag_sz = len; + p2p->frag[pos] = nae_tx_desc(P2D_NEOP, 0, 127, + frag_sz, paddr); + pos++; + len -= frag_sz; + buf += frag_sz; + } + } + + KASSERT(pos != 0, ("Zero-length mbuf chain?\n")); + + /* Make the last one P2D EOP */ + p2p->frag[pos-1] |= (uint64_t)P2D_EOP << 62; + + /* stash useful pointers in the desc */ + p2p->frag[XLP_NTXFRAGS-3] = 0xf00bad; + p2p->frag[XLP_NTXFRAGS-2] = (uintptr_t)p2p; + p2p->frag[XLP_NTXFRAGS-1] = (uintptr_t)mbuf_chain; + + paddr = vtophys(p2p); + msg.msg[0] = nae_tx_desc(P2P, 0, fbid, pos, paddr); + + for (retries = 16; retries > 0; retries--) { + ret = nlm_fmn_msgsend(dst, 1, FMN_SWCODE_NAE, &msg); + if (ret == 0) + return (0); + } + +fail: + if (ret != 0) { + tx_msgstatus = nlm_read_c2_txmsgstatus(); + if ((tx_msgstatus >> 24) & 0x1) + device_printf(sc->xlpge_dev, "Transmit queue full - "); + if ((tx_msgstatus >> 3) & 0x1) + device_printf(sc->xlpge_dev, "ECC error - "); + if ((tx_msgstatus >> 2) & 0x1) + device_printf(sc->xlpge_dev, "Pending Sync - "); + if ((tx_msgstatus >> 1) & 0x1) + device_printf(sc->xlpge_dev, + "Insufficient input queue credits - "); + if (tx_msgstatus & 0x1) + device_printf(sc->xlpge_dev, + "Insufficient output queue credits - "); + } + device_printf(sc->xlpge_dev, "Send failed! err = %d\n", err); + if (p2p) + uma_zfree(nl_tx_desc_zone, p2p); + m_freem(mbuf_chain); + /*atomic_incr_long(&ifp->if_iqdrops); */ + ifp->if_iqdrops++; + return (err); +} + + +static int +nlm_xlpge_gmac_config_speed(struct nlm_xlpge_softc *sc) +{ + struct mii_data *mii; + + if (sc->type == XAUIC || sc->type == ILC) + return (0); + + if (sc->mii_bus) { + mii = device_get_softc(sc->mii_bus); + mii_pollstat(mii); + } + + return (0); +} + +static void +nlm_xlpge_port_disable(struct nlm_xlpge_softc *sc) +{ + struct ifnet *ifp; + + ifp = sc->xlpge_if; + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + + callout_stop(&sc->xlpge_callout); + nlm_mac_disable(sc->base_addr, sc->block, sc->type, sc->port); +} + +static void +nlm_mii_pollstat(void *arg) +{ + struct nlm_xlpge_softc *sc = (struct nlm_xlpge_softc *)arg; + struct mii_data *mii = NULL; + + if (sc->mii_bus) { + mii = device_get_softc(sc->mii_bus); + + KASSERT(mii == NULL, ("mii ptr is NULL")); + + mii_pollstat(mii); + + callout_reset(&sc->xlpge_callout, hz, + nlm_mii_pollstat, sc); + } +} + +static void +nlm_xlpge_port_enable(struct nlm_xlpge_softc *sc) +{ + if ((sc->type != SGMIIC) && (sc->type != XAUIC)) + return; + nlm_mac_enable(sc->base_addr, sc->block, sc->type, sc->port); + nlm_mii_pollstat((void *)sc); +} + +static void +nlm_xlpge_init(void *addr) +{ + struct nlm_xlpge_softc *sc; + struct ifnet *ifp; + struct mii_data *mii = NULL; + + sc = (struct nlm_xlpge_softc *)addr; + ifp = sc->xlpge_if; + + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + return; + + if (sc->mii_bus) { + mii = device_get_softc(sc->mii_bus); + mii_mediachg(mii); + } + + nlm_xlpge_gmac_config_speed(sc); + ifp->if_drv_flags |= IFF_DRV_RUNNING; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + nlm_xlpge_port_enable(sc); + + /* start the callout */ + callout_reset(&sc->xlpge_callout, hz, nlm_mii_pollstat, sc); +} + +/* + * Read the MAC address from FDT or board eeprom. + */ +static void +xlpge_read_mac_addr(struct nlm_xlpge_softc *sc) +{ + + xlpge_get_macaddr(sc->dev_addr); + /* last octet is port specific */ + sc->dev_addr[5] += (sc->block * 4) + sc->port; + + if (sc->type == SGMIIC) + nlm_nae_setup_mac_addr_sgmii(sc->base_addr, sc->block, + sc->port, sc->type, sc->dev_addr); + else if (sc->type == XAUIC) + nlm_nae_setup_mac_addr_xaui(sc->base_addr, sc->block, + sc->port, sc->type, sc->dev_addr); +} + + +static int +xlpge_mediachange(struct ifnet *ifp) +{ + return (0); +} + +static void +xlpge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct nlm_xlpge_softc *sc; + struct mii_data *md; + + md = NULL; + sc = ifp->if_softc; + + if (sc->mii_bus) + md = device_get_softc(sc->mii_bus); + + ifmr->ifm_status = IFM_AVALID; + ifmr->ifm_active = IFM_ETHER; + + if (sc->link == NLM_LINK_DOWN) + return; + + if (md != NULL) + ifmr->ifm_active = md->mii_media.ifm_cur->ifm_media; + ifmr->ifm_status |= IFM_ACTIVE; +} + +static int +nlm_xlpge_ifinit(struct nlm_xlpge_softc *sc) +{ + struct ifnet *ifp; + device_t dev; + int port = sc->block * 4 + sc->port; + + dev = sc->xlpge_dev; + ifp = sc->xlpge_if = if_alloc(IFT_ETHER); + /*(sc->network_sc)->ifp_ports[port].xlpge_if = ifp;*/ + ifp_ports[port].xlpge_if = ifp; + + if (ifp == NULL) { + device_printf(dev, "cannot if_alloc()\n"); + return (ENOSPC); + } + ifp->if_softc = sc; + if_initname(ifp, device_get_name(dev), device_get_unit(dev)); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + sc->if_flags = ifp->if_flags; + /*ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING;*/ + ifp->if_capabilities = 0; + ifp->if_capenable = ifp->if_capabilities; + ifp->if_ioctl = nlm_xlpge_ioctl; + ifp->if_init = nlm_xlpge_init ; + ifp->if_hwassist = 0; + ifp->if_snd.ifq_drv_maxlen = NLM_XLPGE_TXQ_SIZE; /* TODO: make this a sysint */ + IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); + IFQ_SET_READY(&ifp->if_snd); + + ifmedia_init(&sc->xlpge_mii.mii_media, 0, xlpge_mediachange, + xlpge_mediastatus); + ifmedia_add(&sc->xlpge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->xlpge_mii.mii_media, IFM_ETHER | IFM_AUTO); + sc->xlpge_mii.mii_media.ifm_media = + sc->xlpge_mii.mii_media.ifm_cur->ifm_media; + xlpge_read_mac_addr(sc); + + ether_ifattach(ifp, sc->dev_addr); + + /* override if_transmit : per ifnet(9), do it after if_attach */ + ifp->if_transmit = xlpge_tx; + + return (0); +} + +static int +nlm_xlpge_probe(device_t dev) +{ + return (BUS_PROBE_DEFAULT); +} + +static void * +get_buf(void) +{ + struct mbuf *m_new; + uint64_t *md; +#ifdef INVARIANTS + vm_paddr_t temp1, temp2; +#endif + + if ((m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL) + return (NULL); + m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + m_adj(m_new, NAE_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f)); + md = (uint64_t *)m_new->m_data; + md[0] = (intptr_t)m_new; /* Back Ptr */ + md[1] = 0xf00bad; + m_adj(m_new, NAE_CACHELINE_SIZE); + +#ifdef INVARIANTS + temp1 = vtophys((vm_offset_t) m_new->m_data); + temp2 = vtophys((vm_offset_t) m_new->m_data + 1536); + KASSERT(temp1 + 1536) != temp2, + ("Alloced buffer is not contiguous")); +#endif + + return ((void *)m_new->m_data); +} + +static void +nlm_xlpge_mii_init(device_t dev, struct nlm_xlpge_softc *sc) +{ + int error; + + error = mii_attach(dev, &sc->mii_bus, sc->xlpge_if, + xlpge_mediachange, xlpge_mediastatus, + BMSR_DEFCAPMASK, sc->phy_addr, MII_OFFSET_ANY, 0); + + if (error) { + device_printf(dev, "attaching PHYs failed\n"); + sc->mii_bus = NULL; + } + + if (sc->mii_bus != NULL) { + /* enable MDIO interrupts in the PHY */ + /* XXXJC: TODO */ + } +} + +static int +xlpge_stats_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct nlm_xlpge_softc *sc; + uint32_t val; + int reg, field; + + sc = arg1; + field = arg2; + reg = SGMII_STATS_MLR(sc->block, sc->port) + field; + val = nlm_read_nae_reg(sc->base_addr, reg); + return (sysctl_handle_int(oidp, &val, 0, req)); +} + +static void +nlm_xlpge_setup_stats_sysctl(device_t dev, struct nlm_xlpge_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid_list *child; + struct sysctl_oid *tree; + + ctx = device_get_sysctl_ctx(dev); + tree = device_get_sysctl_tree(dev); + child = SYSCTL_CHILDREN(tree); + +#define XLPGE_STAT(name, offset, desc) \ + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, name, \ + CTLTYPE_UINT | CTLFLAG_RD, sc, offset, \ + xlpge_stats_sysctl, "IU", desc) + + XLPGE_STAT("tr127", nlm_sgmii_stats_tr127, "TxRx 64 - 127 Bytes"); + XLPGE_STAT("tr255", nlm_sgmii_stats_tr255, "TxRx 128 - 255 Bytes"); + XLPGE_STAT("tr511", nlm_sgmii_stats_tr511, "TxRx 256 - 511 Bytes"); + XLPGE_STAT("tr1k", nlm_sgmii_stats_tr1k, "TxRx 512 - 1023 Bytes"); + XLPGE_STAT("trmax", nlm_sgmii_stats_trmax, "TxRx 1024 - 1518 Bytes"); + XLPGE_STAT("trmgv", nlm_sgmii_stats_trmgv, "TxRx 1519 - 1522 Bytes"); + + XLPGE_STAT("rbyt", nlm_sgmii_stats_rbyt, "Rx Bytes"); + XLPGE_STAT("rpkt", nlm_sgmii_stats_rpkt, "Rx Packets"); + XLPGE_STAT("rfcs", nlm_sgmii_stats_rfcs, "Rx FCS Error"); + XLPGE_STAT("rmca", nlm_sgmii_stats_rmca, "Rx Multicast Packets"); + XLPGE_STAT("rbca", nlm_sgmii_stats_rbca, "Rx Broadcast Packets"); + XLPGE_STAT("rxcf", nlm_sgmii_stats_rxcf, "Rx Control Frames"); + XLPGE_STAT("rxpf", nlm_sgmii_stats_rxpf, "Rx Pause Frames"); + XLPGE_STAT("rxuo", nlm_sgmii_stats_rxuo, "Rx Unknown Opcode"); + XLPGE_STAT("raln", nlm_sgmii_stats_raln, "Rx Alignment Errors"); + XLPGE_STAT("rflr", nlm_sgmii_stats_rflr, "Rx Framelength Errors"); + XLPGE_STAT("rcde", nlm_sgmii_stats_rcde, "Rx Code Errors"); + XLPGE_STAT("rcse", nlm_sgmii_stats_rcse, "Rx Carrier Sense Errors"); + XLPGE_STAT("rund", nlm_sgmii_stats_rund, "Rx Undersize Packet Errors"); + XLPGE_STAT("rovr", nlm_sgmii_stats_rovr, "Rx Oversize Packet Errors"); + XLPGE_STAT("rfrg", nlm_sgmii_stats_rfrg, "Rx Fragments"); + XLPGE_STAT("rjbr", nlm_sgmii_stats_rjbr, "Rx Jabber"); + + XLPGE_STAT("tbyt", nlm_sgmii_stats_tbyt, "Tx Bytes"); + XLPGE_STAT("tpkt", nlm_sgmii_stats_tpkt, "Tx Packets"); + XLPGE_STAT("tmca", nlm_sgmii_stats_tmca, "Tx Multicast Packets"); + XLPGE_STAT("tbca", nlm_sgmii_stats_tbca, "Tx Broadcast Packets"); + XLPGE_STAT("txpf", nlm_sgmii_stats_txpf, "Tx Pause Frame"); + XLPGE_STAT("tdfr", nlm_sgmii_stats_tdfr, "Tx Deferral Packets"); + XLPGE_STAT("tedf", nlm_sgmii_stats_tedf, "Tx Excessive Deferral Pkts"); + XLPGE_STAT("tscl", nlm_sgmii_stats_tscl, "Tx Single Collisions"); + XLPGE_STAT("tmcl", nlm_sgmii_stats_tmcl, "Tx Multiple Collisions"); + XLPGE_STAT("tlcl", nlm_sgmii_stats_tlcl, "Tx Late Collision Pkts"); + XLPGE_STAT("txcl", nlm_sgmii_stats_txcl, "Tx Excessive Collisions"); + XLPGE_STAT("tncl", nlm_sgmii_stats_tncl, "Tx Total Collisions"); + XLPGE_STAT("tjbr", nlm_sgmii_stats_tjbr, "Tx Jabber Frames"); + XLPGE_STAT("tfcs", nlm_sgmii_stats_tfcs, "Tx FCS Errors"); + XLPGE_STAT("txcf", nlm_sgmii_stats_txcf, "Tx Control Frames"); + XLPGE_STAT("tovr", nlm_sgmii_stats_tovr, "Tx Oversize Frames"); + XLPGE_STAT("tund", nlm_sgmii_stats_tund, "Tx Undersize Frames"); + XLPGE_STAT("tfrg", nlm_sgmii_stats_tfrg, "Tx Fragments"); +#undef XLPGE_STAT +} + +static int +nlm_xlpge_attach(device_t dev) +{ + struct xlp_port_ivars *pv; + struct nlm_xlpge_softc *sc; + int port; + + pv = device_get_ivars(dev); + sc = device_get_softc(dev); + sc->xlpge_dev = dev; + sc->mii_bus = NULL; + sc->block = pv->block; + sc->node = pv->node; + sc->port = pv->port; + sc->type = pv->type; + sc->xlpge_if = NULL; + sc->phy_addr = pv->phy_addr; + sc->mdio_bus = pv->mdio_bus; + sc->portcfg = nae_port_config; + sc->hw_parser_en = pv->hw_parser_en; + + /* default settings */ + sc->speed = NLM_SGMII_SPEED_10; + sc->duplexity = NLM_SGMII_DUPLEX_FULL; + sc->link = NLM_LINK_DOWN; + sc->flowctrl = NLM_FLOWCTRL_DISABLED; + + sc->network_sc = device_get_softc(device_get_parent(dev)); + sc->base_addr = sc->network_sc->base; + sc->prepad_en = sc->network_sc->prepad_en; + sc->prepad_size = sc->network_sc->prepad_size; + + callout_init(&sc->xlpge_callout, CALLOUT_MPSAFE); + + XLPGE_LOCK_INIT(sc, device_get_nameunit(dev)); + + port = (sc->block*4)+sc->port; + sc->nfree_desc = nae_port_config[port].num_free_descs; + sc->txq = nae_port_config[port].txq; + sc->rxfreeq = nae_port_config[port].rxfreeq; + + nlm_xlpge_submit_rx_free_desc(sc, sc->nfree_desc); + if (sc->hw_parser_en) + nlm_enable_hardware_parser_per_port(sc->base_addr, + sc->block, sc->port); + + nlm_xlpge_ifinit(sc); + ifp_ports[port].xlpge_sc = sc; + nlm_xlpge_mii_init(dev, sc); + nlm_xlpge_setup_stats_sysctl(dev, sc); + + return (0); +} + +static int +nlm_xlpge_detach(device_t dev) +{ + return (0); +} + +static int +nlm_xlpge_suspend(device_t dev) +{ + return (0); +} + +static int +nlm_xlpge_resume(device_t dev) +{ + return (0); +} + +static int +nlm_xlpge_shutdown(device_t dev) +{ + return (0); +} + +/* + * miibus function with custom implementation + */ +static int +nlm_xlpge_mii_read(struct device *dev, int phyaddr, int regidx) +{ + struct nlm_xlpge_softc *sc; + int val; + + sc = device_get_softc(dev); + if (sc->type == SGMIIC) + val = nlm_gmac_mdio_read(sc->base_addr, sc->mdio_bus, + BLOCK_7, LANE_CFG, phyaddr, regidx); + else + val = 0xffff; + + return (val); +} + +static int +nlm_xlpge_mii_write(struct device *dev, int phyaddr, int regidx, int val) +{ + struct nlm_xlpge_softc *sc; + + sc = device_get_softc(dev); + if (sc->type == SGMIIC) + nlm_gmac_mdio_write(sc->base_addr, sc->mdio_bus, BLOCK_7, + LANE_CFG, phyaddr, regidx, val); + + return (0); +} + +static void +nlm_xlpge_mii_statchg(device_t dev) +{ + struct nlm_xlpge_softc *sc; + struct mii_data *mii; + char *speed, *duplexity; + + sc = device_get_softc(dev); + if (sc->mii_bus == NULL) + return; + + mii = device_get_softc(sc->mii_bus); + if (mii->mii_media_status & IFM_ACTIVE) { + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) { + sc->speed = NLM_SGMII_SPEED_10; + speed = "10-Mbps"; + } else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) { + sc->speed = NLM_SGMII_SPEED_100; + speed = "100-Mbps"; + } else { /* default to 1G */ + sc->speed = NLM_SGMII_SPEED_1000; + speed = "1-Gbps"; + } + + if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { + sc->duplexity = NLM_SGMII_DUPLEX_FULL; + duplexity = "full"; + } else { + sc->duplexity = NLM_SGMII_DUPLEX_HALF; + duplexity = "half"; + } + + printf("Setup [complex=%d, port=%d] with speed=%s duplex=%s\n", + sc->block, sc->port, speed, duplexity); + + nlm_nae_setup_mac(sc->base_addr, sc->block, sc->port, 0, 1, 1, + sc->speed, sc->duplexity); + } +} + +/* + * xlpge support function implementations + */ +static void +nlm_xlpge_release_mbuf(uint64_t paddr) +{ + uint64_t mag, desc, mbuf; + + paddr += (XLP_NTXFRAGS - 3) * sizeof(uint64_t); + mag = nlm_paddr_ld(paddr); + desc = nlm_paddr_ld(paddr + sizeof(uint64_t)); + mbuf = nlm_paddr_ld(paddr + 2 * sizeof(uint64_t)); + + if (mag != 0xf00bad) { + /* somebody else packet Error - FIXME in intialization */ + printf("cpu %d: ERR Tx packet paddr %jx, mag %jx, desc %jx mbuf %jx\n", + nlm_cpuid(), (uintmax_t)paddr, (uintmax_t)mag, + (intmax_t)desc, (uintmax_t)mbuf); + return; + } + m_freem((struct mbuf *)(uintptr_t)mbuf); + uma_zfree(nl_tx_desc_zone, (void *)(uintptr_t)desc); +} + +static void +nlm_xlpge_rx(struct nlm_xlpge_softc *sc, int port, vm_paddr_t paddr, int len) +{ + struct ifnet *ifp; + struct mbuf *m; + vm_offset_t temp; + unsigned long mag; + int prepad_size; + + ifp = sc->xlpge_if; + temp = nlm_paddr_ld(paddr - NAE_CACHELINE_SIZE); + mag = nlm_paddr_ld(paddr - NAE_CACHELINE_SIZE + sizeof(uint64_t)); + + m = (struct mbuf *)(intptr_t)temp; + if (mag != 0xf00bad) { + /* somebody else packet Error - FIXME in intialization */ + printf("cpu %d: ERR Rx packet paddr %jx, temp %p, mag %lx\n", + nlm_cpuid(), (uintmax_t)paddr, (void *)temp, mag); + return; + } + + m->m_pkthdr.rcvif = ifp; + +#ifdef DUMP_PACKET + { + int i = 0, j = 64; + unsigned char *buf = (char *)m->m_data; + printf("(cpu_%d: nlge_rx, !RX_COPY) Rx Packet: length=%d\n", + nlm_cpuid(), len); + if (len < j) + j = len; + if (sc->prepad_en) + j += ((sc->prepad_size + 1) * 16); + for (i = 0; i < j; i++) { + if (i && (i % 16) == 0) + printf("\n"); + printf("%02x ", buf[i]); + } + printf("\n"); + } +#endif + + if (sc->prepad_en) { + prepad_size = ((sc->prepad_size + 1) * 16); + m->m_data += prepad_size; + m->m_pkthdr.len = m->m_len = (len - prepad_size); + } else + m->m_pkthdr.len = m->m_len = len; + + /*atomic_incr_long(&ifp->if_ipackets);*/ + ifp->if_ipackets++; +#ifdef XLP_DRIVER_LOOPBACK + if (port == 16 || port == 17) + (*ifp->if_input)(ifp, m); + else + xlpge_tx(ifp, m); +#else + (*ifp->if_input)(ifp, m); +#endif +} + +void +nlm_xlpge_submit_rx_free_desc(struct nlm_xlpge_softc *sc, int num) +{ + int i, size, ret, n; + struct nlm_fmn_msg msg; + void *ptr; + + for(i = 0; i < num; i++) { + memset(&msg, 0, sizeof(msg)); + ptr = get_buf(); + if (!ptr) { + device_printf(sc->xlpge_dev, "Cannot allocate mbuf\n"); + break; + } + + msg.msg[0] = vtophys(ptr); + if (msg.msg[0] == 0) { + printf("Bad ptr for %p\n", ptr); + break; + } + size = 1; + + n = 0; + while (1) { + /* on success returns 1, else 0 */ + ret = nlm_fmn_msgsend(sc->rxfreeq, size, 0, &msg); + if (ret == 0) + break; + if (n++ > 10000) { + printf("Too many credit fails for send free desc\n"); + break; + } + } + } +} + +void +nlm_xlpge_msgring_handler(int vc, int size, int code, int src_id, + struct nlm_fmn_msg *msg, void *data) +{ + uint64_t phys_addr; + struct nlm_xlpnae_softc *sc; + struct nlm_xlpge_softc *xlpge_sc; + struct ifnet *ifp; + uint32_t context; + uint32_t port = 0; + uint32_t length; + + sc = (struct nlm_xlpnae_softc *)data; + KASSERT(sc != NULL, ("Null sc in msgring handler")); + + if (size == 1) { /* process transmit complete */ + phys_addr = msg->msg[0] & 0xffffffffffULL; + + /* context is SGMII_RCV_CONTEXT_NUM + three bit vlan type + * or vlan priority + */ + context = (msg->msg[0] >> 40) & 0x3fff; + port = cntx2port[context]; + + if (port >= XLP_MAX_PORTS) { + printf("%s:%d Bad port %d (context=%d)\n", + __func__, __LINE__, port, context); + return; + } + ifp = ifp_ports[port].xlpge_if; + xlpge_sc = ifp_ports[port].xlpge_sc; + + nlm_xlpge_release_mbuf(phys_addr); + + /*atomic_incr_long(&ifp->if_opackets);*/ + ifp->if_opackets++; + + } else if (size > 1) { /* Recieve packet */ + phys_addr = msg->msg[1] & 0xffffffffe0ULL; + length = (msg->msg[1] >> 40) & 0x3fff; + length -= MAC_CRC_LEN; + + /* context is SGMII_RCV_CONTEXT_NUM + three bit vlan type + * or vlan priority + */ + context = (msg->msg[1] >> 54) & 0x3ff; + port = cntx2port[context]; + + if (port >= XLP_MAX_PORTS) { + printf("%s:%d Bad port %d (context=%d)\n", + __func__, __LINE__, port, context); + return; + } + + ifp = ifp_ports[port].xlpge_if; + xlpge_sc = ifp_ports[port].xlpge_sc; + + nlm_xlpge_rx(xlpge_sc, port, phys_addr, length); + /* return back a free descriptor to NA */ + nlm_xlpge_submit_rx_free_desc(xlpge_sc, 1); + } +} diff --git a/sys/mips/nlm/dev/net/xlpge.h b/sys/mips/nlm/dev/net/xlpge.h new file mode 100644 index 0000000..883653d --- /dev/null +++ b/sys/mips/nlm/dev/net/xlpge.h @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __XLPGE_H__ +#define __XLPGE_H__ + +#define NLM_XLPGE_TXQ_SIZE 1024 +#define MAC_CRC_LEN 4 + +enum xlpge_link_state { + NLM_LINK_DOWN, + NLM_LINK_UP +}; + +enum xlpge_floctrl_status { + NLM_FLOWCTRL_DISABLED, + NLM_FLOWCTRL_ENABLED +}; + +struct nlm_xlp_portdata { + struct ifnet *xlpge_if; + struct nlm_xlpge_softc *xlpge_sc; +}; + +struct nlm_xlpnae_softc { + device_t xlpnae_dev; + int node; /* XLP Node id */ + uint64_t base; /* NAE IO base */ + uint64_t poe_base; /* POE IO base */ + uint64_t poedv_base; /* POE distribution vec IO base */ + + int freq; /* frequency of nae block */ + int flow_crc_poly; /* Flow CRC16 polynomial */ + int total_free_desc; /* total for node */ + int max_ports; + int total_num_ports; + int per_port_num_flows; + + u_int nucores; + u_int nblocks; + u_int num_complex; + u_int ncontexts; + + /* Ingress side parameters */ + u_int num_desc; /* no of descriptors in each packet */ + u_int parser_threshold;/* threshold of entries above which */ + /* the parser sequencer is scheduled */ + /* NetIOR configs */ + u_int cmplx_type[8]; /* XXXJC: redundant? */ + struct nae_port_config *portcfg; + u_int xauimask; + u_int sgmiimask; + u_int hw_parser_en; + u_int prepad_en; + u_int prepad_size; + u_int driver_mode; + u_int ieee_1588_en; +}; + +struct nlm_xlpge_softc { + struct ifnet *xlpge_if; /* should be first member */ + /* see - mii.c:miibus_attach() */ + device_t xlpge_dev; + device_t mii_bus; + struct nlm_xlpnae_softc *network_sc; + uint64_t base_addr; /* NAE IO base */ + int node; /* node id (quickread) */ + int block; /* network block id (quickread) */ + int port; /* port id - among the 18 in XLP */ + int type; /* port type - see xlp_gmac_port_types */ + int valid; /* boolean: valid port or not */ + struct mii_data xlpge_mii; + int nfree_desc; /* No of free descriptors sent to port */ + int phy_addr; /* PHY id for the interface */ + + int speed; /* Port speed */ + int duplexity; /* Port duplexity */ + int link; /* Port link status */ + int flowctrl; /* Port flow control setting */ + + unsigned char dev_addr[ETHER_ADDR_LEN]; + struct mtx sc_lock; + int if_flags; + struct nae_port_config *portcfg; + struct callout xlpge_callout; + int mdio_bus; + int txq; + int rxfreeq; + int hw_parser_en; + int prepad_en; + int prepad_size; +}; + +#define XLP_NTXFRAGS 16 +#define NULL_VFBID 127 + +struct xlpge_tx_desc { + uint64_t frag[XLP_NTXFRAGS]; +}; + +#define XLPGE_LOCK_INIT(_sc, _name) \ + mtx_init(&(_sc)->sc_lock, _name, MTX_NETWORK_LOCK, MTX_DEF) +#define XLPGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_lock) +#define XLPGE_LOCK(_sc) mtx_lock(&(_sc)->sc_lock) +#define XLPGE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_lock) +#define XLPGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_lock, MA_OWNED) + +#endif diff --git a/sys/mips/nlm/files.xlp b/sys/mips/nlm/files.xlp index 3d8bb93..fd2e0d0 100644 --- a/sys/mips/nlm/files.xlp +++ b/sys/mips/nlm/files.xlp @@ -17,6 +17,23 @@ mips/nlm/uart_pci_xlp.c optional uart mips/nlm/uart_cpu_xlp.c optional uart mips/nlm/usb_init.c optional usb # +# Network driver and micro-core code +# +mips/nlm/dev/net/nae.c optional xlpge +mips/nlm/dev/net/mdio.c optional xlpge +mips/nlm/dev/net/sgmii.c optional xlpge +mips/nlm/dev/net/xaui.c optional xlpge +mips/nlm/dev/net/xlpge.c optional xlpge +ucore_app.bin optional xlpge \ + compile-with "${CC} -march=mips32 -mabi=32 -msoft-float -I. -I$S -O3 -funroll-loops -finline-limit=20000 -fno-tree-loop-optimize -fomit-frame-pointer -mno-branch-likely -fno-pic -mno-abicalls -ffunction-sections -fdata-sections -G0 -Wall -Werror -c $S/$M/nlm/dev/net/ucore/crt0_basic.S $S/$M/nlm/dev/net/ucore/ucore_app.c && ${LD} -melf32btsmip_fbsd -d -warn-common -T$S/$M/nlm/dev/net/ucore/ld.ucore.S crt0_basic.o ucore_app.o -o ucore_app && ${OBJCOPY} -S -O binary -R .note -R .comment ucore_app ${.TARGET}" \ + no-obj no-implicit-rule before-depend \ + clean "crt0_basic.o ucore_app.o ucore_app ucore_app.bin" +ucore_app_bin.h optional xlpge \ + dependency "ucore_app.bin" \ + compile-with "file2c -sx 'static char ucore_app_bin[] = {' '};' < ucore_app.bin > ${.TARGET}" \ + no-obj no-implicit-rule before-depend \ + clean "ucore_app_bin.h" +# # Security Driver # mips/nlm/dev/sec/nlmsec.c optional nlmsec diff --git a/sys/mips/nlm/hal/interlaken.h b/sys/mips/nlm/hal/interlaken.h new file mode 100644 index 0000000..ce9f840 --- /dev/null +++ b/sys/mips/nlm/hal/interlaken.h @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __NLM_ILAKEN_H__ +#define __NLM_ILAKEN_H__ + +/** +* @file_name interlaken.h +* @author Netlogic Microsystems +* @brief Basic definitions of XLP ILAKEN ports +*/ + +#define ILK_TX_CONTROL(block) NAE_REG(block, 5, 0x00) +#define ILK_TX_RATE_LIMIT(block) NAE_REG(block, 5, 0x01) +#define ILK_TX_META_CTRL(block) NAE_REG(block, 5, 0x02) +#define ILK_RX_CTRL(block) NAE_REG(block, 5, 0x03) +#define ILK_RX_STATUS1(block) NAE_REG(block, 5, 0x04) +#define ILK_RX_STATUS2(block) NAE_REG(block, 5, 0x05) +#define ILK_GENERAL_CTRL1(block) NAE_REG(block, 5, 0x06) +#define ILK_STATUS3(block) NAE_REG(block, 5, 0x07) +#define ILK_RX_FC_TMAP0(block) NAE_REG(block, 5, 0x08) +#define ILK_RX_FC_TMAP1(block) NAE_REG(block, 5, 0x09) +#define ILK_RX_FC_TMAP2(block) NAE_REG(block, 5, 0x0a) +#define ILK_RX_FC_TMAP3(block) NAE_REG(block, 5, 0x0b) +#define ILK_RX_FC_TMAP4(block) NAE_REG(block, 5, 0x0c) +#define ILK_RX_FC_TADDR(block) NAE_REG(block, 5, 0x0d) +#define ILK_GENERAL_CTRL2(block) NAE_REG(block, 5, 0x0e) +#define ILK_GENERAL_CTRL3(block) NAE_REG(block, 5, 0x0f) +#define ILK_SMALL_COUNT0(block) NAE_REG(block, 5, 0x10) +#define ILK_SMALL_COUNT1(block) NAE_REG(block, 5, 0x11) +#define ILK_SMALL_COUNT2(block) NAE_REG(block, 5, 0x12) +#define ILK_SMALL_COUNT3(block) NAE_REG(block, 5, 0x13) +#define ILK_SMALL_COUNT4(block) NAE_REG(block, 5, 0x14) +#define ILK_SMALL_COUNT5(block) NAE_REG(block, 5, 0x15) +#define ILK_SMALL_COUNT6(block) NAE_REG(block, 5, 0x16) +#define ILK_SMALL_COUNT7(block) NAE_REG(block, 5, 0x17) +#define ILK_MID_COUNT0(block) NAE_REG(block, 5, 0x18) +#define ILK_MID_COUNT1(block) NAE_REG(block, 5, 0x19) +#define ILK_LARGE_COUNT0(block) NAE_REG(block, 5, 0x1a) +#define ILK_LARGE_COUNT1(block) NAE_REG(block, 5, 0x1b) +#define ILK_LARGE_COUNT_H0(block) NAE_REG(block, 5, 0x1c) +#define ILK_LARGE_COUNT_H1(block) NAE_REG(block, 5, 0x1d) + +#endif diff --git a/sys/mips/nlm/hal/iomap.h b/sys/mips/nlm/hal/iomap.h index f2d1dd5..7d9ae10 100644 --- a/sys/mips/nlm/hal/iomap.h +++ b/sys/mips/nlm/hal/iomap.h @@ -186,7 +186,7 @@ nlm_irtnum(uint64_t pcibase) } static __inline__ int -nlm_uenginenum(uint64_t pcibase) +nlm_num_uengines(uint64_t pcibase) { return nlm_read_reg(pcibase, XLP_PCI_UCODEINFO_REG); } diff --git a/sys/mips/nlm/hal/mdio.h b/sys/mips/nlm/hal/mdio.h new file mode 100644 index 0000000..6288391 --- /dev/null +++ b/sys/mips/nlm/hal/mdio.h @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __NLM_MDIO_H__ +#define __NLM_MDIO_H__ + +/** +* @file_name mdio.h +* @author Netlogic Microsystems +* @brief Access functions for XLP MDIO +*/ +#define INT_MDIO_CTRL 0x19 +#define INT_MDIO_CTRL_DATA 0x1A +#define INT_MDIO_RD_STAT 0x1B +#define INT_MDIO_LINK_STAT 0x1C +#define EXT_G0_MDIO_CTRL 0x1D +#define EXT_G1_MDIO_CTRL 0x21 +#define EXT_G0_MDIO_CTRL_DATA 0x1E +#define EXT_G1_MDIO_CTRL_DATA 0x22 +#define EXT_G0_MDIO_LINK_STAT 0x20 +#define EXT_G1_MDIO_LINK_STAT 0x24 +#define EXT_G0_MDIO_RD_STAT 0x1F +#define EXT_G1_MDIO_RD_STAT 0x23 + +#define INT_MDIO_CTRL_ST_POS 0 +#define INT_MDIO_CTRL_OP_POS 2 +#define INT_MDIO_CTRL_PHYADDR_POS 4 +#define INT_MDIO_CTRL_DEVTYPE_POS 9 +#define INT_MDIO_CTRL_TA_POS 14 +#define INT_MDIO_CTRL_MIIM_POS 16 +#define INT_MDIO_CTRL_LOAD_POS 19 +#define INT_MDIO_CTRL_XDIV_POS 21 +#define INT_MDIO_CTRL_MCDIV_POS 28 +#define INT_MDIO_CTRL_RST 0x40000000 +#define INT_MDIO_CTRL_SMP 0x00100000 +#define INT_MDIO_CTRL_CMD_LOAD 0x00080000 + +#define INT_MDIO_RD_STAT_MASK 0x0000FFFF +#define INT_MDIO_STAT_LFV 0x00010000 +#define INT_MDIO_STAT_SC 0x00020000 +#define INT_MDIO_STAT_SM 0x00040000 +#define INT_MDIO_STAT_MIILFS 0x00080000 +#define INT_MDIO_STAT_MBSY 0x00100000 + +#define EXT_G_MDIO_CLOCK_DIV_4 0 +#define EXT_G_MDIO_CLOCK_DIV_2 1 +#define EXT_G_MDIO_CLOCK_DIV_1 2 +#define EXT_G_MDIO_REGADDR_POS 5 +#define EXT_G_MDIO_PHYADDR_POS 10 +#define EXT_G_MDIO_CMD_SP 0x00008000 +#define EXT_G_MDIO_CMD_PSIA 0x00010000 +#define EXT_G_MDIO_CMD_LCD 0x00020000 +#define EXT_G_MDIO_CMD_RDS 0x00040000 +#define EXT_G_MDIO_CMD_SC 0x00080000 +#define EXT_G_MDIO_MMRST 0x00100000 +#define EXT_G_MDIO_DIV 0x0000001E + +#define EXT_G_MDIO_RD_STAT_MASK 0x0000FFFF +#define EXT_G_MDIO_STAT_LFV 0x00010000 +#define EXT_G_MDIO_STAT_SC 0x00020000 +#define EXT_G_MDIO_STAT_SM 0x00040000 +#define EXT_G_MDIO_STAT_MIILFS 0x00080000 +#define EXT_G_MDIO_STAT_MBSY 0x80000000 +#define MDIO_OP_CMD_READ 0x10 +#define MDIO_OP_CMD_WRITE 0x01 + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +int nlm_int_gmac_mdio_read(uint64_t, int, int, int, int, int); +int nlm_int_gmac_mdio_write(uint64_t, int, int, int, int, int, uint16_t); +int nlm_int_gmac_mdio_reset(uint64_t, int, int, int); +int nlm_gmac_mdio_read(uint64_t, int, int, int, int, int); +int nlm_gmac_mdio_write(uint64_t, int, int, int, int, int, uint16_t); +int nlm_gmac_mdio_reset(uint64_t, int, int, int); + +#endif /* !(LOCORE) && !(__ASSEMBLY__) */ +#endif diff --git a/sys/mips/nlm/hal/nae.h b/sys/mips/nlm/hal/nae.h new file mode 100644 index 0000000..0738bc7 --- /dev/null +++ b/sys/mips/nlm/hal/nae.h @@ -0,0 +1,646 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __NLM_NAE_H__ +#define __NLM_NAE_H__ + +/** +* @file_name nae.h +* @author Netlogic Microsystems +* @brief Basic definitions of XLP Networt Accelerator Engine +*/ + +/* NAE specific registers */ +#define NAE_REG(blk, intf, reg) (((blk) << 11) | ((intf) << 7) | (reg)) + +/* ingress path registers */ +#define NAE_RX_CONFIG NAE_REG(7, 0, 0x10) +#define NAE_RX_IF_BASE_CONFIG0 NAE_REG(7, 0, 0x12) +#define NAE_RX_IF_BASE_CONFIG1 NAE_REG(7, 0, 0x13) +#define NAE_RX_IF_BASE_CONFIG2 NAE_REG(7, 0, 0x14) +#define NAE_RX_IF_BASE_CONFIG3 NAE_REG(7, 0, 0x15) +#define NAE_RX_IF_BASE_CONFIG4 NAE_REG(7, 0, 0x16) +#define NAE_RX_IF_BASE_CONFIG5 NAE_REG(7, 0, 0x17) +#define NAE_RX_IF_BASE_CONFIG6 NAE_REG(7, 0, 0x18) +#define NAE_RX_IF_BASE_CONFIG7 NAE_REG(7, 0, 0x19) +#define NAE_RX_IF_BASE_CONFIG8 NAE_REG(7, 0, 0x1a) +#define NAE_RX_IF_BASE_CONFIG9 NAE_REG(7, 0, 0x1b) +#define NAE_RX_IF_VEC_VALID NAE_REG(7, 0, 0x1c) +#define NAE_RX_IF_SLOT_CAL NAE_REG(7, 0, 0x1d) +#define NAE_PARSER_CONFIG NAE_REG(7, 0, 0x1e) +#define NAE_PARSER_SEQ_FIFO_CFG NAE_REG(7, 0, 0x1f) +#define NAE_FREE_IN_FIFO_CFG NAE_REG(7, 0, 0x20) +#define NAE_RXBUF_BASE_DPTH_ADDR NAE_REG(7, 0, 0x21) +#define NAE_RXBUF_BASE_DPTH NAE_REG(7, 0, 0x22) +#define NAE_RX_UCORE_CFG NAE_REG(7, 0, 0x23) +#define NAE_RX_UCORE_CAM_MASK0 NAE_REG(7, 0, 0x24) +#define NAE_RX_UCORE_CAM_MASK1 NAE_REG(7, 0, 0x25) +#define NAE_RX_UCORE_CAM_MASK2 NAE_REG(7, 0, 0x26) +#define NAE_RX_UCORE_CAM_MASK3 NAE_REG(7, 0, 0x27) +#define NAE_FREEIN_FIFO_UNIQ_SZ_CFG NAE_REG(7, 0, 0x28) +#define NAE_RX_CRC_POLY0_CFG NAE_REG(7, 0, 0x2a) +#define NAE_RX_CRC_POLY1_CFG NAE_REG(7, 0, 0x2b) +#define NAE_FREE_SPILL0_MEM_CFG NAE_REG(7, 0, 0x2c) +#define NAE_FREE_SPILL1_MEM_CFG NAE_REG(7, 0, 0x2d) +#define NAE_FREEFIFO_THRESH_CFG NAE_REG(7, 0, 0x2e) +#define NAE_FLOW_CRC16_POLY_CFG NAE_REG(7, 0, 0x2f) +#define NAE_EGR_NIOR_CAL_LEN_REG NAE_REG(7, 0, 0x4e) +#define NAE_EGR_NIOR_CRDT_CAL_PROG NAE_REG(7, 0, 0x52) +#define NAE_TEST NAE_REG(7, 0, 0x5f) +#define NAE_BIU_TIMEOUT_CFG NAE_REG(7, 0, 0x60) +#define NAE_BIU_CFG NAE_REG(7, 0, 0x61) +#define NAE_RX_FREE_FIFO_POP NAE_REG(7, 0, 0x62) +#define NAE_RX_DSBL_ECC NAE_REG(7, 0, 0x63) +#define NAE_FLOW_BASEMASK_CFG NAE_REG(7, 0, 0x80) +#define NAE_POE_CLASS_SETUP_CFG NAE_REG(7, 0, 0x81) +#define NAE_UCORE_IFACEMASK_CFG NAE_REG(7, 0, 0x82) +#define NAE_RXBUF_XOFFON_THRESH NAE_REG(7, 0, 0x83) +#define NAE_FLOW_TABLE1_CFG NAE_REG(7, 0, 0x84) +#define NAE_FLOW_TABLE2_CFG NAE_REG(7, 0, 0x85) +#define NAE_FLOW_TABLE3_CFG NAE_REG(7, 0, 0x86) +#define NAE_RX_FREE_FIFO_THRESH NAE_REG(7, 0, 0x87) +#define NAE_RX_PARSER_UNCLA NAE_REG(7, 0, 0x88) +#define NAE_RX_BUF_INTR_THRESH NAE_REG(7, 0, 0x89) +#define NAE_IFACE_FIFO_CFG NAE_REG(7, 0, 0x8a) +#define NAE_PARSER_SEQ_FIFO_THRESH_CFG NAE_REG(7, 0, 0x8b) +#define NAE_RX_ERRINJ_CTRL0 NAE_REG(7, 0, 0x8c) +#define NAE_RX_ERRINJ_CTRL1 NAE_REG(7, 0, 0x8d) +#define NAE_RX_ERR_LATCH0 NAE_REG(7, 0, 0x8e) +#define NAE_RX_ERR_LATCH1 NAE_REG(7, 0, 0x8f) +#define NAE_RX_PERF_CTR_CFG NAE_REG(7, 0, 0xa0) +#define NAE_RX_PERF_CTR_VAL NAE_REG(7, 0, 0xa1) + +/* NAE hardware parser registers */ +#define NAE_L2_TYPE_PORT0 NAE_REG(7, 0, 0x210) +#define NAE_L2_TYPE_PORT1 NAE_REG(7, 0, 0x211) +#define NAE_L2_TYPE_PORT2 NAE_REG(7, 0, 0x212) +#define NAE_L2_TYPE_PORT3 NAE_REG(7, 0, 0x213) +#define NAE_L2_TYPE_PORT4 NAE_REG(7, 0, 0x214) +#define NAE_L2_TYPE_PORT5 NAE_REG(7, 0, 0x215) +#define NAE_L2_TYPE_PORT6 NAE_REG(7, 0, 0x216) +#define NAE_L2_TYPE_PORT7 NAE_REG(7, 0, 0x217) +#define NAE_L2_TYPE_PORT8 NAE_REG(7, 0, 0x218) +#define NAE_L2_TYPE_PORT9 NAE_REG(7, 0, 0x219) +#define NAE_L2_TYPE_PORT10 NAE_REG(7, 0, 0x21a) +#define NAE_L2_TYPE_PORT11 NAE_REG(7, 0, 0x21b) +#define NAE_L2_TYPE_PORT12 NAE_REG(7, 0, 0x21c) +#define NAE_L2_TYPE_PORT13 NAE_REG(7, 0, 0x21d) +#define NAE_L2_TYPE_PORT14 NAE_REG(7, 0, 0x21e) +#define NAE_L2_TYPE_PORT15 NAE_REG(7, 0, 0x21f) +#define NAE_L2_TYPE_PORT16 NAE_REG(7, 0, 0x220) +#define NAE_L2_TYPE_PORT17 NAE_REG(7, 0, 0x221) +#define NAE_L2_TYPE_PORT18 NAE_REG(7, 0, 0x222) +#define NAE_L2_TYPE_PORT19 NAE_REG(7, 0, 0x223) +#define NAE_L3_CTABLE_MASK0 NAE_REG(7, 0, 0x22c) +#define NAE_L3_CTABLE_MASK1 NAE_REG(7, 0, 0x22d) +#define NAE_L3_CTABLE_MASK2 NAE_REG(7, 0, 0x22e) +#define NAE_L3_CTABLE_MASK3 NAE_REG(7, 0, 0x22f) +#define NAE_L3CTABLE0 NAE_REG(7, 0, 0x230) +#define NAE_L3CTABLE1 NAE_REG(7, 0, 0x231) +#define NAE_L3CTABLE2 NAE_REG(7, 0, 0x232) +#define NAE_L3CTABLE3 NAE_REG(7, 0, 0x233) +#define NAE_L3CTABLE4 NAE_REG(7, 0, 0x234) +#define NAE_L3CTABLE5 NAE_REG(7, 0, 0x235) +#define NAE_L3CTABLE6 NAE_REG(7, 0, 0x236) +#define NAE_L3CTABLE7 NAE_REG(7, 0, 0x237) +#define NAE_L3CTABLE8 NAE_REG(7, 0, 0x238) +#define NAE_L3CTABLE9 NAE_REG(7, 0, 0x239) +#define NAE_L3CTABLE10 NAE_REG(7, 0, 0x23a) +#define NAE_L3CTABLE11 NAE_REG(7, 0, 0x23b) +#define NAE_L3CTABLE12 NAE_REG(7, 0, 0x23c) +#define NAE_L3CTABLE13 NAE_REG(7, 0, 0x23d) +#define NAE_L3CTABLE14 NAE_REG(7, 0, 0x23e) +#define NAE_L3CTABLE15 NAE_REG(7, 0, 0x23f) +#define NAE_L4CTABLE0 NAE_REG(7, 0, 0x250) +#define NAE_L4CTABLE1 NAE_REG(7, 0, 0x251) +#define NAE_L4CTABLE2 NAE_REG(7, 0, 0x252) +#define NAE_L4CTABLE3 NAE_REG(7, 0, 0x253) +#define NAE_L4CTABLE4 NAE_REG(7, 0, 0x254) +#define NAE_L4CTABLE5 NAE_REG(7, 0, 0x255) +#define NAE_L4CTABLE6 NAE_REG(7, 0, 0x256) +#define NAE_L4CTABLE7 NAE_REG(7, 0, 0x257) +#define NAE_IPV6_EXT_HEADER0 NAE_REG(7, 0, 0x260) +#define NAE_IPV6_EXT_HEADER1 NAE_REG(7, 0, 0x261) +#define NAE_VLAN_TYPES01 NAE_REG(7, 0, 0x262) +#define NAE_VLAN_TYPES23 NAE_REG(7, 0, 0x263) + +/* NAE Egress path registers */ +#define NAE_TX_CONFIG NAE_REG(7, 0, 0x11) +#define NAE_DMA_TX_CREDIT_TH NAE_REG(7, 0, 0x29) +#define NAE_STG1_STG2CRDT_CMD NAE_REG(7, 0, 0x30) +#define NAE_STG2_EHCRDT_CMD NAE_REG(7, 0, 0x32) +#define NAE_EH_FREECRDT_CMD NAE_REG(7, 0, 0x34) +#define NAE_STG2_STRCRDT_CMD NAE_REG(7, 0, 0x36) +#define NAE_TXFIFO_IFACEMAP_CMD NAE_REG(7, 0, 0x38) +#define NAE_VFBID_DESTMAP_CMD NAE_REG(7, 0, 0x3a) +#define NAE_STG1_PMEM_PROG NAE_REG(7, 0, 0x3c) +#define NAE_STG2_PMEM_PROG NAE_REG(7, 0, 0x3e) +#define NAE_EH_PMEM_PROG NAE_REG(7, 0, 0x40) +#define NAE_FREE_PMEM_PROG NAE_REG(7, 0, 0x42) +#define NAE_TX_DDR_ACTVLIST_CMD NAE_REG(7, 0, 0x44) +#define NAE_TX_IF_BURSTMAX_CMD NAE_REG(7, 0, 0x46) +#define NAE_TX_IF_ENABLE_CMD NAE_REG(7, 0, 0x48) +#define NAE_TX_PKTLEN_PMEM_CMD NAE_REG(7, 0, 0x4a) +#define NAE_TX_SCHED_MAP_CMD0 NAE_REG(7, 0, 0x4c) +#define NAE_TX_SCHED_MAP_CMD1 NAE_REG(7, 0, 0x4d) +#define NAE_TX_PKT_PMEM_CMD0 NAE_REG(7, 0, 0x50) +#define NAE_TX_PKT_PMEM_CMD1 NAE_REG(7, 0, 0x51) +#define NAE_TX_SCHED_CTRL NAE_REG(7, 0, 0x53) +#define NAE_TX_CRC_POLY0 NAE_REG(7, 0, 0x54) +#define NAE_TX_CRC_POLY1 NAE_REG(7, 0, 0x55) +#define NAE_TX_CRC_POLY2 NAE_REG(7, 0, 0x56) +#define NAE_TX_CRC_POLY3 NAE_REG(7, 0, 0x57) +#define NAE_STR_PMEM_CMD NAE_REG(7, 0, 0x58) +#define NAE_TX_IORCRDT_INIT NAE_REG(7, 0, 0x59) +#define NAE_TX_DSBL_ECC NAE_REG(7, 0, 0x5a) +#define NAE_TX_IORCRDT_IGNORE NAE_REG(7, 0, 0x5b) +#define NAE_IF0_1588_TMSTMP_HI NAE_REG(7, 0, 0x300) +#define NAE_IF1_1588_TMSTMP_HI NAE_REG(7, 0, 0x302) +#define NAE_IF2_1588_TMSTMP_HI NAE_REG(7, 0, 0x304) +#define NAE_IF3_1588_TMSTMP_HI NAE_REG(7, 0, 0x306) +#define NAE_IF4_1588_TMSTMP_HI NAE_REG(7, 0, 0x308) +#define NAE_IF5_1588_TMSTMP_HI NAE_REG(7, 0, 0x30a) +#define NAE_IF6_1588_TMSTMP_HI NAE_REG(7, 0, 0x30c) +#define NAE_IF7_1588_TMSTMP_HI NAE_REG(7, 0, 0x30e) +#define NAE_IF8_1588_TMSTMP_HI NAE_REG(7, 0, 0x310) +#define NAE_IF9_1588_TMSTMP_HI NAE_REG(7, 0, 0x312) +#define NAE_IF10_1588_TMSTMP_HI NAE_REG(7, 0, 0x314) +#define NAE_IF11_1588_TMSTMP_HI NAE_REG(7, 0, 0x316) +#define NAE_IF12_1588_TMSTMP_HI NAE_REG(7, 0, 0x318) +#define NAE_IF13_1588_TMSTMP_HI NAE_REG(7, 0, 0x31a) +#define NAE_IF14_1588_TMSTMP_HI NAE_REG(7, 0, 0x31c) +#define NAE_IF15_1588_TMSTMP_HI NAE_REG(7, 0, 0x31e) +#define NAE_IF16_1588_TMSTMP_HI NAE_REG(7, 0, 0x320) +#define NAE_IF17_1588_TMSTMP_HI NAE_REG(7, 0, 0x322) +#define NAE_IF18_1588_TMSTMP_HI NAE_REG(7, 0, 0x324) +#define NAE_IF19_1588_TMSTMP_HI NAE_REG(7, 0, 0x326) +#define NAE_IF0_1588_TMSTMP_LO NAE_REG(7, 0, 0x301) +#define NAE_IF1_1588_TMSTMP_LO NAE_REG(7, 0, 0x303) +#define NAE_IF2_1588_TMSTMP_LO NAE_REG(7, 0, 0x305) +#define NAE_IF3_1588_TMSTMP_LO NAE_REG(7, 0, 0x307) +#define NAE_IF4_1588_TMSTMP_LO NAE_REG(7, 0, 0x309) +#define NAE_IF5_1588_TMSTMP_LO NAE_REG(7, 0, 0x30b) +#define NAE_IF6_1588_TMSTMP_LO NAE_REG(7, 0, 0x30d) +#define NAE_IF7_1588_TMSTMP_LO NAE_REG(7, 0, 0x30f) +#define NAE_IF8_1588_TMSTMP_LO NAE_REG(7, 0, 0x311) +#define NAE_IF9_1588_TMSTMP_LO NAE_REG(7, 0, 0x313) +#define NAE_IF10_1588_TMSTMP_LO NAE_REG(7, 0, 0x315) +#define NAE_IF11_1588_TMSTMP_LO NAE_REG(7, 0, 0x317) +#define NAE_IF12_1588_TMSTMP_LO NAE_REG(7, 0, 0x319) +#define NAE_IF13_1588_TMSTMP_LO NAE_REG(7, 0, 0x31b) +#define NAE_IF14_1588_TMSTMP_LO NAE_REG(7, 0, 0x31d) +#define NAE_IF15_1588_TMSTMP_LO NAE_REG(7, 0, 0x31f) +#define NAE_IF16_1588_TMSTMP_LO NAE_REG(7, 0, 0x321) +#define NAE_IF17_1588_TMSTMP_LO NAE_REG(7, 0, 0x323) +#define NAE_IF18_1588_TMSTMP_LO NAE_REG(7, 0, 0x325) +#define NAE_IF19_1588_TMSTMP_LO NAE_REG(7, 0, 0x327) +#define NAE_TX_EL0 NAE_REG(7, 0, 0x328) +#define NAE_TX_EL1 NAE_REG(7, 0, 0x329) +#define NAE_EIC0 NAE_REG(7, 0, 0x32a) +#define NAE_EIC1 NAE_REG(7, 0, 0x32b) +#define NAE_STG1_STG2CRDT_STATUS NAE_REG(7, 0, 0x32c) +#define NAE_STG2_EHCRDT_STATUS NAE_REG(7, 0, 0x32d) +#define NAE_STG2_FREECRDT_STATUS NAE_REG(7, 0, 0x32e) +#define NAE_STG2_STRCRDT_STATUS NAE_REG(7, 0, 0x32f) +#define NAE_TX_PERF_CNTR_INTR_STATUS NAE_REG(7, 0, 0x330) +#define NAE_TX_PERF_CNTR_ROLL_STATUS NAE_REG(7, 0, 0x331) +#define NAE_TX_PERF_CNTR0 NAE_REG(7, 0, 0x332) +#define NAE_TX_PERF_CNTR1 NAE_REG(7, 0, 0x334) +#define NAE_TX_PERF_CNTR2 NAE_REG(7, 0, 0x336) +#define NAE_TX_PERF_CNTR3 NAE_REG(7, 0, 0x338) +#define NAE_TX_PERF_CNTR4 NAE_REG(7, 0, 0x33a) +#define NAE_TX_PERF_CNTR0_CTL NAE_REG(7, 0, 0x333) +#define NAE_TX_PERF_CNTR1_CTL NAE_REG(7, 0, 0x335) +#define NAE_TX_PERF_CNTR2_CTL NAE_REG(7, 0, 0x337) +#define NAE_TX_PERF_CNTR3_CTL NAE_REG(7, 0, 0x339) +#define NAE_TX_PERF_CNTR4_CTL NAE_REG(7, 0, 0x33b) +#define NAE_VFBID_DESTMAP_STATUS NAE_REG(7, 0, 0x380) +#define NAE_STG2_PMEM_STATUS NAE_REG(7, 0, 0x381) +#define NAE_EH_PMEM_STATUS NAE_REG(7, 0, 0x382) +#define NAE_FREE_PMEM_STATUS NAE_REG(7, 0, 0x383) +#define NAE_TX_DDR_ACTVLIST_STATUS NAE_REG(7, 0, 0x384) +#define NAE_TX_IF_BURSTMAX_STATUS NAE_REG(7, 0, 0x385) +#define NAE_TX_PKTLEN_PMEM_STATUS NAE_REG(7, 0, 0x386) +#define NAE_TX_SCHED_MAP_STATUS0 NAE_REG(7, 0, 0x387) +#define NAE_TX_SCHED_MAP_STATUS1 NAE_REG(7, 0, 0x388) +#define NAE_TX_PKT_PMEM_STATUS NAE_REG(7, 0, 0x389) +#define NAE_STR_PMEM_STATUS NAE_REG(7, 0, 0x38a) + +/* Network interface interrupt registers */ +#define NAE_NET_IF0_INTR_STAT NAE_REG(7, 0, 0x280) +#define NAE_NET_IF1_INTR_STAT NAE_REG(7, 0, 0x282) +#define NAE_NET_IF2_INTR_STAT NAE_REG(7, 0, 0x284) +#define NAE_NET_IF3_INTR_STAT NAE_REG(7, 0, 0x286) +#define NAE_NET_IF4_INTR_STAT NAE_REG(7, 0, 0x288) +#define NAE_NET_IF5_INTR_STAT NAE_REG(7, 0, 0x28a) +#define NAE_NET_IF6_INTR_STAT NAE_REG(7, 0, 0x28c) +#define NAE_NET_IF7_INTR_STAT NAE_REG(7, 0, 0x28e) +#define NAE_NET_IF8_INTR_STAT NAE_REG(7, 0, 0x290) +#define NAE_NET_IF9_INTR_STAT NAE_REG(7, 0, 0x292) +#define NAE_NET_IF10_INTR_STAT NAE_REG(7, 0, 0x294) +#define NAE_NET_IF11_INTR_STAT NAE_REG(7, 0, 0x296) +#define NAE_NET_IF12_INTR_STAT NAE_REG(7, 0, 0x298) +#define NAE_NET_IF13_INTR_STAT NAE_REG(7, 0, 0x29a) +#define NAE_NET_IF14_INTR_STAT NAE_REG(7, 0, 0x29c) +#define NAE_NET_IF15_INTR_STAT NAE_REG(7, 0, 0x29e) +#define NAE_NET_IF16_INTR_STAT NAE_REG(7, 0, 0x2a0) +#define NAE_NET_IF17_INTR_STAT NAE_REG(7, 0, 0x2a2) +#define NAE_NET_IF18_INTR_STAT NAE_REG(7, 0, 0x2a4) +#define NAE_NET_IF19_INTR_STAT NAE_REG(7, 0, 0x2a6) +#define NAE_NET_IF0_INTR_MASK NAE_REG(7, 0, 0x281) +#define NAE_NET_IF1_INTR_MASK NAE_REG(7, 0, 0x283) +#define NAE_NET_IF2_INTR_MASK NAE_REG(7, 0, 0x285) +#define NAE_NET_IF3_INTR_MASK NAE_REG(7, 0, 0x287) +#define NAE_NET_IF4_INTR_MASK NAE_REG(7, 0, 0x289) +#define NAE_NET_IF5_INTR_MASK NAE_REG(7, 0, 0x28b) +#define NAE_NET_IF6_INTR_MASK NAE_REG(7, 0, 0x28d) +#define NAE_NET_IF7_INTR_MASK NAE_REG(7, 0, 0x28f) +#define NAE_NET_IF8_INTR_MASK NAE_REG(7, 0, 0x291) +#define NAE_NET_IF9_INTR_MASK NAE_REG(7, 0, 0x293) +#define NAE_NET_IF10_INTR_MASK NAE_REG(7, 0, 0x295) +#define NAE_NET_IF11_INTR_MASK NAE_REG(7, 0, 0x297) +#define NAE_NET_IF12_INTR_MASK NAE_REG(7, 0, 0x299) +#define NAE_NET_IF13_INTR_MASK NAE_REG(7, 0, 0x29b) +#define NAE_NET_IF14_INTR_MASK NAE_REG(7, 0, 0x29d) +#define NAE_NET_IF15_INTR_MASK NAE_REG(7, 0, 0x29f) +#define NAE_NET_IF16_INTR_MASK NAE_REG(7, 0, 0x2a1) +#define NAE_NET_IF17_INTR_MASK NAE_REG(7, 0, 0x2a3) +#define NAE_NET_IF18_INTR_MASK NAE_REG(7, 0, 0x2a5) +#define NAE_NET_IF19_INTR_MASK NAE_REG(7, 0, 0x2a7) +#define NAE_COMMON0_INTR_STAT NAE_REG(7, 0, 0x2a8) +#define NAE_COMMON0_INTR_MASK NAE_REG(7, 0, 0x2a9) +#define NAE_COMMON1_INTR_STAT NAE_REG(7, 0, 0x2aa) +#define NAE_COMMON1_INTR_MASK NAE_REG(7, 0, 0x2ab) + +/* Network Interface Low-block Registers */ +#define NAE_PHY_LANE0_STATUS(block) NAE_REG(block, 0xe, 0) +#define NAE_PHY_LANE1_STATUS(block) NAE_REG(block, 0xe, 1) +#define NAE_PHY_LANE2_STATUS(block) NAE_REG(block, 0xe, 2) +#define NAE_PHY_LANE3_STATUS(block) NAE_REG(block, 0xe, 3) +#define NAE_PHY_LANE0_CTRL(block) NAE_REG(block, 0xe, 4) +#define NAE_PHY_LANE1_CTRL(block) NAE_REG(block, 0xe, 5) +#define NAE_PHY_LANE2_CTRL(block) NAE_REG(block, 0xe, 6) +#define NAE_PHY_LANE3_CTRL(block) NAE_REG(block, 0xe, 7) + +/* Network interface Top-block registers */ +#define NAE_LANE_CFG_CPLX_0_1 NAE_REG(7, 0, 0x780) +#define NAE_LANE_CFG_CPLX_2_3 NAE_REG(7, 0, 0x781) +#define NAE_LANE_CFG_CPLX_4 NAE_REG(7, 0, 0x782) +#define NAE_LANE_CFG_SOFTRESET NAE_REG(7, 0, 0x783) +#define NAE_1588_PTP_OFFSET_HI NAE_REG(7, 0, 0x784) +#define NAE_1588_PTP_OFFSET_LO NAE_REG(7, 0, 0x785) +#define NAE_1588_PTP_INC_DEN NAE_REG(7, 0, 0x786) +#define NAE_1588_PTP_INC_NUM NAE_REG(7, 0, 0x787) +#define NAE_1588_PTP_INC_INTG NAE_REG(7, 0, 0x788) +#define NAE_1588_PTP_CONTROL NAE_REG(7, 0, 0x789) +#define NAE_1588_PTP_STATUS NAE_REG(7, 0, 0x78a) +#define NAE_1588_PTP_USER_VALUE_HI NAE_REG(7, 0, 0x78b) +#define NAE_1588_PTP_USER_VALUE_LO NAE_REG(7, 0, 0x78c) +#define NAE_1588_PTP_TMR1_HI NAE_REG(7, 0, 0x78d) +#define NAE_1588_PTP_TMR1_LO NAE_REG(7, 0, 0x78e) +#define NAE_1588_PTP_TMR2_HI NAE_REG(7, 0, 0x78f) +#define NAE_1588_PTP_TMR2_LO NAE_REG(7, 0, 0x790) +#define NAE_1588_PTP_TMR3_HI NAE_REG(7, 0, 0x791) +#define NAE_1588_PTP_TMR3_LO NAE_REG(7, 0, 0x792) +#define NAE_TX_FC_CAL_IDX_TBL_CTRL NAE_REG(7, 0, 0x793) +#define NAE_TX_FC_CAL_TBL_CTRL NAE_REG(7, 0, 0x794) +#define NAE_TX_FC_CAL_TBL_DATA0 NAE_REG(7, 0, 0x795) +#define NAE_TX_FC_CAL_TBL_DATA1 NAE_REG(7, 0, 0x796) +#define NAE_TX_FC_CAL_TBL_DATA2 NAE_REG(7, 0, 0x797) +#define NAE_TX_FC_CAL_TBL_DATA3 NAE_REG(7, 0, 0x798) +#define NAE_INT_MDIO_CTRL NAE_REG(7, 0, 0x799) +#define NAE_INT_MDIO_CTRL_DATA NAE_REG(7, 0, 0x79a) +#define NAE_INT_MDIO_RD_STAT NAE_REG(7, 0, 0x79b) +#define NAE_INT_MDIO_LINK_STAT NAE_REG(7, 0, 0x79c) +#define NAE_EXT_G0_MDIO_CTRL NAE_REG(7, 0, 0x79d) +#define NAE_EXT_G1_MDIO_CTRL NAE_REG(7, 0, 0x7a1) +#define NAE_EXT_G0_MDIO_CTRL_DATA NAE_REG(7, 0, 0x79e) +#define NAE_EXT_G1_MDIO_CTRL_DATA NAE_REG(7, 0, 0x7a2) +#define NAE_EXT_G0_MDIO_RD_STAT NAE_REG(7, 0, 0x79f) +#define NAE_EXT_G1_MDIO_RD_STAT NAE_REG(7, 0, 0x7a3) +#define NAE_EXT_G0_MDIO_LINK_STAT NAE_REG(7, 0, 0x7a0) +#define NAE_EXT_G1_MDIO_LINK_STAT NAE_REG(7, 0, 0x7a4) +#define NAE_EXT_XG0_MDIO_CTRL NAE_REG(7, 0, 0x7a5) +#define NAE_EXT_XG1_MDIO_CTRL NAE_REG(7, 0, 0x7a9) +#define NAE_EXT_XG0_MDIO_CTRL_DATA NAE_REG(7, 0, 0x7a6) +#define NAE_EXT_XG1_MDIO_CTRL_DATA NAE_REG(7, 0, 0x7aa) +#define NAE_EXT_XG0_MDIO_RD_STAT NAE_REG(7, 0, 0x7a7) +#define NAE_EXT_XG1_MDIO_RD_STAT NAE_REG(7, 0, 0x7ab) +#define NAE_EXT_XG0_MDIO_LINK_STAT NAE_REG(7, 0, 0x7a8) +#define NAE_EXT_XG1_MDIO_LINK_STAT NAE_REG(7, 0, 0x7ac) +#define NAE_GMAC_FC_SLOT0 NAE_REG(7, 0, 0x7ad) +#define NAE_GMAC_FC_SLOT1 NAE_REG(7, 0, 0x7ae) +#define NAE_GMAC_FC_SLOT2 NAE_REG(7, 0, 0x7af) +#define NAE_GMAC_FC_SLOT3 NAE_REG(7, 0, 0x7b0) +#define NAE_NETIOR_NTB_SLOT NAE_REG(7, 0, 0x7b1) +#define NAE_NETIOR_MISC_CTRL0 NAE_REG(7, 0, 0x7b2) +#define NAE_NETIOR_INT0 NAE_REG(7, 0, 0x7b3) +#define NAE_NETIOR_INT0_MASK NAE_REG(7, 0, 0x7b4) +#define NAE_NETIOR_INT1 NAE_REG(7, 0, 0x7b5) +#define NAE_NETIOR_INT1_MASK NAE_REG(7, 0, 0x7b6) +#define NAE_GMAC_PFC_REPEAT NAE_REG(7, 0, 0x7b7) +#define NAE_XGMAC_PFC_REPEAT NAE_REG(7, 0, 0x7b8) +#define NAE_NETIOR_MISC_CTRL1 NAE_REG(7, 0, 0x7b9) +#define NAE_NETIOR_MISC_CTRL2 NAE_REG(7, 0, 0x7ba) +#define NAE_NETIOR_INT2 NAE_REG(7, 0, 0x7bb) +#define NAE_NETIOR_INT2_MASK NAE_REG(7, 0, 0x7bc) +#define NAE_NETIOR_MISC_CTRL3 NAE_REG(7, 0, 0x7bd) + +/* Network interface lane configuration registers */ +#define NAE_LANE_CFG_MISCREG1 NAE_REG(7, 0xf, 0x39) +#define NAE_LANE_CFG_MISCREG2 NAE_REG(7, 0xf, 0x3A) + +/* Network interface soft reset register */ +#define NAE_SOFT_RESET NAE_REG(7, 0xf, 3) + +/* ucore instruction/shared CAM RAM access */ +#define NAE_UCORE_SHARED_RAM_OFFSET 0x10000 + +#define PORTS_PER_CMPLX 4 +#define NAE_CACHELINE_SIZE 64 + +#define PHY_LANE_0_CTRL 4 +#define PHY_LANE_1_CTRL 5 +#define PHY_LANE_2_CTRL 6 +#define PHY_LANE_3_CTRL 7 + +#define PHY_LANE_STAT_SRCS 0x00000001 +#define PHY_LANE_STAT_STD 0x00000010 +#define PHY_LANE_STAT_SFEA 0x00000020 +#define PHY_LANE_STAT_STCS 0x00000040 +#define PHY_LANE_STAT_SPC 0x00000200 +#define PHY_LANE_STAT_XLF 0x00000400 +#define PHY_LANE_STAT_PCR 0x00000800 + +#define PHY_LANE_CTRL_DATA_POS 0 +#define PHY_LANE_CTRL_ADDR_POS 8 +#define PHY_LANE_CTRL_CMD_READ 0x00010000 +#define PHY_LANE_CTRL_CMD_WRITE 0x00000000 +#define PHY_LANE_CTRL_CMD_START 0x00020000 +#define PHY_LANE_CTRL_CMD_PENDING 0x00040000 +#define PHY_LANE_CTRL_ALL 0x00200000 +#define PHY_LANE_CTRL_FAST_INIT 0x00400000 +#define PHY_LANE_CTRL_REXSEL_POS 23 +#define PHY_LANE_CTRL_PHYMODE_POS 25 +#define PHY_LANE_CTRL_PWRDOWN 0x20000000 +#define PHY_LANE_CTRL_RST 0x40000000 +#define PHY_LANE_CTRL_RST_XAUI 0xc0000000 +#define PHY_LANE_CTRL_BPC_XAUI 0x80000000 + +#define LANE_CFG_CPLX_0_1 0x0 +#define LANE_CFG_CPLX_2_3 0x1 +#define LANE_CFG_CPLX_4 0x2 + +#define MAC_CONF1 0x0 +#define MAC_CONF2 0x1 +#define MAX_FRM 0x4 + +#define NETIOR_GMAC_CTRL1 0x7F +#define NETIOR_GMAC_CTRL2 0x7E +#define NETIOR_GMAC_CTRL3 0x7C + +#define SGMII_CAL_SLOTS 3 +#define XAUI_CAL_SLOTS 13 +#define IL8_CAL_SLOTS 26 +#define IL4_CAL_SLOTS 10 + +#define NAE_DRR_QUANTA 2048 + +#define XLP3XX_STG2_FIFO_SZ 512 +#define XLP3XX_EH_FIFO_SZ 512 +#define XLP3XX_FROUT_FIFO_SZ 512 +#define XLP3XX_MS_FIFO_SZ 512 +#define XLP3XX_PKT_FIFO_SZ 8192 +#define XLP3XX_PKTLEN_FIFO_SZ 512 + +#define XLP3XX_MAX_STG2_OFFSET 0x7F +#define XLP3XX_MAX_EH_OFFSET 0x1f +#define XLP3XX_MAX_FREE_OUT_OFFSET 0x1f +#define XLP3XX_MAX_MS_OFFSET 0xF +#define XLP3XX_MAX_PMEM_OFFSET 0x7FE + +#define XLP3XX_STG1_2_CREDIT XLP3XX_STG2_FIFO_SZ +#define XLP3XX_STG2_EH_CREDIT XLP3XX_EH_FIFO_SZ +#define XLP3XX_STG2_FROUT_CREDIT XLP3XX_FROUT_FIFO_SZ +#define XLP3XX_STG2_MS_CREDIT XLP3XX_MS_FIFO_SZ + +#define XLP8XX_STG2_FIFO_SZ 2048 +#define XLP8XX_EH_FIFO_SZ 4096 +#define XLP8XX_FROUT_FIFO_SZ 4096 +#define XLP8XX_MS_FIFO_SZ 2048 +#define XLP8XX_PKT_FIFO_SZ 16384 +#define XLP8XX_PKTLEN_FIFO_SZ 2048 + +#define XLP8XX_MAX_STG2_OFFSET 0x7F +#define XLP8XX_MAX_EH_OFFSET 0x7F +#define XLP8XX_MAX_FREE_OUT_OFFSET 0x7F +#define XLP8XX_MAX_MS_OFFSET 0x1F +#define XLP8XX_MAX_PMEM_OFFSET 0x7FE + +#define XLP8XX_STG1_2_CREDIT XLP8XX_STG2_FIFO_SZ +#define XLP8XX_STG2_EH_CREDIT XLP8XX_EH_FIFO_SZ +#define XLP8XX_STG2_FROUT_CREDIT XLP8XX_FROUT_FIFO_SZ +#define XLP8XX_STG2_MS_CREDIT XLP8XX_MS_FIFO_SZ + +#define MAX_CAL_SLOTS 64 +#define XLP_MAX_PORTS 18 +#define XLP_STORM_MAX_PORTS 8 + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#define nlm_read_nae_reg(b, r) nlm_read_reg_xkphys(b, r) +#define nlm_write_nae_reg(b, r, v) nlm_write_reg_xkphys(b, r, v) +#define nlm_get_nae_pcibase(node) \ + nlm_pcicfg_base(XLP_IO_NAE_OFFSET(node)) +#define nlm_get_nae_regbase(node) \ + nlm_xkphys_map_pcibar0(nlm_get_nae_pcibase(node)) + +#define MAX_POE_CLASSES 8 +#define MAX_POE_CLASS_CTXT_TBL_SZ ((NUM_CONTEXTS / MAX_POE_CLASSES) + 1) +#define TXINITIORCR(x) (((x) & 0x7ffff) << 8) + +enum XLPNAE_TX_TYPE { + P2D_NEOP = 0, + P2P, + P2D_EOP, + MSC +}; + +enum nblock_type { + SGMIIC = 1, + XAUIC = 2, + ILC = 3 +}; + +enum nae_interface_type { + GMAC_0 = 0, + GMAC_1, + GMAC_2, + GMAC_3, + XGMAC, + INTERLAKEN, + PHY = 0xE, + LANE_CFG = 0xF, +}; + +enum { + LM_UNCONNECTED = 0, + LM_SGMII = 1, + LM_XAUI = 2, + LM_IL = 3, +}; + +enum nae_block { + BLOCK_0 = 0, + BLOCK_1, + BLOCK_2, + BLOCK_3, + BLOCK_4, + BLOCK_5, + BLOCK_6, + BLOCK_7, +}; + +enum { + PHYMODE_NONE = 0, + PHYMODE_HS_SGMII = 1, + PHYMODE_XAUI = 1, + PHYMODE_SGMII = 2, + PHYMODE_IL = 3, +}; + +static __inline int +nae_num_complex(uint64_t nae_pcibase) +{ + return (nlm_read_reg(nae_pcibase, XLP_PCI_DEVINFO_REG0) & 0xff); +} + +static __inline int +nae_num_context(uint64_t nae_pcibase) +{ + return (nlm_read_reg(nae_pcibase, XLP_PCI_DEVINFO_REG5)); +} + +/* per port config structure */ +struct nae_port_config { + int num_channels; + int num_free_descs; + int free_desc_sizes; + int ucore_mask; + int loopback_mode; /* is complex is in loopback? */ + uint32_t freein_spill_size; /* Freein spill size for each port */ + uint32_t free_fifo_size; /* (512entries x 2desc/entry)1024desc */ + uint32_t iface_fifo_size;/* 256 entries x 64B/entry = 16KB */ + uint32_t pseq_fifo_size; /* 1024 entries - 1 pktlen/entry */ + uint32_t rxbuf_size; /* 4096 entries x 64B = 256KB */ + uint32_t rx_if_base_config; + uint32_t rx_slots_reqd; + uint32_t tx_slots_reqd; + uint32_t stg2_fifo_size; + uint32_t eh_fifo_size; + uint32_t frout_fifo_size; + uint32_t ms_fifo_size; + uint32_t pkt_fifo_size; + uint32_t pktlen_fifo_size; + uint32_t max_stg2_offset; + uint32_t max_eh_offset; + uint32_t max_frout_offset; + uint32_t max_ms_offset; + uint32_t max_pmem_offset; + uint32_t stg1_2_credit; + uint32_t stg2_eh_credit; + uint32_t stg2_frout_credit; + uint32_t stg2_ms_credit; + uint32_t vlan_pri_en; + uint32_t txq; + uint32_t rxfreeq; + uint32_t ieee1588_inc_intg; + uint32_t ieee1588_inc_den; + uint32_t ieee1588_inc_num; + uint64_t ieee1588_userval; + uint64_t ieee1588_ptpoff; + uint64_t ieee1588_tmr1; + uint64_t ieee1588_tmr2; + uint64_t ieee1588_tmr3; +}; + +void nlm_nae_flush_free_fifo(uint64_t nae_base, int nblocks); +void nlm_program_nae_parser_seq_fifo(uint64_t, int, struct nae_port_config *); +void nlm_setup_rx_cal_cfg(uint64_t, int, struct nae_port_config *); +void nlm_setup_tx_cal_cfg(uint64_t, int, struct nae_port_config *cfg); +void nlm_deflate_frin_fifo_carving(uint64_t, int); +void nlm_reset_nae(int); +int nlm_set_nae_frequency(int, int); +void nlm_setup_poe_class_config(uint64_t nae_base, int max_poe_classes, + int num_contexts, int *poe_cl_tbl); +void nlm_setup_vfbid_mapping(uint64_t); +void nlm_setup_flow_crc_poly(uint64_t, uint32_t); +void nlm_setup_iface_fifo_cfg(uint64_t, int, struct nae_port_config *); +void nlm_setup_rx_base_config(uint64_t, int, struct nae_port_config *); +void nlm_setup_rx_buf_config(uint64_t, int, struct nae_port_config *); +void nlm_setup_freein_fifo_cfg(uint64_t, int, struct nae_port_config *); +int nlm_get_flow_mask(int); +void nlm_program_flow_cfg(uint64_t, int, uint32_t, uint32_t); +void xlp_ax_nae_lane_reset_txpll(uint64_t, int, int, int); +void xlp_nae_lane_reset_txpll(uint64_t, int, int, int); +void xlp_nae_config_lane_gmac(uint64_t, int); +void config_egress_fifo_carvings(uint64_t, int, int, int, int, + struct nae_port_config *); +void config_egress_fifo_credits(uint64_t, int, int, int, int, + struct nae_port_config *); +void nlm_config_freein_fifo_uniq_cfg(uint64_t, int, int); +void nlm_config_ucore_iface_mask_cfg(uint64_t, int, int); +int nlm_nae_init_netior(uint64_t nae_base, int nblocks); +void nlm_nae_init_ingress(uint64_t, uint32_t); +void nlm_nae_init_egress(uint64_t); +uint32_t ucore_spray_config(uint32_t, uint32_t, int); +void nlm_nae_init_ucore(uint64_t nae_base, int if_num, uint32_t ucore_mask); +int nlm_nae_open_if(uint64_t, int, int, int, uint32_t); +void nlm_mac_enable(uint64_t, int, int, int); +void nlm_mac_disable(uint64_t, int, int, int); +uint64_t nae_tx_desc(u_int, u_int, u_int, u_int, uint64_t); +void nlm_setup_l2type(uint64_t, int, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); +void nlm_setup_l3ctable_mask(uint64_t, int, uint32_t, uint32_t); +void nlm_setup_l3ctable_even(uint64_t, int, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t); +void nlm_setup_l3ctable_odd(uint64_t, int, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); +void nlm_setup_l4ctable_even(uint64_t, int, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); +void nlm_setup_l4ctable_odd(uint64_t, int, uint32_t, uint32_t, uint32_t, uint32_t); +void nlm_enable_hardware_parser(uint64_t); +void nlm_enable_hardware_parser_per_port(uint64_t, int, int); +void nlm_prepad_enable(uint64_t, int); +void nlm_setup_1588_timer(uint64_t, struct nae_port_config *); + +#endif /* !(LOCORE) && !(__ASSEMBLY__) */ + +#endif diff --git a/sys/mips/nlm/hal/poe.h b/sys/mips/nlm/hal/poe.h new file mode 100644 index 0000000..312dfc0 --- /dev/null +++ b/sys/mips/nlm/hal/poe.h @@ -0,0 +1,352 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __NLM_POE_H__ +#define __NLM_POE_H__ + +/** +* @file_name poe.h +* @author Netlogic Microsystems +* @brief Basic definitions of XLP Packet Order Engine +*/ + +/* POE specific registers */ +#define POE_CL0_ENQ_SPILL_BASE_LO 0x0 +#define POE_CL1_ENQ_SPILL_BASE_LO 0x2 +#define POE_CL2_ENQ_SPILL_BASE_LO 0x4 +#define POE_CL3_ENQ_SPILL_BASE_LO 0x6 +#define POE_CL4_ENQ_SPILL_BASE_LO 0x8 +#define POE_CL5_ENQ_SPILL_BASE_LO 0xa +#define POE_CL6_ENQ_SPILL_BASE_LO 0xc +#define POE_CL7_ENQ_SPILL_BASE_LO 0xe +#define POE_CL0_ENQ_SPILL_BASE_HI 0x1 +#define POE_CL1_ENQ_SPILL_BASE_HI 0x3 +#define POE_CL2_ENQ_SPILL_BASE_HI 0x5 +#define POE_CL3_ENQ_SPILL_BASE_HI 0x7 +#define POE_CL4_ENQ_SPILL_BASE_HI 0x9 +#define POE_CL5_ENQ_SPILL_BASE_HI 0xb +#define POE_CL6_ENQ_SPILL_BASE_HI 0xd +#define POE_CL7_ENQ_SPILL_BASE_HI 0xf +#define POE_CL0_DEQ_SPILL_BASE_LO 0x10 +#define POE_CL1_DEQ_SPILL_BASE_LO 0x12 +#define POE_CL2_DEQ_SPILL_BASE_LO 0x14 +#define POE_CL3_DEQ_SPILL_BASE_LO 0x16 +#define POE_CL4_DEQ_SPILL_BASE_LO 0x18 +#define POE_CL5_DEQ_SPILL_BASE_LO 0x1a +#define POE_CL6_DEQ_SPILL_BASE_LO 0x1c +#define POE_CL7_DEQ_SPILL_BASE_LO 0x1e +#define POE_CL0_DEQ_SPILL_BASE_HI 0x11 +#define POE_CL1_DEQ_SPILL_BASE_HI 0x13 +#define POE_CL2_DEQ_SPILL_BASE_HI 0x15 +#define POE_CL3_DEQ_SPILL_BASE_HI 0x17 +#define POE_CL4_DEQ_SPILL_BASE_HI 0x19 +#define POE_CL5_DEQ_SPILL_BASE_HI 0x1b +#define POE_CL6_DEQ_SPILL_BASE_HI 0x1d +#define POE_CL7_DEQ_SPILL_BASE_HI 0x1f +#define POE_MSG_STORAGE_BASE_ADDR_LO 0x20 +#define POE_MSG_STORAGE_BASE_ADDR_HI 0x21 +#define POE_FBP_BASE_ADDR_LO 0x22 +#define POE_FBP_BASE_ADDR_HI 0x23 +#define POE_CL0_ENQ_SPILL_MAXLINE_LO 0x24 +#define POE_CL1_ENQ_SPILL_MAXLINE_LO 0x25 +#define POE_CL2_ENQ_SPILL_MAXLINE_LO 0x26 +#define POE_CL3_ENQ_SPILL_MAXLINE_LO 0x27 +#define POE_CL4_ENQ_SPILL_MAXLINE_LO 0x28 +#define POE_CL5_ENQ_SPILL_MAXLINE_LO 0x29 +#define POE_CL6_ENQ_SPILL_MAXLINE_LO 0x2a +#define POE_CL7_ENQ_SPILL_MAXLINE_LO 0x2b +#define POE_CL0_ENQ_SPILL_MAXLINE_HI 0x2c +#define POE_CL1_ENQ_SPILL_MAXLINE_HI 0x2d +#define POE_CL2_ENQ_SPILL_MAXLINE_HI 0x2e +#define POE_CL3_ENQ_SPILL_MAXLINE_HI 0x2f +#define POE_CL4_ENQ_SPILL_MAXLINE_HI 0x30 +#define POE_CL5_ENQ_SPILL_MAXLINE_HI 0x31 +#define POE_CL6_ENQ_SPILL_MAXLINE_HI 0x32 +#define POE_CL7_ENQ_SPILL_MAXLINE_HI 0x33 +#define POE_MAX_FLOW_MSG0 0x40 +#define POE_MAX_FLOW_MSG1 0x41 +#define POE_MAX_FLOW_MSG2 0x42 +#define POE_MAX_FLOW_MSG3 0x43 +#define POE_MAX_FLOW_MSG4 0x44 +#define POE_MAX_FLOW_MSG5 0x45 +#define POE_MAX_FLOW_MSG6 0x46 +#define POE_MAX_FLOW_MSG7 0x47 +#define POE_MAX_MSG_CL0 0x48 +#define POE_MAX_MSG_CL1 0x49 +#define POE_MAX_MSG_CL2 0x4a +#define POE_MAX_MSG_CL3 0x4b +#define POE_MAX_MSG_CL4 0x4c +#define POE_MAX_MSG_CL5 0x4d +#define POE_MAX_MSG_CL6 0x4e +#define POE_MAX_MSG_CL7 0x4f +#define POE_MAX_LOC_BUF_STG_CL0 0x50 +#define POE_MAX_LOC_BUF_STG_CL1 0x51 +#define POE_MAX_LOC_BUF_STG_CL2 0x52 +#define POE_MAX_LOC_BUF_STG_CL3 0x53 +#define POE_MAX_LOC_BUF_STG_CL4 0x54 +#define POE_MAX_LOC_BUF_STG_CL5 0x55 +#define POE_MAX_LOC_BUF_STG_CL6 0x56 +#define POE_MAX_LOC_BUF_STG_CL7 0x57 +#define POE_ENQ_MSG_COUNT0_SIZE 0x58 +#define POE_ENQ_MSG_COUNT1_SIZE 0x59 +#define POE_ENQ_MSG_COUNT2_SIZE 0x5a +#define POE_ENQ_MSG_COUNT3_SIZE 0x5b +#define POE_ENQ_MSG_COUNT4_SIZE 0x5c +#define POE_ENQ_MSG_COUNT5_SIZE 0x5d +#define POE_ENQ_MSG_COUNT6_SIZE 0x5e +#define POE_ENQ_MSG_COUNT7_SIZE 0x5f +#define POE_ERR_MSG_DESCRIP_LO0 0x60 +#define POE_ERR_MSG_DESCRIP_LO1 0x62 +#define POE_ERR_MSG_DESCRIP_LO2 0x64 +#define POE_ERR_MSG_DESCRIP_LO3 0x66 +#define POE_ERR_MSG_DESCRIP_HI0 0x61 +#define POE_ERR_MSG_DESCRIP_HI1 0x63 +#define POE_ERR_MSG_DESCRIP_HI2 0x65 +#define POE_ERR_MSG_DESCRIP_HI3 0x67 +#define POE_OOO_MSG_CNT_LO 0x68 +#define POE_IN_ORDER_MSG_CNT_LO 0x69 +#define POE_LOC_BUF_STOR_CNT_LO 0x6a +#define POE_EXT_BUF_STOR_CNT_LO 0x6b +#define POE_LOC_BUF_ALLOC_CNT_LO 0x6c +#define POE_EXT_BUF_ALLOC_CNT_LO 0x6d +#define POE_OOO_MSG_CNT_HI 0x6e +#define POE_IN_ORDER_MSG_CNT_HI 0x6f +#define POE_LOC_BUF_STOR_CNT_HI 0x70 +#define POE_EXT_BUF_STOR_CNT_HI 0x71 +#define POE_LOC_BUF_ALLOC_CNT_HI 0x72 +#define POE_EXT_BUF_ALLOC_CNT_HI 0x73 +#define POE_MODE_ERR_FLOW_ID 0x74 +#define POE_STATISTICS_ENABLE 0x75 +#define POE_MAX_SIZE_FLOW 0x76 +#define POE_MAX_SIZE 0x77 +#define POE_FBP_SP 0x78 +#define POE_FBP_SP_EN 0x79 +#define POE_LOC_ALLOC_EN 0x7a +#define POE_EXT_ALLOC_EN 0x7b +#define POE_DISTR_0_DROP_CNT 0xc0 +#define POE_DISTR_1_DROP_CNT 0xc1 +#define POE_DISTR_2_DROP_CNT 0xc2 +#define POE_DISTR_3_DROP_CNT 0xc3 +#define POE_DISTR_4_DROP_CNT 0xc4 +#define POE_DISTR_5_DROP_CNT 0xc5 +#define POE_DISTR_6_DROP_CNT 0xc6 +#define POE_DISTR_7_DROP_CNT 0xc7 +#define POE_DISTR_8_DROP_CNT 0xc8 +#define POE_DISTR_9_DROP_CNT 0xc9 +#define POE_DISTR_10_DROP_CNT 0xca +#define POE_DISTR_11_DROP_CNT 0xcb +#define POE_DISTR_12_DROP_CNT 0xcc +#define POE_DISTR_13_DROP_CNT 0xcd +#define POE_DISTR_14_DROP_CNT 0xce +#define POE_DISTR_15_DROP_CNT 0xcf +#define POE_CLASS_0_DROP_CNT 0xd0 +#define POE_CLASS_1_DROP_CNT 0xd1 +#define POE_CLASS_2_DROP_CNT 0xd2 +#define POE_CLASS_3_DROP_CNT 0xd3 +#define POE_CLASS_4_DROP_CNT 0xd4 +#define POE_CLASS_5_DROP_CNT 0xd5 +#define POE_CLASS_6_DROP_CNT 0xd6 +#define POE_CLASS_7_DROP_CNT 0xd7 +#define POE_DISTR_C0_DROP_CNT 0xd8 +#define POE_DISTR_C1_DROP_CNT 0xd9 +#define POE_DISTR_C2_DROP_CNT 0xda +#define POE_DISTR_C3_DROP_CNT 0xdb +#define POE_DISTR_C4_DROP_CNT 0xdc +#define POE_DISTR_C5_DROP_CNT 0xdd +#define POE_DISTR_C6_DROP_CNT 0xde +#define POE_DISTR_C7_DROP_CNT 0xdf +#define POE_CPU_DROP_CNT 0xe0 +#define POE_MAX_FLOW_DROP_CNT 0xe1 +#define POE_INTERRUPT_VEC 0x140 +#define POE_INTERRUPT_MASK 0x141 +#define POE_FATALERR_MASK 0x142 +#define POE_IDI_CFG 0x143 +#define POE_TIMEOUT_VALUE 0x144 +#define POE_CACHE_ALLOC_EN 0x145 +#define POE_FBP_ECC_ERR_CNT 0x146 +#define POE_MSG_STRG_ECC_ERR_CNT 0x147 +#define POE_FID_INFO_ECC_ERR_CNT 0x148 +#define POE_MSG_INFO_ECC_ERR_CNT 0x149 +#define POE_LL_ECC_ERR_CNT 0x14a +#define POE_SIZE_ECC_ERR_CNT 0x14b +#define POE_FMN_TXCR_ECC_ERR_CNT 0x14c +#define POE_ENQ_INSPIL_ECC_ERR_CNT 0x14d +#define POE_ENQ_OUTSPIL_ECC_ERR_CNT 0x14e +#define POE_DEQ_OUTSPIL_ECC_ERR_CNT 0x14f +#define POE_ENQ_MSG_SENT 0x150 +#define POE_ENQ_MSG_CNT 0x151 +#define POE_FID_RDATA 0x152 +#define POE_FID_WDATA 0x153 +#define POE_FID_CMD 0x154 +#define POE_FID_ADDR 0x155 +#define POE_MSG_INFO_CMD 0x156 +#define POE_MSG_INFO_ADDR 0x157 +#define POE_MSG_INFO_RDATA 0x158 +#define POE_LL_CMD 0x159 +#define POE_LL_ADDR 0x15a +#define POE_LL_RDATA 0x15b +#define POE_MSG_STG_CMD 0x15c +#define POE_MSG_STG_ADDR 0x15d +#define POE_MSG_STG_RDATA 0x15e +#define POE_DISTR_THRESHOLD_0 0x1c0 +#define POE_DISTR_THRESHOLD_1 0x1c1 +#define POE_DISTR_THRESHOLD_2 0x1c2 +#define POE_DISTR_THRESHOLD_3 0x1c3 +#define POE_DISTR_THRESHOLD_4 0x1c4 +#define POE_DISTR_THRESHOLD(i) (0x1c0 + (i)) +#define POE_DISTR_EN 0x1c5 +#define POE_ENQ_SPILL_THOLD 0x1c8 +#define POE_DEQ_SPILL_THOLD 0x1c9 +#define POE_DEQ_SPILL_TIMER 0x1ca +#define POE_DISTR_CLASS_DROP_EN 0x1cb +#define POE_DISTR_VEC_DROP_EN 0x1cc +#define POE_DISTR_DROP_TIMER 0x1cd +#define POE_ERROR_LOG_W0 0x1ce +#define POE_ERROR_LOG_W1 0x1cf +#define POE_ERROR_LOG_W2 0x1d0 +#define POE_ERR_INJ_CTRL0 0x1d1 +#define POE_TX_TIMER 0x1d4 + +#define NUM_DIST_VEC 16 +#define NUM_WORDS_PER_DV 16 +#define MAX_DV_TBL_ENTRIES (NUM_DIST_VEC * NUM_WORDS_PER_DV) +#define POE_DIST_THRESHOLD_VAL 0xa + +/* + * POE distribution vectors + * + * Each vector is 512 bit with msb indicating vc 512 and lsb indicating vc 0 + * 512-bit-vector is specified as 16 32-bit words. + * Left most word has the vc range 511-479 right most word has vc range 31 - 0 + * Each word has the MSB select higer vc number and LSB select lower vc num + */ +#define POE_DISTVECT_BASE 0x100 +#define POE_DISTVECT(vec) (POE_DISTVECT_BASE + 16 * (vec)) +#define POE_DISTVECT_OFFSET(node,cpu) (4 * (3 - (node)) + (3 - (cpu)/8)) +#define POE_DISTVECT_SHIFT(node,cpu) (((cpu) % 8 ) * 4) + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#define nlm_read_poe_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_poe_reg(b, r, v) nlm_write_reg(b, r, v) +#define nlm_read_poedv_reg(b, r) nlm_read_reg_xkphys(b, r) +#define nlm_write_poedv_reg(b, r, v) nlm_write_reg_xkphys(b, r, v) +#define nlm_get_poe_pcibase(node) \ + nlm_pcicfg_base(XLP_IO_POE_OFFSET(node)) +#define nlm_get_poe_regbase(node) \ + (nlm_get_poe_pcibase(node) + XLP_IO_PCI_HDRSZ) +#define nlm_get_poedv_regbase(node) \ + nlm_xkphys_map_pcibar0(nlm_get_poe_pcibase(node)) + +static __inline int +nlm_poe_max_flows(uint64_t poe_pcibase) +{ + return (nlm_read_reg(poe_pcibase, XLP_PCI_DEVINFO_REG0)); +} + +/* + * Helper function, calculate the distribution vector + * cm0, cm1, cm2, cm3 : CPU masks for nodes 0..3 + * thr_vcmask: destination VCs for a thread + */ +static __inline void +nlm_calc_poe_distvec(uint32_t cm0, uint32_t cm1, uint32_t cm2, uint32_t cm3, + uint32_t thr_vcmask, uint32_t *distvec) +{ + uint32_t cpumask = 0, val; + int i, cpu, node, startcpu, index; + + thr_vcmask &= 0xf; + for (node = 0; node < XLP_MAX_NODES; node++) { + switch (node) { + case 0: cpumask = cm0; break; + case 1: cpumask = cm1; break; + case 2: cpumask = cm2; break; + case 3: cpumask = cm3; break; + } + + for (i = 0; i < 4; i++) { + val = 0; + startcpu = 31 - i * 8; + for (cpu = startcpu; cpu >= startcpu - 7; cpu--) { + val <<= 4; + if (cpumask & (1U << cpu)) + val |= thr_vcmask; + } + index = POE_DISTVECT_OFFSET(node, startcpu); + distvec[index] = val; + } + } +} + +static __inline int +nlm_write_poe_distvec(uint64_t poedv_base, int vec, uint32_t *distvec) +{ + uint32_t reg; + int i; + + if (vec < 0 || vec >= NUM_DIST_VEC) + return (-1); + + for (i = 0; i < NUM_WORDS_PER_DV; i++) { + reg = POE_DISTVECT(vec) + i; + nlm_write_poedv_reg(poedv_base, reg, distvec[i]); + } + + return (0); +} + +static __inline void +nlm_config_poe(uint64_t poe_base, uint64_t poedv_base) +{ + uint32_t zerodv[NUM_WORDS_PER_DV]; + int i; + + /* First disable distribution vector logic */ + nlm_write_poe_reg(poe_base, POE_DISTR_EN, 0); + + memset(zerodv, 0, sizeof(zerodv)); + for (i = 0; i < NUM_DIST_VEC; i++) + nlm_write_poe_distvec(poedv_base, i, zerodv); + + /* set the threshold */ + for (i = 0; i < 5; i++) + nlm_write_poe_reg(poe_base, POE_DISTR_THRESHOLD(i), + POE_DIST_THRESHOLD_VAL); + + nlm_write_poe_reg(poe_base, POE_DISTR_EN, 1); + + /* always enable local message store */ + nlm_write_poe_reg(poe_base, POE_LOC_ALLOC_EN, 1); + + nlm_write_poe_reg(poe_base, POE_TX_TIMER, 0x3); +} +#endif /* !(LOCORE) && !(__ASSEMBLY__) */ +#endif diff --git a/sys/mips/nlm/hal/sgmii.h b/sys/mips/nlm/hal/sgmii.h new file mode 100644 index 0000000..2bd418b --- /dev/null +++ b/sys/mips/nlm/hal/sgmii.h @@ -0,0 +1,217 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __NLM_SGMII_H__ +#define __NLM_SGMII_H__ + +/** +* @file_name sgmii.h +* @author Netlogic Microsystems +* @brief Basic definitions of XLP SGMII ports +*/ + +#define SGMII_MAC_CONF1(block, i) NAE_REG(block, i, 0x00) +#define SGMII_MAC_CONF2(block, i) NAE_REG(block, i, 0x01) +#define SGMII_IPG_IFG(block, i) NAE_REG(block, i, 0x02) +#define SGMII_HLF_DUP(block, i) NAE_REG(block, i, 0x03) +#define SGMII_MAX_FRAME(block, i) NAE_REG(block, i, 0x04) +#define SGMII_TEST(block, i) NAE_REG(block, i, 0x07) +#define SGMII_MIIM_CONF(block, i) NAE_REG(block, i, 0x08) +#define SGMII_MIIM_CMD(block, i) NAE_REG(block, i, 0x09) +#define SGMII_MIIM_ADDR(block, i) NAE_REG(block, i, 0x0a) +#define SGMII_MIIM_CTRL(block, i) NAE_REG(block, i, 0x0b) +#define SGMII_MIIM_STAT(block, i) NAE_REG(block, i, 0x0c) +#define SGMII_MIIM_IND(block, i) NAE_REG(block, i, 0x0d) +#define SGMII_IO_CTRL(block, i) NAE_REG(block, i, 0x0e) +#define SGMII_IO_STAT(block, i) NAE_REG(block, i, 0x0f) +#define SGMII_STATS_MLR(block, i) NAE_REG(block, i, 0x1f) +#define SGMII_STATS_TR64(block, i) NAE_REG(block, i, 0x20) +#define SGMII_STATS_TR127(block, i) NAE_REG(block, i, 0x21) +#define SGMII_STATS_TR255(block, i) NAE_REG(block, i, 0x22) +#define SGMII_STATS_TR511(block, i) NAE_REG(block, i, 0x23) +#define SGMII_STATS_TR1K(block, i) NAE_REG(block, i, 0x24) +#define SGMII_STATS_TRMAX(block, i) NAE_REG(block, i, 0x25) +#define SGMII_STATS_TRMGV(block, i) NAE_REG(block, i, 0x26) +#define SGMII_STATS_RBYT(block, i) NAE_REG(block, i, 0x27) +#define SGMII_STATS_RPKT(block, i) NAE_REG(block, i, 0x28) +#define SGMII_STATS_RFCS(block, i) NAE_REG(block, i, 0x29) +#define SGMII_STATS_RMCA(block, i) NAE_REG(block, i, 0x2a) +#define SGMII_STATS_RBCA(block, i) NAE_REG(block, i, 0x2b) +#define SGMII_STATS_RXCF(block, i) NAE_REG(block, i, 0x2c) +#define SGMII_STATS_RXPF(block, i) NAE_REG(block, i, 0x2d) +#define SGMII_STATS_RXUO(block, i) NAE_REG(block, i, 0x2e) +#define SGMII_STATS_RALN(block, i) NAE_REG(block, i, 0x2f) +#define SGMII_STATS_RFLR(block, i) NAE_REG(block, i, 0x30) +#define SGMII_STATS_RCDE(block, i) NAE_REG(block, i, 0x31) +#define SGMII_STATS_RCSE(block, i) NAE_REG(block, i, 0x32) +#define SGMII_STATS_RUND(block, i) NAE_REG(block, i, 0x33) +#define SGMII_STATS_ROVR(block, i) NAE_REG(block, i, 0x34) +#define SGMII_STATS_RFRG(block, i) NAE_REG(block, i, 0x35) +#define SGMII_STATS_RJBR(block, i) NAE_REG(block, i, 0x36) +#define SGMII_STATS_TBYT(block, i) NAE_REG(block, i, 0x38) +#define SGMII_STATS_TPKT(block, i) NAE_REG(block, i, 0x39) +#define SGMII_STATS_TMCA(block, i) NAE_REG(block, i, 0x3a) +#define SGMII_STATS_TBCA(block, i) NAE_REG(block, i, 0x3b) +#define SGMII_STATS_TXPF(block, i) NAE_REG(block, i, 0x3c) +#define SGMII_STATS_TDFR(block, i) NAE_REG(block, i, 0x3d) +#define SGMII_STATS_TEDF(block, i) NAE_REG(block, i, 0x3e) +#define SGMII_STATS_TSCL(block, i) NAE_REG(block, i, 0x3f) +#define SGMII_STATS_TMCL(block, i) NAE_REG(block, i, 0x40) +#define SGMII_STATS_TLCL(block, i) NAE_REG(block, i, 0x41) +#define SGMII_STATS_TXCL(block, i) NAE_REG(block, i, 0x42) +#define SGMII_STATS_TNCL(block, i) NAE_REG(block, i, 0x43) +#define SGMII_STATS_TJBR(block, i) NAE_REG(block, i, 0x46) +#define SGMII_STATS_TFCS(block, i) NAE_REG(block, i, 0x47) +#define SGMII_STATS_TXCF(block, i) NAE_REG(block, i, 0x48) +#define SGMII_STATS_TOVR(block, i) NAE_REG(block, i, 0x49) +#define SGMII_STATS_TUND(block, i) NAE_REG(block, i, 0x4a) +#define SGMII_STATS_TFRG(block, i) NAE_REG(block, i, 0x4b) +#define SGMII_STATS_CAR1(block, i) NAE_REG(block, i, 0x4c) +#define SGMII_STATS_CAR2(block, i) NAE_REG(block, i, 0x4d) +#define SGMII_STATS_CAM1(block, i) NAE_REG(block, i, 0x4e) +#define SGMII_STATS_CAM2(block, i) NAE_REG(block, i, 0x4f) +#define SGMII_MAC_ADDR0_LO(block, i) NAE_REG(block, i, 0x50) +#define SGMII_MAC_ADDR0_HI(block, i) NAE_REG(block, i, 0x51) +#define SGMII_MAC_ADDR1_LO(block, i) NAE_REG(block, i, 0x52) +#define SGMII_MAC_ADDR1_HI(block, i) NAE_REG(block, i, 0x53) +#define SGMII_MAC_ADDR2_LO(block, i) NAE_REG(block, i, 0x54) +#define SGMII_MAC_ADDR2_HI(block, i) NAE_REG(block, i, 0x55) +#define SGMII_MAC_ADDR3_LO(block, i) NAE_REG(block, i, 0x56) +#define SGMII_MAC_ADDR3_HI(block, i) NAE_REG(block, i, 0x57) +#define SGMII_MAC_ADDR_MASK0_LO(block, i) NAE_REG(block, i, 0x58) +#define SGMII_MAC_ADDR_MASK0_HI(block, i) NAE_REG(block, i, 0x59) +#define SGMII_MAC_ADDR_MASK1_LO(block, i) NAE_REG(block, i, 0x5a) +#define SGMII_MAC_ADDR_MASK1_HI(block, i) NAE_REG(block, i, 0x5b) +#define SGMII_MAC_FILTER_CONFIG(block, i) NAE_REG(block, i, 0x5c) +#define SGMII_HASHTBL_VEC_B31_0(block, i) NAE_REG(block, i, 0x60) +#define SGMII_HASHTBL_VEC_B63_32(block, i) NAE_REG(block, i, 0x61) +#define SGMII_HASHTBL_VEC_B95_64(block, i) NAE_REG(block, i, 0x62) +#define SGMII_HASHTBL_VEC_B127_96(block, i) NAE_REG(block, i, 0x63) +#define SGMII_HASHTBL_VEC_B159_128(block, i) NAE_REG(block, i, 0x64) +#define SGMII_HASHTBL_VEC_B191_160(block, i) NAE_REG(block, i, 0x65) +#define SGMII_HASHTBL_VEC_B223_192(block, i) NAE_REG(block, i, 0x66) +#define SGMII_HASHTBL_VEC_B255_224(block, i) NAE_REG(block, i, 0x67) +#define SGMII_HASHTBL_VEC_B287_256(block, i) NAE_REG(block, i, 0x68) +#define SGMII_HASHTBL_VEC_B319_288(block, i) NAE_REG(block, i, 0x69) +#define SGMII_HASHTBL_VEC_B351_320(block, i) NAE_REG(block, i, 0x6a) +#define SGMII_HASHTBL_VEC_B383_352(block, i) NAE_REG(block, i, 0x6b) +#define SGMII_HASHTBL_VEC_B415_384(block, i) NAE_REG(block, i, 0x6c) +#define SGMII_HASHTBL_VEC_B447_416(block, i) NAE_REG(block, i, 0x6d) +#define SGMII_HASHTBL_VEC_B479_448(block, i) NAE_REG(block, i, 0x6e) +#define SGMII_HASHTBL_VEC_B511_480(block, i) NAE_REG(block, i, 0x6f) + +#define SGMII_NETIOR_VLANTYPE_FILTER(block, i) NAE_REG(block, i, 0x76) +#define SGMII_NETIOR_RXDROP_CNTR(block, i) NAE_REG(block, i, 0x77) +#define SGMII_NETIOR_PAUSE_QUANTAMULT(block, i) NAE_REG(block, i, 0x78) +#define SGMII_NETIOR_MAC_CTRL_OPCODE(block, i) NAE_REG(block, i, 0x79) +#define SGMII_NETIOR_MAC_DA_H(block, i) NAE_REG(block, i, 0x7a) +#define SGMII_NETIOR_MAC_DA_L(block, i) NAE_REG(block, i, 0x7b) +#define SGMII_NET_IFACE_CTRL3(block, i) NAE_REG(block, i, 0x7c) +#define SGMII_NETIOR_GMAC_STAT(block, i) NAE_REG(block, i, 0x7d) +#define SGMII_NET_IFACE_CTRL2(block, i) NAE_REG(block, i, 0x7e) +#define SGMII_NET_IFACE_CTRL(block, i) NAE_REG(block, i, 0x7f) + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) +/* speed */ +enum nlm_sgmii_speed { + NLM_SGMII_SPEED_10, + NLM_SGMII_SPEED_100, + NLM_SGMII_SPEED_1000, + NLM_SGMII_SPEED_RSVD +}; + +/* duplexity */ +enum nlm_sgmii_duplex_mode { + NLM_SGMII_DUPLEX_AUTO, + NLM_SGMII_DUPLEX_HALF, + NLM_SGMII_DUPLEX_FULL +}; + +/* stats */ +enum { + nlm_sgmii_stats_mlr, + nlm_sgmii_stats_tr64, + nlm_sgmii_stats_tr127, + nlm_sgmii_stats_tr255, + nlm_sgmii_stats_tr511, + nlm_sgmii_stats_tr1k, + nlm_sgmii_stats_trmax, + nlm_sgmii_stats_trmgv, + nlm_sgmii_stats_rbyt, + nlm_sgmii_stats_rpkt, + nlm_sgmii_stats_rfcs, + nlm_sgmii_stats_rmca, + nlm_sgmii_stats_rbca, + nlm_sgmii_stats_rxcf, + nlm_sgmii_stats_rxpf, + nlm_sgmii_stats_rxuo, + nlm_sgmii_stats_raln, + nlm_sgmii_stats_rflr, + nlm_sgmii_stats_rcde, + nlm_sgmii_stats_rcse, + nlm_sgmii_stats_rund, + nlm_sgmii_stats_rovr, + nlm_sgmii_stats_rfrg, + nlm_sgmii_stats_rjbr, + nlm_sgmii_stats_rdummy, /* not used */ + nlm_sgmii_stats_tbyt, + nlm_sgmii_stats_tpkt, + nlm_sgmii_stats_tmca, + nlm_sgmii_stats_tbca, + nlm_sgmii_stats_txpf, + nlm_sgmii_stats_tdfr, + nlm_sgmii_stats_tedf, + nlm_sgmii_stats_tscl, + nlm_sgmii_stats_tmcl, + nlm_sgmii_stats_tlcl, + nlm_sgmii_stats_txcl, + nlm_sgmii_stats_tncl, + nlm_sgmii_stats_tjbr, + nlm_sgmii_stats_tfcs, + nlm_sgmii_stats_txcf, + nlm_sgmii_stats_tovr, + nlm_sgmii_stats_tund, + nlm_sgmii_stats_tfrg, + nlm_sgmii_stats_car1, + nlm_sgmii_stats_car2, + nlm_sgmii_stats_cam1, + nlm_sgmii_stats_cam2 +}; + +void nlm_configure_sgmii_interface(uint64_t, int, int, int, int); +void nlm_sgmii_pcs_init(uint64_t, uint32_t); +void nlm_nae_setup_mac(uint64_t, int, int, int, int, int, int, int); +void nlm_nae_setup_rx_mode_sgmii(uint64_t, int, int, int, int, int, + int, int); +void nlm_nae_setup_mac_addr_sgmii(uint64_t, int, int, int, uint8_t *); + +#endif /* !(LOCORE) && !(__ASSEMBLY__) */ + +#endif diff --git a/sys/mips/nlm/hal/ucore_loader.h b/sys/mips/nlm/hal/ucore_loader.h new file mode 100644 index 0000000..8298c82 --- /dev/null +++ b/sys/mips/nlm/hal/ucore_loader.h @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __NLM_UCORE_LOADER_H__ +#define __NLM_UCORE_LOADER_H__ + +/** +* @file_name ucore_loader.h +* @author Netlogic Microsystems +* @brief Ucore loader API header +*/ + +#define CODE_SIZE_PER_UCORE (4 << 10) + +static __inline__ void +nlm_ucore_load_image(uint64_t nae_base, int ucore) +{ + uint64_t addr = nae_base + NAE_UCORE_SHARED_RAM_OFFSET + + (ucore * CODE_SIZE_PER_UCORE); + uint32_t *p = (uint32_t *)ucore_app_bin; + int i, size; + + size = sizeof(ucore_app_bin)/sizeof(uint32_t); + for (i = 0; i < size; i++, addr += 4) + nlm_store_word_daddr(addr, p[i]); + + /* add a 'nop' if number of instructions are odd */ + if (size & 0x1) + nlm_store_word_daddr(addr, 0x0); +} + +static __inline int +nlm_ucore_write_sharedmem(uint64_t nae_base, int index, uint32_t data) +{ + uint32_t ucore_cfg; + uint64_t addr = nae_base + NAE_UCORE_SHARED_RAM_OFFSET; + + if (index > 128) + return (-1); + + ucore_cfg = nlm_read_nae_reg(nae_base, NAE_RX_UCORE_CFG); + /* set iram to zero */ + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, + (ucore_cfg & ~(0x1 << 7))); + + nlm_store_word_daddr(addr + (index * 4), data); + + /* restore ucore config */ + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, ucore_cfg); + return (0); +} + +static __inline uint32_t +nlm_ucore_read_sharedmem(uint64_t nae_base, int index) +{ + uint64_t addr = nae_base + NAE_UCORE_SHARED_RAM_OFFSET; + uint32_t ucore_cfg, val; + + ucore_cfg = nlm_read_nae_reg(nae_base, NAE_RX_UCORE_CFG); + /* set iram to zero */ + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, + (ucore_cfg & ~(0x1 << 7))); + + val = nlm_load_word_daddr(addr + (index * 4)); + + /* restore ucore config */ + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, ucore_cfg); + + return val; +} + +static __inline__ int +nlm_ucore_load_all(uint64_t nae_base, uint32_t ucore_mask, int nae_reset_done) +{ + int i, count = 0; + uint32_t mask; + uint32_t ucore_cfg = 0; + + mask = ucore_mask & 0xffff; + + /* Stop all ucores */ + if (nae_reset_done == 0) { /* Skip the Ucore reset if NAE reset is done */ + ucore_cfg = nlm_read_nae_reg(nae_base, NAE_RX_UCORE_CFG); + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, + ucore_cfg | (1 << 24)); + + /* poll for ucore to get in to a wait state */ + do { + ucore_cfg = nlm_read_nae_reg(nae_base, + NAE_RX_UCORE_CFG); + } while ((ucore_cfg & (1 << 25)) == 0); + } + + for (i = 0; i < sizeof(ucore_mask) * NBBY; i++) { + if ((mask & (1 << i)) == 0) + continue; + nlm_ucore_load_image(nae_base, i); + count++; + } + + /* Enable per-domain ucores */ + ucore_cfg = nlm_read_nae_reg(nae_base, NAE_RX_UCORE_CFG); + + /* write one to reset bits to put the ucores in reset */ + ucore_cfg = ucore_cfg | (((mask) & 0xffff) << 8); + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, ucore_cfg); + + /* write zero to reset bits to pull them out of reset */ + ucore_cfg = ucore_cfg & (~(((mask) & 0xffff) << 8)) & ~(1 << 24); + nlm_write_nae_reg(nae_base, NAE_RX_UCORE_CFG, ucore_cfg); + + return (count); +} +#endif diff --git a/sys/mips/nlm/hal/xaui.h b/sys/mips/nlm/hal/xaui.h new file mode 100644 index 0000000..e73cf38 --- /dev/null +++ b/sys/mips/nlm/hal/xaui.h @@ -0,0 +1,193 @@ +/*- + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __NLM_XAUI_H__ +#define __NLM_XAUI_H__ + +/** +* @file_name xaui.h +* @author Netlogic Microsystems +* @brief Basic definitions of XLP XAUI ports +*/ +#define XAUI_CONFIG0(block) NAE_REG(block, 4, 0x00) +#define XAUI_CONFIG1(block) NAE_REG(block, 4, 0x01) +#define XAUI_CONFIG2(block) NAE_REG(block, 4, 0x02) +#define XAUI_CONFIG3(block) NAE_REG(block, 4, 0x03) +/* +#define XAUI_MAC_ADDR0_LO(block) NAE_REG(block, 4, 0x04) +#define XAUI_MAC_ADDR0_HI(block) NAE_REG(block, 4, 0x05) +*/ +#define XAUI_MAX_FRAME_LEN(block) NAE_REG(block, 4, 0x08) +#define XAUI_REVISION_LVL(block) NAE_REG(block, 4, 0x0b) +#define XAUI_MII_MGMT_CMD(block) NAE_REG(block, 4, 0x10) +#define XAUI_MII_MGMT_FIELD(block) NAE_REG(block, 4, 0x11) +#define XAUI_MII_MGMT_CFG(block) NAE_REG(block, 4, 0x12) +#define XAUI_MIIM_LINK_FALL_VEC(block) NAE_REG(block, 4, 0x13) +#define XAUI_MII_MGMT_IND(block) NAE_REG(block, 4, 0x14) +#define XAUI_STATS_MLR(block) NAE_REG(block, 4, 0x1f) +#define XAUI_STATS_TR64(block) NAE_REG(block, 4, 0x20) +#define XAUI_STATS_TR127(block) NAE_REG(block, 4, 0x21) +#define XAUI_STATS_TR255(block) NAE_REG(block, 4, 0x22) +#define XAUI_STATS_TR511(block) NAE_REG(block, 4, 0x23) +#define XAUI_STATS_TR1K(block) NAE_REG(block, 4, 0x24) +#define XAUI_STATS_TRMAX(block) NAE_REG(block, 4, 0x25) +#define XAUI_STATS_TRMGV(block) NAE_REG(block, 4, 0x26) +#define XAUI_STATS_RBYT(block) NAE_REG(block, 4, 0x27) +#define XAUI_STATS_RPKT(block) NAE_REG(block, 4, 0x28) +#define XAUI_STATS_RFCS(block) NAE_REG(block, 4, 0x29) +#define XAUI_STATS_RMCA(block) NAE_REG(block, 4, 0x2a) +#define XAUI_STATS_RBCA(block) NAE_REG(block, 4, 0x2b) +#define XAUI_STATS_RXCF(block) NAE_REG(block, 4, 0x2c) +#define XAUI_STATS_RXPF(block) NAE_REG(block, 4, 0x2d) +#define XAUI_STATS_RXUO(block) NAE_REG(block, 4, 0x2e) +#define XAUI_STATS_RALN(block) NAE_REG(block, 4, 0x2f) +#define XAUI_STATS_RFLR(block) NAE_REG(block, 4, 0x30) +#define XAUI_STATS_RCDE(block) NAE_REG(block, 4, 0x31) +#define XAUI_STATS_RCSE(block) NAE_REG(block, 4, 0x32) +#define XAUI_STATS_RUND(block) NAE_REG(block, 4, 0x33) +#define XAUI_STATS_ROVR(block) NAE_REG(block, 4, 0x34) +#define XAUI_STATS_RFRG(block) NAE_REG(block, 4, 0x35) +#define XAUI_STATS_RJBR(block) NAE_REG(block, 4, 0x36) +#define XAUI_STATS_TBYT(block) NAE_REG(block, 4, 0x38) +#define XAUI_STATS_TPKT(block) NAE_REG(block, 4, 0x39) +#define XAUI_STATS_TMCA(block) NAE_REG(block, 4, 0x3a) +#define XAUI_STATS_TBCA(block) NAE_REG(block, 4, 0x3b) +#define XAUI_STATS_TXPF(block) NAE_REG(block, 4, 0x3c) +#define XAUI_STATS_TDFR(block) NAE_REG(block, 4, 0x3d) +#define XAUI_STATS_TEDF(block) NAE_REG(block, 4, 0x3e) +#define XAUI_STATS_TSCL(block) NAE_REG(block, 4, 0x3f) +#define XAUI_STATS_TMCL(block) NAE_REG(block, 4, 0x40) +#define XAUI_STATS_TLCL(block) NAE_REG(block, 4, 0x41) +#define XAUI_STATS_TXCL(block) NAE_REG(block, 4, 0x42) +#define XAUI_STATS_TNCL(block) NAE_REG(block, 4, 0x43) +#define XAUI_STATS_TJBR(block) NAE_REG(block, 4, 0x46) +#define XAUI_STATS_TFCS(block) NAE_REG(block, 4, 0x47) +#define XAUI_STATS_TXCF(block) NAE_REG(block, 4, 0x48) +#define XAUI_STATS_TOVR(block) NAE_REG(block, 4, 0x49) +#define XAUI_STATS_TUND(block) NAE_REG(block, 4, 0x4a) +#define XAUI_STATS_TFRG(block) NAE_REG(block, 4, 0x4b) +#define XAUI_STATS_CAR1(block) NAE_REG(block, 4, 0x4c) +#define XAUI_STATS_CAR2(block) NAE_REG(block, 4, 0x4d) +#define XAUI_STATS_CAM1(block) NAE_REG(block, 4, 0x4e) +#define XAUI_STATS_CAM2(block) NAE_REG(block, 4, 0x4f) +#define XAUI_MAC_ADDR0_LO(block) NAE_REG(block, 4, 0x50) +#define XAUI_MAC_ADDR0_HI(block) NAE_REG(block, 4, 0x51) +#define XAUI_MAC_ADDR1_LO(block) NAE_REG(block, 4, 0x52) +#define XAUI_MAC_ADDR1_HI(block) NAE_REG(block, 4, 0x53) +#define XAUI_MAC_ADDR2_LO(block) NAE_REG(block, 4, 0x54) +#define XAUI_MAC_ADDR2_HI(block) NAE_REG(block, 4, 0x55) +#define XAUI_MAC_ADDR3_LO(block) NAE_REG(block, 4, 0x56) +#define XAUI_MAC_ADDR3_HI(block) NAE_REG(block, 4, 0x57) +#define XAUI_MAC_ADDR_MASK0_LO(block) NAE_REG(block, 4, 0x58) +#define XAUI_MAC_ADDR_MASK0_HI(block) NAE_REG(block, 4, 0x59) +#define XAUI_MAC_ADDR_MASK1_LO(block) NAE_REG(block, 4, 0x5a) +#define XAUI_MAC_ADDR_MASK1_HI(block) NAE_REG(block, 4, 0x5b) +#define XAUI_MAC_FILTER_CFG(block) NAE_REG(block, 4, 0x5c) +#define XAUI_HASHTBL_VEC_B31_0(block) NAE_REG(block, 4, 0x60) +#define XAUI_HASHTBL_VEC_B63_32(block) NAE_REG(block, 4, 0x61) +#define XAUI_HASHTBL_VEC_B95_64(block) NAE_REG(block, 4, 0x62) +#define XAUI_HASHTBL_VEC_B127_96(block) NAE_REG(block, 4, 0x63) +#define XAUI_HASHTBL_VEC_B159_128(block) NAE_REG(block, 4, 0x64) +#define XAUI_HASHTBL_VEC_B191_160(block) NAE_REG(block, 4, 0x65) +#define XAUI_HASHTBL_VEC_B223_192(block) NAE_REG(block, 4, 0x66) +#define XAUI_HASHTBL_VEC_B255_224(block) NAE_REG(block, 4, 0x67) +#define XAUI_HASHTBL_VEC_B287_256(block) NAE_REG(block, 4, 0x68) +#define XAUI_HASHTBL_VEC_B319_288(block) NAE_REG(block, 4, 0x69) +#define XAUI_HASHTBL_VEC_B351_320(block) NAE_REG(block, 4, 0x6a) +#define XAUI_HASHTBL_VEC_B383_352(block) NAE_REG(block, 4, 0x6b) +#define XAUI_HASHTBL_VEC_B415_384(block) NAE_REG(block, 4, 0x6c) +#define XAUI_HASHTBL_VEC_B447_416(block) NAE_REG(block, 4, 0x6d) +#define XAUI_HASHTBL_VEC_B479_448(block) NAE_REG(block, 4, 0x6e) +#define XAUI_HASHTBL_VEC_B511_480(block) NAE_REG(block, 4, 0x6f) + +#define XAUI_NETIOR_XGMAC_MISC0(block) NAE_REG(block, 4, 0x76) +#define XAUI_NETIOR_RX_ABORT_DROP_COUNT(block) NAE_REG(block, 4, 0x77) +#define XAUI_NETIOR_MACCTRL_PAUSE_QUANTA(block) NAE_REG(block, 4, 0x78) +#define XAUI_NETIOR_MACCTRL_OPCODE(block) NAE_REG(block, 4, 0x79) +#define XAUI_NETIOR_MAC_DA_H(block) NAE_REG(block, 4, 0x7a) +#define XAUI_NETIOR_MAC_DA_L(block) NAE_REG(block, 4, 0x7b) +#define XAUI_NETIOR_XGMAC_STAT(block) NAE_REG(block, 4, 0x7c) +#define XAUI_NETIOR_XGMAC_CTRL3(block) NAE_REG(block, 4, 0x7d) +#define XAUI_NETIOR_XGMAC_CTRL2(block) NAE_REG(block, 4, 0x7e) +#define XAUI_NETIOR_XGMAC_CTRL1(block) NAE_REG(block, 4, 0x7f) + +#define LANE_RX_CLK (1 << 0) +#define LANE_TX_CLK (1 << 6) + +#define XAUI_LANE_FAULT 0x400 +#define XAUI_CONFIG_0 0 + +#define XAUI_CONFIG_MACRST 0x80000000 +#define XAUI_CONFIG_RSTRCTL 0x00400000 +#define XAUI_CONFIG_RSTRFN 0x00200000 +#define XAUI_CONFIG_RSTTCTL 0x00040000 +#define XAUI_CONFIG_RSTTFN 0x00020000 +#define XAUI_CONFIG_RSTMIIM 0x00010000 + +#define XAUI_CONFIG_1 1 + +#define XAUI_CONFIG_TCTLEN 0x80000000 +#define XAUI_CONFIG_TFEN 0x40000000 +#define XAUI_CONFIG_RCTLEN 0x20000000 +#define XAUI_CONFIG_RFEN 0x10000000 +#define XAUI_CONFIG_DRPLT64 0x00000020 +#define XAUI_CONFIG_LENCHK 0x00000008 +#define XAUI_CONFIG_GENFCS 0x00000004 +#define XAUI_CONFIG_PAD_0 0x00000000 +#define XAUI_CONFIG_PAD_64 0x00000001 +#define XAUI_CONFIG_PAD_COND 0x00000002 +#define XAUI_CONFIG_PAD_68 0x00000003 + +#define XAUI_PHY_CTRL_1 0x00 + +#define NETIOR_XGMAC_CTRL1 0x7F +#define NETIOR_XGMAC_CTRL3 0x7D + +#define NETIOR_XGMAC_VLAN_DC_POS 28 +#define NETIOR_XGMAC_PHYADDR_POS 23 +#define NETIOR_XGMAC_DEVID_POS 18 +#define NETIOR_XGMAC_STATS_EN_POS 17 +#define NETIOR_XGMAC_TX_PFC_EN_POS 14 +#define NETIOR_XGMAC_RX_PFC_EN_POS 13 +#define NETIOR_XGMAC_SOFT_RST_POS 11 +#define NETIOR_XGMAC_TX_PAUSE_POS 10 + +#define NETIOR_XGMAC_STATS_CLR_POS 16 + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +void nlm_xaui_pcs_init(uint64_t, int); +void nlm_nae_setup_rx_mode_xaui(uint64_t, int, int, int, int, int, int, int); +void nlm_nae_setup_mac_addr_xaui(uint64_t, int, int, int, unsigned char *); +void nlm_config_xaui_mtu(uint64_t, int, int, int); +void nlm_config_xaui(uint64_t, int, int, int, int); + +#endif /* !(LOCORE) && !(__ASSEMBLY__) */ + +#endif diff --git a/sys/mips/nlm/msgring.h b/sys/mips/nlm/msgring.h index 446bad8..9ce5c43 100644 --- a/sys/mips/nlm/msgring.h +++ b/sys/mips/nlm/msgring.h @@ -32,6 +32,13 @@ #ifndef _NLM_MSGRING_H #define _NLM_MSGRING_H #define CMS_DEFAULT_CREDIT 50 +/* + * packets are sent to VC 0 of a thread + * freebacks are sent to VC 3 of a thread + */ +#define XLPGE_RX_VC 0 +#define XLPGE_FB_VC 3 + extern uint32_t xlp_msg_thread_mask; struct nlm_fmn_msg; |