diff options
Diffstat (limited to 'firmware/usrp3/lib/ethernet.c')
-rw-r--r-- | firmware/usrp3/lib/ethernet.c | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/firmware/usrp3/lib/ethernet.c b/firmware/usrp3/lib/ethernet.c index 91efbfe1d..e5226489f 100644 --- a/firmware/usrp3/lib/ethernet.c +++ b/firmware/usrp3/lib/ethernet.c @@ -21,7 +21,7 @@ #endif #include "../x300/x300_defs.h" #include "ethernet.h" -#include "mdelay.h" +#include "cron.h" #include <trace.h> #include "wb_i2c.h" #include "wb_utils.h" @@ -161,8 +161,8 @@ ge_write_mdio(const uint32_t base, const uint32_t address, const uint32_t port, static uint32_t read_mdio(const uint8_t eth, const uint32_t address, const uint32_t device, const uint32_t port) { - const uint32_t rb_addr = (eth==0) ? RB_ETH_TYPE0 : RB_ETH_TYPE1; - const uint32_t base = (eth==0) ? XGE0_BASE : XGE1_BASE; + const uint32_t rb_addr = (eth==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE; + const uint32_t base = (eth==0) ? SFP0_MAC_BASE : SFP1_MAC_BASE; if (wb_peek32(SR_ADDR(RB0_BASE, rb_addr)) != 0) { return xge_read_mdio(base, address, device, port); @@ -175,8 +175,8 @@ static uint32_t read_mdio(const uint8_t eth, const uint32_t address, const uint3 static void write_mdio(const uint8_t eth, const uint32_t address, const uint32_t device, const uint32_t port, const uint32_t data) { - const uint32_t rb_addr = (eth==0) ? RB_ETH_TYPE0 : RB_ETH_TYPE1; - const uint32_t base = (eth==0) ? XGE0_BASE : XGE1_BASE; + const uint32_t rb_addr = (eth==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE; + const uint32_t base = (eth==0) ? SFP0_MAC_BASE : SFP1_MAC_BASE; if (wb_peek32(SR_ADDR(RB0_BASE, rb_addr)) != 0) { return xge_write_mdio(base, address, device, port, data); @@ -220,7 +220,7 @@ xge_read_sfpp_type(const uint32_t base, const uint32_t delay_ms) int x; // Delay read of SFPP if (delay_ms) - mdelay(delay_ms); + sleep_ms(delay_ms); // Read ID code from SFP x = xge_i2c_rd(base, MODULE_DEV_ADDR, 3); // I2C Error? @@ -312,10 +312,9 @@ static void xge_mac_init(const uint32_t base) } // base is pointer to XGE MAC on Wishbone. -static void xge_phy_init(const uint8_t eth, const uint32_t mdio_port_arg) +static void xge_phy_init(const uint8_t eth, const uint32_t 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."); @@ -323,23 +322,24 @@ static void xge_phy_init(const uint8_t eth, const uint32_t mdio_port_arg) 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); + uint32_t loopCount = 0; while(x&(1<<15)) { x = read_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port); + if( loopCount++ > 200 ) break; // usually succeeds after 22 or 23 polls } } -void update_eth_state(const uint32_t eth) +void update_eth_state(const uint32_t eth, const uint32_t sfp_type) { 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); + const uint32_t status_reg_addr = (eth==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS; 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); + if (sfp_type == RB_SFP_10G_ETH) { + xge_mac_init((eth==0) ? SFP0_MAC_BASE : SFP1_MAC_BASE); + xge_phy_init(eth, MDIO_PORT); } else { //No-op for 1G } @@ -347,7 +347,7 @@ void update_eth_state(const uint32_t eth) int8_t timeout = 100; bool link_up = false; do { - if (is_10g) { + if (sfp_type == RB_SFP_10G_ETH) { 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; @@ -362,54 +362,66 @@ void update_eth_state(const uint32_t eth) } 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) +void poll_sfpp_status(const uint32_t sfp) { - 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 )); + uint32_t type = wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE)); + uint32_t status = wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS)); - 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)); - - //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) { + if (status & SFPP_STATUS_MODABS_CHG) { // MODDET has changed state since last checked - if (x & SFPP_STATUS_MODABS) { + if (status & 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); + UHD_FW_TRACE_FSTR(INFO, "An SFP+ module has been removed from eth port %d.", sfp); } 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); + UHD_FW_TRACE_FSTR(INFO, "A new SFP+ module has been inserted into eth port %d.", sfp); + if (type == RB_SFP_10G_ETH) { + xge_read_sfpp_type((sfp==0) ? I2C0_BASE : I2C2_BASE,1); + } } } + + if (status & SFPP_STATUS_RXLOS_CHG) { + UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d RXLOS changed state: %d", sfp, (status & SFPP_STATUS_RXLOS)); + } + if (status & SFPP_STATUS_TXFAULT_CHG) { + UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d TXFAULT changed state: %d", sfp, ((status & SFPP_STATUS_TXFAULT) >> 1)); + } + if (status & SFPP_STATUS_MODABS_CHG) { + UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d MODABS changed state: %d", sfp, ((status & SFPP_STATUS_MODABS) >> 2)); + } + + //update the link up status + const bool old_link_up = links_up[sfp]; + if (type == RB_SFP_AURORA) { + links_up[sfp] = ((wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS)) >> 16) & 0x1) != 0; + } else { + if ((status & SFPP_STATUS_RXLOS_CHG) || + (status & SFPP_STATUS_TXFAULT_CHG) || + (status & SFPP_STATUS_MODABS_CHG)) + { + update_eth_state(sfp, type); + } + } + if (old_link_up != links_up[sfp]) { + UHD_FW_TRACE_FSTR(INFO, "The link on SFP port %u is %s", sfp, links_up[sfp]?"up":"down"); + } } -void ethernet_init(const uint32_t eth) +void ethernet_init(const uint32_t sfp) { #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(DEBUG, "eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d", - eth, + uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS )); + UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d", + sfp, (x & SFPP_STATUS_RXLOS), ((x & SFPP_STATUS_TXFAULT) >> 1), ((x & SFPP_STATUS_MODABS) >> 2)); #endif - links_up[eth] = false; - update_eth_state(eth); + update_eth_state(sfp, wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE))); } // |