diff options
author | Ashish Chaudhari <ashish@ettus.com> | 2015-02-17 12:23:09 -0800 |
---|---|---|
committer | Ashish Chaudhari <ashish@ettus.com> | 2015-02-17 12:23:09 -0800 |
commit | 230cf5d76ac2417c36713e82bcd0fbe7986b7847 (patch) | |
tree | 3b26eddabd81588a32b956d7f1d0ed3f5c42c135 | |
parent | 3157734691882662fae4f86475a78db8fee1b441 (diff) | |
download | uhd-230cf5d76ac2417c36713e82bcd0fbe7986b7847.tar.gz uhd-230cf5d76ac2417c36713e82bcd0fbe7986b7847.tar.bz2 uhd-230cf5d76ac2417c36713e82bcd0fbe7986b7847.zip |
x300: Multiple firmware fixes for Vivado
- Refactored SFP+ hotplug handler
- GigE link state comes from SFP+ status and PHY status
- Multiple tracing enhancements
- Bumped firmware compat number to 4
- Bumpled FPGA compat number to 10
-rw-r--r-- | firmware/usrp3/include/ethernet.h | 5 | ||||
-rw-r--r-- | firmware/usrp3/lib/ethernet.c | 157 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_defs.h | 1 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_init.c | 34 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_main.c | 4 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_fw_common.h | 4 |
6 files changed, 111 insertions, 94 deletions
diff --git a/firmware/usrp3/include/ethernet.h b/firmware/usrp3/include/ethernet.h index 52f14d05b..a6bacfcd0 100644 --- a/firmware/usrp3/include/ethernet.h +++ b/firmware/usrp3/include/ethernet.h @@ -31,7 +31,7 @@ typedef void (*ethernet_link_changed_callback_t)(int ethnum, int speed); /*! * \brief one time call to initialize ethernet */ -void xge_ethernet_init(const uint32_t eth); +void ethernet_init(const uint32_t eth); /*! * \brief Return number of ethernet interfaces @@ -44,8 +44,7 @@ void dump_mdio_regs(const uint8_t eth, uint32_t mdio_port); /*! * \brief Test status of SFP+ modules */ -void -xge_poll_sfpp_status(const uint32_t eth); +void poll_sfpp_status(const uint32_t eth); //! get the link status of eth (true for link up) bool ethernet_get_link_up(const uint32_t eth); diff --git a/firmware/usrp3/lib/ethernet.c b/firmware/usrp3/lib/ethernet.c index a15f56498..91efbfe1d 100644 --- a/firmware/usrp3/lib/ethernet.c +++ b/firmware/usrp3/lib/ethernet.c @@ -305,94 +305,111 @@ unknown: return SFFP_TYPE_UNKNOWN; } -static void -xge_mac_init(const uint32_t base) +static void xge_mac_init(const uint32_t base) { - UHD_FW_TRACE(INFO, "Begining XGE MAC init sequence."); - xge_regs->config = XGE_TX_ENABLE; + UHD_FW_TRACE(DEBUG, "Begining XGE MAC init sequence."); + xge_regs->config = XGE_TX_ENABLE; } // base is pointer to XGE MAC on Wishbone. -static void -xge_phy_init(const uint8_t eth, const uint32_t mdio_port) +static void xge_phy_init(const uint8_t eth, const uint32_t mdio_port_arg) { - int x; - // Read LASI Ctrl register to capture state. - //y = xge_read_mdio(0x9002,XGE_MDIO_DEVICE_PMA,XGE_MDIO_ADDR_PHY_A); - UHD_FW_TRACE(INFO, "Begining XGE PHY init sequence."); - // Software reset - x = read_mdio(eth, 0x0, XGE_MDIO_DEVICE_PMA,mdio_port); - x = x | (1 << 15); - write_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port,x); - while(x&(1<<15)) - x = read_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port); + int x; + uint32_t mdio_port = eth==0 ? 1 : mdio_port_arg; + // Read LASI Ctrl register to capture state. + //y = xge_read_mdio(0x9002,XGE_MDIO_DEVICE_PMA,XGE_MDIO_ADDR_PHY_A); + UHD_FW_TRACE(DEBUG, "Begining XGE PHY init sequence."); + // Software reset + x = read_mdio(eth, 0x0, XGE_MDIO_DEVICE_PMA,mdio_port); + x = x | (1 << 15); + write_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port,x); + while(x&(1<<15)) { + x = read_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port); + } } -void -xge_poll_sfpp_status(const uint32_t eth) +void update_eth_state(const uint32_t eth) { - uint32_t x; - // Has MODDET/MODAbS changed since we last looked? - x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 )); - - if (x & SFPP_STATUS_RXLOS_CHG) - UHD_FW_TRACE_FSTR(INFO, "eth%1d RXLOS changed state: %d", eth, (x & SFPP_STATUS_RXLOS)); - if (x & SFPP_STATUS_TXFAULT_CHG) - UHD_FW_TRACE_FSTR(INFO, "eth%1d TXFAULT changed state: %d", eth, ((x & SFPP_STATUS_TXFAULT) >> 1)); - if (x & SFPP_STATUS_MODABS_CHG) - UHD_FW_TRACE_FSTR(INFO, "eth%1d MODABS changed state: %d", eth, ((x & SFPP_STATUS_MODABS) >> 2)); - - if (x & (SFPP_STATUS_RXLOS_CHG|SFPP_STATUS_TXFAULT_CHG|SFPP_STATUS_MODABS_CHG)) - { - if (( x & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0) - { - if (wb_peek32(SR_ADDR(RB0_BASE, eth == 0 ? RB_ETH_TYPE0 : RB_ETH_TYPE1)) == 1) - { - xge_ethernet_init(eth); - dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT); - mdelay(100); - dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT); - mdelay(100); - dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT); - } + const bool old_link_up = links_up[eth]; + const uint32_t status_reg_addr = (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1; + const bool is_10g = (wb_peek32(SR_ADDR(RB0_BASE, eth == 0 ? RB_ETH_TYPE0 : RB_ETH_TYPE1)) == 1); + + uint32_t sfpp_status = wb_peek32(SR_ADDR(RB0_BASE, status_reg_addr)) & 0xFFFF; + if ((sfpp_status & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0) { + //SFP+ pin state changed. Reinitialize PHY and MAC + if (is_10g) { + xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE); + xge_phy_init(eth ,MDIO_PORT); + } else { + //No-op for 1G + } + + int8_t timeout = 100; + bool link_up = false; + do { + if (is_10g) { + link_up = ((read_mdio(eth, XGE_MDIO_STATUS1,XGE_MDIO_DEVICE_PMA,MDIO_PORT)) & (1 << 2)) != 0; + } else { + link_up = ((wb_peek32(SR_ADDR(RB0_BASE, status_reg_addr)) >> 16) & 0x1) != 0; + } + } while (!link_up && timeout-- > 0); + + links_up[eth] = link_up; } - } - - if (x & SFPP_STATUS_MODABS_CHG) { - // MODDET has changed state since last checked - if (x & SFPP_STATUS_MODABS) { - // MODDET is high, module currently removed. - UHD_FW_TRACE_FSTR(INFO, "An SFP+ module has been removed from eth port %d.", eth); - } else { - // MODDET is low, module currently inserted. - // Return status. - UHD_FW_TRACE_FSTR(INFO, "A new SFP+ module has been inserted into eth port %d.", eth); - xge_read_sfpp_type((eth==0) ? I2C0_BASE : I2C2_BASE,1); + else + { + links_up[eth] = false; } - } - //update the link up status - const bool old_link_up = links_up[eth]; - links_up[eth] = ((read_mdio(eth, XGE_MDIO_STATUS1,XGE_MDIO_DEVICE_PMA,MDIO_PORT)) & (1 << 2)) != 0; - //The link became up, send a GARP so everyone knows our mac/ip association if (!old_link_up && links_up[eth]) u3_net_stack_send_arp_request(eth, u3_net_stack_get_ip_addr(eth)); + UHD_FW_TRACE_FSTR(INFO, "The link on eth port %u is %s", eth, links_up[eth]?"up":"down"); } +void poll_sfpp_status(const uint32_t eth) +{ + uint32_t x; + // Has MODDET/MODAbS changed since we last looked? + x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 )); + + if (x & SFPP_STATUS_RXLOS_CHG) + UHD_FW_TRACE_FSTR(DEBUG, "eth%1d RXLOS changed state: %d", eth, (x & SFPP_STATUS_RXLOS)); + if (x & SFPP_STATUS_TXFAULT_CHG) + UHD_FW_TRACE_FSTR(DEBUG, "eth%1d TXFAULT changed state: %d", eth, ((x & SFPP_STATUS_TXFAULT) >> 1)); + if (x & SFPP_STATUS_MODABS_CHG) + UHD_FW_TRACE_FSTR(DEBUG, "eth%1d MODABS changed state: %d", eth, ((x & SFPP_STATUS_MODABS) >> 2)); -void -xge_ethernet_init(const uint32_t eth) + //update the link up status + if ((x & SFPP_STATUS_RXLOS_CHG) || (x & SFPP_STATUS_TXFAULT_CHG) || (x & SFPP_STATUS_MODABS_CHG)) + { + update_eth_state(eth); + } + + if (x & SFPP_STATUS_MODABS_CHG) { + // MODDET has changed state since last checked + if (x & SFPP_STATUS_MODABS) { + // MODDET is high, module currently removed. + UHD_FW_TRACE_FSTR(INFO, "An SFP+ module has been removed from eth port %d.", eth); + } else { + // MODDET is low, module currently inserted. + // Return status. + UHD_FW_TRACE_FSTR(INFO, "A new SFP+ module has been inserted into eth port %d.", eth); + xge_read_sfpp_type((eth==0) ? I2C0_BASE : I2C2_BASE,1); + } + } +} + +void ethernet_init(const uint32_t eth) { - xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE); - //xge_hard_phy_reset(); - xge_phy_init(eth ,MDIO_PORT); #ifdef UHD_FW_TRACE_LEVEL - uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 )); - UHD_FW_TRACE_FSTR(INFO, "eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d", - eth, - (x & SFPP_STATUS_RXLOS), - ((x & SFPP_STATUS_TXFAULT) >> 1), - ((x & SFPP_STATUS_MODABS) >> 2)); + uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 )); + UHD_FW_TRACE_FSTR(DEBUG, "eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d", + eth, + (x & SFPP_STATUS_RXLOS), + ((x & SFPP_STATUS_TXFAULT) >> 1), + ((x & SFPP_STATUS_MODABS) >> 2)); #endif + links_up[eth] = false; + update_eth_state(eth); } // diff --git a/firmware/usrp3/x300/x300_defs.h b/firmware/usrp3/x300/x300_defs.h index 65c5d5a23..c4011bd12 100644 --- a/firmware/usrp3/x300/x300_defs.h +++ b/firmware/usrp3/x300/x300_defs.h @@ -51,6 +51,7 @@ static const int RB_SPI_RDY = 1; static const int RB_SPI_DATA = 2; static const int RB_ETH_TYPE0 = 4; static const int RB_ETH_TYPE1 = 5; +static const int RB_FPGA_COMPAT = 6; static const int RB_SFPP_STATUS0 = 8; static const int RB_SFPP_STATUS1 = 9; diff --git a/firmware/usrp3/x300/x300_init.c b/firmware/usrp3/x300/x300_init.c index 480e68a14..ef97412a2 100644 --- a/firmware/usrp3/x300/x300_init.c +++ b/firmware/usrp3/x300/x300_init.c @@ -130,7 +130,11 @@ void x300_init(void) //udp_uart_init(UART0_BASE, X300_GPSDO_UDP_PORT); //now we can init the rest with prints - UHD_FW_TRACE_FSTR(INFO, "[ZPU Init Begin -- CPU CLOCK is %d MHz]", (CPU_CLOCK/1000000)); + UHD_FW_TRACE(INFO, "[ZPU Initializing]"); + UHD_FW_TRACE_FSTR(INFO, "-- Firmware Compat Number: %u.%u", (int)X300_FW_COMPAT_MAJOR, (int)X300_FW_COMPAT_MINOR); + uint32_t fpga_compat = wb_peek32(SR_ADDR(SET0_BASE, RB_FPGA_COMPAT)); + UHD_FW_TRACE_FSTR(INFO, "-- FPGA Compat Number: %u.%u", (fpga_compat>>16), (fpga_compat&0xFFFF)); + UHD_FW_TRACE_FSTR(INFO, "-- Clock Frequency: %u MHz", (CPU_CLOCK/1000000)); //i2c rate init wb_i2c_init(I2C0_BASE, CPU_CLOCK); @@ -140,30 +144,26 @@ void x300_init(void) //hold phy in reset wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), SW_RST_PHY); - UHD_FW_TRACE_FSTR(INFO, "eth0 is %2dG", ((wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE0))==1) ? 10 : 1)); - UHD_FW_TRACE_FSTR(INFO, "eth1 is %2dG", ((wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE1))==1) ? 10 : 1)); - //setup net stack and eth state machines init_network(); //phy reset release wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), 0); - // For eth interfaces, initialize the PHY's - mdelay(100); - if (wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE0)) == 1) { - xge_ethernet_init(0); - } - if (wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE1)) == 1) { - xge_ethernet_init(1); - } - //print network summary for (uint8_t e = 0; e < ethernet_ninterfaces(); e++) { - UHD_FW_TRACE_FSTR(INFO, " MAC%u: %s", (int)e, mac_addr_to_str(u3_net_stack_get_mac_addr(e))); - UHD_FW_TRACE_FSTR(INFO, " IP%u: %s", (int)e, ip_addr_to_str(u3_net_stack_get_ip_addr(e))); - UHD_FW_TRACE_FSTR(INFO, " SUBNET%u: %s", (int)e, ip_addr_to_str(u3_net_stack_get_subnet(e))); - UHD_FW_TRACE_FSTR(INFO, " BCAST%u: %s", (int)e, ip_addr_to_str(u3_net_stack_get_bcast(e))); + uint32_t offset = SR_ADDR(RB0_BASE, ((e==1)?RB_ETH_TYPE1:RB_ETH_TYPE0)); + UHD_FW_TRACE_FSTR(INFO, "Ethernet Port %u:", (int)e); + UHD_FW_TRACE_FSTR(INFO, "-- PHY: %s", ((wb_peek32(offset)==1) ? "10Gbps" : "1Gbps")); + UHD_FW_TRACE_FSTR(INFO, "-- MAC: %s", mac_addr_to_str(u3_net_stack_get_mac_addr(e))); + UHD_FW_TRACE_FSTR(INFO, "-- IP: %s", ip_addr_to_str(u3_net_stack_get_ip_addr(e))); + UHD_FW_TRACE_FSTR(INFO, "-- SUBNET: %s", ip_addr_to_str(u3_net_stack_get_subnet(e))); + UHD_FW_TRACE_FSTR(INFO, "-- BCAST: %s", ip_addr_to_str(u3_net_stack_get_bcast(e))); } + + // For eth interfaces, initialize the PHY's + mdelay(100); + ethernet_init(0); + ethernet_init(1); } diff --git a/firmware/usrp3/x300/x300_main.c b/firmware/usrp3/x300/x300_main.c index b8c4fb41a..3b812a2c4 100644 --- a/firmware/usrp3/x300/x300_main.c +++ b/firmware/usrp3/x300/x300_main.c @@ -445,12 +445,12 @@ int main(void) static const uint32_t tick_delta = CPU_CLOCK/1000; if (ticks_passed > tick_delta) { + poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events. + poll_sfpp_status(1); // Every so often poll XGE Phy to look for SFP+ hotplug events. handle_link_state(); //deal with router table update handle_claim(); //deal with the host claim register update_leds(); //run the link and activity leds garp(); //send periodic garps - xge_poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events. - xge_poll_sfpp_status(1); // Every so often poll XGE Phy to look for SFP+ hotplug events. last_cronjob = wb_peek32(SR_ADDR(RB0_BASE, RB_COUNTER)); } diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h index 42583f7f0..a526cabe5 100644 --- a/host/lib/usrp/x300/x300_fw_common.h +++ b/host/lib/usrp/x300/x300_fw_common.h @@ -29,9 +29,9 @@ extern "C" { #endif -#define X300_FW_COMPAT_MAJOR 3 +#define X300_FW_COMPAT_MAJOR 4 #define X300_FW_COMPAT_MINOR 0 -#define X300_FPGA_COMPAT_MAJOR 9 +#define X300_FPGA_COMPAT_MAJOR 10 //shared memory sections - in between the stack and the program space #define X300_FW_SHMEM_BASE 0x6000 |