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
--
2.30.2
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.
Signed-off-by: Oleksij Rempel <[email protected]>
Reviewed-by: Abel Vesa <[email protected]>
---
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
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index e8aacb0ee6ac..a75d59f7cb8a 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -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
diff --git a/drivers/clk/imx/clk-gpr-mux.c b/drivers/clk/imx/clk-gpr-mux.c
new file mode 100644
index 000000000000..47a3e3cdcc82
--- /dev/null
+++ b/drivers/clk/imx/clk-gpr-mux.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ */
+
+#define pr_fmt(fmt) "imx:clk-gpr-mux: " fmt
+
+#include <linux/module.h>
+
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk.h"
+
+struct imx_clk_gpr {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u32 mask;
+ u32 reg;
+ const u32 *mux_table;
+};
+
+static struct imx_clk_gpr *to_imx_clk_gpr(struct clk_hw *hw)
+{
+ return container_of(hw, struct imx_clk_gpr, hw);
+}
+
+static u8 imx_clk_gpr_mux_get_parent(struct clk_hw *hw)
+{
+ struct imx_clk_gpr *priv = to_imx_clk_gpr(hw);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(priv->regmap, priv->reg, &val);
+ if (ret)
+ goto get_parent_err;
+
+ val &= priv->mask;
+
+ ret = clk_mux_val_to_index(hw, priv->mux_table, 0, val);
+ if (ret < 0)
+ goto get_parent_err;
+
+ return ret;
+
+get_parent_err:
+ pr_err("failed to get parent (%pe)\n", ERR_PTR(ret));
+
+ /* return some realistic non negative value. Potentially we could
+ * give index to some dummy error parent.
+ */
+ return 0;
+}
+
+static int imx_clk_gpr_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct imx_clk_gpr *priv = to_imx_clk_gpr(hw);
+ unsigned int val = clk_mux_index_to_val(priv->mux_table, 0, index);
+
+ return regmap_update_bits(priv->regmap, priv->reg, priv->mask, val);
+}
+
+static int imx_clk_gpr_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return clk_mux_determine_rate_flags(hw, req, 0);
+}
+
+const struct clk_ops imx_clk_gpr_mux_ops = {
+ .get_parent = imx_clk_gpr_mux_get_parent,
+ .set_parent = imx_clk_gpr_mux_set_parent,
+ .determine_rate = imx_clk_gpr_mux_determine_rate,
+};
+
+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)
+{
+ struct clk_init_data init = { };
+ struct imx_clk_gpr *priv;
+ struct regmap *regmap;
+ struct clk_hw *hw;
+ int ret;
+
+ regmap = syscon_regmap_lookup_by_compatible(compatible);
+ if (IS_ERR(regmap)) {
+ pr_err("failed to find %s regmap\n", compatible);
+ return ERR_CAST(regmap);
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &imx_clk_gpr_mux_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+ priv->hw.init = &init;
+ priv->regmap = regmap;
+ priv->mux_table = mux_table;
+ priv->reg = reg;
+ priv->mask = mask;
+
+ hw = &priv->hw;
+ ret = clk_hw_register(NULL, &priv->hw);
+ if (ret) {
+ kfree(priv);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index c4c73477e772..afc1ea0f5bcf 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -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
--
2.30.2
On this board the PHY is the ref clock provider. So, configure ethernet
reference clock as input.
Signed-off-by: Oleksij Rempel <[email protected]>
---
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts b/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts
index 864dc5018451..33825b5a8f26 100644
--- a/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts
+++ b/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts
@@ -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 {
--
2.30.2
On 23-01-31 09:46:23, Oleksij Rempel wrote:
> changes v3:
> - add Reviewed-by: Abel Vesa <[email protected]>
> - rebase on top of abelvesa/for-next
Applied all clk/imx ones. Thanks!
>
> 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
>
> --
> 2.30.2
>
On Tue, Jan 31, 2023 at 09:46:23AM +0100, Oleksij Rempel wrote:
> 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
Applied all mach-imx and DTS ones, thanks!