diff options
author | Jayachandran C. <jchandra@FreeBSD.org> | 2012-03-27 14:05:12 +0000 |
---|---|---|
committer | Jayachandran C. <jchandra@FreeBSD.org> | 2012-03-27 14:05:12 +0000 |
commit | 35011d20cbe2b5a1098fbb9580e4fa0dc632cfe9 (patch) | |
tree | ae659c962d005114389e060c8a8057ddfcad9afd /sys/mips/nlm/board.c | |
parent | 6f33c108f78bcc270cec72e50a69e31b13bc3ef6 (diff) | |
download | src-35011d20cbe2b5a1098fbb9580e4fa0dc632cfe9.tar.gz src-35011d20cbe2b5a1098fbb9580e4fa0dc632cfe9.zip |
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]
Notes
Notes:
svn path=/head/; revision=233545
Diffstat (limited to 'sys/mips/nlm/board.c')
-rw-r--r-- | sys/mips/nlm/board.c | 390 |
1 files changed, 388 insertions, 2 deletions
diff --git a/sys/mips/nlm/board.c b/sys/mips/nlm/board.c index c84ea33c45d3..b4b0439dd372 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); } |