diff options
Diffstat (limited to 'firmware/usrp3')
| -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 | 
5 files changed, 109 insertions, 92 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));          } | 
