net/ngbe: fix external PHY power down
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy_rtl.c
index 8383092..3a2d624 100644 (file)
@@ -4,8 +4,6 @@
 
 #include "ngbe_phy_rtl.h"
 
-#define RTL_PHY_RST_WAIT_PERIOD               5
-
 s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw,
                u32 reg_addr, u32 device_type, u16 *phy_data)
 {
@@ -38,6 +36,30 @@ s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
        return 0;
 }
 
+static void ngbe_phy_led_ctrl_rtl(struct ngbe_hw *hw)
+{
+       u16 value = 0;
+
+       if (hw->led_conf != 0xFFFF)
+               value = hw->led_conf & 0xFFFF;
+       else
+               value = 0x205B;
+
+       hw->phy.write_reg(hw, RTL_LCR, 0xd04, value);
+       hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
+
+       hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &value);
+       if (hw->led_conf != 0xFFFF) {
+               value &= ~0x73;
+               value |= hw->led_conf >> 16;
+       } else {
+               value &= 0xFFFC;
+               /*act led blinking mode set to 60ms*/
+               value |= 0x2;
+       }
+       hw->phy.write_reg(hw, RTL_LPCR, 0xd04, value);
+}
+
 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
 {
        int i;
@@ -57,38 +79,48 @@ s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
                msec_delay(10);
        }
        if (i == 15) {
-               DEBUGOUT("GPhy reset exceeds maximum times.\n");
+               DEBUGOUT("GPhy reset exceeds maximum times.");
                return NGBE_ERR_PHY_TIMEOUT;
        }
 
-       for (i = 0; i < 1000; i++) {
-               hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
-               if (value & RTL_INSR_ACCESS)
-                       break;
+       hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
+       hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
+       if (!(value & RTL_SCR_EFUSE)) {
+               DEBUGOUT("Write EFUSE failed.");
+               return NGBE_ERR_PHY_TIMEOUT;
        }
 
-       hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
        for (i = 0; i < 1000; i++) {
                hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
                if (value & RTL_INSR_ACCESS)
                        break;
+               msec_delay(1);
        }
        if (i == 1000)
-               return NGBE_ERR_PHY_TIMEOUT;
+               DEBUGOUT("PHY wait mdio 1 access timeout.");
+
 
        hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
+       hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
+       if (!(value & RTL_SCR_EXTINI)) {
+               DEBUGOUT("Write EXIINI failed.");
+               return NGBE_ERR_PHY_TIMEOUT;
+       }
+
        for (i = 0; i < 1000; i++) {
                hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
                if (value & RTL_INSR_ACCESS)
                        break;
+               msec_delay(1);
        }
        if (i == 1000)
-               return NGBE_ERR_PHY_TIMEOUT;
+               DEBUGOUT("PHY wait mdio 2 access timeout.");
 
        for (i = 0; i < 1000; i++) {
                hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value);
                if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON)
                        break;
+               msec_delay(1);
        }
        if (i == 1000)
                return NGBE_ERR_PHY_TIMEOUT;
@@ -108,8 +140,6 @@ s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
        u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
        u16 value = 0;
 
-       DEBUGFUNC("ngbe_setup_phy_link_rtl");
-
        UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
 
        hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
@@ -129,7 +159,7 @@ s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
                        break;
                default:
                        value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
-                       DEBUGOUT("unknown speed = 0x%x.\n", speed);
+                       DEBUGOUT("unknown speed = 0x%x.", speed);
                        break;
                }
                /* duplex full */
@@ -211,40 +241,62 @@ s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
        hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
 
 skip_an:
-       autoneg_reg = 0x205B;
-       hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg);
-       hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
-
-       hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg);
-       autoneg_reg = autoneg_reg & 0xFFFC;
-       /* act led blinking mode set to 60ms */
-       autoneg_reg |= 0x2;
-       hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg);
+       ngbe_phy_led_ctrl_rtl(hw);
 
        return 0;
 }
 
 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
 {
-       u16 value = 0, i;
+       u16 value = 0;
        s32 status = 0;
 
-       DEBUGFUNC("ngbe_reset_phy_rtl");
-
        value |= RTL_BMCR_RESET;
        status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
 
-       for (i = 0; i < RTL_PHY_RST_WAIT_PERIOD; i++) {
-               status = hw->phy.read_reg(hw, RTL_BMCR, RTL_DEV_ZERO, &value);
-               if (!(value & RTL_BMCR_RESET))
-                       break;
-               msleep(1);
-       }
+       msec_delay(5);
 
-       if (i == RTL_PHY_RST_WAIT_PERIOD) {
-               DEBUGOUT("PHY reset polling failed to complete.\n");
-               return NGBE_ERR_RESET_FAILED;
-       }
+       return status;
+}
+
+s32 ngbe_get_phy_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
+{
+       u16 value;
+       s32 status = 0;
+
+       status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
+       value &= RTL_ANAR_APAUSE | RTL_ANAR_PAUSE;
+       *pause_bit = (u8)(value >> 10);
+       return status;
+}
+
+s32 ngbe_get_phy_lp_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
+{
+       u16 value;
+       s32 status = 0;
+
+       status = hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
+
+       status = hw->phy.read_reg(hw, RTL_BMSR, RTL_DEV_ZERO, &value);
+       value = value & RTL_BMSR_ANC;
+
+       /* if AN complete then check lp adv pause */
+       status = hw->phy.read_reg(hw, RTL_ANLPAR, RTL_DEV_ZERO, &value);
+       value &= RTL_ANLPAR_LP;
+       *pause_bit = (u8)(value >> 10);
+       return status;
+}
+
+s32 ngbe_set_phy_pause_adv_rtl(struct ngbe_hw *hw, u16 pause_bit)
+{
+       u16 value;
+       s32 status = 0;
+
+       status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
+       value &= ~(RTL_ANAR_APAUSE | RTL_ANAR_PAUSE);
+       value |= pause_bit;
+
+       status = hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, value);
 
        return status;
 }
@@ -257,8 +309,6 @@ s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
        u16 phy_data = 0;
        u16 insr = 0;
 
-       DEBUGFUNC("ngbe_check_phy_link_rtl");
-
        hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
 
        /* Initialize speed and link to default case */