#include "ixgbe_api.h"
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
#include "if_ix_mdio_hw.h"
static s32
ixgbe_read_mdio_unlocked_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data)
{
u32 i, data, command;
command = (reg << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(phy << IXGBE_MSCA_PHY_ADDR_SHIFT) |
IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC |
IXGBE_MSCA_MDI_COMMAND;
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
if (!(command & IXGBE_MSCA_MDI_COMMAND))
break;
}
if (command & IXGBE_MSCA_MDI_COMMAND)
return IXGBE_ERR_PHY;
data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
*phy_data = (u16)data;
return IXGBE_SUCCESS;
}
static s32
ixgbe_write_mdio_unlocked_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 phy_data)
{
u32 i, command;
IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
command = (reg << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(phy << IXGBE_MSCA_PHY_ADDR_SHIFT) |
IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
IXGBE_MSCA_MDI_COMMAND;
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
if (!(command & IXGBE_MSCA_MDI_COMMAND))
break;
}
if (command & IXGBE_MSCA_MDI_COMMAND)
return IXGBE_ERR_PHY;
return IXGBE_SUCCESS;
}
static bool
ixgbe_check_mdio_is_x550em(struct ixgbe_hw *hw)
{
switch (hw->device_id) {
case IXGBE_DEV_ID_X550EM_A_KR:
case IXGBE_DEV_ID_X550EM_A_KR_L:
case IXGBE_DEV_ID_X550EM_A_SFP_N:
case IXGBE_DEV_ID_X550EM_A_SGMII:
case IXGBE_DEV_ID_X550EM_A_SGMII_L:
case IXGBE_DEV_ID_X550EM_A_10G_T:
case IXGBE_DEV_ID_X550EM_A_SFP:
case IXGBE_DEV_ID_X550EM_A_1G_T:
case IXGBE_DEV_ID_X550EM_A_1G_T_L:
return true;
default:
return false;
}
}
s32
ixgbe_read_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data)
{
u32 gssr = hw->phy.phy_semaphore_mask;
s32 ret;
if (ixgbe_check_mdio_is_x550em(hw))
gssr |= IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_TOKEN_SM;
if (hw->mac.ops.acquire_swfw_sync(hw, gssr)) {
*phy_data = -1;
return IXGBE_ERR_TIMEOUT;
}
ret = ixgbe_read_mdio_unlocked_c22(hw, phy, reg, phy_data);
if (ret != IXGBE_SUCCESS)
*phy_data = -1;
hw->mac.ops.release_swfw_sync(hw, gssr);
return ret;
}
s32
ixgbe_write_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 data)
{
u32 gssr = hw->phy.phy_semaphore_mask;
s32 ret;
if (ixgbe_check_mdio_is_x550em(hw))
gssr |= IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_TOKEN_SM;
if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
return IXGBE_ERR_TIMEOUT;
ret = ixgbe_write_mdio_unlocked_c22(hw, phy, reg, data);
hw->mac.ops.release_swfw_sync(hw, gssr);
return ret;
}