Add PHY tunable callbacks to allow configuring BroadRReach Master/Slave mode. Signed-off-by: Marek Vasut <marex@xxxxxxx> Cc: Andrew Lunn <andrew@xxxxxxx> Cc: Florian Fainelli <f.fainelli@xxxxxxxxx> Cc: Guenter Roeck <linux@xxxxxxxxxxxx> Cc: Heiner Kallweit <hkallweit1@xxxxxxxxx> Cc: Jean Delvare <jdelvare@xxxxxxxx> Cc: linux-hwmon@xxxxxxxxxxxxxxx --- drivers/net/phy/nxp-tja11xx.c | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c index f1aeef449c33..78f6594a6acc 100644 --- a/drivers/net/phy/nxp-tja11xx.c +++ b/drivers/net/phy/nxp-tja11xx.c @@ -26,6 +26,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) @@ -115,6 +116,11 @@ static int tja11xx_enable_link_control(struct phy_device *phydev) return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL); } +static int tja11xx_disable_link_control(struct phy_device *phydev) +{ + return phy_clear_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL); +} + static int tja11xx_wakeup(struct phy_device *phydev) { int ret; @@ -299,6 +305,52 @@ static void tja11xx_get_stats(struct phy_device *phydev, } } +static int tja11xx_get_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, void *data) +{ + u8 *mode = (u8 *)data; + int ret; + + switch (tuna->id) { + case ETHTOOL_PHY_BRR_MODE: + ret = phy_read(phydev, MII_CFG1); + if (ret < 0) + return ret; + *mode = !!(ret & MII_CFG1_MASTER_SLAVE); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int tja11xx_set_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, const void *data) +{ + u8 mode = *(u8 *)data; + int ret; + + switch (tuna->id) { + case ETHTOOL_PHY_BRR_MODE: + ret = tja11xx_disable_link_control(phydev); + if (ret) + return ret; + + ret = phy_modify(phydev, MII_CFG1, MII_CFG1_MASTER_SLAVE, + mode ? MII_CFG1_MASTER_SLAVE : 0); + if (ret) + return ret; + + ret = tja11xx_enable_link_control(phydev); + if (ret) + return ret; + + /* TJA1100 needs this to bring the link back up. */ + return genphy_soft_reset(phydev); + default: + return -EOPNOTSUPP; + } +} + static int tja11xx_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *value) @@ -425,6 +477,9 @@ static struct phy_driver tja11xx_driver[] = { .get_sset_count = tja11xx_get_sset_count, .get_strings = tja11xx_get_strings, .get_stats = tja11xx_get_stats, + /* Tunables */ + .get_tunable = tja11xx_get_tunable, + .set_tunable = tja11xx_set_tunable, }, { PHY_ID_MATCH_MODEL(PHY_ID_TJA1101), .name = "NXP TJA1101", @@ -444,6 +499,9 @@ static struct phy_driver tja11xx_driver[] = { .get_sset_count = tja11xx_get_sset_count, .get_strings = tja11xx_get_strings, .get_stats = tja11xx_get_stats, + /* Tunables */ + .get_tunable = tja11xx_get_tunable, + .set_tunable = tja11xx_set_tunable, } }; -- 2.25.1