From owner-svn-src-all@FreeBSD.ORG Tue Mar 27 14:05:12 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EC47A106566B; Tue, 27 Mar 2012 14:05:12 +0000 (UTC) (envelope-from jchandra@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D3E2C8FC17; Tue, 27 Mar 2012 14:05:12 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2RE5C3l088877; Tue, 27 Mar 2012 14:05:12 GMT (envelope-from jchandra@svn.freebsd.org) Received: (from jchandra@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2RE5Cip088870; Tue, 27 Mar 2012 14:05:12 GMT (envelope-from jchandra@svn.freebsd.org) Message-Id: <201203271405.q2RE5Cip088870@svn.freebsd.org> From: "Jayachandran C." Date: Tue, 27 Mar 2012 14:05:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r233545 - in head/sys/mips: conf nlm nlm/dev/net nlm/dev/net/ucore nlm/hal X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Mar 2012 14:05:13 -0000 Author: jchandra Date: Tue Mar 27 14:05:12 2012 New Revision: 233545 URL: http://svn.freebsd.org/changeset/base/233545 Log: 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] Added: head/sys/mips/nlm/dev/net/ head/sys/mips/nlm/dev/net/mdio.c (contents, props changed) head/sys/mips/nlm/dev/net/nae.c (contents, props changed) head/sys/mips/nlm/dev/net/sgmii.c (contents, props changed) head/sys/mips/nlm/dev/net/ucore/ head/sys/mips/nlm/dev/net/ucore/crt0_basic.S (contents, props changed) head/sys/mips/nlm/dev/net/ucore/ld.ucore.S (contents, props changed) head/sys/mips/nlm/dev/net/ucore/ucore.h (contents, props changed) head/sys/mips/nlm/dev/net/ucore/ucore_app.c (contents, props changed) head/sys/mips/nlm/dev/net/xaui.c (contents, props changed) head/sys/mips/nlm/dev/net/xlpge.c (contents, props changed) head/sys/mips/nlm/dev/net/xlpge.h (contents, props changed) head/sys/mips/nlm/hal/interlaken.h (contents, props changed) head/sys/mips/nlm/hal/mdio.h (contents, props changed) head/sys/mips/nlm/hal/nae.h (contents, props changed) head/sys/mips/nlm/hal/poe.h (contents, props changed) head/sys/mips/nlm/hal/sgmii.h (contents, props changed) head/sys/mips/nlm/hal/ucore_loader.h (contents, props changed) head/sys/mips/nlm/hal/xaui.h (contents, props changed) Modified: head/sys/mips/conf/std.XLP head/sys/mips/nlm/board.c head/sys/mips/nlm/board.h head/sys/mips/nlm/files.xlp head/sys/mips/nlm/hal/iomap.h head/sys/mips/nlm/msgring.h Modified: head/sys/mips/conf/std.XLP ============================================================================== --- head/sys/mips/conf/std.XLP Tue Mar 27 14:02:22 2012 (r233544) +++ head/sys/mips/conf/std.XLP Tue Mar 27 14:05:12 2012 (r233545) @@ -71,6 +71,7 @@ device bpf # Network device miibus device ether +device xlpge #device re device msk device em Modified: head/sys/mips/nlm/board.c ============================================================================== --- head/sys/mips/nlm/board.c Tue Mar 27 14:02:22 2012 (r233544) +++ head/sys/mips/nlm/board.c Tue Mar 27 14:05:12 2012 (r233545) @@ -44,16 +44,289 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include +#include 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); } Modified: head/sys/mips/nlm/board.h ============================================================================== --- head/sys/mips/nlm/board.h Tue Mar 27 14:02:22 2012 (r233544) +++ head/sys/mips/nlm/board.h Tue Mar 27 14:05:12 2012 (r233545) @@ -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 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 Added: head/sys/mips/nlm/dev/net/mdio.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/nlm/dev/net/mdio.c Tue Mar 27 14:05:12 2012 (r233545) @@ -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 +__FBSDID("$FreeBSD$"); +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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); +} Added: head/sys/mips/nlm/dev/net/nae.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/nlm/dev/net/nae.c Tue Mar 27 14:05:12 2012 (r233545) @@ -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 +__FBSDID("$FreeBSD$"); +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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++) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***