[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220428082848.12191-3-josua@solid-run.com>
Date: Thu, 28 Apr 2022 11:28:47 +0300
From: Josua Mayer <josua@...id-run.com>
To: netdev@...r.kernel.org
Cc: alvaro.karsz@...id-run.com, Josua Mayer <josua@...id-run.com>,
Michael Hennerich <michael.hennerich@...log.com>,
Andrew Lunn <andrew@...n.ch>,
Heiner Kallweit <hkallweit1@...il.com>,
Russell King <linux@...linux.org.uk>,
"David S. Miller" <davem@...emloft.net>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>
Subject: [PATCH v3 2/3] 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.
Co-developed-by: Alvaro Karsz <alvaro.karsz@...id-run.com>
Signed-off-by: Alvaro Karsz <alvaro.karsz@...id-run.com>
Signed-off-by: Josua Mayer<josua@...id-run.com>
---
V2 -> V3: fix integer-as-null-pointer compiler warning
V1 -> V2: revised dts property name for clock(s)
V1 -> V2: implemented all 6 bits in the clock configuration register
drivers/net/phy/adin.c | 44 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index 5ce6da62cc8e..2de3eaddfb8e 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,37 @@ 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, "125mhz-recovered") == 0) {
+ sel |= ADIN1300_GE_CLK_CFG_RCVR_125;
+ } else if(strcmp(val, "adaptive-free-running") == 0) {
+ sel |= ADIN1300_GE_CLK_CFG_HRT_FREE;
+ } else if(strcmp(val, "adaptive-recovered") == 0) {
+ sel |= ADIN1300_GE_CLK_CFG_HRT_RCVR;
+ } 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 +495,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));
--
2.34.1
Powered by blists - more mailing lists