Date: Sat, 28 Aug 2010 19:02:52 +0000 (UTC) From: "Jayachandran C." <jchandra@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r211946 - in head/sys/mips/rmi: . dev/nlge Message-ID: <201008281902.o7SJ2qD7040851@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jchandra Date: Sat Aug 28 19:02:51 2010 New Revision: 211946 URL: http://svn.freebsd.org/changeset/base/211946 Log: New driver nlge for XLR/XLS Network Accelerator. This will support the XGMAC and XAUI 10G interfaces in addition RGMII/SGMII 1G interfaces. This driver is work in progress. board.c and board.h expanded to include more info. Only one of rge and nlge can be enabled at a time, rge will be deprecated when nlge stabilizes. Submitted by: Sriram Gorti <srgorti at netlogicmicro com> Added: head/sys/mips/rmi/dev/nlge/ head/sys/mips/rmi/dev/nlge/if_nlge.c (contents, props changed) head/sys/mips/rmi/dev/nlge/if_nlge.h (contents, props changed) Modified: head/sys/mips/rmi/board.c head/sys/mips/rmi/board.h head/sys/mips/rmi/files.xlr head/sys/mips/rmi/iodi.c Modified: head/sys/mips/rmi/board.c ============================================================================== --- head/sys/mips/rmi/board.c Sat Aug 28 18:49:51 2010 (r211945) +++ head/sys/mips/rmi/board.c Sat Aug 28 19:02:51 2010 (r211946) @@ -78,13 +78,12 @@ static int xls_rxstn_to_txstn_map[128] = [120 ... 127] = TX_STN_SAE }; -struct stn_cc *xlr_core_cc_configs[] = {&cc_table_cpu_0, &cc_table_cpu_1, - &cc_table_cpu_2, &cc_table_cpu_3, - &cc_table_cpu_4, &cc_table_cpu_5, -&cc_table_cpu_6, &cc_table_cpu_7}; +struct stn_cc *xlr_core_cc_configs[] = { &cc_table_cpu_0, &cc_table_cpu_1, + &cc_table_cpu_2, &cc_table_cpu_3, &cc_table_cpu_4, &cc_table_cpu_5, + &cc_table_cpu_6, &cc_table_cpu_7}; -struct stn_cc *xls_core_cc_configs[] = {&xls_cc_table_cpu_0, &xls_cc_table_cpu_1, -&xls_cc_table_cpu_2, &xls_cc_table_cpu_3}; +struct stn_cc *xls_core_cc_configs[] = { &xls_cc_table_cpu_0, &xls_cc_table_cpu_1, + &xls_cc_table_cpu_2, &xls_cc_table_cpu_3 }; struct xlr_board_info xlr_board_info; @@ -98,6 +97,174 @@ xlr_pcmcia_present(void) return ((resetconf & 0x4000) != 0); } +static void +xlr_board_specific_overrides(struct xlr_board_info* board) +{ + struct xlr_gmac_block_t *blk1, *blk2; + + blk1 = &board->gmac_block[1]; + blk2 = &board->gmac_block[2]; + + switch (xlr_boot1_info.board_major_version) { + case RMI_XLR_BOARD_ARIZONA_I: + /* ATX-I has SPI-4, not XGMAC */ + blk1->type = XLR_SPI4; + blk1->enabled = 0; /* nlge does not + support SPI-4 */ + blk2->type = XLR_SPI4; + blk2->enabled = 0; + break; + + case RMI_XLR_BOARD_ARIZONA_II: + /* XGMII_A --> VSC7281, XGMII_B --> VSC7281 */ + blk1->enabled = 1; + blk1->num_ports = 1; + blk1->gmac_port[0].valid = 1; + + blk2->enabled = 1; + blk2->num_ports = 1; + blk2->gmac_port[0].valid = 1; + default: + break; + } +} + +static int +quad0_xaui(void) +{ + xlr_reg_t *gpio_mmio = + (unsigned int *)(DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET); + uint32_t bit24; + + bit24 = (xlr_read_reg(gpio_mmio, 0x15) >> 24) & 0x1; + return (bit24); +} + +static int +quad1_xaui(void) +{ + xlr_reg_t *gpio_mmio = + (unsigned int *)(DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET); + uint32_t bit25; + + bit25 = (xlr_read_reg(gpio_mmio, 0x15) >> 25) & 0x1; + return (bit25); +} + +static void +xls_board_specific_overrides(struct xlr_board_info* board) +{ + struct xlr_gmac_block_t *blk0, *blk1; + int i; + + blk0 = &board->gmac_block[0]; + blk1 = &board->gmac_block[1]; + + switch (xlr_boot1_info.board_major_version) { + case RMI_XLR_BOARD_ARIZONA_VI: + blk0->mode = XLR_PORT0_RGMII; + blk0->gmac_port[0].type = XLR_RGMII; + blk0->gmac_port[0].phy_addr = 0; + blk0->gmac_port[0].mii_addr = XLR_IO_GMAC_4_OFFSET; + /* Because of the Octal PHY, SGMII Quad1 is MII is also bound + * to the PHY attached to SGMII0_MDC/MDIO/MDINT. */ + for (i = 0; i < 4; i++) { + blk1->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET; + } + blk1->gmac_port[1].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[2].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[3].mii_addr = XLR_IO_GMAC_0_OFFSET; + + blk1->gmac_port[1].serdes_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[2].serdes_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[3].serdes_addr = XLR_IO_GMAC_0_OFFSET; + + /* RGMII MDIO interrupt is thru NA1 and SGMII MDIO + * interrupts for ports in blk1 are from NA0 */ + blk0->gmac_port[0].mdint_id = 1; + + blk1->gmac_port[0].mdint_id = 0; + blk1->gmac_port[1].mdint_id = 0; + blk1->gmac_port[2].mdint_id = 0; + blk1->gmac_port[3].mdint_id = 0; + break; + + case RMI_XLR_BOARD_ARIZONA_VIII: + /* There is just one Octal PHY on the board and it is + * connected to the MII interface for NA Quad 0. */ + blk1->gmac_port[0].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[1].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[2].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk1->gmac_port[3].mii_addr = XLR_IO_GMAC_0_OFFSET; + + /* Board 8.3 (Lite) has XLS108 */ + if (xlr_boot1_info.board_minor_version == 3) { + /* NA0 has 3 ports */ + blk0->gmac_port[3].valid = 1; + blk0->num_ports--; + /* NA1 is completely disabled */ + blk1->enabled = 0; + } + + break; + + case RMI_XLR_BOARD_ARIZONA_XI: + case RMI_XLR_BOARD_ARIZONA_XII: + if (quad0_xaui()) { /* GMAC ports 0-3 are set to XAUI */ + /* only GMAC0 is active i.e, the 0-th port on this quad. + * Disable all the other 7 possible ports. */ + for (i = 1; i < MAX_NA_PORTS; i++) { + memset(&blk0->gmac_port[i], 0, + sizeof(blk0->gmac_port[i])); + } + /* Setup for XAUI on N/w Acc0: gmac0 */ + blk0->type = XLR_XGMAC; + blk0->mode = XLR_XAUI; + blk0->num_ports = 1; + blk0->gmac_port[0].type = XLR_XAUI; + blk1->gmac_port[0].phy_addr = 16; + blk0->gmac_port[0].tx_bucket_id = blk0->station_txbase; + /* Other addresses etc need not be modified as XAUI_0 + * shares its addresses with SGMII GMAC_0, which was + * set in the caller. */ + } + else { + blk0->num_ports = 1; /* only 1 RGMII port */ + blk0->mode = XLR_PORT0_RGMII; + blk0->gmac_port[0].type = XLR_RGMII; + blk0->gmac_port[0].phy_addr = 0; + blk0->gmac_port[0].mii_addr = XLR_IO_GMAC_0_OFFSET; + } + + if (quad1_xaui()) { /* GMAC ports 4-7 are used for XAUI */ + /* only GMAC4 is active i.e, the 0-th port on this quad. + * Disable all the other 7 possible ports. */ + for (i = 1; i < MAX_NA_PORTS; i++) { + memset(&blk1->gmac_port[i], 0, + sizeof(blk1->gmac_port[i])); + } + /* Setup for XAUI on N/w Acc1: gmac4 */ + blk1->type = XLR_XGMAC; + blk1->mode = XLR_XAUI; + blk1->num_ports = 1; + /* XAUI and SGMII ports share FMN buckets on N/w Acc 1; + so, station_txbase, station_rfr need not be + patched up. */ + blk1->gmac_port[0].type = XLR_XAUI; + blk1->gmac_port[0].phy_addr = 16; + blk1->gmac_port[0].tx_bucket_id = blk1->station_txbase; + /* Other addresses etc need not be modified as XAUI_1 + * shares its addresses with SGMII GMAC_4, which was + * set in the caller. */ + } + break; + + default: + break; + } +} + /* * All our knowledge of chip and board that cannot be detected by probing * at run-time goes here @@ -105,6 +272,57 @@ xlr_pcmcia_present(void) int xlr_board_info_setup() { + struct xlr_gmac_block_t *blk0, *blk1, *blk2; + int i; + + /* This setup code is long'ish because the same base driver + * (if_nlge.c) is used for different: + * - CPUs (XLR/XLS) + * - boards (for each CPU, multiple board configs are possible + * and available). + * + * At the time of writing, there are atleast 12 boards, 4 with XLR + * and 8 with XLS. This means that the base driver needs to work with + * 12 different configurations, with varying levels of differences. + * To accomodate the different configs, the xlr_board_info struct + * has various attributes for paramters that could be different. + * These attributes are setup here and can be used directly in the + * base driver. + * It was seen that the setup code is not entirely trivial and + * it is possible to organize it in different ways. In the following, + * we choose an approach that sacrifices code-compactness/speed for + * readability. This is because configuration code executes once + * per reboot and hence has a minimal performance impact. + * On the other hand, driver debugging/enhancements require + * that different engineers can quickly comprehend the setup + * sequence. Hence, readability is seen as the key requirement for + * this code. It is for the reader to decide how much of this + * requirement is met with the current code organization !! + * + * The initialization is organized thus: + * + * if (CPU is XLS) { + * // initialize per XLS architecture + * // default inits (per chip spec) + * // board-specific overrides + * } else if (CPU is XLR) { + * // initialize per XLR architecture + * // default inits (per chip spec) + * // board-specific overrides + * } + * + * Within each CPU-specific initialization, all the default + * initializations are done first. This is followed up with + * board specific overrides. + */ + + /* start with a clean slate */ + memset(&xlr_board_info, 0, sizeof(xlr_board_info)); + xlr_board_info.ata = xlr_pcmcia_present(); + + blk0 = &xlr_board_info.gmac_block[0]; + blk1 = &xlr_board_info.gmac_block[1]; + blk2 = &xlr_board_info.gmac_block[2]; if (xlr_is_xls()) { xlr_board_info.is_xls = 1; @@ -113,98 +331,154 @@ xlr_board_info_setup() /* Board version 8 has NAND flash */ xlr_board_info.cfi = (xlr_boot1_info.board_major_version != RMI_XLR_BOARD_ARIZONA_VIII); - xlr_board_info.ata = xlr_pcmcia_present(); xlr_board_info.pci_irq = 0; xlr_board_info.credit_configs = xls_core_cc_configs; - xlr_board_info.bucket_sizes = &xls_bucket_sizes; - xlr_board_info.msgmap = xls_rxstn_to_txstn_map; - xlr_board_info.gmacports = 8; - - /* network block 0 */ - xlr_board_info.gmac_block[0].type = XLR_GMAC; - xlr_board_info.gmac_block[0].enabled = 0xf; - xlr_board_info.gmac_block[0].credit_config = &xls_cc_table_gmac0; - xlr_board_info.gmac_block[0].station_txbase = MSGRNG_STNID_GMACTX0; - xlr_board_info.gmac_block[0].station_rfr = MSGRNG_STNID_GMACRFR_0; - if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI || - xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI || - xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XII) - xlr_board_info.gmac_block[0].mode = XLR_PORT0_RGMII; - else - xlr_board_info.gmac_block[0].mode = XLR_SGMII; - xlr_board_info.gmac_block[0].baseaddr = XLR_IO_GMAC_0_OFFSET; - xlr_board_info.gmac_block[0].baseirq = PIC_GMAC_0_IRQ; - xlr_board_info.gmac_block[0].baseinst = 0; - - /* network block 1 */ - xlr_board_info.gmac_block[1].type = XLR_GMAC; - xlr_board_info.gmac_block[1].enabled = xlr_is_xls1xx() ? 0 : 0xf; - if (xlr_is_xls4xx_lite()) { - xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET); - uint32_t tmp; - - /* some ports are not enabled on the condor 4xx, figure this - out from the GPIO fuse bank */ - tmp = xlr_read_reg(mmio, 35); - if (tmp & (1<<28)) - xlr_board_info.gmac_block[1].enabled &= ~0x8; - if (tmp & (1<<29)) - xlr_board_info.gmac_block[1].enabled &= ~0x4; - } - xlr_board_info.gmac_block[1].credit_config = &xls_cc_table_gmac1; - xlr_board_info.gmac_block[1].station_txbase = MSGRNG_STNID_GMAC1_TX0; - xlr_board_info.gmac_block[1].station_rfr = MSGRNG_STNID_GMAC1_FR_0; - xlr_board_info.gmac_block[1].mode = XLR_SGMII; - xlr_board_info.gmac_block[1].baseaddr = XLR_IO_GMAC_4_OFFSET; - xlr_board_info.gmac_block[1].baseirq = PIC_XGS_0_IRQ; - xlr_board_info.gmac_block[1].baseinst = 4; - - /* network block 2 */ - xlr_board_info.gmac_block[2].enabled = 0; /* disabled on XLS */ - } else { + xlr_board_info.bucket_sizes = &xls_bucket_sizes; + xlr_board_info.msgmap = xls_rxstn_to_txstn_map; + xlr_board_info.gmacports = MAX_NA_PORTS; + + /* ---------------- Network Acc 0 ---------------- */ + + blk0->type = XLR_GMAC; + blk0->enabled = 0xf; + blk0->credit_config = &xls_cc_table_gmac0; + blk0->station_id = TX_STN_GMAC0; + blk0->station_txbase = MSGRNG_STNID_GMACTX0; + blk0->station_rfr = MSGRNG_STNID_GMACRFR_0; + blk0->mode = XLR_SGMII; + blk0->baseaddr = XLR_IO_GMAC_0_OFFSET; + blk0->baseirq = PIC_GMAC_0_IRQ; + blk0->baseinst = 0; + + /* By default, assume SGMII is setup. But this can change based + on board-specific or setting-specific info. */ + for (i = 0; i < 4; i++) { + blk0->gmac_port[i].valid = 1; + blk0->gmac_port[i].instance = i + blk0->baseinst; + blk0->gmac_port[i].type = XLR_SGMII; + blk0->gmac_port[i].phy_addr = i + 16; + blk0->gmac_port[i].tx_bucket_id = + blk0->station_txbase + i; + blk0->gmac_port[i].mdint_id = 0; + blk0->num_ports++; + blk0->gmac_port[i].base_addr = XLR_IO_GMAC_0_OFFSET + i * 0x1000; + blk0->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET; + blk0->gmac_port[i].pcs_addr = XLR_IO_GMAC_0_OFFSET; + blk0->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET; + } + + /* ---------------- Network Acc 1 ---------------- */ + blk1->type = XLR_GMAC; + blk1->enabled = 0xf; + blk1->credit_config = &xls_cc_table_gmac1; + blk1->station_id = TX_STN_GMAC1; + blk1->station_txbase = MSGRNG_STNID_GMAC1_TX0; + blk1->station_rfr = MSGRNG_STNID_GMAC1_FR_0; + blk1->mode = XLR_SGMII; + blk1->baseaddr = XLR_IO_GMAC_4_OFFSET; + blk1->baseirq = PIC_XGS_0_IRQ; + blk1->baseinst = 4; + + for (i = 0; i < 4; i++) { + blk1->gmac_port[i].valid = 1; + blk1->gmac_port[i].instance = i + blk1->baseinst; + blk1->gmac_port[i].type = XLR_SGMII; + blk1->gmac_port[i].phy_addr = i + 20; + blk1->gmac_port[i].tx_bucket_id = + blk1->station_txbase + i; + blk1->gmac_port[i].mdint_id = 1; + blk1->num_ports++; + blk1->gmac_port[i].base_addr = XLR_IO_GMAC_4_OFFSET + i * 0x1000; + blk1->gmac_port[i].mii_addr = XLR_IO_GMAC_4_OFFSET; + blk1->gmac_port[i].pcs_addr = XLR_IO_GMAC_4_OFFSET; + blk1->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET; + } + + /* ---------------- Network Acc 2 ---------------- */ + xlr_board_info.gmac_block[2].enabled = 0; /* disabled on XLS */ + + xls_board_specific_overrides(&xlr_board_info); + + } else { /* XLR */ xlr_board_info.is_xls = 0; xlr_board_info.nr_cpus = 32; xlr_board_info.usb = 0; xlr_board_info.cfi = 1; - xlr_board_info.ata = xlr_pcmcia_present(); xlr_board_info.pci_irq = 0; xlr_board_info.credit_configs = xlr_core_cc_configs; - xlr_board_info.bucket_sizes = &bucket_sizes; - xlr_board_info.msgmap = xlr_rxstn_to_txstn_map; - xlr_board_info.gmacports = 4; - - /* GMAC0 */ - xlr_board_info.gmac_block[0].type = XLR_GMAC; - xlr_board_info.gmac_block[0].enabled = 0xf; - xlr_board_info.gmac_block[0].credit_config = &cc_table_gmac; - xlr_board_info.gmac_block[0].station_txbase = MSGRNG_STNID_GMACTX0; - xlr_board_info.gmac_block[0].station_rfr = MSGRNG_STNID_GMACRFR_0; - xlr_board_info.gmac_block[0].mode = XLR_RGMII; - xlr_board_info.gmac_block[0].baseaddr = XLR_IO_GMAC_0_OFFSET; - xlr_board_info.gmac_block[0].baseirq = PIC_GMAC_0_IRQ; - xlr_board_info.gmac_block[0].baseinst = 0; - - /* XGMAC0 */ - xlr_board_info.gmac_block[1].type = XLR_XGMAC; - xlr_board_info.gmac_block[1].enabled = 1; - xlr_board_info.gmac_block[1].credit_config = &cc_table_xgs_0; - xlr_board_info.gmac_block[1].station_txbase = MSGRNG_STNID_XGS0_TX; - xlr_board_info.gmac_block[1].station_rfr = MSGRNG_STNID_XGS0FR; - xlr_board_info.gmac_block[1].mode = -1; - xlr_board_info.gmac_block[1].baseaddr = XLR_IO_XGMAC_0_OFFSET; - xlr_board_info.gmac_block[1].baseirq = PIC_XGS_0_IRQ; - xlr_board_info.gmac_block[1].baseinst = 4; - - /* XGMAC1 */ - xlr_board_info.gmac_block[2].type = XLR_XGMAC; - xlr_board_info.gmac_block[2].enabled = 1; - xlr_board_info.gmac_block[2].credit_config = &cc_table_xgs_1; - xlr_board_info.gmac_block[2].station_txbase = MSGRNG_STNID_XGS1_TX; - xlr_board_info.gmac_block[2].station_rfr = MSGRNG_STNID_XGS1FR; - xlr_board_info.gmac_block[2].mode = -1; - xlr_board_info.gmac_block[2].baseaddr = XLR_IO_XGMAC_1_OFFSET; - xlr_board_info.gmac_block[2].baseirq = PIC_XGS_1_IRQ; - xlr_board_info.gmac_block[2].baseinst = 5; - } - return 0; + xlr_board_info.bucket_sizes = &bucket_sizes; + xlr_board_info.msgmap = xlr_rxstn_to_txstn_map; + xlr_board_info.gmacports = 4; + + /* ---------------- GMAC0 ---------------- */ + blk0->type = XLR_GMAC; + blk0->enabled = 0xf; + blk0->credit_config = &cc_table_gmac; + blk0->station_id = TX_STN_GMAC; + blk0->station_txbase = MSGRNG_STNID_GMACTX0; + blk0->station_rfr = MSGRNG_STNID_GMACRFR_0; + blk0->mode = XLR_RGMII; + blk0->baseaddr = XLR_IO_GMAC_0_OFFSET; + blk0->baseirq = PIC_GMAC_0_IRQ; + blk0->baseinst = 0; + + /* first, do the common/easy stuff for all the ports */ + for (i = 0; i < 4; i++) { + blk0->gmac_port[i].valid = 1; + blk0->gmac_port[i].instance = i + blk0->baseinst; + blk0->gmac_port[i].type = XLR_RGMII; + blk0->gmac_port[i].phy_addr = i; + blk0->gmac_port[i].tx_bucket_id = + blk0->station_txbase + i; + blk0->gmac_port[i].mdint_id = 0; + blk0->gmac_port[i].base_addr = XLR_IO_GMAC_0_OFFSET + i * 0x1000; + blk0->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET; + /* RGMII ports, no PCS/SERDES */ + blk0->num_ports++; + } + + /* ---------------- XGMAC0 ---------------- */ + blk1->type = XLR_XGMAC; + blk1->mode = XLR_XGMII; + blk1->enabled = 0; + blk1->credit_config = &cc_table_xgs_0; + blk1->station_txbase = MSGRNG_STNID_XGS0_TX; + blk1->station_rfr = MSGRNG_STNID_XMAC0RFR; + blk1->station_id = TX_STN_XGS_0; /* TBD: is this correct ? */ + blk1->baseaddr = XLR_IO_XGMAC_0_OFFSET; + blk1->baseirq = PIC_XGS_0_IRQ; + blk1->baseinst = 4; + + blk1->gmac_port[0].type = XLR_XGMII; + blk1->gmac_port[0].instance = 0; + blk1->gmac_port[0].phy_addr = 0; + blk1->gmac_port[0].base_addr = XLR_IO_XGMAC_0_OFFSET; + blk1->gmac_port[0].mii_addr = XLR_IO_XGMAC_0_OFFSET; + blk1->gmac_port[0].tx_bucket_id = blk1->station_txbase; + blk1->gmac_port[0].mdint_id = 1; + + /* ---------------- XGMAC1 ---------------- */ + blk2->type = XLR_XGMAC; + blk2->mode = XLR_XGMII; + blk2->enabled = 0; + blk2->credit_config = &cc_table_xgs_1; + blk2->station_txbase = MSGRNG_STNID_XGS1_TX; + blk2->station_rfr = MSGRNG_STNID_XMAC1RFR; + blk2->station_id = TX_STN_XGS_1; /* TBD: is this correct ? */ + blk2->baseaddr = XLR_IO_XGMAC_1_OFFSET; + blk2->baseirq = PIC_XGS_1_IRQ; + blk2->baseinst = 5; + + blk2->gmac_port[0].type = XLR_XGMII; + blk2->gmac_port[0].instance = 0; + blk2->gmac_port[0].phy_addr = 0; + blk2->gmac_port[0].base_addr = XLR_IO_XGMAC_1_OFFSET; + blk2->gmac_port[0].mii_addr = XLR_IO_XGMAC_1_OFFSET; + blk2->gmac_port[0].tx_bucket_id = blk2->station_txbase; + blk2->gmac_port[0].mdint_id = 2; + + /* Done with default setup. Now do board-specific tweaks. */ + xlr_board_specific_overrides(&xlr_board_info); + } + return 0; } Modified: head/sys/mips/rmi/board.h ============================================================================== --- head/sys/mips/rmi/board.h Sat Aug 28 18:49:51 2010 (r211945) +++ head/sys/mips/rmi/board.h Sat Aug 28 19:02:51 2010 (r211946) @@ -132,41 +132,53 @@ xlr_is_xls4xx_lite(void) uint32_t chipid = xlr_processor_id(); return (chipid == 0x88 || chipid == 0x8c); -} + } + +/* SPI-4 --> 8 ports, 1G MAC --> 4 ports and 10G MAC --> 1 port */ +#define MAX_NA_PORTS 8 /* all our knowledge of chip and board that cannot be detected run-time goes here */ -enum gmac_block_types { - XLR_GMAC, XLR_XGMAC, XLR_SPI4 -}; - -enum gmac_block_modes { - XLR_RGMII, XLR_SGMII, XLR_PORT0_RGMII -}; +enum gmac_block_types { XLR_GMAC, XLR_XGMAC, XLR_SPI4}; +enum gmac_port_types { XLR_RGMII, XLR_SGMII, XLR_PORT0_RGMII, XLR_XGMII, XLR_XAUI }; struct xlr_board_info { int is_xls; int nr_cpus; - int usb; /* usb enabled ? */ - int cfi; /* NOR flash */ - int ata; /* PCMCIA/compactflash driver */ + int usb; /* usb enabled ? */ + int cfi; /* compact flash driver for NOR? */ + int ata; /* ata driver */ int pci_irq; - struct stn_cc **credit_configs; /* pointer to Core station credits */ - struct bucket_size *bucket_sizes; /* pointer to Core station - * bucket */ - int *msgmap; /* mapping of message station to devices */ - int gmacports; /* number of gmac ports on the board */ - struct xlr_gmac_block_t { - int type; /* see enum gmac_block_types */ - unsigned int enabled; /* mask of ports enabled */ - struct stn_cc *credit_config; /* credit configuration */ - int station_txbase; /* station id for tx */ - int station_rfr;/* free desc bucket */ - int mode; /* see gmac_block_modes */ - uint32_t baseaddr; /* IO base */ - int baseirq; /* first irq for this block, the rest are in - * sequence */ - int baseinst; /* the first rge unit for this block */ - } gmac_block[3]; + struct stn_cc **credit_configs; /* pointer to Core station credits */ + struct bucket_size *bucket_sizes; /* pointer to Core station bucket */ + int *msgmap; /* mapping of message station to devices */ + int gmacports; /* number of gmac ports on the board */ + struct xlr_gmac_block_t { /* refers to the set of GMACs controlled by a + network accelarator */ + int type; /* see enum gmac_block_types */ + unsigned int enabled; /* mask of ports enabled */ + struct stn_cc *credit_config; /* credit configuration */ + int station_id; /* station id for sending msgs */ + int station_txbase; /* station id for tx */ + int station_rfr; /* free desc bucket */ + int mode; /* see gmac_block_modes */ + uint32_t baseaddr; /* IO base */ + int baseirq; /* first irq for this block, the rest are in sequence */ + int baseinst; /* the first rge unit for this block */ + int num_ports; + struct xlr_gmac_port { + int valid; + int type; /* see enum gmac_port_types */ + uint32_t instance; /* identifies the GMAC to which + this port is bound to. */ + uint32_t phy_addr; + uint32_t base_addr; + uint32_t mii_addr; + uint32_t pcs_addr; + uint32_t serdes_addr; + uint32_t tx_bucket_id; + uint32_t mdint_id; + } gmac_port[MAX_NA_PORTS]; + } gmac_block [3]; }; extern struct xlr_board_info xlr_board_info; Added: head/sys/mips/rmi/dev/nlge/if_nlge.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/rmi/dev/nlge/if_nlge.c Sat Aug 28 19:02:51 2010 (r211946) @@ -0,0 +1,2444 @@ +/*- + * Copyright (c) 2003-2009 RMI 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. + * 3. Neither the name of RMI Corporation, nor the names of its contributors, + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. + * + * RMI_BSD */ + +/* + * The XLR device supports upto four 10/100/1000 Ethernet MACs and upto + * two 10G Ethernet MACs (of XGMII). Alternatively, each 10G port can used + * as a SPI-4 interface, with 8 ports per such interface. The MACs are + * encapsulated in another hardware block referred to as network accelerator, + * such that there are three instances of these in a XLR. One of them controls + * the four 1G RGMII ports while one each of the others controls an XGMII port. + * Enabling MACs requires configuring the corresponding network accelerator + * and the individual port. + * The XLS device supports upto 8 10/100/1000 Ethernet MACs or max 2 10G + * Ethernet MACs. The 1G MACs are of SGMII and 10G MACs are of XAUI + * interface. These ports are part of two network accelerators. + * The nlge driver configures and initializes non-SPI4 Ethernet ports in the + * XLR/XLS devices and enables data transfer on them. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include "opt_device_polling.h" +#endif + +#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 <sys/smp.h> +#include <sys/sysctl.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 <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/rmi/interrupt.h> +#include <mips/rmi/msgring.h> +#include <mips/rmi/iomap.h> +#include <mips/rmi/debug.h> +#include <mips/rmi/pic.h> +#include <mips/rmi/xlrconfig.h> +#include <mips/rmi/shared_structs.h> +#include <mips/rmi/board.h> +#include <mips/rmi/rmi_mips_exts.h> +#include <mips/rmi/dev/xlr/atx_cpld.h> +#include <mips/rmi/dev/xlr/xgmac_mdio.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> +#include "miidevs.h" +#include <dev/mii/brgphyreg.h> +#include "miibus_if.h" + +#include <mips/rmi/dev/nlge/if_nlge.h> + +MODULE_DEPEND(nlna, nlge, 1, 1, 1); +MODULE_DEPEND(nlge, ether, 1, 1, 1); +MODULE_DEPEND(nlge, miibus, 1, 1, 1); + +/* Network accelarator entry points */ +static int nlna_probe(device_t); +static int nlna_attach(device_t); +static int nlna_detach(device_t); +static int nlna_suspend(device_t); +static int nlna_resume(device_t); +static int nlna_shutdown(device_t); + +/* GMAC port entry points */ +static int nlge_probe(device_t); +static int nlge_attach(device_t); +static int nlge_detach(device_t); +static int nlge_suspend(device_t); +static int nlge_resume(device_t); +static void nlge_init(void *); +static int nlge_ioctl(struct ifnet *, u_long, caddr_t); +static void nlge_start(struct ifnet *); +static void nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len); + +static int nlge_mii_write(struct device *, int, int, int); +static int nlge_mii_read(struct device *, int, int); +static void nlge_mac_mii_statchg(device_t); +static int nlge_mediachange(struct ifnet *ifp); +static void nlge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr); + +/* Other internal/helper functions */ +static void *get_buf(void); +static struct mbuf *get_mbuf(void); + +static void nlna_add_to_port_set(struct nlge_port_set *pset, + struct nlge_softc *sc); +static void nlna_config_pde(struct nlna_softc *); +static void nlna_config_parser(struct nlna_softc *); +static void nlna_config_classifier(struct nlna_softc *); +static void nlna_config_fifo_spill_area(struct nlna_softc *sc); +static void nlna_config_common(struct nlna_softc *); +static void nlna_disable_ports(struct nlna_softc *sc); +static void nlna_enable_intr(struct nlna_softc *sc); +static void nlna_disable_intr(struct nlna_softc *sc); +static void nlna_enable_ports(struct nlna_softc *sc); +static void nlna_get_all_softc(device_t iodi_dev, + struct nlna_softc **sc_vec, uint32_t vec_sz); +static void nlna_hw_init(struct nlna_softc *sc); +static int nlna_is_last_active_na(struct nlna_softc *sc); +static void nlna_media_specific_config(struct nlna_softc *sc); +static void nlna_reset_ports(struct nlna_softc *sc, + struct xlr_gmac_block_t *blk); +static struct nlna_softc *nlna_sc_init(device_t dev, + struct xlr_gmac_block_t *blk); +static __inline__ int nlna_send_free_desc(struct nlna_softc *nlna, + vm_paddr_t addr); +static void nlna_setup_intr(struct nlna_softc *sc); +static void nlna_smp_update_pde(void *dummy __unused); +static void nlna_submit_rx_free_desc(struct nlna_softc *sc, + uint32_t n_desc); + +static int nlge_gmac_config_speed(struct nlge_softc *, int quick); +static void nlge_hw_init(struct nlge_softc *sc); +static int nlge_if_init(struct nlge_softc *sc); +static void nlge_intr(void *arg); +static int nlge_irq_init(struct nlge_softc *sc); +static void nlge_irq_fini(struct nlge_softc *sc); +static void nlge_media_specific_init(struct nlge_softc *sc); +static void nlge_mii_init(device_t dev, struct nlge_softc *sc); +static int nlge_mii_read_internal(xlr_reg_t *mii_base, int phyaddr, + int regidx); +static void nlge_mii_write_internal(xlr_reg_t *mii_base, int phyaddr, + int regidx, int regval); +void nlge_msgring_handler(int bucket, int size, int code, + int stid, struct msgrng_msg *msg, void *data); +static void nlge_port_disable(int id, xlr_reg_t *base, int port_type); +static void nlge_port_enable(struct nlge_softc *sc); +static void nlge_read_mac_addr(struct nlge_softc *sc); +static void nlge_sc_init(struct nlge_softc *sc, device_t dev, + struct xlr_gmac_port *port_info); +static void nlge_set_mac_addr(struct nlge_softc *sc); +static void nlge_set_port_attribs(struct nlge_softc *, + struct xlr_gmac_port *); +static void nlge_sgmii_init(struct nlge_softc *sc); +static void nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc); + +static int prepare_fmn_message(struct nlge_softc *sc, + struct msgrng_msg *msg, uint32_t *n_entries, struct mbuf *m_head, + uint64_t fr_stid, struct nlge_tx_desc **tx_desc); + +static void release_mbuf(uint64_t phy_addr); +static void release_tx_desc(struct msgrng_msg *msg, int rel_buf); +static int send_fmn_msg_tx(struct nlge_softc *, struct msgrng_msg *, + uint32_t n_entries); + +//#define DEBUG +#ifdef DEBUG +static int mac_debug = 1; +static int reg_dump = 0; +#undef PDEBUG +#define PDEBUG(fmt, args...) \ + do {\ + if (mac_debug) {\ + printf("[%s@%d|%s]: cpu_%d: " fmt, \ + __FILE__, __LINE__, __FUNCTION__, PCPU_GET(cpuid), ##args);\ + }\ + } while(0); + +/* Debug/dump functions */ +static void dump_reg(xlr_reg_t *addr, uint32_t offset, char *name); +static void dump_gmac_registers(struct nlge_softc *); +static void dump_na_registers(xlr_reg_t *base, int port_id); +static void dump_mac_stats(struct nlge_softc *sc); +static void dump_mii_regs(struct nlge_softc *sc) __attribute__((used)); +static void dump_mii_data(struct mii_data *mii) __attribute__((used)); +static void dump_board_info(struct xlr_board_info *); +static void dump_pcs_regs(struct nlge_softc *sc, int phy); + +#else +#undef PDEBUG +#define PDEBUG(fmt, args...) +#define dump_reg(a, o, n) /* nop */ +#define dump_gmac_registers(a) /* nop */ +#define dump_na_registers(a, p) /* nop */ +#define dump_board_info(b) /* nop */ +#define dump_mac_stats(sc) /* nop */ +#define dump_mii_regs(sc) /* nop */ +#define dump_mii_data(mii) /* nop */ +#define dump_pcs_regs(sc, phy) /* nop */ +#endif + +/* Wrappers etc. to export the driver entry points. */ +static device_method_t nlna_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nlna_probe), + DEVMETHOD(device_attach, nlna_attach), + DEVMETHOD(device_detach, nlna_detach), + DEVMETHOD(device_shutdown, nlna_shutdown), + DEVMETHOD(device_suspend, nlna_suspend), + DEVMETHOD(device_resume, nlna_resume), + + /* bus interface : TBD : what are these for ? */ + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + { 0, 0 } +}; + +static driver_t nlna_driver = { + "nlna", + nlna_methods, + sizeof(struct nlna_softc) +}; + +static devclass_t nlna_devclass; + +static device_method_t nlge_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nlge_probe), + DEVMETHOD(device_attach, nlge_attach), + DEVMETHOD(device_detach, nlge_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, nlge_suspend), + DEVMETHOD(device_resume, nlge_resume), + + /* MII interface */ + DEVMETHOD(miibus_readreg, nlge_mii_read), + DEVMETHOD(miibus_writereg, nlge_mii_write), + DEVMETHOD(miibus_statchg, nlge_mac_mii_statchg), + + {0, 0} +}; + +static driver_t nlge_driver = { + "nlge", + nlge_methods, + sizeof(struct nlge_softc) +}; + +static devclass_t nlge_devclass; + +DRIVER_MODULE(nlna, iodi, nlna_driver, nlna_devclass, 0, 0); +DRIVER_MODULE(nlge, nlna, nlge_driver, nlge_devclass, 0, 0); +DRIVER_MODULE(miibus, nlge, miibus_driver, miibus_devclass, 0, 0); + +static uma_zone_t nl_tx_desc_zone; + +/* Function to atomically increment an integer with the given value. */ +static __inline__ unsigned int +ldadd_wu(unsigned int value, unsigned long *addr) +{ + __asm__ __volatile__( ".set push\n" + ".set noreorder\n" + "move $8, %2\n" + "move $9, %3\n" + /* "ldaddwu $8, $9\n" */ + ".word 0x71280011\n" + "move %0, $8\n" + ".set pop\n" + : "=&r"(value), "+m"(*addr) + : "0"(value), "r" ((unsigned long)addr) + : "$8", "$9"); + return value; +} + +static __inline__ uint32_t +xlr_enable_kx(void) +{ + uint32_t sr = mips_rd_status(); + + mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); + return sr; +} + +static int +nlna_probe(device_t dev) +{ + return (BUS_PROBE_DEFAULT); +} + +/* + * Add all attached GMAC/XGMAC ports to the device tree. Port + * configuration is spread in two regions - common configuration + * for all ports in the NA and per-port configuration in MAC-specific + * region. This function does the following: + * - adds the ports to the device tree + * - reset the ports + * - do all the common initialization + * - invoke bus_generic_attach for per-port configuration + * - supply initial free rx descriptors to ports + * - initialize s/w data structures + * - finally, enable interrupts (only in the last NA). + * + * For reference, sample address space for common and per-port + * registers is given below. + * + * The address map for RNA0 is: (typical value) + * + * XLR_IO_BASE +--------------------------------------+ 0xbef0_0000 + * | | + * | | + * | | + * | | + * | | + * | | + * GMAC0 ---> +--------------------------------------+ 0xbef0_c000 + * | | + * | | + * (common) -> |......................................| 0xbef0_c400 + * | | + * | (RGMII/SGMII: common registers) | + * | | + * GMAC1 ---> |--------------------------------------| 0xbef0_d000 + * | | + * | | + * (common) -> |......................................| 0xbef0_d400 + * | | + * | (RGMII/SGMII: common registers) | + * | | + * |......................................| + * and so on .... + * + * Ref: Figure 14-3 and Table 14-1 of XLR PRM + */ +static int +nlna_attach(device_t dev) +{ + struct xlr_gmac_block_t *block_info; + device_t gmac_dev; + struct nlna_softc *sc; + int error; + int i; + int id; + + id = device_get_unit(dev); + block_info = device_get_ivars(dev); + if (!block_info->enabled) { + return 0; + } + +#ifdef DEBUG + dump_board_info(&xlr_board_info); +#endif + block_info->baseaddr += DEFAULT_XLR_IO_BASE; + + /* Initialize nlna state in softc structure */ + sc = nlna_sc_init(dev, block_info); + + /* Add device's for the ports controlled by this NA. */ + if (block_info->type == XLR_GMAC) { + KASSERT(id < 2, ("No GMACs supported with this network" + "accelerator: %d", id)); + for (i = 0; i < sc->num_ports; i++) { + gmac_dev = device_add_child(dev, "nlge", -1); + device_set_ivars(gmac_dev, &block_info->gmac_port[i]); + } + } else if (block_info->type == XLR_XGMAC) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008281902.o7SJ2qD7040851>