From 9a499b2bfa684abe77033c76740a597da8f09f11 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 9 Jun 2020 15:37:39 +0200 Subject: net: phy: mscc: make clock-output configurable on vsc85xx The vsc8530/8531/8540/8541 phys have a configurable clock output that can emit 25, 50 and 125 MHz rates, which in turn may be needed for stable network connections. This follows a similar change introduced into the Linux kernel at https://lore.kernel.org/netdev/20200609133140.1421109-2-heiko@sntech.de Signed-off-by: Heiko Stuebner Reviewed-by: Philipp Tomsich --- drivers/net/phy/mscc.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index 709979f48c..64e9093827 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -157,6 +157,14 @@ #define INT_MEM_DATA_M GENMASK(7, 0) #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x)) +/* Extended page GPIO register 13G */ +#define MSCC_CLKOUT_CNTL 13 +#define CLKOUT_ENABLE BIT(15) +#define CLKOUT_FREQ_MASK GENMASK(14, 13) +#define CLKOUT_FREQ_25M (0x0 << 13) +#define CLKOUT_FREQ_50M (0x1 << 13) +#define CLKOUT_FREQ_125M (0x2 << 13) + /* Extended page GPIO register 18G */ #define MSCC_PHY_PROC_CMD 18 #define PROC_CMD_NCOMPLETED BIT(15) @@ -1210,6 +1218,47 @@ static int vsc8531_vsc8541_mac_config(struct phy_device *phydev) return 0; } +static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev) +{ + struct ofnode_phandle_args phandle_args; + u32 clkout_rate = 0; + u16 reg_val; + int retval; + + retval = dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL, + 0, 0, &phandle_args); + if (!retval) + clkout_rate = ofnode_read_u32_default(phandle_args.node, + "vsc8531,clk-out-frequency", 0); + + switch (clkout_rate) { + case 0: + reg_val = 0; + break; + case 25000000: + reg_val = CLKOUT_FREQ_25M | CLKOUT_ENABLE; + break; + case 50000000: + reg_val = CLKOUT_FREQ_50M | CLKOUT_ENABLE; + break; + case 125000000: + reg_val = CLKOUT_FREQ_125M | CLKOUT_ENABLE; + break; + default: + printf("PHY 8530/31 invalid clkout rate %u\n", + clkout_rate); + return -EINVAL; + } + + phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_GPIO); + phy_write(phydev, MDIO_DEVAD_NONE, MSCC_CLKOUT_CNTL, reg_val); + phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_STD); + + return 0; +} + static int vsc8531_config(struct phy_device *phydev) { int retval = -EINVAL; @@ -1267,6 +1316,11 @@ static int vsc8531_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STD); + /* Configure the clk output */ + retval = vsc8531_vsc8541_clkout_config(phydev); + if (retval != 0) + return retval; + return genphy_config_aneg(phydev); } @@ -1327,6 +1381,11 @@ static int vsc8541_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STD); + /* Configure the clk output */ + retval = vsc8531_vsc8541_clkout_config(phydev); + if (retval != 0) + return retval; + return genphy_config_aneg(phydev); } -- cgit v1.2.3