diff options
author | Oleksij Rempel <o.rempel@pengutronix.de> | 2020-05-05 09:35:06 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-07 03:45:45 +0300 |
commit | b883e47bde4b3eaf18e8d0d73709b33942b4a589 (patch) | |
tree | fc04060f03d67fca8157b07d648bd7113e6d914b /drivers/net | |
parent | bdbdac7649fac05f88c9f7ab18121a17fb591687 (diff) | |
download | linux-b883e47bde4b3eaf18e8d0d73709b33942b4a589.tar.xz |
net: phy: tja11xx: add support for master-slave configuration
The TJA11xx PHYs have a vendor specific Master/Slave configuration bit,
which is not compatible with IEEE 803.2-2018 spec for 100Base-T1
devices. So, provide a custom config_ange call back to solve this
problem.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/phy/nxp-tja11xx.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c index cc766b2d4136..ca5f9d4dc57e 100644 --- a/drivers/net/phy/nxp-tja11xx.c +++ b/drivers/net/phy/nxp-tja11xx.c @@ -30,6 +30,7 @@ #define MII_ECTRL_WAKE_REQUEST BIT(0) #define MII_CFG1 18 +#define MII_CFG1_MASTER_SLAVE BIT(15) #define MII_CFG1_AUTO_OP BIT(14) #define MII_CFG1_SLEEP_CONFIRM BIT(6) #define MII_CFG1_LED_MODE_MASK GENMASK(5, 4) @@ -167,6 +168,32 @@ static int tja11xx_soft_reset(struct phy_device *phydev) return genphy_soft_reset(phydev); } +static int tja11xx_config_aneg(struct phy_device *phydev) +{ + u16 ctl = 0; + int ret; + + switch (phydev->master_slave_set) { + case MASTER_SLAVE_CFG_MASTER_FORCE: + ctl |= MII_CFG1_MASTER_SLAVE; + break; + case MASTER_SLAVE_CFG_SLAVE_FORCE: + break; + case MASTER_SLAVE_CFG_UNKNOWN: + case MASTER_SLAVE_CFG_UNSUPPORTED: + return 0; + default: + phydev_warn(phydev, "Unsupported Master/Slave mode\n"); + return -ENOTSUPP; + } + + ret = phy_modify_changed(phydev, MII_CFG1, MII_CFG1_MASTER_SLAVE, ctl); + if (ret < 0) + return ret; + + return __genphy_config_aneg(phydev, ret); +} + static int tja11xx_config_init(struct phy_device *phydev) { int ret; @@ -224,10 +251,22 @@ static int tja11xx_read_status(struct phy_device *phydev) { int ret; + phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; + phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; + ret = genphy_update_link(phydev); if (ret) return ret; + ret = phy_read(phydev, MII_CFG1); + if (ret < 0) + return ret; + + if (ret & MII_CFG1_MASTER_SLAVE) + phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; + else + phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; + if (phydev->link) { ret = phy_read(phydev, MII_COMMSTAT); if (ret < 0) @@ -504,6 +543,7 @@ static struct phy_driver tja11xx_driver[] = { .features = PHY_BASIC_T1_FEATURES, .probe = tja11xx_probe, .soft_reset = tja11xx_soft_reset, + .config_aneg = tja11xx_config_aneg, .config_init = tja11xx_config_init, .read_status = tja11xx_read_status, .suspend = genphy_suspend, @@ -519,6 +559,7 @@ static struct phy_driver tja11xx_driver[] = { .features = PHY_BASIC_T1_FEATURES, .probe = tja11xx_probe, .soft_reset = tja11xx_soft_reset, + .config_aneg = tja11xx_config_aneg, .config_init = tja11xx_config_init, .read_status = tja11xx_read_status, .suspend = genphy_suspend, @@ -533,6 +574,7 @@ static struct phy_driver tja11xx_driver[] = { .features = PHY_BASIC_T1_FEATURES, .probe = tja1102_p0_probe, .soft_reset = tja11xx_soft_reset, + .config_aneg = tja11xx_config_aneg, .config_init = tja11xx_config_init, .read_status = tja11xx_read_status, .match_phy_device = tja1102_p0_match_phy_device, @@ -551,6 +593,7 @@ static struct phy_driver tja11xx_driver[] = { .features = PHY_BASIC_T1_FEATURES, /* currently no probe for Port 1 is need */ .soft_reset = tja11xx_soft_reset, + .config_aneg = tja11xx_config_aneg, .config_init = tja11xx_config_init, .read_status = tja11xx_read_status, .match_phy_device = tja1102_p1_match_phy_device, |