mbox series

[v2,00/19] ARM: imx: make Ethernet refclock configurable

Message ID 20230117061453.3723649-1-o.rempel@pengutronix.de
Headers show
Series ARM: imx: make Ethernet refclock configurable | expand

Message

Oleksij Rempel Jan. 17, 2023, 6:14 a.m. UTC
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 <lee@kernel.org>"
- reword some commits as suggested by Fabio

Most of i.MX SoC variants have configurable FEC/Ethernet reference clock
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 topology
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

Comments

Abel Vesa Jan. 29, 2023, 5:33 p.m. UTC | #1
On 23-01-17 07:14:48, Oleksij Rempel wrote:
> Add imx_obtain_fixed_of_clock() to optionally add clock not configured in
> the devicetree.
> 
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>

Reviewed-by: Abel Vesa <abel.vesa@linaro.org>

> ---
>  drivers/clk/imx/clk.c | 14 ++++++++++++++
>  drivers/clk/imx/clk.h |  3 +++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
> index b636cc099d96..5f1f729008ee 100644
> --- a/drivers/clk/imx/clk.c
> +++ b/drivers/clk/imx/clk.c
> @@ -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;
> diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
> index 801213109697..f0a24cd54d1c 100644
> --- a/drivers/clk/imx/clk.h
> +++ b/drivers/clk/imx/clk.h
> @@ -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,
> -- 
> 2.30.2
>
Abel Vesa Jan. 29, 2023, 5:36 p.m. UTC | #2
On 23-01-17 07:14:35, Oleksij Rempel wrote:
> Almost(?) every i'MX variant has clk mux for ethernet (rgmii/rmii) reference

i.MX

> 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 <o.rempel@pengutronix.de>

Reviewed-by: Abel Vesa <abel.vesa@linaro.org>

> ---
>  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 689b3ad927c0..801213109697 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
>
Abel Vesa Jan. 30, 2023, 10:11 p.m. UTC | #3
On 23-01-17 07:14:34, Oleksij Rempel wrote:
> 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 <lee@kernel.org>"
> - reword some commits as suggested by Fabio


Unfortunatley it doesn't apply on my tree. Can you please rebase and resend?

Thanks.

> 
> Most of i.MX SoC variants have configurable FEC/Ethernet reference clock
> 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 topology
> 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
>