mirror of
https://github.com/torvalds/linux.git
synced 2024-12-12 06:02:38 +00:00
net: phy: adin: add support for clock output
The ADIN1300 supports generating certain clocks on its GP_CLK pin, as well as providing the reference clock on CLK25_REF. Add support for selecting the clock via device-tree properties. Technically the phy also supports a recovered 125MHz clock for synchronous ethernet. SyncE should be configured dynamically at runtime, however Linux does not currently have a toggle for this, so support is explicitly omitted. Co-developed-by: Alvaro Karsz <alvaro.karsz@solid-run.com> Signed-off-by: Alvaro Karsz <alvaro.karsz@solid-run.com> Signed-off-by: Josua Mayer<josua@solid-run.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
1f77204e11
commit
ce3342161e
@ -99,6 +99,15 @@
|
|||||||
#define ADIN1300_GE_SOFT_RESET_REG 0xff0c
|
#define ADIN1300_GE_SOFT_RESET_REG 0xff0c
|
||||||
#define ADIN1300_GE_SOFT_RESET BIT(0)
|
#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_CFG_REG 0xff23
|
||||||
#define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
|
#define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
|
||||||
#define ADIN1300_GE_RGMII_RX_SEL(x) \
|
#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)
|
static int adin_config_init(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -455,6 +491,10 @@ static int adin_config_init(struct phy_device *phydev)
|
|||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
rc = adin_config_clk_out(phydev);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
phydev_dbg(phydev, "PHY is using mode '%s'\n",
|
phydev_dbg(phydev, "PHY is using mode '%s'\n",
|
||||||
phy_modes(phydev->interface));
|
phy_modes(phydev->interface));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user