net: phy: marvell10g: add MDI swap reporting
Add reporting of the MDI swap to the Marvell 10G PHY driver by providing a generic implementation for the standard 10GBASE-T pair swap register and polarity register. We also support reading the MDI swap status for 1G and below from a PCS register. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
05ca1b327e
Коммит
ea4efe25ec
|
@ -29,6 +29,11 @@ enum {
|
|||
MV_PCS_BASE_R = 0x1000,
|
||||
MV_PCS_1000BASEX = 0x2000,
|
||||
|
||||
MV_PCS_PAIRSWAP = 0x8182,
|
||||
MV_PCS_PAIRSWAP_MASK = 0x0003,
|
||||
MV_PCS_PAIRSWAP_AB = 0x0002,
|
||||
MV_PCS_PAIRSWAP_NONE = 0x0003,
|
||||
|
||||
/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
|
||||
* registers appear to set themselves to the 0x800X when AN is
|
||||
* restarted, but status registers appear readable from either.
|
||||
|
@ -180,6 +185,9 @@ static int mv3310_config_aneg(struct phy_device *phydev)
|
|||
u32 advertising;
|
||||
int ret;
|
||||
|
||||
/* We don't support manual MDI control */
|
||||
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
|
||||
|
||||
if (phydev->autoneg == AUTONEG_DISABLE) {
|
||||
ret = genphy_c45_pma_setup_forced(phydev);
|
||||
if (ret < 0)
|
||||
|
@ -269,6 +277,7 @@ static int mv3310_read_status(struct phy_device *phydev)
|
|||
phydev->link = 0;
|
||||
phydev->pause = 0;
|
||||
phydev->asym_pause = 0;
|
||||
phydev->mdix = 0;
|
||||
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
|
||||
if (val < 0)
|
||||
|
@ -323,6 +332,28 @@ static int mv3310_read_status(struct phy_device *phydev)
|
|||
return val;
|
||||
}
|
||||
|
||||
if (phydev->speed == SPEED_10000) {
|
||||
val = genphy_c45_read_mdix(phydev);
|
||||
if (val < 0)
|
||||
return val;
|
||||
} else {
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PAIRSWAP);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
switch (val & MV_PCS_PAIRSWAP_MASK) {
|
||||
case MV_PCS_PAIRSWAP_AB:
|
||||
phydev->mdix = ETH_TP_MDI_X;
|
||||
break;
|
||||
case MV_PCS_PAIRSWAP_NONE:
|
||||
phydev->mdix = ETH_TP_MDI;
|
||||
break;
|
||||
default:
|
||||
phydev->mdix = ETH_TP_MDI_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
|
||||
/* The PHY automatically switches its serdes interface (and
|
||||
|
|
|
@ -233,6 +233,39 @@ int genphy_c45_read_pma(struct phy_device *phydev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
|
||||
|
||||
/**
|
||||
* genphy_c45_read_mdix - read mdix status from PMA
|
||||
* @phydev: target phy_device struct
|
||||
*/
|
||||
int genphy_c45_read_mdix(struct phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (phydev->speed == SPEED_10000) {
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
|
||||
MDIO_PMA_10GBT_SWAPPOL);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
switch (val) {
|
||||
case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
|
||||
phydev->mdix = ETH_TP_MDI;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
phydev->mdix = ETH_TP_MDI_X;
|
||||
break;
|
||||
|
||||
default:
|
||||
phydev->mdix = ETH_TP_MDI_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
|
||||
|
||||
/* The gen10g_* functions are the old Clause 45 stub */
|
||||
|
||||
static int gen10g_config_aneg(struct phy_device *phydev)
|
||||
|
|
|
@ -901,6 +901,7 @@ int genphy_c45_read_lpa(struct phy_device *phydev);
|
|||
int genphy_c45_read_pma(struct phy_device *phydev);
|
||||
int genphy_c45_pma_setup_forced(struct phy_device *phydev);
|
||||
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
|
||||
int genphy_c45_read_mdix(struct phy_device *phydev);
|
||||
|
||||
static inline int phy_read_status(struct phy_device *phydev)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче