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>,
	kernel@pengutronix.de, Fabio Estevam <festevam@gmail.com>,
	NXP Linux Team <linux-imx@nxp.com>, Lee Jones <lee@kernel.org>,
	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 v1 01/20] clk: imx: add clk-gpr-mux driver
Date: Fri, 13 Jan 2023 15:26:59 +0100	[thread overview]
Message-ID: <20230113142718.3038265-2-o.rempel@pengutronix.de> (raw)
In-Reply-To: <20230113142718.3038265-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>
---
 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


  reply	other threads:[~2023-01-13 14:33 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-13 14:26 [PATCH v1 00/20] ARM: imx: make Ethernet refclock configurable Oleksij Rempel
2023-01-13 14:26 ` Oleksij Rempel [this message]
2023-01-13 14:27 ` [PATCH v1 02/20] clk: imx6q: add ethernet refclock mux support Oleksij Rempel
2023-01-13 22:56   ` kernel test robot
2023-01-15  6:25   ` kernel test robot
2023-01-13 14:27 ` [PATCH v1 03/20] ARM: imx6q: skip ethernet refclock reconfiguration if enet_clk_ref is present Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 04/20] ARM: imx6q: use of_clk_get_by_name() instead of_clk_get() to get ptp clock Oleksij Rempel
2023-01-14  0:15   ` Stephen Boyd
2023-01-13 14:27 ` [PATCH v1 05/20] ARM: dts: imx6qdl: use enet_clk_ref instead of enet_out for the FEC node Oleksij Rempel
2023-01-16  1:01   ` Peng Fan
2023-01-16  5:26     ` Oleksij Rempel
2023-01-17  1:45       ` Peng Fan
2023-01-13 14:27 ` [PATCH v1 06/20] ARM: dts: imx6dl-lanmcu: configure ethernet reference clock parent Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 07/20] ARM: dts: imx6dl-alti6p: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 08/20] ARM: dts: imx6dl-plybas: " Oleksij Rempel
2023-01-14 11:39   ` Fabio Estevam
2023-01-13 14:27 ` [PATCH v1 09/20] ARM: dts: imx6dl-plym2m: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 10/20] ARM: dts: imx6dl-prtmvt: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 11/20] ARM: dts: imx6dl-victgo: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 12/20] ARM: dts: imx6q-prtwd2: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 13/20] ARM: dts: imx6qdl-skov-cpu: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 14/20] ARM: dts: imx6dl-eckelmann-ci4x10: " Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 15/20] clk: imx: add imx_obtain_fixed_of_clock() Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 16/20] clk: imx6ul: fix enet1 gate configuration Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 17/20] clk: imx6ul: add ethernet refclock mux support Oleksij Rempel
2023-01-13 14:48   ` Lee Jones
2023-01-14  1:07   ` kernel test robot
2023-01-15  8:46   ` kernel test robot
2023-01-13 14:27 ` [PATCH v1 18/20] ARM: dts: imx6ul: set enet_clk_ref to CLK_ENETx_REF_SEL Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 19/20] ARM: mach-imx: imx6ul: remove not optional ethernet refclock overwrite Oleksij Rempel
2023-01-13 14:27 ` [PATCH v1 20/20] ARM: dts: imx6ul-prti6g: configure ethernet reference clock parent Oleksij Rempel

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=20230113142718.3038265-2-o.rempel@pengutronix.de \
    --to=o.rempel@pengutronix.de \
    --cc=abelvesa@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=festevam@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=lee@kernel.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).