net/ngbe: support RSS hash
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy_yt.c
index a5b0322..2a7061c 100644 (file)
@@ -78,6 +78,130 @@ s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
        return 0;
 }
 
+s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
+               u32 reg_addr, u32 device_type, u16 *phy_data)
+{
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
+       ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
+
+       return 0;
+}
+
+s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
+               u32 reg_addr, u32 device_type, u16 phy_data)
+{
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
+       ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
+
+       return 0;
+}
+
+s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
+{
+       u16 value = 0;
+
+       DEBUGFUNC("ngbe_init_phy_yt");
+
+       if (hw->phy.type != ngbe_phy_yt8521s_sfi)
+               return 0;
+
+       /* select sds area register */
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
+       /* enable interrupts */
+       ngbe_write_phy_reg_mdi(hw, YT_INTR, 0, YT_INTR_ENA_MASK);
+
+       /* select fiber_to_rgmii first in multiplex */
+       ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value);
+       value |= YT_MISC_FIBER_PRIO;
+       ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value);
+
+       hw->phy.read_reg(hw, YT_BCR, 0, &value);
+       value |= YT_BCR_PWDN;
+       hw->phy.write_reg(hw, YT_BCR, 0, value);
+
+       return 0;
+}
+
+s32 ngbe_setup_phy_link_yt(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_yt");
+       UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+
+       hw->phy.autoneg_advertised = 0;
+
+       if (hw->phy.type == ngbe_phy_yt8521s) {
+               /*disable 100/10base-T Self-negotiation ability*/
+               hw->phy.read_reg(hw, YT_ANA, 0, &value);
+               value &= ~(YT_ANA_100BASET_FULL | YT_ANA_10BASET_FULL);
+               hw->phy.write_reg(hw, YT_ANA, 0, value);
+
+               /*disable 1000base-T Self-negotiation ability*/
+               hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
+               value &= ~YT_MS_1000BASET_FULL;
+               hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
+
+               if (speed & NGBE_LINK_SPEED_1GB_FULL) {
+                       hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+                       value_r9 |= YT_MS_1000BASET_FULL;
+               }
+               if (speed & NGBE_LINK_SPEED_100M_FULL) {
+                       hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
+                       value_r4 |= YT_ANA_100BASET_FULL;
+               }
+               if (speed & NGBE_LINK_SPEED_10M_FULL) {
+                       hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
+                       value_r4 |= YT_ANA_10BASET_FULL;
+               }
+
+               /* enable 1000base-T Self-negotiation ability */
+               hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
+               value |= value_r9;
+               hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
+
+               /* enable 100/10base-T Self-negotiation ability */
+               hw->phy.read_reg(hw, YT_ANA, 0, &value);
+               value |= value_r4;
+               hw->phy.write_reg(hw, YT_ANA, 0, value);
+
+               /* software reset to make the above configuration take effect*/
+               hw->phy.read_reg(hw, YT_BCR, 0, &value);
+               value |= YT_BCR_RESET;
+               hw->phy.write_reg(hw, YT_BCR, 0, value);
+       } else {
+               hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+
+               /* RGMII_Config1 : Config rx and tx training delay */
+               value = YT_RGMII_CONF1_RXDELAY |
+                       YT_RGMII_CONF1_TXDELAY_FE |
+                       YT_RGMII_CONF1_TXDELAY;
+               ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
+               value = YT_CHIP_MODE_SEL(1) |
+                       YT_CHIP_SW_LDO_EN |
+                       YT_CHIP_SW_RST;
+               ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
+
+               /* software reset */
+               ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
+
+               /* power on phy */
+               hw->phy.read_reg(hw, YT_BCR, 0, &value);
+               value &= ~YT_BCR_PWDN;
+               hw->phy.write_reg(hw, YT_BCR, 0, value);
+       }
+
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
+       ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
+
+       return 0;
+}
+
 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
 {
        u32 i;
@@ -110,3 +234,39 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
        return status;
 }
 
+s32 ngbe_check_phy_link_yt(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_yt");
+
+       /* Initialize speed and link to default case */
+       *link_up = false;
+       *speed = NGBE_LINK_SPEED_UNKNOWN;
+
+       ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
+       ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
+
+       status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
+       phy_link = phy_data & YT_SPST_LINK;
+       phy_speed = phy_data & YT_SPST_SPEED_MASK;
+
+       if (phy_link) {
+               *link_up = true;
+
+               if (phy_speed == YT_SPST_SPEED_1000M)
+                       *speed = NGBE_LINK_SPEED_1GB_FULL;
+               else if (phy_speed == YT_SPST_SPEED_100M)
+                       *speed = NGBE_LINK_SPEED_100M_FULL;
+               else if (phy_speed == YT_SPST_SPEED_10M)
+                       *speed = NGBE_LINK_SPEED_10M_FULL;
+       }
+
+       return status;
+}
+