Skip to content

Commit 06d5f34

Browse files
Russell Kingdavem330
authored andcommitted
net: phy: at803x: use operating parameters from PHY-specific status
Read the PHY-specific status register for the current operating mode (speed and duplex) of the PHY. This register reflects the actual mode that the PHY has resolved depending on either the advertisements of autoneg is enabled, or the forced mode if autoneg is disabled. This ensures that phylib's software state always tracks the hardware state. It seems both AR8033 (which uses the AR8031 ID) and AR8035 support this status register. AR8030 is not known at the present time. This patch depends on "net: phy: extract pause mode" and "net: phy: extract link partner advertisement reading". Reported-by: tinywrkb <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Tested-by: tinywrkb <[email protected]> Fixes: 5502b21 ("net: phy: use phy_resolve_aneg_linkmode in genphy_read_status") Signed-off-by: Russell King <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2d880b8 commit 06d5f34

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

drivers/net/phy/at803x.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@
1515
#include <linux/of_gpio.h>
1616
#include <linux/gpio/consumer.h>
1717

18+
#define AT803X_SPECIFIC_STATUS 0x11
19+
#define AT803X_SS_SPEED_MASK (3 << 14)
20+
#define AT803X_SS_SPEED_1000 (2 << 14)
21+
#define AT803X_SS_SPEED_100 (1 << 14)
22+
#define AT803X_SS_SPEED_10 (0 << 14)
23+
#define AT803X_SS_DUPLEX BIT(13)
24+
#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
25+
#define AT803X_SS_MDIX BIT(6)
26+
1827
#define AT803X_INTR_ENABLE 0x12
1928
#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
2029
#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
@@ -357,6 +366,64 @@ static int at803x_aneg_done(struct phy_device *phydev)
357366
return aneg_done;
358367
}
359368

369+
static int at803x_read_status(struct phy_device *phydev)
370+
{
371+
int ss, err, old_link = phydev->link;
372+
373+
/* Update the link, but return if there was an error */
374+
err = genphy_update_link(phydev);
375+
if (err)
376+
return err;
377+
378+
/* why bother the PHY if nothing can have changed */
379+
if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
380+
return 0;
381+
382+
phydev->speed = SPEED_UNKNOWN;
383+
phydev->duplex = DUPLEX_UNKNOWN;
384+
phydev->pause = 0;
385+
phydev->asym_pause = 0;
386+
387+
err = genphy_read_lpa(phydev);
388+
if (err < 0)
389+
return err;
390+
391+
/* Read the AT8035 PHY-Specific Status register, which indicates the
392+
* speed and duplex that the PHY is actually using, irrespective of
393+
* whether we are in autoneg mode or not.
394+
*/
395+
ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
396+
if (ss < 0)
397+
return ss;
398+
399+
if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
400+
switch (ss & AT803X_SS_SPEED_MASK) {
401+
case AT803X_SS_SPEED_10:
402+
phydev->speed = SPEED_10;
403+
break;
404+
case AT803X_SS_SPEED_100:
405+
phydev->speed = SPEED_100;
406+
break;
407+
case AT803X_SS_SPEED_1000:
408+
phydev->speed = SPEED_1000;
409+
break;
410+
}
411+
if (ss & AT803X_SS_DUPLEX)
412+
phydev->duplex = DUPLEX_FULL;
413+
else
414+
phydev->duplex = DUPLEX_HALF;
415+
if (ss & AT803X_SS_MDIX)
416+
phydev->mdix = ETH_TP_MDI_X;
417+
else
418+
phydev->mdix = ETH_TP_MDI;
419+
}
420+
421+
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
422+
phy_resolve_aneg_pause(phydev);
423+
424+
return 0;
425+
}
426+
360427
static struct phy_driver at803x_driver[] = {
361428
{
362429
/* ATHEROS 8035 */
@@ -370,6 +437,7 @@ static struct phy_driver at803x_driver[] = {
370437
.suspend = at803x_suspend,
371438
.resume = at803x_resume,
372439
/* PHY_GBIT_FEATURES */
440+
.read_status = at803x_read_status,
373441
.ack_interrupt = at803x_ack_interrupt,
374442
.config_intr = at803x_config_intr,
375443
}, {
@@ -399,6 +467,7 @@ static struct phy_driver at803x_driver[] = {
399467
.suspend = at803x_suspend,
400468
.resume = at803x_resume,
401469
/* PHY_GBIT_FEATURES */
470+
.read_status = at803x_read_status,
402471
.aneg_done = at803x_aneg_done,
403472
.ack_interrupt = &at803x_ack_interrupt,
404473
.config_intr = &at803x_config_intr,

0 commit comments

Comments
 (0)