net: phy: mscc: make clock-output configurable on vsc85xx
authorHeiko Stuebner <heiko.stuebner@theobroma-systems.com>
Tue, 9 Jun 2020 13:37:39 +0000 (15:37 +0200)
committerTom Rini <trini@konsulko.com>
Wed, 30 Sep 2020 20:48:18 +0000 (16:48 -0400)
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 <heiko.stuebner@theobroma-systems.com>
Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
drivers/net/phy/mscc.c

index 709979f48c99b246aa752841b24359863790d85a..64e9093827a5816249d3d2d66baad5bc781f5f2f 100644 (file)
 #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);
 }