mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-25 07:14:36 +08:00
net: phy: add qca8081 read_status
1. Separate the function at803x_read_specific_status from the at803x_read_status, since it can be reused by the read_status of qca8081 phy driver excepting adding the 2500M speed. 2. Add the qca8081 read_status function qca808x_read_status. Signed-off-by: Luo Jie <luoj@codeaurora.org> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
daf61732a4
commit
79c7bc0521
@ -41,6 +41,9 @@
|
|||||||
#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
|
#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
|
||||||
#define AT803X_SS_MDIX BIT(6)
|
#define AT803X_SS_MDIX BIT(6)
|
||||||
|
|
||||||
|
#define QCA808X_SS_SPEED_MASK GENMASK(9, 7)
|
||||||
|
#define QCA808X_SS_SPEED_2500 4
|
||||||
|
|
||||||
#define AT803X_INTR_ENABLE 0x12
|
#define AT803X_INTR_ENABLE 0x12
|
||||||
#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
|
#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
|
||||||
#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
|
#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
|
||||||
@ -959,27 +962,9 @@ static void at803x_link_change_notify(struct phy_device *phydev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int at803x_read_status(struct phy_device *phydev)
|
static int at803x_read_specific_status(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int ss, err, old_link = phydev->link;
|
int ss;
|
||||||
|
|
||||||
/* Update the link, but return if there was an error */
|
|
||||||
err = genphy_update_link(phydev);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* why bother the PHY if nothing can have changed */
|
|
||||||
if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
phydev->speed = SPEED_UNKNOWN;
|
|
||||||
phydev->duplex = DUPLEX_UNKNOWN;
|
|
||||||
phydev->pause = 0;
|
|
||||||
phydev->asym_pause = 0;
|
|
||||||
|
|
||||||
err = genphy_read_lpa(phydev);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* Read the AT8035 PHY-Specific Status register, which indicates the
|
/* Read the AT8035 PHY-Specific Status register, which indicates the
|
||||||
* speed and duplex that the PHY is actually using, irrespective of
|
* speed and duplex that the PHY is actually using, irrespective of
|
||||||
@ -990,13 +975,19 @@ static int at803x_read_status(struct phy_device *phydev)
|
|||||||
return ss;
|
return ss;
|
||||||
|
|
||||||
if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
|
if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
|
||||||
int sfc;
|
int sfc, speed;
|
||||||
|
|
||||||
sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
|
sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
|
||||||
if (sfc < 0)
|
if (sfc < 0)
|
||||||
return sfc;
|
return sfc;
|
||||||
|
|
||||||
switch (FIELD_GET(AT803X_SS_SPEED_MASK, ss)) {
|
/* qca8081 takes the different bits for speed value from at803x */
|
||||||
|
if (phydev->drv->phy_id == QCA8081_PHY_ID)
|
||||||
|
speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss);
|
||||||
|
else
|
||||||
|
speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss);
|
||||||
|
|
||||||
|
switch (speed) {
|
||||||
case AT803X_SS_SPEED_10:
|
case AT803X_SS_SPEED_10:
|
||||||
phydev->speed = SPEED_10;
|
phydev->speed = SPEED_10;
|
||||||
break;
|
break;
|
||||||
@ -1006,6 +997,9 @@ static int at803x_read_status(struct phy_device *phydev)
|
|||||||
case AT803X_SS_SPEED_1000:
|
case AT803X_SS_SPEED_1000:
|
||||||
phydev->speed = SPEED_1000;
|
phydev->speed = SPEED_1000;
|
||||||
break;
|
break;
|
||||||
|
case QCA808X_SS_SPEED_2500:
|
||||||
|
phydev->speed = SPEED_2500;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (ss & AT803X_SS_DUPLEX)
|
if (ss & AT803X_SS_DUPLEX)
|
||||||
phydev->duplex = DUPLEX_FULL;
|
phydev->duplex = DUPLEX_FULL;
|
||||||
@ -1030,6 +1024,35 @@ static int at803x_read_status(struct phy_device *phydev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at803x_read_status(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int err, old_link = phydev->link;
|
||||||
|
|
||||||
|
/* Update the link, but return if there was an error */
|
||||||
|
err = genphy_update_link(phydev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* why bother the PHY if nothing can have changed */
|
||||||
|
if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
phydev->speed = SPEED_UNKNOWN;
|
||||||
|
phydev->duplex = DUPLEX_UNKNOWN;
|
||||||
|
phydev->pause = 0;
|
||||||
|
phydev->asym_pause = 0;
|
||||||
|
|
||||||
|
err = genphy_read_lpa(phydev);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = at803x_read_specific_status(phydev);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
|
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
|
||||||
phy_resolve_aneg_pause(phydev);
|
phy_resolve_aneg_pause(phydev);
|
||||||
|
|
||||||
@ -1434,6 +1457,33 @@ static int qca83xx_suspend(struct phy_device *phydev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qca808x_read_status(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising,
|
||||||
|
ret & MDIO_AN_10GBT_STAT_LP2_5G);
|
||||||
|
|
||||||
|
ret = genphy_read_status(phydev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = at803x_read_specific_status(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (phydev->link && phydev->speed == SPEED_2500)
|
||||||
|
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
||||||
|
else
|
||||||
|
phydev->interface = PHY_INTERFACE_MODE_SMII;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct phy_driver at803x_driver[] = {
|
static struct phy_driver at803x_driver[] = {
|
||||||
{
|
{
|
||||||
/* Qualcomm Atheros AR8035 */
|
/* Qualcomm Atheros AR8035 */
|
||||||
@ -1605,6 +1655,7 @@ static struct phy_driver at803x_driver[] = {
|
|||||||
.get_wol = at803x_get_wol,
|
.get_wol = at803x_get_wol,
|
||||||
.suspend = genphy_suspend,
|
.suspend = genphy_suspend,
|
||||||
.resume = genphy_resume,
|
.resume = genphy_resume,
|
||||||
|
.read_status = qca808x_read_status,
|
||||||
}, };
|
}, };
|
||||||
|
|
||||||
module_phy_driver(at803x_driver);
|
module_phy_driver(at803x_driver);
|
||||||
|
Loading…
Reference in New Issue
Block a user