X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fngbe%2Fbase%2Fngbe_phy_mvl.c;h=2eb351d2582315b22f5235b66cef106f9a762ca1;hb=f40e9f0e2278daf72d7f308f17e5f591d3ce8b09;hp=12484782526d05f743cd1cb16c44673046632759;hpb=44e97550ca68785ee3a5af9dbc11c2a932a6e777;p=dpdk.git diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c index 1248478252..2eb351d258 100644 --- a/drivers/net/ngbe/base/ngbe_phy_mvl.c +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c @@ -48,6 +48,128 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, return 0; } +s32 ngbe_init_phy_mvl(struct ngbe_hw *hw) +{ + s32 ret_val = 0; + u16 value = 0; + int i; + + DEBUGFUNC("ngbe_init_phy_mvl"); + + /* enable interrupts, only link status change and an done is allowed */ + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 2); + ngbe_read_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, &value); + value &= ~MVL_RGM_CTL2_TTC; + value |= MVL_RGM_CTL2_RTC; + ngbe_write_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, value); + + hw->phy.write_reg(hw, MVL_CTRL, 0, MVL_CTRL_RESET); + for (i = 0; i < 15; i++) { + ngbe_read_phy_reg_mdi(hw, MVL_CTRL, 0, &value); + if (value & MVL_CTRL_RESET) + msleep(1); + else + break; + } + + if (i == 15) { + DEBUGOUT("phy reset exceeds maximum waiting period.\n"); + return NGBE_ERR_TIMEOUT; + } + + ret_val = hw->phy.reset_hw(hw); + if (ret_val) + return ret_val; + + /* set LED2 to interrupt output and INTn active low */ + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3); + ngbe_read_phy_reg_mdi(hw, MVL_LEDTCR, 0, &value); + value |= MVL_LEDTCR_INTR_EN; + value &= ~(MVL_LEDTCR_INTR_POL); + ngbe_write_phy_reg_mdi(hw, MVL_LEDTCR, 0, value); + + if (hw->phy.type == ngbe_phy_mvl_sfi) { + hw->phy.read_reg(hw, MVL_CTRL1, 0, &value); + value &= ~MVL_CTRL1_INTR_POL; + ngbe_write_phy_reg_mdi(hw, MVL_CTRL1, 0, value); + } + + /* enable link status change and AN complete interrupts */ + value = MVL_INTR_EN_ANC | MVL_INTR_EN_LSC; + hw->phy.write_reg(hw, MVL_INTR_EN, 0, value); + + /* LED control */ + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3); + ngbe_read_phy_reg_mdi(hw, MVL_LEDFCR, 0, &value); + value &= ~(MVL_LEDFCR_CTL0 | MVL_LEDFCR_CTL1); + value |= MVL_LEDFCR_CTL0_CONF | MVL_LEDFCR_CTL1_CONF; + ngbe_write_phy_reg_mdi(hw, MVL_LEDFCR, 0, value); + ngbe_read_phy_reg_mdi(hw, MVL_LEDPCR, 0, &value); + value &= ~(MVL_LEDPCR_CTL0 | MVL_LEDPCR_CTL1); + value |= MVL_LEDPCR_CTL0_CONF | MVL_LEDPCR_CTL1_CONF; + ngbe_write_phy_reg_mdi(hw, MVL_LEDPCR, 0, value); + + return ret_val; +} + +s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete) +{ + u16 value_r4 = 0; + u16 value_r9 = 0; + u16 value; + + DEBUGFUNC("ngbe_setup_phy_link_mvl"); + UNREFERENCED_PARAMETER(autoneg_wait_to_complete); + + hw->phy.autoneg_advertised = 0; + + if (hw->phy.type == ngbe_phy_mvl) { + if (speed & NGBE_LINK_SPEED_1GB_FULL) { + value_r9 |= MVL_PHY_1000BASET_FULL; + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; + } + + if (speed & NGBE_LINK_SPEED_100M_FULL) { + value_r4 |= MVL_PHY_100BASET_FULL; + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL; + } + + if (speed & NGBE_LINK_SPEED_10M_FULL) { + value_r4 |= MVL_PHY_10BASET_FULL; + hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL; + } + + hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= ~(MVL_PHY_100BASET_FULL | + MVL_PHY_100BASET_HALF | + MVL_PHY_10BASET_FULL | + MVL_PHY_10BASET_HALF); + value_r4 |= value; + hw->phy.write_reg(hw, MVL_ANA, 0, value_r4); + + hw->phy.read_reg(hw, MVL_PHY_1000BASET, 0, &value); + value &= ~(MVL_PHY_1000BASET_FULL | + MVL_PHY_1000BASET_HALF); + value_r9 |= value; + hw->phy.write_reg(hw, MVL_PHY_1000BASET, 0, value_r9); + } else { + hw->phy.autoneg_advertised = 1; + + hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= ~(MVL_PHY_1000BASEX_HALF | MVL_PHY_1000BASEX_FULL); + value |= MVL_PHY_1000BASEX_FULL; + hw->phy.write_reg(hw, MVL_ANA, 0, value); + } + + value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE; + ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value); + + hw->phy.read_reg(hw, MVL_INTR, 0, &value); + + return 0; +} + s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) { u32 i; @@ -87,3 +209,100 @@ s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) return status; } +s32 ngbe_get_phy_advertised_pause_mvl(struct ngbe_hw *hw, u8 *pause_bit) +{ + u16 value; + s32 status = 0; + + if (hw->phy.type == ngbe_phy_mvl) { + status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= MVL_CANA_ASM_PAUSE | MVL_CANA_PAUSE; + *pause_bit = (u8)(value >> 10); + } else { + status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= MVL_FANA_PAUSE_MASK; + *pause_bit = (u8)(value >> 7); + } + + return status; +} + +s32 ngbe_get_phy_lp_advertised_pause_mvl(struct ngbe_hw *hw, u8 *pause_bit) +{ + u16 value; + s32 status = 0; + + if (hw->phy.type == ngbe_phy_mvl) { + status = hw->phy.read_reg(hw, MVL_LPAR, 0, &value); + value &= MVL_CLPAR_ASM_PAUSE | MVL_CLPAR_PAUSE; + *pause_bit = (u8)(value >> 10); + } else { + status = hw->phy.read_reg(hw, MVL_LPAR, 0, &value); + value &= MVL_FLPAR_PAUSE_MASK; + *pause_bit = (u8)(value >> 7); + } + + return status; +} + +s32 ngbe_set_phy_pause_adv_mvl(struct ngbe_hw *hw, u16 pause_bit) +{ + u16 value; + s32 status = 0; + + DEBUGFUNC("ngbe_set_phy_pause_adv_mvl"); + + if (hw->phy.type == ngbe_phy_mvl) { + status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= ~(MVL_CANA_ASM_PAUSE | MVL_CANA_PAUSE); + } else { + status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); + value &= ~MVL_FANA_PAUSE_MASK; + } + + value |= pause_bit; + status = hw->phy.write_reg(hw, MVL_ANA, 0, value); + + return status; +} + +s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw, + u32 *speed, bool *link_up) +{ + s32 status = 0; + u16 phy_link = 0; + u16 phy_speed = 0; + u16 phy_data = 0; + u16 insr = 0; + + DEBUGFUNC("ngbe_check_phy_link_mvl"); + + /* Initialize speed and link to default case */ + *link_up = false; + *speed = NGBE_LINK_SPEED_UNKNOWN; + + hw->phy.read_reg(hw, MVL_INTR, 0, &insr); + + /* + * Check current speed and link status of the PHY register. + * This is a vendor specific register and may have to + * be changed for other copper PHYs. + */ + status = hw->phy.read_reg(hw, MVL_PHYSR, 0, &phy_data); + phy_link = phy_data & MVL_PHYSR_LINK; + phy_speed = phy_data & MVL_PHYSR_SPEED_MASK; + + if (phy_link == MVL_PHYSR_LINK) { + *link_up = true; + + if (phy_speed == MVL_PHYSR_SPEED_1000M) + *speed = NGBE_LINK_SPEED_1GB_FULL; + else if (phy_speed == MVL_PHYSR_SPEED_100M) + *speed = NGBE_LINK_SPEED_100M_FULL; + else if (phy_speed == MVL_PHYSR_SPEED_10M) + *speed = NGBE_LINK_SPEED_10M_FULL; + } + + return status; +} +