net: phy: aquantia: check for changed interface mode in read_status

Depending on the auto-negotiated speed the PHY may change the interface
mode. Check for new mode and set phydev->interface accordingly.

Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
[hkallweit1@gmail.com: picked from bigger patch and reworked]
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Nikita Yushchenko 2019-03-19 23:05:50 +01:00 committed by David S. Miller
parent 570c8a7d53
commit 1e614b5086

View File

@ -10,6 +10,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/bitfield.h>
#include <linux/phy.h> #include <linux/phy.h>
#include "aquantia.h" #include "aquantia.h"
@ -22,6 +23,13 @@
#define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQCS109 0x03a1b5c2
#define PHY_ID_AQR405 0x03a1b4b0 #define PHY_ID_AQR405 0x03a1b4b0
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
#define MDIO_AN_VEND_PROV 0xc400 #define MDIO_AN_VEND_PROV 0xc400
#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) #define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15)
#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) #define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14)
@ -178,6 +186,40 @@ static int aqr_read_status(struct phy_device *phydev)
return genphy_c45_read_status(phydev); return genphy_c45_read_status(phydev);
} }
static int aqr107_read_status(struct phy_device *phydev)
{
int val, ret;
ret = aqr_read_status(phydev);
if (ret)
return ret;
if (!phydev->link)
return 0;
val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS);
if (val < 0)
return val;
switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) {
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR:
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI:
phydev->interface = PHY_INTERFACE_MODE_10GKR;
break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII:
phydev->interface = PHY_INTERFACE_MODE_SGMII;
break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
break;
default:
phydev->interface = PHY_INTERFACE_MODE_NA;
break;
}
return 0;
}
static int aqr107_config_init(struct phy_device *phydev) static int aqr107_config_init(struct phy_device *phydev)
{ {
/* Check that the PHY interface type is compatible */ /* Check that the PHY interface type is compatible */
@ -254,7 +296,7 @@ static struct phy_driver aqr_driver[] = {
.config_aneg = aqr_config_aneg, .config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr, .config_intr = aqr_config_intr,
.ack_interrupt = aqr_ack_interrupt, .ack_interrupt = aqr_ack_interrupt,
.read_status = aqr_read_status, .read_status = aqr107_read_status,
}, },
{ {
PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), PHY_ID_MATCH_MODEL(PHY_ID_AQCS109),
@ -266,7 +308,7 @@ static struct phy_driver aqr_driver[] = {
.config_aneg = aqr_config_aneg, .config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr, .config_intr = aqr_config_intr,
.ack_interrupt = aqr_ack_interrupt, .ack_interrupt = aqr_ack_interrupt,
.read_status = aqr_read_status, .read_status = aqr107_read_status,
}, },
{ {
PHY_ID_MATCH_MODEL(PHY_ID_AQR405), PHY_ID_MATCH_MODEL(PHY_ID_AQR405),