reg.addr = reg_addr;
ngbe_mdi_map_register(®, ®22);
- wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
+ if (!(reg22.page == 0xa43 &&
+ (reg22.addr == 0x1a || reg22.addr == 0x1d)))
+ wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
*phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr));
return 0;
reg.addr = reg_addr;
ngbe_mdi_map_register(®, ®22);
- wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
+ if (!(reg22.page == 0xa43 &&
+ (reg22.addr == 0x1a || reg22.addr == 0x1d)))
+ wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data);
return 0;
hw->phy.write_reg(hw, RTL_LPCR, 0xd04, value);
}
+static s32 ngbe_wait_mdio_access_on(struct ngbe_hw *hw)
+{
+ int i;
+ u16 val = 0;
+
+ for (i = 0; i < 100; i++) {
+ /* irq status */
+ hw->phy.read_reg(hw, RTL_INSR, 0xa43, &val);
+ if (val & RTL_INSR_ACCESS)
+ break;
+ msec_delay(1);
+ }
+
+ if (i == 100) {
+ DEBUGOUT("wait_mdio_access_on timeout");
+ return NGBE_ERR_PHY_TIMEOUT;
+ }
+
+ return 0;
+}
+
+static void ngbe_efuse_calibration(struct ngbe_hw *hw)
+{
+ u32 efuse[2];
+
+ ngbe_wait_mdio_access_on(hw);
+
+ efuse[0] = hw->gphy_efuse[0];
+ efuse[1] = hw->gphy_efuse[1];
+
+ if (!efuse[0] && !efuse[1]) {
+ efuse[0] = 0xFFFFFFFF;
+ efuse[1] = 0xFFFFFFFF;
+ }
+
+ /* calibration */
+ efuse[0] |= 0xF0000100;
+ efuse[1] |= 0xFF807FFF;
+ DEBUGOUT("port %d efuse[0] = %08x, efuse[1] = %08x",
+ hw->bus.lan_id, efuse[0], efuse[1]);
+
+ /* EODR, Efuse Output Data Register */
+ hw->phy.write_reg(hw, 16, 0xa46, (efuse[0] >> 0) & 0xFFFF);
+ hw->phy.write_reg(hw, 17, 0xa46, (efuse[0] >> 16) & 0xFFFF);
+ hw->phy.write_reg(hw, 18, 0xa46, (efuse[1] >> 0) & 0xFFFF);
+ hw->phy.write_reg(hw, 19, 0xa46, (efuse[1] >> 16) & 0xFFFF);
+}
+
s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
{
int i;
u16 value = 0;
- /* enable interrupts, only link status change and an done is allowed */
- value = RTL_INER_LSC | RTL_INER_ANC;
- hw->phy.write_reg(hw, RTL_INER, 0xa42, value);
-
- hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
+ hw->init_phy = true;
+ msec_delay(1);
for (i = 0; i < 15; i++) {
if (!rd32m(hw, NGBE_STAT,
return NGBE_ERR_PHY_TIMEOUT;
}
+ ngbe_efuse_calibration(hw);
+
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)) {
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)
- DEBUGOUT("PHY wait mdio 1 access timeout.");
+ ngbe_wait_mdio_access_on(hw);
+ hw->phy.write_reg(hw, 27, 0xa42, 0x8011);
+ hw->phy.write_reg(hw, 28, 0xa42, 0x5737);
hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
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)
- DEBUGOUT("PHY wait mdio 2 access timeout.");
+ ngbe_wait_mdio_access_on(hw);
- for (i = 0; i < 1000; i++) {
+ for (i = 0; i < 100; 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)
+ if (i == 100)
return NGBE_ERR_PHY_TIMEOUT;
+ /* Disable EEE */
+ hw->phy.write_reg(hw, 0x11, 0xa4b, 0x1110);
+ hw->phy.write_reg(hw, 0xd, 0x0, 0x0007);
+ hw->phy.write_reg(hw, 0xe, 0x0, 0x003c);
+ hw->phy.write_reg(hw, 0xd, 0x0, 0x4007);
+ hw->phy.write_reg(hw, 0xe, 0x0, 0x0000);
+
+ hw->init_phy = false;
+
return 0;
}
UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+ hw->init_phy = true;
+ msec_delay(1);
+
hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
if (!hw->mac.autoneg) {
skip_an:
ngbe_phy_led_ctrl_rtl(hw);
+ hw->init_phy = false;
+
return 0;
}
u16 phy_data = 0;
u16 insr = 0;
+ if (hw->init_phy)
+ return -1;
+
hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
/* Initialize speed and link to default case */