devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Oleksij Rempel <o.rempel@pengutronix.de>
To: Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Shawn Guo <shawnguo@kernel.org>,
	Sascha Hauer <s.hauer@pengutronix.de>,
	Abel Vesa <abelvesa@kernel.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Richard Cochran <richardcochran@gmail.com>
Cc: Oleksij Rempel <o.rempel@pengutronix.de>,
	Abel Vesa <abel.vesa@linaro.org>,
	kernel@pengutronix.de, Fabio Estevam <festevam@gmail.com>,
	NXP Linux Team <linux-imx@nxp.com>,
	Russell King <linux@armlinux.org.uk>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-clk@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH v3 01/19] clk: imx: add clk-gpr-mux driver
Date: Tue, 31 Jan 2023 09:46:24 +0100	[thread overview]
Message-ID: <20230131084642.709385-2-o.rempel@pengutronix.de> (raw)
In-Reply-To: <20230131084642.709385-1-o.rempel@pengutronix.de>

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 <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 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


  reply	other threads:[~2023-01-31  8:51 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-31  8:46 [PATCH v3 00/19] ARM: imx: make Ethernet refclock configurable Oleksij Rempel
2023-01-31  8:46 ` Oleksij Rempel [this message]
2023-01-31  8:46 ` [PATCH v3 02/19] clk: imx6q: add ethernet refclock mux support Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 03/19] ARM: imx6q: skip ethernet refclock reconfiguration if enet_clk_ref is present Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 04/19] ARM: dts: imx6qdl: use enet_clk_ref instead of enet_out for the FEC node Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 05/19] ARM: dts: imx6dl-lanmcu: configure ethernet reference clock parent Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 06/19] ARM: dts: imx6dl-alti6p: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 07/19] ARM: dts: imx6dl-plybas: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 08/19] ARM: dts: imx6dl-plym2m: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 09/19] ARM: dts: imx6dl-prtmvt: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 10/19] ARM: dts: imx6dl-victgo: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 11/19] ARM: dts: imx6q-prtwd2: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 12/19] ARM: dts: imx6qdl-skov-cpu: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 13/19] ARM: dts: imx6dl-eckelmann-ci4x10: " Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 14/19] clk: imx: add imx_obtain_fixed_of_clock() Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 15/19] clk: imx6ul: fix enet1 gate configuration Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 16/19] clk: imx6ul: add ethernet refclock mux support Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 17/19] ARM: dts: imx6ul: set enet_clk_ref to CLK_ENETx_REF_SEL Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 18/19] ARM: mach-imx: imx6ul: remove not optional ethernet refclock overwrite Oleksij Rempel
2023-01-31  8:46 ` [PATCH v3 19/19] ARM: dts: imx6ul-prti6g: configure ethernet reference clock parent Oleksij Rempel
2023-01-31 12:51 ` [PATCH v3 00/19] ARM: imx: make Ethernet refclock configurable Abel Vesa
2023-03-06  2:02 ` Shawn Guo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230131084642.709385-2-o.rempel@pengutronix.de \
    --to=o.rempel@pengutronix.de \
    --cc=abel.vesa@linaro.org \
    --cc=abelvesa@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=festevam@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=mturquette@baylibre.com \
    --cc=netdev@vger.kernel.org \
    --cc=richardcochran@gmail.com \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=sboyd@kernel.org \
    --cc=shawnguo@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).