summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-05-19 05:58:36 +0300
committerJakub Kicinski <kuba@kernel.org>2022-05-19 05:58:37 +0300
commit638c1152d50facbf00b447037f62bb58577233e3 (patch)
treef1a613a04862936f7fce4aee60a9b3ac08d3ad0d
parenta3641ca416a3da7cbeae5bcf1fc26ba9797a1438 (diff)
parent654cd22227e6394f17b2f7c10d9fa9130db193fe (diff)
downloadlinux-638c1152d50facbf00b447037f62bb58577233e3.tar.xz
Merge branch 'adin-add-support-for-clock-output'
Josua Mayer says: ==================== adin: add support for clock output This patch series adds support for configuring the two clock outputs of adin 1200 and 1300 PHYs. Certain network controllers require an external reference clock which can be provided by the PHY. One of the replies to v1 was asking why the common clock framework isn't used. Currently no PHY driver has implemented providing a clock to the network controller. Instead they rely on vendor extensions to make the appropriate configuration. For example ar8035 uses qca,clk-out-frequency - this patchset aimed to replicate the same functionality. Finally the 125MHz free-running clock is enabled in the device-tree for SolidRun i.MX6 SoMs, to support revisions 1.9 and later, where the original phy has been replaced with an adin 1300. To avoid introducing new warning messages during boot for SoMs before rev 1.9, the status field of the new phy node is disabled by default, and will be enabled by U-Boot on demand. ==================== Link: https://lore.kernel.org/r/20220517085143.3749-1-josua@solid-run.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/net/adi,adin.yaml15
-rw-r--r--arch/arm/boot/dts/imx6qdl-sr-som.dtsi10
-rw-r--r--drivers/net/phy/adin.c40
3 files changed, 65 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/net/adi,adin.yaml b/Documentation/devicetree/bindings/net/adi,adin.yaml
index 1129f2b58e98..77750df0c2c4 100644
--- a/Documentation/devicetree/bindings/net/adi,adin.yaml
+++ b/Documentation/devicetree/bindings/net/adi,adin.yaml
@@ -36,6 +36,21 @@ properties:
enum: [ 4, 8, 12, 16, 20, 24 ]
default: 8
+ adi,phy-output-clock:
+ description: Select clock output on GP_CLK pin. Two clocks are available:
+ A 25MHz reference and a free-running 125MHz.
+ The phy can alternatively automatically switch between the reference and
+ the 125MHz clocks based on its internal state.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - 25mhz-reference
+ - 125mhz-free-running
+ - adaptive-free-running
+
+ adi,phy-output-reference-clock:
+ description: Enable 25MHz reference clock output on CLK25_REF pin.
+ type: boolean
+
unevaluatedProperties: false
examples:
diff --git a/arch/arm/boot/dts/imx6qdl-sr-som.dtsi b/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
index f86efd0ccc40..ce543e325cd3 100644
--- a/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
@@ -83,6 +83,16 @@
qca,clk-out-frequency = <125000000>;
qca,smarteee-tw-us-1g = <24>;
};
+
+ /*
+ * ADIN1300 (som rev 1.9 or later) is always at address 1. It
+ * will be enabled automatically by U-Boot if detected.
+ */
+ ethernet-phy@1 {
+ reg = <1>;
+ adi,phy-output-clock = "125mhz-free-running";
+ status = "disabled";
+ };
};
};
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));