ADIN1300 supports software control over pin polarity for both LED_0 and LINK_ST pins. Configure the polarity during probe based on device-tree properties. Led polarity is only set if specified in device-tree, otherwise the phy can choose either active-low or active-high based on external line voltage. Link-status polarity is set to active-high as default if not specified, which is always the reset-default. Signed-off-by: Josua Mayer <josua@xxxxxxxxxxxxx> --- drivers/net/phy/adin.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c index 2e1a46e121d9..53159dea6381 100644 --- a/drivers/net/phy/adin.c +++ b/drivers/net/phy/adin.c @@ -114,6 +114,9 @@ #define ADIN1300_CDIAG_FLT_DIST(x) (0xba21 + (x)) +#define ADIN1300_LED_A_INV_EN_REG 0xbc01 +#define ADIN1300_LED_A_INV_EN BIT(0) + #define ADIN1300_GE_SOFT_RESET_REG 0xff0c #define ADIN1300_GE_SOFT_RESET BIT(0) @@ -158,6 +161,9 @@ #define ADIN1300_RMII_20_BITS 0x0004 #define ADIN1300_RMII_24_BITS 0x0005 +#define ADIN1300_GE_LNK_STAT_INV_EN_REG 0xff3c +#define ADIN1300_GE_LNK_STAT_INV_EN BIT(0) + /** * struct adin_cfg_reg_map - map a config value to aregister value * @cfg: value in device configuration @@ -522,6 +528,49 @@ static int adin_config_clk_out(struct phy_device *phydev) ADIN1300_GE_CLK_CFG_MASK, sel); } +static int adin_config_pin_polarity(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + int ret; + u32 val; + + /* set led polarity, if property present */ + if (device_property_present(dev, "adi,led-polarity")) { + ret = device_property_read_u32(dev, "adi,led-polarity", &val); + if (ret) { + return ret; + } else if (val > 1) { + phydev_err(phydev, "invalid adi,led-polarity\n"); + return -EINVAL; + } + + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, + ADIN1300_LED_A_INV_EN_REG, + ADIN1300_LED_A_INV_EN, val); + if (ret) + return ret; + } + + /* set link-status polarity, default to active-high (0) */ + if (device_property_present(dev, "adi,link-st-polarity")) { + ret = device_property_read_u32(dev, "adi,link-st-polarity", &val); + if (ret) { + return ret; + } else if (val > 1) { + phydev_err(phydev, "invalid adi,link-st-polarity\n"); + return -EINVAL; + } + } else { + val = 0; + } + + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, + ADIN1300_GE_LNK_STAT_INV_EN_REG, + ADIN1300_GE_LNK_STAT_INV_EN, val); + + return ret; +} + static int adin_config_init(struct phy_device *phydev) { int rc; @@ -548,6 +597,10 @@ static int adin_config_init(struct phy_device *phydev) if (rc < 0) return rc; + rc = adin_config_pin_polarity(phydev); + if (rc < 0) + return rc; + phydev_dbg(phydev, "PHY is using mode '%s'\n", phy_modes(phydev->interface)); -- 2.35.3