diff options
Diffstat (limited to 'drivers/net/phy/adin.c')
-rw-r--r-- | drivers/net/phy/adin.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c index 5ce6da62cc8e..ee374a85544a 100644 --- a/drivers/net/phy/adin.c +++ b/drivers/net/phy/adin.c @@ -99,6 +99,15 @@ #define ADIN1300_GE_SOFT_RESET_REG 0xff0c #define ADIN1300_GE_SOFT_RESET BIT(0) +#define ADIN1300_GE_CLK_CFG_REG 0xff1f +#define ADIN1300_GE_CLK_CFG_MASK GENMASK(5, 0) +#define ADIN1300_GE_CLK_CFG_RCVR_125 BIT(5) +#define ADIN1300_GE_CLK_CFG_FREE_125 BIT(4) +#define ADIN1300_GE_CLK_CFG_REF_EN BIT(3) +#define ADIN1300_GE_CLK_CFG_HRT_RCVR BIT(2) +#define ADIN1300_GE_CLK_CFG_HRT_FREE BIT(1) +#define ADIN1300_GE_CLK_CFG_25 BIT(0) + #define ADIN1300_GE_RGMII_CFG_REG 0xff23 #define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6) #define ADIN1300_GE_RGMII_RX_SEL(x) \ @@ -433,6 +442,33 @@ static int adin_set_tunable(struct phy_device *phydev, } } +static int adin_config_clk_out(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + const char *val = NULL; + u8 sel = 0; + + device_property_read_string(dev, "adi,phy-output-clock", &val); + if (!val) { + /* property not present, do not enable GP_CLK pin */ + } else if (strcmp(val, "25mhz-reference") == 0) { + sel |= ADIN1300_GE_CLK_CFG_25; + } else if (strcmp(val, "125mhz-free-running") == 0) { + sel |= ADIN1300_GE_CLK_CFG_FREE_125; + } else if (strcmp(val, "adaptive-free-running") == 0) { + sel |= ADIN1300_GE_CLK_CFG_HRT_FREE; + } else { + phydev_err(phydev, "invalid adi,phy-output-clock\n"); + return -EINVAL; + } + + if (device_property_read_bool(dev, "adi,phy-output-reference-clock")) + sel |= ADIN1300_GE_CLK_CFG_REF_EN; + + return phy_modify_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_CLK_CFG_REG, + ADIN1300_GE_CLK_CFG_MASK, sel); +} + static int adin_config_init(struct phy_device *phydev) { int rc; @@ -455,6 +491,10 @@ static int adin_config_init(struct phy_device *phydev) if (rc < 0) return rc; + rc = adin_config_clk_out(phydev); + if (rc < 0) + return rc; + phydev_dbg(phydev, "PHY is using mode '%s'\n", phy_modes(phydev->interface)); |