Skip to contentSkip to conversation

ARM: imx: make Ethernet refclock configurable

PATCH Applied Oleksij Rempel 3 participants 22 messages Jan 31, 2023 – Mar 6, 2023

Subsystems (9)
lore
Share & tools
lore
#0 lore raw

v3 cover ARM: imx: make Ethernet refclock configurable

changes v3:
- add Reviewed-by: Abel Vesa <[email protected]>
- rebase on top of abelvesa/for-next

changes v2:
- remove "ARM: imx6q: use of_clk_get_by_name() instead of_clk_get() to get ptp clock" patch
- fix build warnings
- add "Acked-by: Lee Jones <[email protected]>"
- reword some commits as suggested by Fabio

Most of i.MX SoC variants have configurable FEC/Ethernet reference lock
used by RMII specification. This functionality is located in the general purpose registers (GRPx) and till now was not implemented as part of SoC clock tree.

With this patch set, we move forward and add this missing functionality to some of i.MX clk drivers. So, we will be able to configure clock opology
by using devicetree and be able to troubleshoot clock dependencies by using clk_summary etc.

Currently implemented and tested i.MX6Q, i.MX6DL and i.MX6UL variants.

Oleksij Rempel (19):
clk: imx: add clk-gpr-mux driver
clk: imx6q: add ethernet refclock mux support
ARM: imx6q: skip ethernet refclock reconfiguration if enet_clk_ref is
present
ARM: dts: imx6qdl: use enet_clk_ref instead of enet_out for the FEC
node
ARM: dts: imx6dl-lanmcu: configure ethernet reference clock parent
ARM: dts: imx6dl-alti6p: configure ethernet reference clock parent
ARM: dts: imx6dl-plybas: configure ethernet reference clock parent
ARM: dts: imx6dl-plym2m: configure ethernet reference clock parent
ARM: dts: imx6dl-prtmvt: configure ethernet reference clock parent
ARM: dts: imx6dl-victgo: configure ethernet reference clock parent
ARM: dts: imx6q-prtwd2: configure ethernet reference clock parent
ARM: dts: imx6qdl-skov-cpu: configure ethernet reference clock parent
ARM: dts: imx6dl-eckelmann-ci4x10: configure ethernet reference clock
parent
clk: imx: add imx_obtain_fixed_of_clock()
clk: imx6ul: fix enet1 gate configuration
clk: imx6ul: add ethernet refclock mux support
ARM: dts: imx6ul: set enet_clk_ref to CLK_ENETx_REF_SEL
ARM: mach-imx: imx6ul: remove not optional ethernet refclock overwrite
ARM: dts: imx6ul-prti6g: configure ethernet reference clock parent

 arch/arm/boot/dts/imx6dl-alti6p.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts |  13 +-
 arch/arm/boot/dts/imx6dl-lanmcu.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-plybas.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-plym2m.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-prtmvt.dts           |  11 +-
 arch/arm/boot/dts/imx6dl-victgo.dts           |  12 +-
 arch/arm/boot/dts/imx6q-prtwd2.dts            |  17 ++-
 arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi       |  12 +-
 arch/arm/boot/dts/imx6qdl.dtsi                |   4 +-
 arch/arm/boot/dts/imx6ul-prti6g.dts           |  14 ++-
 arch/arm/boot/dts/imx6ul.dtsi                 |  10 +-
 arch/arm/mach-imx/mach-imx6q.c                |  10 +-
 arch/arm/mach-imx/mach-imx6ul.c               |  20 ---
 drivers/clk/imx/Makefile                      |   1 +
 drivers/clk/imx/clk-gpr-mux.c                 | 119 ++++++++++++++++++
 drivers/clk/imx/clk-imx6q.c                   |  13 ++
 drivers/clk/imx/clk-imx6ul.c                  |  33 ++++-
 drivers/clk/imx/clk.c                         |  14 +++
 drivers/clk/imx/clk.h                         |   8 ++
 include/dt-bindings/clock/imx6qdl-clock.h     |   4 +-
 include/dt-bindings/clock/imx6ul-clock.h      |   7 +-
 include/linux/mfd/syscon/imx6q-iomuxc-gpr.h   |   6 +-
 23 files changed, 296 insertions(+), 80 deletions(-)
 create mode 100644 drivers/clk/imx/clk-gpr-mux.c
Signature · 1 line
2.30.2
#1 lore raw

PATCH v3 1/19 clk: imx: add clk-gpr-mux driver

Almost(?) every i.MX variant has clk mux for ethernet (rgmii/rmii) reference clock located in the GPR1 register. So far this clk is configured in different ways:
- mach-imx6q is doing mux configuration based on ptp vs enet_ref clk comparison.
- mach-imx7d is setting mux to PAD for all boards
- mach-imx6ul is setting mux to internal clock for all boards.

Since we have imx7d and imx6ul board variants which do not work with configurations forced by kernel mach code, we need to implement this clk mux properly as part of the clk framework. Which is done by this patch.

---
 drivers/clk/imx/Makefile      |   1 +
 drivers/clk/imx/clk-gpr-mux.c | 119 ++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk.h         |   5 ++
 3 files changed, 125 insertions(+)
 create mode 100644 drivers/clk/imx/clk-gpr-mux.c
drivers/clk/imx/Makefile +1 -0
index e8aacb0ee6ac..a75d59f7cb8a 100644
@@ -22,6 +22,7 @@ mxc-clk-objs += clk-pllv3.o
 mxc-clk-objs += clk-pllv4.o
 mxc-clk-objs += clk-pll14xx.o
 mxc-clk-objs += clk-sscg-pll.o
+mxc-clk-objs += clk-gpr-mux.o
 obj-$(CONFIG_MXC_CLK) += mxc-clk.o
 
 obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
drivers/clk/imx/clk-gpr-mux.c new file +119 -0

119 lines not on this page · raw message

drivers/clk/imx/clk.h +5 -0
index c4c73477e772..afc1ea0f5bcf 100644
@@ -458,4 +458,9 @@ struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name
 		unsigned long flags, void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock);
+
+struct clk_hw *imx_clk_gpr_mux(const char *name, const char *compatible,
+			       u32 reg, const char **parent_names,
+			       u8 num_parents, const u32 *mux_table, u32 mask);
+
 #endif
Signature · 1 line
2.30.2
#2 lore raw

PATCH v3 2/19 clk: imx6q: add ethernet refclock mux support

In reply to Oleksij Rempel

Add ethernet refclock mux support and set it to internal clock by default. This configuration will not affect existing boards since machine code currently overwrites this default.

The machine code will be fixed in a separate patch.

---
 drivers/clk/imx/clk-imx6q.c               | 13 +++++++++++++
 include/dt-bindings/clock/imx6qdl-clock.h |  4 +++-
 2 files changed, 16 insertions(+), 1 deletion(-)
drivers/clk/imx/clk-imx6q.c +13 -0
index da71e064531e..bf4c1d9c9928 100644
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -115,6 +116,10 @@ static struct clk_div_table video_div_table[] = {
 	{ /* sentinel */ }
 };
 
+static const char * enet_ref_sels[] = { "enet_ref", "enet_ref_pad", };
+static const u32 enet_ref_sels_table[] = { IMX6Q_GPR1_ENET_CLK_SEL_ANATOP, IMX6Q_GPR1_ENET_CLK_SEL_PAD };
+static const u32 enet_ref_sels_table_mask = IMX6Q_GPR1_ENET_CLK_SEL_ANATOP;
+
 static unsigned int share_count_esai;
 static unsigned int share_count_asrc;
 static unsigned int share_count_ssi1;
@@ -908,6 +913,12 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
 		hws[IMX6QDL_CLK_GPT_3M] = hws[IMX6QDL_CLK_GPT_IPG_PER];
 
+	hws[IMX6QDL_CLK_ENET_REF_PAD] = imx6q_obtain_fixed_clk_hw(ccm_node, "enet_ref_pad", 0);
+
+	hws[IMX6QDL_CLK_ENET_REF_SEL] = imx_clk_gpr_mux("enet_ref_sel", "fsl,imx6q-iomuxc-gpr",
+				IOMUXC_GPR1, enet_ref_sels, ARRAY_SIZE(enet_ref_sels),
+				enet_ref_sels_table, enet_ref_sels_table_mask);
+
 	imx_check_clk_hws(hws, IMX6QDL_CLK_END);
 
 	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
@@ -974,6 +985,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 			       hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk);
 	}
 
+	clk_set_parent(hws[IMX6QDL_CLK_ENET_REF_SEL]->clk, hws[IMX6QDL_CLK_ENET_REF]->clk);
+
 	imx_register_uart_clocks();
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
include/dt-bindings/clock/imx6qdl-clock.h +3 -1
index e20c43cc36f6..e5b2a1ba02bc 100644
@@ -273,6 +273,8 @@
 #define IMX6QDL_CLK_MMDC_P0_IPG			263
 #define IMX6QDL_CLK_DCIC1			264
 #define IMX6QDL_CLK_DCIC2			265
-#define IMX6QDL_CLK_END				266
+#define IMX6QDL_CLK_ENET_REF_SEL		266
+#define IMX6QDL_CLK_ENET_REF_PAD		267
+#define IMX6QDL_CLK_END				268
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6QDL_H */
Signature · 1 line
2.30.2
#3 lore raw

PATCH v3 3/19 ARM: imx6q: skip ethernet refclock reconfiguration if enet_clk_ref is present

In reply to Oleksij Rempel

Current mach-imx6q code has following logic:
- if ptp clock of the ethernet controller node is attached to the SoC internal enet_ref clock, then we configure RMII reference clock pin as output by setting IOMUXC_GPR1 BIT(21).
In this case - MAC (SoC) is the clock provider, PHY is the clock consumer.
- if ptp clock of the ethernet controller node is not attached to the enet_ref clock, then we configure RMII reference clock pin as input by clearing IOMUXC_GPR1 BIT(21).
In this case - PHY is the clock provider, MAC is the clock consumer.

According to the Freescale MX6SDL ReferenceManual v4, IOMUXC_GPR1 BIT(21) (page 2033) this configuration bit is not related to the PTP (IEEE1588) clock:
21 ENET_CLK_SEL - choose enet reference clk mode:
0 - get enet tx reference clk from pad (external OSC for both external
PHY and Internal Controller)
1 - get enet tx reference clk from internal clock from anatop (loopback
through pad), this clock also sent out to external PHY.

According to the Documentation/devicetree/bindings/net/fsl,fec.yaml:
The "ptp"(option), for IEEE1588 timer clock that requires the clock. The "enet_clk_ref"(option), for MAC transmit/receiver reference clock like RGMII TXC clock or RMII reference clock. It depends on board design, the clock is required if RGMII TXC and RMII reference clock source from SOC internal PLL.
The "enet_out"(option), output clock for external device, like supply clock for PHY. The clock is required if PHY clock source from SOC.

We can see, that "enet_clk_ref" clock is the best fit for this purpose. Other properties like "ptp" is designed for IEEE1588 and "enet_out" do not have real functionality within imx related clock infrastructure.

Since the "enet_clk_ref" is not used by the imx6qdl devicetrees, we can use it as indicator of potentially properly configured DT. At same time we can keep ptp clock based logic as the fallback for old DTs.

---
 arch/arm/mach-imx/mach-imx6q.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
arch/arm/mach-imx/mach-imx6q.c +9 -1
index c9d7c29d95e1..7f6200925752 100644
@@ -79,7 +79,7 @@ static void __init imx6q_enet_phy_init(void)
 static void __init imx6q_1588_init(void)
 {
 	struct device_node *np;
-	struct clk *ptp_clk;
+	struct clk *ptp_clk, *fec_enet_ref;
 	struct clk *enet_ref;
 	struct regmap *gpr;
 	u32 clksel;
@@ -90,6 +90,14 @@ static void __init imx6q_1588_init(void)
 		return;
 	}
 
+	/*
+	 * If enet_clk_ref configured, we assume DT did it properly and .
+	 * clk-imx6q.c will do needed configuration.
+	 */
+	fec_enet_ref = of_clk_get_by_name(np, "enet_clk_ref");
+	if (!IS_ERR(fec_enet_ref))
+		goto put_node;
+
 	ptp_clk = of_clk_get(np, 2);
 	if (IS_ERR(ptp_clk)) {
 		pr_warn("%s: failed to get ptp clock\n", __func__);
Signature · 1 line
2.30.2
#4 lore raw

PATCH v3 4/19 ARM: dts: imx6qdl: use enet_clk_ref instead of enet_out for the FEC node

In reply to Oleksij Rempel

Old imx6q machine code makes RGMII/RMII clock direction decision based on configuration of "ptp" clock. "enet_out" is not used and make no real sense, since we can't configure it as output or use it as clock provider.

Instead of "enet_out" use "enet_clk_ref" which is actual selector to choose between internal and external clock source:

FEC MAC <---------- enet_clk_ref <--------- SoC PLL

                         \
			  ^------<-> refclock PAD (bi directional)
---
 arch/arm/boot/dts/imx6qdl.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/boot/dts/imx6qdl.dtsi +2 -2
index ff1e0173b39b..71522263031a 100644
@@ -1050,8 +1050,8 @@ fec: ethernet@2188000 {
 				clocks = <&clks IMX6QDL_CLK_ENET>,
 					 <&clks IMX6QDL_CLK_ENET>,
 					 <&clks IMX6QDL_CLK_ENET_REF>,
-					 <&clks IMX6QDL_CLK_ENET_REF>;
-				clock-names = "ipg", "ahb", "ptp", "enet_out";
+					 <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+				clock-names = "ipg", "ahb", "ptp", "enet_clk_ref";
 				fsl,stop-mode = <&gpr 0x34 27>;
 				status = "disabled";
 			};
Signature · 1 line
2.30.2
#5 lore raw

PATCH v3 5/19 ARM: dts: imx6dl-lanmcu: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-lanmcu.dts | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/boot/dts/imx6dl-lanmcu.dts +8 -4
index 6b6e6fcdea9c..fa823988312d 100644
@@ -21,6 +21,7 @@ clock_ksz8081: clock-ksz8081 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	backlight: backlight {
@@ -109,14 +110,17 @@ &can2 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&clock_ksz8081>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clock_ksz8081>;
+};
+
 &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clock_ksz8081>;
-	clock-names = "ipg", "ahb", "ptp";
 	phy-handle = <&rgmii_phy>;
 	status = "okay";
 
Signature · 1 line
2.30.2
#6 lore raw

PATCH v3 6/19 ARM: dts: imx6dl-alti6p: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-alti6p.dts | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/boot/dts/imx6dl-alti6p.dts +8 -4
index e8325fd680d9..e6a4e2770640 100644
@@ -22,6 +22,7 @@ clock_ksz8081: clock-ksz8081 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	i2c2-mux {
@@ -191,6 +192,13 @@ &can1 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&clock_ksz8081>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clock_ksz8081>;
+};
+
 &ecspi1 {
 	cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
 	pinctrl-names = "default";
@@ -208,10 +216,6 @@ &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clock_ksz8081>;
-	clock-names = "ipg", "ahb", "ptp";
 	status = "okay";
 
 	mdio {
Signature · 1 line
2.30.2
#7 lore raw

PATCH v3 7/19 ARM: dts: imx6dl-plybas: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-plybas.dts | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/boot/dts/imx6dl-plybas.dts +8 -4
index c52e6caf3996..e98046eea7a4 100644
@@ -75,6 +75,7 @@ clk50m_phy: phy-clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	reg_5v0: regulator-5v0 {
@@ -99,6 +100,13 @@ &can2 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&clk50m_phy>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clk50m_phy>;
+};
+
 &ecspi1 {
 	cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
 	pinctrl-names = "default";
@@ -116,10 +124,6 @@ &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clk50m_phy>;
-	clock-names = "ipg", "ahb", "ptp";
 	phy-handle = <&rgmii_phy>;
 	status = "okay";
 
Signature · 1 line
2.30.2
#8 lore raw

PATCH v3 8/19 ARM: dts: imx6dl-plym2m: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-plym2m.dts | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/boot/dts/imx6dl-plym2m.dts +8 -4
index 522660c912a0..e3c10483f33b 100644
@@ -84,6 +84,7 @@ clk50m_phy: phy-clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	reg_3v3: regulator-3v3 {
@@ -173,6 +174,13 @@ &can1 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&clk50m_phy>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clk50m_phy>;
+};
+
 &ecspi1 {
 	cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
 	pinctrl-names = "default";
@@ -254,10 +262,6 @@ &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clk50m_phy>;
-	clock-names = "ipg", "ahb", "ptp";
 	phy-handle = <&rgmii_phy>;
 	status = "okay";
 
Signature · 1 line
2.30.2
#9 lore raw

PATCH v3 9/19 ARM: dts: imx6dl-prtmvt: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-prtmvt.dts | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
arch/arm/boot/dts/imx6dl-prtmvt.dts +5 -6
index 1f8cddd83ccb..5f4fa796ca18 100644
@@ -193,6 +193,7 @@ clk50m_phy: phy-clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	reg_1v8: regulator-1v8 {
@@ -293,8 +294,10 @@ &can2 {
 };
 
 &clks {
-	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>;
-	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>;
+	clocks = <&clk50m_phy>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, <&clk50m_phy>;
 };
 
 &ecspi1 {
@@ -314,10 +317,6 @@ &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clk50m_phy>;
-	clock-names = "ipg", "ahb", "ptp";
 	phy-handle = <&rmii_phy>;
 	status = "okay";
 
Signature · 1 line
2.30.2
#10 lore raw

PATCH v3 10/19 ARM: dts: imx6dl-victgo: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-victgo.dts | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/boot/dts/imx6dl-victgo.dts +8 -4
index 72df1dba83be..23274be08e61 100644
@@ -54,6 +54,7 @@ clk50m_phy: phy-clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	rotary-encoder {
@@ -134,6 +135,13 @@ vdiv_hitch_pos: voltage-divider-hitch-pos {
 	};
 };
 
+&clks {
+	clocks = <&clk50m_phy>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clk50m_phy>;
+};
+
 &ecspi2 {
 	cs-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
 	pinctrl-names = "default";
@@ -182,10 +190,6 @@ &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clk50m_phy>;
-	clock-names = "ipg", "ahb", "ptp";
 	phy-handle = <&rmii_phy>;
 	status = "okay";
 
Signature · 1 line
2.30.2
#11 lore raw

PATCH v3 11/19 ARM: dts: imx6q-prtwd2: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6q-prtwd2.dts | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)
arch/arm/boot/dts/imx6q-prtwd2.dts +14 -3
index 349959d38020..54a57a4548e2 100644
@@ -22,6 +22,13 @@ memory@80000000 {
 		reg = <0x80000000 0x20000000>;
 	};
 
+	clk50m_phy: phy-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
+	};
+
 	usdhc2_wifi_pwrseq: usdhc2_wifi_pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		pinctrl-names = "default";
@@ -49,13 +56,17 @@ &can1 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&clk50m_phy>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clk50m_phy>;
+};
+
 &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rmii";
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>;
-	clock-names = "ipg", "ahb";
 	status = "okay";
 
 	fixed-link {
Signature · 1 line
2.30.2
#12 lore raw

PATCH v3 12/19 ARM: dts: imx6qdl-skov-cpu: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi +8 -4
index 3def1b621c8e..2731faede1cb 100644
@@ -105,6 +105,7 @@ clk50m_phy: phy-clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	reg_3v3: regulator-3v3 {
@@ -232,13 +233,16 @@ adc: adc@0 {
 	};
 };
 
+&clks {
+	clocks = <&clk50m_phy>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&clk50m_phy>;
+};
+
 &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&clk50m_phy>;
-	clock-names = "ipg", "ahb", "ptp";
 	phy-mode = "rmii";
 	phy-supply = <&reg_3v3>;
 	status = "okay";
Signature · 1 line
2.30.2
#13 lore raw

PATCH v3 13/19 ARM: dts: imx6dl-eckelmann-ci4x10: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

---
 arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts +8 -5
index 864dc5018451..33825b5a8f26 100644
@@ -28,6 +28,7 @@ rmii_clk: clock-rmii {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet_ref_pad";
 	};
 
 	reg_usb_h1_vbus: regulator-usb-h1-vbus {
@@ -64,6 +65,13 @@ &can2 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&rmii_clk>;
+	clock-names = "enet_ref_pad";
+	assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF_SEL>;
+	assigned-clock-parents = <&rmii_clk>;
+};
+
 &ecspi2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_ecspi2>;
@@ -297,11 +305,6 @@ &fec {
 	phy-mode = "rmii";
 	phy-reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
 	phy-handle = <&phy>;
-	clocks = <&clks IMX6QDL_CLK_ENET>,
-		 <&clks IMX6QDL_CLK_ENET>,
-		 <&rmii_clk>,
-		 <&clks IMX6QDL_CLK_ENET_REF>;
-	clock-names = "ipg", "ahb", "ptp", "enet_out";
 	status = "okay";
 
 	mdio {
Signature · 1 line
2.30.2
#14 lore raw

PATCH v3 14/19 clk: imx: add imx_obtain_fixed_of_clock()

In reply to Oleksij Rempel

Add imx_obtain_fixed_of_clock() to optionally add clock not configured in the devicetree.

---
 drivers/clk/imx/clk.c | 14 ++++++++++++++
 drivers/clk/imx/clk.h |  3 +++
 2 files changed, 17 insertions(+)
drivers/clk/imx/clk.c +14 -0
index 4f7db3c9e144..19cde59a20cb 100644
@@ -110,6 +110,20 @@ struct clk_hw *imx_obtain_fixed_clock_hw(
 	return __clk_get_hw(clk);
 }
 
+struct clk_hw *imx_obtain_fixed_of_clock(struct device_node *np,
+					 const char *name, unsigned long rate)
+{
+	struct clk *clk = of_clk_get_by_name(np, name);
+	struct clk_hw *hw;
+
+	if (IS_ERR(clk))
+		hw = imx_obtain_fixed_clock_hw(name, rate);
+	else
+		hw = __clk_get_hw(clk);
+
+	return hw;
+}
+
 struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name)
 {
 	struct clk *clk;
drivers/clk/imx/clk.h +3 -0
index afc1ea0f5bcf..3d94722bbf99 100644
@@ -288,6 +288,9 @@ struct clk * imx_obtain_fixed_clock(
 struct clk_hw *imx_obtain_fixed_clock_hw(
 			const char *name, unsigned long rate);
 
+struct clk_hw *imx_obtain_fixed_of_clock(struct device_node *np,
+					 const char *name, unsigned long rate);
+
 struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name);
 
 struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
Signature · 1 line
2.30.2
#15 lore raw

PATCH v3 15/19 clk: imx6ul: fix enet1 gate configuration

In reply to Oleksij Rempel

According to the "i.MX 6UltraLite Applications Processor Reference Manual, Rev. 2, 03/2017", BIT(13) is ENET1_125M_EN which is not controlling root of PLL6. It is controlling ENET1 separately.

So, instead of this picture (implementation before this patch):
fec1 <- enet_ref (divider) <---------------------------,

                                                       |- pll6_enet (gate)

fec2 <- enet2_ref_125m (gate) <- enet2_ref (divider) <-´

we should have this one (after this patch):
fec1 <- enet1_ref_125m (gate) <- enet1_ref (divider) <-,

                                                       |- pll6_enet

fec2 <- enet2_ref_125m (gate) <- enet2_ref (divider) <-´

With this fix, the RMII reference clock will be turned off, after setting network interface down on each separate interface
(ip l s dev eth0 down). Which was not working before, on system with both FECs enabled.

---
 drivers/clk/imx/clk-imx6ul.c             | 7 ++++---
 include/dt-bindings/clock/imx6ul-clock.h | 3 ++-
 2 files changed, 6 insertions(+), 4 deletions(-)
drivers/clk/imx/clk-imx6ul.c +4 -3
index 67a7a77ca540..c3c465c1b0e7 100644
@@ -176,7 +176,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 	hws[IMX6UL_CLK_PLL3_USB_OTG]	= imx_clk_hw_gate("pll3_usb_otg",	"pll3_bypass", base + 0x10, 13);
 	hws[IMX6UL_CLK_PLL4_AUDIO]	= imx_clk_hw_gate("pll4_audio",	"pll4_bypass", base + 0x70, 13);
 	hws[IMX6UL_CLK_PLL5_VIDEO]	= imx_clk_hw_gate("pll5_video",	"pll5_bypass", base + 0xa0, 13);
-	hws[IMX6UL_CLK_PLL6_ENET]	= imx_clk_hw_gate("pll6_enet",	"pll6_bypass", base + 0xe0, 13);
+	hws[IMX6UL_CLK_PLL6_ENET]	= imx_clk_hw_fixed_factor("pll6_enet",	"pll6_bypass", 1, 1);
 	hws[IMX6UL_CLK_PLL7_USB_HOST]	= imx_clk_hw_gate("pll7_usb_host",	"pll7_bypass", base + 0x20, 13);
 
 	/*
@@ -205,12 +205,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 	hws[IMX6UL_CLK_PLL3_PFD2] = imx_clk_hw_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,	 2);
 	hws[IMX6UL_CLK_PLL3_PFD3] = imx_clk_hw_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,	 3);
 
-	hws[IMX6UL_CLK_ENET_REF] = clk_hw_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+	hws[IMX6UL_CLK_ENET_REF] = clk_hw_register_divider_table(NULL, "enet1_ref", "pll6_enet", 0,
 			base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
 	hws[IMX6UL_CLK_ENET2_REF] = clk_hw_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
 			base + 0xe0, 2, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
 
-	hws[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_hw_gate("enet_ref_125m", "enet2_ref", base + 0xe0, 20);
+	hws[IMX6UL_CLK_ENET1_REF_125M] = imx_clk_hw_gate("enet1_ref_125m", "enet1_ref", base + 0xe0, 13);
+	hws[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_hw_gate("enet2_ref_125m", "enet2_ref", base + 0xe0, 20);
 	hws[IMX6UL_CLK_ENET_PTP_REF]	= imx_clk_hw_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
 	hws[IMX6UL_CLK_ENET_PTP]	= imx_clk_hw_gate("enet_ptp", "enet_ptp_ref", base + 0xe0, 21);
 
include/dt-bindings/clock/imx6ul-clock.h +2 -1
index 79094338e6f1..b44920f1edb0 100644
@@ -256,7 +256,8 @@
 #define IMX6UL_CLK_GPIO4		247
 #define IMX6UL_CLK_GPIO5		248
 #define IMX6UL_CLK_MMDC_P1_IPG		249
+#define IMX6UL_CLK_ENET1_REF_125M	250
 
-#define IMX6UL_CLK_END			250
+#define IMX6UL_CLK_END			251
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
Signature · 1 line
2.30.2
#16 lore raw

PATCH v3 16/19 clk: imx6ul: add ethernet refclock mux support

In reply to Oleksij Rempel

Add ethernet refclock mux support and set it to internal clock by default. This configuration will not affect existing boards.

clock tree before this patch:
fec1 <- enet1_ref_125m (gate) <- enet1_ref (divider) <-,

                                                       |- pll6_enet

fec2 <- enet2_ref_125m (gate) <- enet2_ref (divider) <-´

after this patch:
fec1 <- enet1_ref_sel(mux) <- enet1_ref_125m (gate) <- ...
`--<> enet1_ref_pad |- pll6_enet
fec2 <- enet2_ref_sel(mux) <- enet2_ref_125m (gate) <- ...

               `--<> enet2_ref_pad
---
 drivers/clk/imx/clk-imx6ul.c                | 26 +++++++++++++++++++++
 include/dt-bindings/clock/imx6ul-clock.h    |  6 ++++-
 include/linux/mfd/syscon/imx6q-iomuxc-gpr.h |  6 +++--
 3 files changed, 35 insertions(+), 3 deletions(-)
drivers/clk/imx/clk-imx6ul.c +26 -0
index c3c465c1b0e7..2836adb817b7 100644
@@ -10,6 +10,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -94,6 +95,17 @@ static const struct clk_div_table video_div_table[] = {
 	{ }
 };
 
+static const char * enet1_ref_sels[] = { "enet1_ref_125m", "enet1_ref_pad", };
+static const u32 enet1_ref_sels_table[] = { IMX6UL_GPR1_ENET1_TX_CLK_DIR,
+					    IMX6UL_GPR1_ENET1_CLK_SEL };
+static const u32 enet1_ref_sels_table_mask = IMX6UL_GPR1_ENET1_TX_CLK_DIR |
+					     IMX6UL_GPR1_ENET1_CLK_SEL;
+static const char * enet2_ref_sels[] = { "enet2_ref_125m", "enet2_ref_pad", };
+static const u32 enet2_ref_sels_table[] = { IMX6UL_GPR1_ENET2_TX_CLK_DIR,
+					    IMX6UL_GPR1_ENET2_CLK_SEL };
+static const u32 enet2_ref_sels_table_mask = IMX6UL_GPR1_ENET2_TX_CLK_DIR |
+					     IMX6UL_GPR1_ENET2_CLK_SEL;
+
 static u32 share_count_asrc;
 static u32 share_count_audio;
 static u32 share_count_sai1;
@@ -472,6 +484,17 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 	/* mask handshake of mmdc */
 	imx_mmdc_mask_handshake(base, 0);
 
+	hws[IMX6UL_CLK_ENET1_REF_PAD] = imx_obtain_fixed_of_clock(ccm_node, "enet1_ref_pad", 0);
+
+	hws[IMX6UL_CLK_ENET1_REF_SEL] = imx_clk_gpr_mux("enet1_ref_sel", "fsl,imx6ul-iomuxc-gpr",
+				IOMUXC_GPR1, enet1_ref_sels, ARRAY_SIZE(enet1_ref_sels),
+				enet1_ref_sels_table, enet1_ref_sels_table_mask);
+	hws[IMX6UL_CLK_ENET2_REF_PAD] = imx_obtain_fixed_of_clock(ccm_node, "enet2_ref_pad", 0);
+
+	hws[IMX6UL_CLK_ENET2_REF_SEL] = imx_clk_gpr_mux("enet2_ref_sel", "fsl,imx6ul-iomuxc-gpr",
+				IOMUXC_GPR1, enet2_ref_sels, ARRAY_SIZE(enet2_ref_sels),
+				enet2_ref_sels_table, enet2_ref_sels_table_mask);
+
 	imx_check_clk_hws(hws, IMX6UL_CLK_END);
 
 	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
@@ -516,6 +539,9 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 		clk_set_parent(hws[IMX6ULL_CLK_EPDC_PRE_SEL]->clk, hws[IMX6UL_CLK_PLL3_PFD2]->clk);
 
 	clk_set_parent(hws[IMX6UL_CLK_ENFC_SEL]->clk, hws[IMX6UL_CLK_PLL2_PFD2]->clk);
+
+	clk_set_parent(hws[IMX6UL_CLK_ENET1_REF_SEL]->clk, hws[IMX6UL_CLK_ENET_REF]->clk);
+	clk_set_parent(hws[IMX6UL_CLK_ENET2_REF_SEL]->clk, hws[IMX6UL_CLK_ENET2_REF]->clk);
 }
 
 CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
include/dt-bindings/clock/imx6ul-clock.h +5 -1
index b44920f1edb0..66239ebc0e23 100644
@@ -257,7 +257,11 @@
 #define IMX6UL_CLK_GPIO5		248
 #define IMX6UL_CLK_MMDC_P1_IPG		249
 #define IMX6UL_CLK_ENET1_REF_125M	250
+#define IMX6UL_CLK_ENET1_REF_SEL	251
+#define IMX6UL_CLK_ENET1_REF_PAD	252
+#define IMX6UL_CLK_ENET2_REF_SEL	253
+#define IMX6UL_CLK_ENET2_REF_PAD	254
 
-#define IMX6UL_CLK_END			251
+#define IMX6UL_CLK_END			255
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h +4 -2
index d4b5e527a7a3..09c6b3184bb0 100644
@@ -451,8 +451,10 @@
 #define IMX6SX_GPR12_PCIE_RX_EQ_2			(0x2 << 0)
 
 /* For imx6ul iomux gpr register field define */
-#define IMX6UL_GPR1_ENET1_CLK_DIR		(0x1 << 17)
-#define IMX6UL_GPR1_ENET2_CLK_DIR		(0x1 << 18)
+#define IMX6UL_GPR1_ENET2_TX_CLK_DIR		BIT(18)
+#define IMX6UL_GPR1_ENET1_TX_CLK_DIR		BIT(17)
+#define IMX6UL_GPR1_ENET2_CLK_SEL		BIT(14)
+#define IMX6UL_GPR1_ENET1_CLK_SEL		BIT(13)
 #define IMX6UL_GPR1_ENET1_CLK_OUTPUT		(0x1 << 17)
 #define IMX6UL_GPR1_ENET2_CLK_OUTPUT		(0x1 << 18)
 #define IMX6UL_GPR1_ENET_CLK_DIR		(0x3 << 17)
Signature · 1 line
2.30.2
#17 lore raw

PATCH v3 17/19 ARM: dts: imx6ul: set enet_clk_ref to CLK_ENETx_REF_SEL

In reply to Oleksij Rempel

IMX6UL_CLK_ENETx_REF is behind of CLK_ENETx_REF_SEL:

FEC MAC <---------- CLK_ENETx_REF_SEL <--------- CLK_ENETx_REF

		       \
		        ^------<-> CLK_ENETx_REF_PAD

We should point to the clock selector instead. So, we will be able to use external clock source from CLK_ENETx_REF_PAD as well.

At same time, remove enet_out clk. It is using always the same clock as enet_clk_ref and do not help to solve any challenges of this HW.

---
 arch/arm/boot/dts/imx6ul.dtsi | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)
arch/arm/boot/dts/imx6ul.dtsi +4 -6
index 2b5996395701..fa9afedb6549 100644
@@ -532,10 +532,9 @@ fec2: ethernet@20b4000 {
 				clocks = <&clks IMX6UL_CLK_ENET>,
 					 <&clks IMX6UL_CLK_ENET_AHB>,
 					 <&clks IMX6UL_CLK_ENET_PTP>,
-					 <&clks IMX6UL_CLK_ENET2_REF_125M>,
-					 <&clks IMX6UL_CLK_ENET2_REF_125M>;
+					 <&clks IMX6UL_CLK_ENET2_REF_SEL>;
 				clock-names = "ipg", "ahb", "ptp",
-					      "enet_clk_ref", "enet_out";
+					      "enet_clk_ref";
 				fsl,num-tx-queues = <1>;
 				fsl,num-rx-queues = <1>;
 				fsl,stop-mode = <&gpr 0x10 4>;
@@ -880,10 +879,9 @@ fec1: ethernet@2188000 {
 				clocks = <&clks IMX6UL_CLK_ENET>,
 					 <&clks IMX6UL_CLK_ENET_AHB>,
 					 <&clks IMX6UL_CLK_ENET_PTP>,
-					 <&clks IMX6UL_CLK_ENET_REF>,
-					 <&clks IMX6UL_CLK_ENET_REF>;
+					 <&clks IMX6UL_CLK_ENET1_REF_SEL>;
 				clock-names = "ipg", "ahb", "ptp",
-					      "enet_clk_ref", "enet_out";
+					      "enet_clk_ref";
 				fsl,num-tx-queues = <1>;
 				fsl,num-rx-queues = <1>;
 				fsl,stop-mode = <&gpr 0x10 3>;
Signature · 1 line
2.30.2
#18 lore raw

PATCH v3 18/19 ARM: mach-imx: imx6ul: remove not optional ethernet refclock overwrite

In reply to Oleksij Rempel

Ethernet refclock direction is board specific and should be configurable by devicetree. In fact there are board not working with this defaults, which will be fixed by separate patch.

---
 arch/arm/mach-imx/mach-imx6ul.c | 20 --------------------
 1 file changed, 20 deletions(-)
arch/arm/mach-imx/mach-imx6ul.c +0 -20
index 35e81201cb5d..9208a2d6a9da 100644
@@ -4,8 +4,6 @@
  */
 #include <linux/irqchip.h>
 #include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-#include <linux/micrel_phy.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
 #include <linux/regmap.h>
@@ -16,30 +14,12 @@
 #include "cpuidle.h"
 #include "hardware.h"
 
-static void __init imx6ul_enet_clk_init(void)
-{
-	struct regmap *gpr;
-
-	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
-	if (!IS_ERR(gpr))
-		regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_ENET_CLK_DIR,
-				   IMX6UL_GPR1_ENET_CLK_OUTPUT);
-	else
-		pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
-}
-
-static inline void imx6ul_enet_init(void)
-{
-	imx6ul_enet_clk_init();
-}
-
 static void __init imx6ul_init_machine(void)
 {
 	imx_print_silicon_rev(cpu_is_imx6ull() ? "i.MX6ULL" : "i.MX6UL",
 		imx_get_soc_revision());
 
 	of_platform_default_populate(NULL, NULL, NULL);
-	imx6ul_enet_init();
 	imx_anatop_init();
 	imx6ul_pm_init();
 }
Signature · 1 line
2.30.2
#19 lore raw

PATCH v3 19/19 ARM: dts: imx6ul-prti6g: configure ethernet reference clock parent

In reply to Oleksij Rempel

On this board the PHY is the ref clock provider. So, configure ethernet reference clock as input.

Without this patch we have relatively high amount of dropped packets.

---
 arch/arm/boot/dts/imx6ul-prti6g.dts | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)
arch/arm/boot/dts/imx6ul-prti6g.dts +8 -6
index c18390f238e1..b7c96fbe7a91 100644
@@ -26,6 +26,7 @@ clock_ksz8081_out: clock-ksz8081-out {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
+		clock-output-names = "enet1_ref_pad";
 	};
 
 	leds {
@@ -60,6 +61,13 @@ &can2 {
 	status = "okay";
 };
 
+&clks {
+	clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>, <&clock_ksz8081_out>;
+	clock-names = "ckil", "osc", "ipp_di0", "ipp_di1", "enet1_ref_pad";
+	assigned-clocks = <&clks IMX6UL_CLK_ENET1_REF_SEL>;
+	assigned-clock-parents = <&clock_ksz8081_out>;
+};
+
 &ecspi1 {
 	cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
 	pinctrl-names = "default";
@@ -85,12 +93,6 @@ &fec1 {
 	pinctrl-0 = <&pinctrl_eth1>;
 	phy-mode = "rmii";
 	phy-handle = <&rmii_phy>;
-	clocks = <&clks IMX6UL_CLK_ENET>,
-		 <&clks IMX6UL_CLK_ENET_AHB>,
-		 <&clks IMX6UL_CLK_ENET_PTP>,
-		 <&clock_ksz8081_out>;
-	clock-names = "ipg", "ahb", "ptp",
-		      "enet_clk_ref";
 	status = "okay";
 
 	mdio {
Signature · 1 line
2.30.2
Applied
#20 lore raw
In reply to Oleksij Rempel
Quoted 3 lines · Oleksij Rempel

changes v3:
- add Reviewed-by: Abel Vesa <[email protected]>
- rebase on top of abelvesa/for-next

Applied all clk/imx ones. Thanks!

Quoted 76 lines

changes v2:
- remove "ARM: imx6q: use of_clk_get_by_name() instead of_clk_get() to get ptp clock" patch
- fix build warnings
- add "Acked-by: Lee Jones <[email protected]>"
- reword some commits as suggested by Fabio

Most of i.MX SoC variants have configurable FEC/Ethernet reference lock
used by RMII specification. This functionality is located in the general purpose registers (GRPx) and till now was not implemented as part of SoC clock tree.

With this patch set, we move forward and add this missing functionality to some of i.MX clk drivers. So, we will be able to configure clock opology
by using devicetree and be able to troubleshoot clock dependencies by using clk_summary etc.

Currently implemented and tested i.MX6Q, i.MX6DL and i.MX6UL variants.

Oleksij Rempel (19):
clk: imx: add clk-gpr-mux driver
clk: imx6q: add ethernet refclock mux support
ARM: imx6q: skip ethernet refclock reconfiguration if enet_clk_ref is
present
ARM: dts: imx6qdl: use enet_clk_ref instead of enet_out for the FEC
node
ARM: dts: imx6dl-lanmcu: configure ethernet reference clock parent
ARM: dts: imx6dl-alti6p: configure ethernet reference clock parent
ARM: dts: imx6dl-plybas: configure ethernet reference clock parent
ARM: dts: imx6dl-plym2m: configure ethernet reference clock parent
ARM: dts: imx6dl-prtmvt: configure ethernet reference clock parent
ARM: dts: imx6dl-victgo: configure ethernet reference clock parent
ARM: dts: imx6q-prtwd2: configure ethernet reference clock parent
ARM: dts: imx6qdl-skov-cpu: configure ethernet reference clock parent
ARM: dts: imx6dl-eckelmann-ci4x10: configure ethernet reference clock
parent
clk: imx: add imx_obtain_fixed_of_clock()
clk: imx6ul: fix enet1 gate configuration
clk: imx6ul: add ethernet refclock mux support
ARM: dts: imx6ul: set enet_clk_ref to CLK_ENETx_REF_SEL
ARM: mach-imx: imx6ul: remove not optional ethernet refclock overwrite
ARM: dts: imx6ul-prti6g: configure ethernet reference clock parent

 arch/arm/boot/dts/imx6dl-alti6p.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts |  13 +-
 arch/arm/boot/dts/imx6dl-lanmcu.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-plybas.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-plym2m.dts           |  12 +-
 arch/arm/boot/dts/imx6dl-prtmvt.dts           |  11 +-
 arch/arm/boot/dts/imx6dl-victgo.dts           |  12 +-
 arch/arm/boot/dts/imx6q-prtwd2.dts            |  17 ++-
 arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi       |  12 +-
 arch/arm/boot/dts/imx6qdl.dtsi                |   4 +-
 arch/arm/boot/dts/imx6ul-prti6g.dts           |  14 ++-
 arch/arm/boot/dts/imx6ul.dtsi                 |  10 +-
 arch/arm/mach-imx/mach-imx6q.c                |  10 +-
 arch/arm/mach-imx/mach-imx6ul.c               |  20 ---
 drivers/clk/imx/Makefile                      |   1 +
 drivers/clk/imx/clk-gpr-mux.c                 | 119 ++++++++++++++++++
 drivers/clk/imx/clk-imx6q.c                   |  13 ++
 drivers/clk/imx/clk-imx6ul.c                  |  33 ++++-
 drivers/clk/imx/clk.c                         |  14 +++
 drivers/clk/imx/clk.h                         |   8 ++
 include/dt-bindings/clock/imx6qdl-clock.h     |   4 +-
 include/dt-bindings/clock/imx6ul-clock.h      |   7 +-
 include/linux/mfd/syscon/imx6q-iomuxc-gpr.h   |   6 +-
 23 files changed, 296 insertions(+), 80 deletions(-)
 create mode 100644 drivers/clk/imx/clk-gpr-mux.c
Signature · 1 line
2.30.2
Applied
#21 lore raw
In reply to Oleksij Rempel
Quoted 41 lines · Oleksij Rempel

changes v3:
- add Reviewed-by: Abel Vesa <[email protected]>
- rebase on top of abelvesa/for-next

changes v2:
- remove "ARM: imx6q: use of_clk_get_by_name() instead of_clk_get() to get ptp clock" patch
- fix build warnings
- add "Acked-by: Lee Jones <[email protected]>"
- reword some commits as suggested by Fabio

Most of i.MX SoC variants have configurable FEC/Ethernet reference lock
used by RMII specification. This functionality is located in the general purpose registers (GRPx) and till now was not implemented as part of SoC clock tree.

With this patch set, we move forward and add this missing functionality to some of i.MX clk drivers. So, we will be able to configure clock opology
by using devicetree and be able to troubleshoot clock dependencies by using clk_summary etc.

Currently implemented and tested i.MX6Q, i.MX6DL and i.MX6UL variants.

Oleksij Rempel (19):
clk: imx: add clk-gpr-mux driver
clk: imx6q: add ethernet refclock mux support
ARM: imx6q: skip ethernet refclock reconfiguration if enet_clk_ref is
present
ARM: dts: imx6qdl: use enet_clk_ref instead of enet_out for the FEC
node
ARM: dts: imx6dl-lanmcu: configure ethernet reference clock parent
ARM: dts: imx6dl-alti6p: configure ethernet reference clock parent
ARM: dts: imx6dl-plybas: configure ethernet reference clock parent
ARM: dts: imx6dl-plym2m: configure ethernet reference clock parent
ARM: dts: imx6dl-prtmvt: configure ethernet reference clock parent
ARM: dts: imx6dl-victgo: configure ethernet reference clock parent
ARM: dts: imx6q-prtwd2: configure ethernet reference clock parent
ARM: dts: imx6qdl-skov-cpu: configure ethernet reference clock parent

Quoted 8 lines

ARM: dts: imx6dl-eckelmann-ci4x10: configure ethernet reference clock
parent
clk: imx: add imx_obtain_fixed_of_clock()
clk: imx6ul: fix enet1 gate configuration
clk: imx6ul: add ethernet refclock mux support
ARM: dts: imx6ul: set enet_clk_ref to CLK_ENETx_REF_SEL
ARM: mach-imx: imx6ul: remove not optional ethernet refclock overwrite
ARM: dts: imx6ul-prti6g: configure ethernet reference clock parent

Applied all mach-imx and DTS ones, thanks!