Linux-Clk Archive on lore.kernel.org
 help / Atom feed
* [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc
@ 2019-01-08  9:00 Jacky Bai
  2019-01-08  9:00 ` [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm Jacky Bai
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Jacky Bai @ 2019-01-08  9:00 UTC (permalink / raw)
  To: sboyd, mturquette, robh+dt, shawnguo
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

New PLLs are introduced on i.MX8M Mini SOC.
PLL1416X is Integer PLL, PLL1443X is a Frac PLL.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
 drivers/clk/imx/Makefile      |   3 +-
 drivers/clk/imx/clk-pll14xx.c | 409 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk.h         |  23 +++
 3 files changed, 434 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-pll14xx.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 73119fb..ff74287 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -18,7 +18,8 @@ obj-$(CONFIG_MXC_CLK) += \
 	clk-pllv2.o \
 	clk-pllv3.o \
 	clk-pllv4.o \
-	clk-sccg-pll.o
+	clk-sccg-pll.o \
+	clk-pll14xx.o
 
 obj-$(CONFIG_MXC_CLK_SCU) += \
 	clk-scu.o \
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
new file mode 100644
index 0000000..c9f83fd
--- /dev/null
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017-2018 NXP.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+
+#include "clk.h"
+
+#define GNRL_CTL	0x0
+#define DIV_CTL		0x4
+#define LOCK_STATUS	BIT(31)
+#define LOCK_SEL_MASK	BIT(29)
+#define CLKE_MASK	BIT(11)
+#define RST_MASK	BIT(9)
+#define BYPASS_MASK	BIT(4)
+#define MDIV_SHIFT	12
+#define MDIV_MASK	GENMASK(21, 12)
+#define PDIV_SHIFT	4
+#define PDIV_MASK	GENMASK(9, 4)
+#define SDIV_SHIFT	0
+#define SDIV_MASK	GENMASK(2, 0)
+#define KDIV_SHIFT	0
+#define KDIV_MASK	GENMASK(15, 0)
+
+struct clk_pll14xx {
+	struct clk_hw			hw;
+	void __iomem			*base;
+	enum imx_pll14xx_type		type;
+	struct imx_pll14xx_rate_table	*rate_table;
+	int rate_count;
+};
+
+#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
+
+static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
+		struct clk_pll14xx *pll, unsigned long rate)
+{
+	const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+	}
+
+	return NULL;
+}
+
+static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long *prate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
+	int i;
+
+	/* Assumming rate_table is in descending order */
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate >= rate_table[i].rate)
+			return rate_table[i].rate;
+	}
+	/* return minimum supported value */
+	return rate_table[i - 1].rate;
+}
+
+static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div;
+	u64 fvco = parent_rate;
+
+	pll_gnrl = readl_relaxed(pll->base);
+	pll_div = readl_relaxed(pll->base + 4);
+	mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+	pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
+	sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
+
+	fvco *= mdiv;
+	do_div(fvco, pdiv << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1;
+	short int kdiv;
+	u64 fvco = parent_rate;
+
+	pll_gnrl = readl_relaxed(pll->base);
+	pll_div_ctl0 = readl_relaxed(pll->base + 4);
+	pll_div_ctl1 = readl_relaxed(pll->base + 8);
+	mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+	pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+	sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
+	kdiv = pll_div_ctl1 & KDIV_MASK;
+
+	/* fvco = (m * 65536 + k) * Fin / (p * 65536) */
+	fvco *= (mdiv * 65536 + kdiv);
+	pdiv *= 65536;
+
+	do_div(fvco, pdiv << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
+					  u32 pll_div)
+{
+	u32 old_mdiv, old_pdiv;
+
+	old_mdiv = (pll_div >> MDIV_SHIFT) & MDIV_MASK;
+	old_pdiv = (pll_div >> PDIV_SHIFT) & PDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
+}
+
+static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
+					  u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+	u32 old_mdiv, old_pdiv, old_kdiv;
+
+	old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
+	old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
+	old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+		rate->kdiv != old_kdiv);
+}
+
+static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
+					  u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+	u32 old_mdiv, old_pdiv, old_kdiv;
+
+	old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
+	old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
+	old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+		rate->kdiv != old_kdiv);
+}
+
+static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	/* Wait for PLL to lock */
+	do {
+		if (readl_relaxed(pll->base) & LOCK_STATUS)
+			break;
+		if (time_after(jiffies, timeout))
+			break;
+	} while (1);
+
+	return readl_relaxed(pll->base) & LOCK_STATUS ? 0 : -ETIMEDOUT;
+}
+
+static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate,
+				 unsigned long prate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	const struct imx_pll14xx_rate_table *rate;
+	u32 tmp, div_val;
+	int ret;
+
+	rate = imx_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+		       drate, clk_hw_get_name(hw));
+		return -EINVAL;
+	}
+
+	tmp = readl_relaxed(pll->base + 4);
+
+	if (!clk_pll1416x_mp_change(rate, tmp)) {
+		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+		tmp |= rate->sdiv << SDIV_SHIFT;
+		writel_relaxed(tmp, pll->base + 4);
+
+		return 0;
+	}
+
+	/* Bypass clock and set lock to pll output lock */
+	tmp = readl_relaxed(pll->base);
+	tmp |= LOCK_SEL_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	/* Enable RST */
+	tmp &= ~RST_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+		(rate->sdiv << SDIV_SHIFT);
+	writel_relaxed(div_val, pll->base + 0x4);
+
+	/*
+	 * According to SPEC, t3 - t2 need to be greater than
+	 * 1us and 1/FREF, respectively.
+	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+	 * 3us.
+	 */
+	udelay(3);
+
+	/* Disable RST */
+	tmp |= RST_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	/* Wait Lock */
+	ret = clk_pll14xx_wait_lock(pll);
+	if (ret)
+		return ret;
+
+	/* Bypass */
+	tmp &= ~BYPASS_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	return 0;
+}
+
+static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
+				 unsigned long prate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	const struct imx_pll14xx_rate_table *rate;
+	u32 tmp, div_val;
+	int ret;
+
+	rate = imx_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, clk_hw_get_name(hw));
+		return -EINVAL;
+	}
+
+	tmp = readl_relaxed(pll->base + 4);
+	div_val = readl_relaxed(pll->base + 8);
+
+	if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
+		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+		tmp |= rate->sdiv << SDIV_SHIFT;
+		writel_relaxed(tmp, pll->base + 4);
+
+		return 0;
+	}
+
+	/* Enable RST */
+	tmp = readl_relaxed(pll->base);
+	tmp &= ~RST_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+		(rate->sdiv << SDIV_SHIFT);
+	writel_relaxed(div_val, pll->base + 0x4);
+	writel_relaxed(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
+
+	/*
+	 * According to SPEC, t3 - t2 need to be greater than
+	 * 1us and 1/FREF, respectively.
+	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+	 * 3us.
+	 */
+	udelay(3);
+
+	/* Disable RST */
+	tmp |= RST_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	/* Wait Lock*/
+	ret = clk_pll14xx_wait_lock(pll);
+	if (ret)
+		return ret;
+
+	/* Bypass */
+	tmp &= ~BYPASS_MASK;
+	writel_relaxed(tmp, pll->base);
+
+	return 0;
+}
+
+static int clk_pll14xx_prepare(struct clk_hw *hw)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	u32 val;
+
+	/*
+	 * RESETB = 1 from 0, PLL starts its normal
+	 * operation after lock time
+	 */
+	val = readl_relaxed(pll->base + GNRL_CTL);
+	val |= RST_MASK;
+	writel_relaxed(val, pll->base + GNRL_CTL);
+
+	return clk_pll14xx_wait_lock(pll);
+}
+
+static int clk_pll14xx_is_prepared(struct clk_hw *hw)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	u32 val;
+
+	val = readl_relaxed(pll->base + GNRL_CTL);
+
+	return (val & RST_MASK) ? 1 : 0;
+}
+
+static void clk_pll14xx_unprepare(struct clk_hw *hw)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+	u32 val;
+
+	/*
+	 * Set RST to 0, power down mode is enabled and
+	 * every digital block is reset
+	 */
+	val = readl_relaxed(pll->base + GNRL_CTL);
+	val &= ~RST_MASK;
+	writel_relaxed(val, pll->base + GNRL_CTL);
+}
+
+static const struct clk_ops clk_pll1416x_ops = {
+	.prepare	= clk_pll14xx_prepare,
+	.unprepare	= clk_pll14xx_unprepare,
+	.is_prepared	= clk_pll14xx_is_prepared,
+	.recalc_rate	= clk_pll1416x_recalc_rate,
+	.round_rate	= clk_pll14xx_round_rate,
+	.set_rate	= clk_pll1416x_set_rate,
+};
+
+static const struct clk_ops clk_pll1416x_min_ops = {
+	.recalc_rate	= clk_pll1416x_recalc_rate,
+};
+
+static const struct clk_ops clk_pll1443x_ops = {
+	.prepare	= clk_pll14xx_prepare,
+	.unprepare	= clk_pll14xx_unprepare,
+	.is_prepared	= clk_pll14xx_is_prepared,
+	.recalc_rate	= clk_pll1443x_recalc_rate,
+	.round_rate	= clk_pll14xx_round_rate,
+	.set_rate	= clk_pll1443x_set_rate,
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+			    void __iomem *base,
+			    const struct imx_pll14xx_clk *pll_clk)
+{
+	struct clk_pll14xx *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+	int len;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = pll_clk->flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	if (pll_clk->rate_table) {
+		for (len = 0; pll_clk->rate_table[len].rate != 0; )
+			len++;
+
+		pll->rate_count = len;
+		pll->rate_table = kmemdup(pll_clk->rate_table,
+					  pll->rate_count *
+					  sizeof(struct imx_pll14xx_rate_table),
+					  GFP_KERNEL);
+		WARN(!pll->rate_table, "%s : could not alloc rate table\n", __func__);
+	}
+
+	switch (pll_clk->type) {
+	case PLL_1416X:
+		if (!pll->rate_table)
+			init.ops = &clk_pll1416x_min_ops;
+		else
+			init.ops = &clk_pll1416x_ops;
+		break;
+	case PLL_1443X:
+		init.ops = &clk_pll1443x_ops;
+		break;
+	default:
+		pr_err("%s: Unknown pll type for pll clk %s\n",
+		       __func__, name);
+	};
+
+	pll->base = base;
+	pll->hw.init = &init;
+	pll->type = pll_clk->type;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll %s %lu\n",
+			__func__, name, PTR_ERR(clk));
+		kfree(pll);
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 028312d..27372f7 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -27,6 +27,29 @@ enum imx_sccg_pll_type {
 	SCCG_PLL2,
 };
 
+enum imx_pll14xx_type {
+	PLL_1416X,
+	PLL_1443X,
+};
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+struct imx_pll14xx_rate_table {
+	unsigned int rate;
+	unsigned int pdiv;
+	unsigned int mdiv;
+	unsigned int sdiv;
+	unsigned int kdiv;
+};
+
+struct imx_pll14xx_clk {
+	enum imx_pll14xx_type type;
+	const struct imx_pll14xx_rate_table *rate_table;
+	int flags;
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+		 void __iomem *base, const struct imx_pll14xx_clk *pll_clk);
+
 struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
 		const char *parent, void __iomem *base);
 
-- 
1.9.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm
  2019-01-08  9:00 [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Jacky Bai
@ 2019-01-08  9:00 ` Jacky Bai
  2019-01-09 20:36   ` Stephen Boyd
  2019-01-21 20:33   ` Rob Herring
  2019-01-08  9:01 ` [PATCH 3/3] clk: imx: Add clock driver support " Jacky Bai
  2019-01-09 20:35 ` [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Stephen Boyd
  2 siblings, 2 replies; 10+ messages in thread
From: Jacky Bai @ 2019-01-08  9:00 UTC (permalink / raw)
  To: sboyd, mturquette, robh+dt, shawnguo
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

Add the clock binding doc for i.MX8MM.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
 .../devicetree/bindings/clock/imx8mm-clock.txt     |  19 ++
 include/dt-bindings/clock/imx8mm-clock.h           | 244 +++++++++++++++++++++
 2 files changed, 263 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mm-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mm-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
new file mode 100644
index 0000000..034b6d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
@@ -0,0 +1,19 @@
+* Clock bindings for NXP i.MX8M Mini
+
+Required properties:
+- compatible: Should be "fsl,imx8mm-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+          entry in clock-names
+- clock-names: should include the following entries:
+    - "osc_32k"
+    - "osc_24m"
+    - "clk_ext1"
+    - "clk_ext2"
+    - "clk_ext3"
+    - "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h
+for the full list of i.MX8M Mini clock IDs.
diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h
new file mode 100644
index 0000000..0301581
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mm-clock.h
@@ -0,0 +1,244 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2017-2018 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MM_H
+#define __DT_BINDINGS_CLOCK_IMX8MM_H
+
+#define	IMX8MM_CLK_DUMMY			0
+#define	IMX8MM_CLK_32K				1
+#define	IMX8MM_CLK_24M				2
+#define	IMX8MM_OSC_HDMI_CLK			3
+#define	IMX8MM_CLK_EXT1				4
+#define	IMX8MM_CLK_EXT2				5
+#define	IMX8MM_CLK_EXT3				6
+#define	IMX8MM_CLK_EXT4				7
+#define	IMX8MM_AUDIO_PLL1_REF_SEL		8
+#define	IMX8MM_AUDIO_PLL2_REF_SEL		9
+#define	IMX8MM_VIDEO_PLL1_REF_SEL		10
+#define	IMX8MM_DRAM_PLL_REF_SEL			11
+#define	IMX8MM_GPU_PLL_REF_SEL			12
+#define	IMX8MM_VPU_PLL_REF_SEL			13
+#define	IMX8MM_ARM_PLL_REF_SEL			14
+#define	IMX8MM_SYS_PLL1_REF_SEL			15
+#define	IMX8MM_SYS_PLL2_REF_SEL			16
+#define	IMX8MM_SYS_PLL3_REF_SEL			17
+#define	IMX8MM_AUDIO_PLL1			18
+#define	IMX8MM_AUDIO_PLL2			19
+#define	IMX8MM_VIDEO_PLL1			20
+#define	IMX8MM_DRAM_PLL				21
+#define	IMX8MM_GPU_PLL				22
+#define	IMX8MM_VPU_PLL				23
+#define	IMX8MM_ARM_PLL				24
+#define	IMX8MM_SYS_PLL1				25
+#define	IMX8MM_SYS_PLL2				26
+#define	IMX8MM_SYS_PLL3				27
+#define	IMX8MM_AUDIO_PLL1_BYPASS		28
+#define	IMX8MM_AUDIO_PLL2_BYPASS		29
+#define	IMX8MM_VIDEO_PLL1_BYPASS		30
+#define	IMX8MM_DRAM_PLL_BYPASS			31
+#define	IMX8MM_GPU_PLL_BYPASS			32
+#define	IMX8MM_VPU_PLL_BYPASS			33
+#define	IMX8MM_ARM_PLL_BYPASS			34
+#define	IMX8MM_SYS_PLL1_BYPASS			35
+#define	IMX8MM_SYS_PLL2_BYPASS			36
+#define	IMX8MM_SYS_PLL3_BYPASS			37
+#define	IMX8MM_AUDIO_PLL1_OUT			38
+#define	IMX8MM_AUDIO_PLL2_OUT			39
+#define	IMX8MM_VIDEO_PLL1_OUT			40
+#define	IMX8MM_DRAM_PLL_OUT			41
+#define	IMX8MM_GPU_PLL_OUT			42
+#define	IMX8MM_VPU_PLL_OUT			43
+#define	IMX8MM_ARM_PLL_OUT			44
+#define	IMX8MM_SYS_PLL1_OUT			45
+#define	IMX8MM_SYS_PLL2_OUT			46
+#define	IMX8MM_SYS_PLL3_OUT			47
+#define	IMX8MM_SYS_PLL1_40M			48
+#define	IMX8MM_SYS_PLL1_80M			49
+#define	IMX8MM_SYS_PLL1_100M			50
+#define	IMX8MM_SYS_PLL1_133M			51
+#define	IMX8MM_SYS_PLL1_160M			52
+#define	IMX8MM_SYS_PLL1_200M			53
+#define	IMX8MM_SYS_PLL1_266M			54
+#define	IMX8MM_SYS_PLL1_400M			55
+#define	IMX8MM_SYS_PLL1_800M			56
+#define	IMX8MM_SYS_PLL2_50M			57
+#define	IMX8MM_SYS_PLL2_100M			58
+#define	IMX8MM_SYS_PLL2_125M			59
+#define	IMX8MM_SYS_PLL2_166M			60
+#define	IMX8MM_SYS_PLL2_200M			61
+#define	IMX8MM_SYS_PLL2_250M			62
+#define	IMX8MM_SYS_PLL2_333M			63
+#define	IMX8MM_SYS_PLL2_500M			64
+#define	IMX8MM_SYS_PLL2_1000M			65
+
+/* core */
+#define	IMX8MM_CLK_A53_SRC			66
+#define	IMX8MM_CLK_M4_SRC			67
+#define	IMX8MM_CLK_VPU_SRC			68
+#define	IMX8MM_CLK_GPU3D_SRC			69
+#define	IMX8MM_CLK_GPU2D_SRC			70
+#define	IMX8MM_CLK_A53_CG			71
+#define	IMX8MM_CLK_M4_CG			72
+#define	IMX8MM_CLK_VPU_CG			73
+#define	IMX8MM_CLK_GPU3D_CG			74
+#define	IMX8MM_CLK_GPU2D_CG			75
+#define	IMX8MM_CLK_A53_DIV			76
+#define	IMX8MM_CLK_M4_DIV			77
+#define	IMX8MM_CLK_VPU_DIV			78
+#define	IMX8MM_CLK_GPU3D_DIV			79
+#define	IMX8MM_CLK_GPU2D_DIV			80
+
+/* bus */
+#define	IMX8MM_CLK_MAIN_AXI			81
+#define	IMX8MM_CLK_ENET_AXI			82
+#define	IMX8MM_CLK_NAND_USDHC_BUS		83
+#define	IMX8MM_CLK_VPU_BUS			84
+#define	IMX8MM_CLK_DISP_AXI			85
+#define	IMX8MM_CLK_DISP_APB			86
+#define	IMX8MM_CLK_DISP_RTRM			87
+#define	IMX8MM_CLK_USB_BUS			88
+#define	IMX8MM_CLK_GPU_AXI			89
+#define	IMX8MM_CLK_GPU_AHB			90
+#define	IMX8MM_CLK_NOC				91
+#define	IMX8MM_CLK_NOC_APB			92
+
+#define	IMX8MM_CLK_AHB				93
+#define	IMX8MM_CLK_AUDIO_AHB			94
+#define IMX8MM_CLK_IPG_ROOT			95
+#define IMX8MM_CLK_IPG_AUDIO_ROOT		96
+
+#define	IMX8MM_CLK_DRAM_ALT			97
+#define	IMX8MM_CLK_DRAM_APB			98
+#define	IMX8MM_CLK_VPU_G1			99
+#define	IMX8MM_CLK_VPU_G2			100
+#define	IMX8MM_CLK_DISP_DTRC			101
+#define	IMX8MM_CLK_DISP_DC8000			102
+#define	IMX8MM_CLK_PCIE1_CTRL			103
+#define	IMX8MM_CLK_PCIE1_PHY			104
+#define	IMX8MM_CLK_PCIE1_AUX			105
+#define	IMX8MM_CLK_DC_PIXEL			106
+#define	IMX8MM_CLK_LCDIF_PIXEL			107
+#define	IMX8MM_CLK_SAI1				108
+#define	IMX8MM_CLK_SAI2				109
+#define	IMX8MM_CLK_SAI3				110
+#define	IMX8MM_CLK_SAI4				111
+#define	IMX8MM_CLK_SAI5				112
+#define	IMX8MM_CLK_SAI6				113
+#define	IMX8MM_CLK_SPDIF1			114
+#define	IMX8MM_CLK_SPDIF2			115
+#define	IMX8MM_CLK_ENET_REF			116
+#define	IMX8MM_CLK_ENET_TIMER			117
+#define	IMX8MM_CLK_ENET_PHY_REF			118
+#define	IMX8MM_CLK_NAND				119
+#define	IMX8MM_CLK_QSPI				120
+#define	IMX8MM_CLK_USDHC1			121
+#define	IMX8MM_CLK_USDHC2			122
+#define	IMX8MM_CLK_I2C1				123
+#define	IMX8MM_CLK_I2C2				124
+#define	IMX8MM_CLK_I2C3				125
+#define	IMX8MM_CLK_I2C4				126
+#define	IMX8MM_CLK_UART1			127
+#define	IMX8MM_CLK_UART2			128
+#define	IMX8MM_CLK_UART3			129
+#define	IMX8MM_CLK_UART4			130
+#define	IMX8MM_CLK_USB_CORE_REF			131
+#define	IMX8MM_CLK_USB_PHY_REF			132
+#define	IMX8MM_CLK_ECSPI1			133
+#define	IMX8MM_CLK_ECSPI2			134
+#define	IMX8MM_CLK_PWM1				135
+#define	IMX8MM_CLK_PWM2				136
+#define	IMX8MM_CLK_PWM3				137
+#define	IMX8MM_CLK_PWM4				138
+#define	IMX8MM_CLK_GPT1				139
+#define	IMX8MM_CLK_WDOG				140
+#define	IMX8MM_CLK_WRCLK			141
+#define	IMX8MM_CLK_DSI_CORE			142
+#define	IMX8MM_CLK_DSI_PHY_REF			143
+#define	IMX8MM_CLK_DSI_DBI			144
+#define	IMX8MM_CLK_USDHC3			145
+#define	IMX8MM_CLK_CSI1_CORE			146
+#define	IMX8MM_CLK_CSI1_PHY_REF			147
+#define	IMX8MM_CLK_CSI1_ESC			148
+#define	IMX8MM_CLK_CSI2_CORE			149
+#define	IMX8MM_CLK_CSI2_PHY_REF			150
+#define	IMX8MM_CLK_CSI2_ESC			151
+#define	IMX8MM_CLK_PCIE2_CTRL			152
+#define	IMX8MM_CLK_PCIE2_PHY			153
+#define	IMX8MM_CLK_PCIE2_AUX			154
+#define	IMX8MM_CLK_ECSPI3			155
+#define	IMX8MM_CLK_PDM				156
+#define	IMX8MM_CLK_VPU_H1			157
+#define	IMX8MM_CLK_CLKO1			158
+
+#define	IMX8MM_CLK_ECSPI1_ROOT			159
+#define	IMX8MM_CLK_ECSPI2_ROOT			160
+#define	IMX8MM_CLK_ECSPI3_ROOT			161
+#define	IMX8MM_CLK_ENET1_ROOT			162
+#define	IMX8MM_CLK_GPT1_ROOT			163
+#define	IMX8MM_CLK_I2C1_ROOT			164
+#define	IMX8MM_CLK_I2C2_ROOT			165
+#define	IMX8MM_CLK_I2C3_ROOT			166
+#define	IMX8MM_CLK_I2C4_ROOT			167
+#define	IMX8MM_CLK_OCOTP_ROOT			168
+#define	IMX8MM_CLK_PCIE1_ROOT			169
+#define	IMX8MM_CLK_PWM1_ROOT			170
+#define	IMX8MM_CLK_PWM2_ROOT			171
+#define	IMX8MM_CLK_PWM3_ROOT			172
+#define	IMX8MM_CLK_PWM4_ROOT			173
+#define	IMX8MM_CLK_QSPI_ROOT			174
+#define	IMX8MM_CLK_NAND_ROOT			175
+#define	IMX8MM_CLK_SAI1_ROOT			176
+#define	IMX8MM_CLK_SAI1_IPG			177
+#define	IMX8MM_CLK_SAI2_ROOT			178
+#define	IMX8MM_CLK_SAI2_IPG			179
+#define	IMX8MM_CLK_SAI3_ROOT			180
+#define	IMX8MM_CLK_SAI3_IPG			181
+#define	IMX8MM_CLK_SAI4_ROOT			182
+#define	IMX8MM_CLK_SAI4_IPG			183
+#define	IMX8MM_CLK_SAI5_ROOT			184
+#define	IMX8MM_CLK_SAI5_IPG			185
+#define	IMX8MM_CLK_SAI6_ROOT			186
+#define	IMX8MM_CLK_SAI6_IPG			187
+#define	IMX8MM_CLK_UART1_ROOT			188
+#define	IMX8MM_CLK_UART2_ROOT			189
+#define	IMX8MM_CLK_UART3_ROOT			190
+#define	IMX8MM_CLK_UART4_ROOT			191
+#define	IMX8MM_CLK_USB1_CTRL_ROOT		192
+#define	IMX8MM_CLK_GPU3D_ROOT			193
+#define	IMX8MM_CLK_USDHC1_ROOT			194
+#define	IMX8MM_CLK_USDHC2_ROOT			195
+#define	IMX8MM_CLK_WDOG1_ROOT			196
+#define	IMX8MM_CLK_WDOG2_ROOT			197
+#define	IMX8MM_CLK_WDOG3_ROOT			198
+#define	IMX8MM_CLK_VPU_G1_ROOT			199
+#define	IMX8MM_CLK_GPU_BUS_ROOT			200
+#define	IMX8MM_CLK_VPU_H1_ROOT			201
+#define	IMX8MM_CLK_VPU_G2_ROOT			202
+#define	IMX8MM_CLK_PDM_ROOT			203
+#define	IMX8MM_CLK_DISP_ROOT			204
+#define	IMX8MM_CLK_DISP_AXI_ROOT		205
+#define	IMX8MM_CLK_DISP_APB_ROOT		206
+#define	IMX8MM_CLK_DISP_RTRM_ROOT		207
+#define	IMX8MM_CLK_USDHC3_ROOT			208
+#define	IMX8MM_CLK_TMU_ROOT			209
+#define	IMX8MM_CLK_VPU_DEC_ROOT			210
+#define	IMX8MM_CLK_SDMA1_ROOT			211
+#define	IMX8MM_CLK_SDMA2_ROOT			212
+#define	IMX8MM_CLK_SDMA3_ROOT			213
+#define	IMX8MM_CLK_GPT_3M			214
+#define	IMX8MM_CLK_ARM				215
+#define	IMX8MM_CLK_PDM_IPG			216
+#define	IMX8MM_CLK_GPU2D_ROOT			217
+#define	IMX8MM_CLK_MU_ROOT			218
+#define	IMX8MM_CLK_CSI1_ROOT			219
+
+#define IMX8MM_CLK_DRAM_CORE			220
+#define IMX8MM_CLK_DRAM_ALT_ROOT		221
+
+#define IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK	222
+
+#define	IMX8MM_CLK_END				223
+
+#endif
-- 
1.9.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/3] clk: imx: Add clock driver support for imx8mm
  2019-01-08  9:00 [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Jacky Bai
  2019-01-08  9:00 ` [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm Jacky Bai
@ 2019-01-08  9:01 ` " Jacky Bai
  2019-01-09 20:32   ` Stephen Boyd
  2019-01-09 20:35 ` [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Stephen Boyd
  2 siblings, 1 reply; 10+ messages in thread
From: Jacky Bai @ 2019-01-08  9:01 UTC (permalink / raw)
  To: sboyd, mturquette, robh+dt, shawnguo
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

Add clock driver support for i.MX8MM SOC.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
 drivers/clk/imx/Kconfig      |   6 +
 drivers/clk/imx/Makefile     |   1 +
 drivers/clk/imx/clk-imx8mm.c | 686 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 693 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mm.c

diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 4aae31a..0eaf418 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -8,6 +8,12 @@ config MXC_CLK_SCU
 	bool
 	depends on IMX_SCU
 
+config CLK_IMX8MM
+	bool "IMX8MM CCM Clock Driver"
+	depends on ARCH_MXC && ARM64
+	help
+	    Build the driver for i.MX8MM CCM Clock Driver
+
 config CLK_IMX8MQ
 	bool "IMX8MQ CCM Clock Driver"
 	depends on ARCH_MXC && ARM64
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index ff74287..0d5180f 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_MXC_CLK_SCU) += \
 	clk-scu.o \
 	clk-lpcg-scu.o
 
+obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
 
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
new file mode 100644
index 0000000..7cd9e86
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -0,0 +1,686 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017-2018 NXP.
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_pdm;
+static u32 share_count_nand;
+
+#define PLL_1416X_RATE(_rate, _m, _p, _s)		\
+	{						\
+		.rate	=	(_rate),		\
+		.mdiv	=	(_m),			\
+		.pdiv	=	(_p),			\
+		.sdiv	=	(_s),			\
+	}
+
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k)		\
+	{						\
+		.rate	=	(_rate),		\
+		.mdiv	=	(_m),			\
+		.pdiv	=	(_p),			\
+		.sdiv	=	(_s),			\
+		.kdiv	=	(_k),			\
+	}
+
+static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
+	PLL_1416X_RATE(1800000000U, 225, 3, 0),
+	PLL_1416X_RATE(1600000000U, 200, 3, 0),
+	PLL_1416X_RATE(1200000000U, 300, 3, 1),
+	PLL_1416X_RATE(1000000000U, 250, 3, 1),
+	PLL_1416X_RATE(800000000U,  200, 3, 1),
+	PLL_1416X_RATE(750000000U,  250, 2, 2),
+	PLL_1416X_RATE(700000000U,  350, 3, 2),
+	PLL_1416X_RATE(600000000U,  300, 3, 2),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_audiopll_tbl[] = {
+	PLL_1443X_RATE(786432000U, 655, 5, 2, 23593),
+	PLL_1443X_RATE(722534400U, 301, 5, 1, 3670),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_videopll_tbl[] = {
+	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+	PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
+	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+};
+
+static struct imx_pll14xx_clk imx8mm_audio_pll __initdata = {
+		.type = PLL_1443X,
+		.rate_table = imx8mm_audiopll_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mm_video_pll __initdata = {
+		.type = PLL_1443X,
+		.rate_table = imx8mm_videopll_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
+		.type = PLL_1443X,
+		.rate_table = imx8mm_drampll_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
+		.type = PLL_1416X,
+		.rate_table = imx8mm_pll1416x_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mm_gpu_pll __initdata = {
+		.type = PLL_1416X,
+		.rate_table = imx8mm_pll1416x_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mm_vpu_pll __initdata = {
+		.type = PLL_1416X,
+		.rate_table = imx8mm_pll1416x_tbl,
+};
+
+static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
+		.type = PLL_1416X,
+		.rate_table = imx8mm_pll1416x_tbl,
+};
+
+static const char *pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char *sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mm_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
+					"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_m4_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "sys_pll1_266m",
+				       "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_vpu_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
+					"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mm_gpu3d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out",
+					  "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_gpu2d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out",
+					  "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m", "sys_pll2_250m",
+					     "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "sys_pll1_100m",};
+
+static const char *imx8mm_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
+					     "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
+					       "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
+
+static const char *imx8mm_vpu_bus_sels[] = {"osc_24m", "sys_pll1_800m", "vpu_pll_out", "audio_pll2_out",
+					    "sys_pll3_out", "sys_pll2_1000m", "sys_pll2_200m", "sys_pll1_100m", };
+
+static const char *imx8mm_disp_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m", "sys_pll3_out",
+					     "sys_pll1_40m", "audio_pll2_out", "clk_ext1", "clk_ext4", };
+
+static const char *imx8mm_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m", "sys_pll3_out",
+					     "sys_pll1_40m", "audio_pll2_out", "clk_ext1", "clk_ext3", };
+
+static const char *imx8mm_disp_rtrm_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll2_200m", "sys_pll2_1000m",
+					      "audio_pll1_out", "video_pll1_out", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", "sys_pll2_100m",
+					    "sys_pll2_200m", "clk_ext2", "clk_ext4", "audio_pll2_out", };
+
+static const char *imx8mm_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", "sys_pll3_out", "sys_pll2_1000m",
+					    "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", "sys_pll3_out", "sys_pll2_1000m",
+					    "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out", "sys_pll2_1000m", "sys_pll2_500m",
+					"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_noc_apb_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll3_out", "sys_pll2_333m", "sys_pll2_200m",
+					    "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
+					"sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", "sys_pll2_1000m",
+					      "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m", "sys_pll2_500m",
+					     "sys_pll2_1000m", "sys_pll3_out", "audio_pll1_out", "sys_pll1_266m", };
+
+static const char *imx8mm_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+					     "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_vpu_g1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
+					   "sys_pll1_100m", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
+
+static const char *imx8mm_vpu_g2_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
+					   "sys_pll1_100m", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
+
+static const char *imx8mm_disp_dtrc_sels[] = {"osc_24m", "video_pll2_out", "sys_pll1_800m", "sys_pll2_1000m",
+					      "sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
+
+static const char *imx8mm_disp_dc8000_sels[] = {"osc_24m", "video_pll2_out", "sys_pll1_800m", "sys_pll2_1000m",
+						"sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
+
+static const char *imx8mm_pcie1_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m", "sys_pll1_266m",
+					       "sys_pll1_800m", "sys_pll2_500m", "sys_pll2_333m", "sys_pll3_out", };
+
+static const char *imx8mm_pcie1_phy_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll2_500m", "clk_ext1", "clk_ext2",
+					      "clk_ext3", "clk_ext4", "sys_pll1_400m", };
+
+static const char *imx8mm_pcie1_aux_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m", "sys_pll3_out",
+					      "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_160m", "sys_pll1_200m", };
+
+static const char *imx8mm_dc_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out",
+					     "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
+
+static const char *imx8mm_lcdif_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out",
+						"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
+
+static const char *imx8mm_sai1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					 "sys_pll1_133m", "osc_hdmi", "clk_ext1", "clk_ext2", };
+
+static const char *imx8mm_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					 "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					 "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
+
+static const char *imx8mm_sai4_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					 "sys_pll1_133m", "osc_hdmi", "clk_ext1", "clk_ext2", };
+
+static const char *imx8mm_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					 "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					 "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
+
+static const char *imx8mm_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					   "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_spdif2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+					   "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
+
+static const char *imx8mm_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m", "sys_pll2_100m",
+					     "sys_pll1_160m", "audio_pll1_out", "video_pll1_out", "clk_ext4", };
+
+static const char *imx8mm_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", "clk_ext1", "clk_ext2",
+					       "clk_ext3", "clk_ext4", "video_pll1_out", };
+
+static const char *imx8mm_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m", "sys_pll2_200m",
+					     "sys_pll2_500m", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", "sys_pll1_400m",
+					 "audio_pll2_out", "sys_pll3_out", "sys_pll2_250m", "video_pll1_out", };
+
+static const char *imx8mm_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					 "audio_pll2_out", "sys_pll1_266m", "sys_pll3_out", "sys_pll1_100m", };
+
+static const char *imx8mm_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+					  "sys_pll3_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
+
+static const char *imx8mm_uart2_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+					  "sys_pll3_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_uart3_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+					  "sys_pll3_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
+
+static const char *imx8mm_uart4_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+					  "sys_pll3_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_usb_core_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", "sys_pll2_100m",
+					     "sys_pll2_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", "sys_pll2_100m",
+					     "sys_pll2_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+					   "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+					   "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+					 "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+					 "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+					 "sys3_pll2_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+					 "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", "sys_pll1_40m",
+					 "video_pll1_out", "sys_pll1_800m", "audio_pll1_out", "clk_ext1" };
+
+static const char *imx8mm_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
+					 "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
+
+static const char *imx8mm_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out", "sys_pll3_out", "sys_pll2_200m",
+					  "sys_pll1_266m", "sys_pll2_500m", "sys_pll1_100m", };
+
+static const char *imx8mm_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
+					     "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m", "sys_pll1_800m",
+					    "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m", "sys_pll1_800m",
+					    "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
+
+static const char *imx8mm_csi1_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
+					      "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", "sys_pll1_800m",
+					     "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi1_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_800m",
+					     "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_csi2_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
+					      "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", "sys_pll1_800m",
+					     "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_800m",
+					     "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_pcie2_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m", "sys_pll1_266m",
+					       "sys_pll1_800m", "sys_pll2_500m", "sys_pll2_333m", "sys_pll3_out", };
+
+static const char *imx8mm_pcie2_phy_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll2_500m", "clk_ext1",
+					      "clk_ext2", "clk_ext3", "clk_ext4", "sys_pll1_400m", };
+
+static const char *imx8mm_pcie2_aux_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m", "sys_pll3_out",
+					      "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_160m", "sys_pll1_200m", };
+
+static const char *imx8mm_ecspi3_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+					   "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", "sys_pll1_800m",
+					"sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_vpu_h1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
+					   "audio_pll2_clk", "sys_pll2_125m", "sys_pll3_clk", "audio_pll1_out", };
+
+static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+
+static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", "sys_pll1_200m", "audio_pll2_clk",
+					 "vpu_pll", "sys_pll1_80m", };
+
+static struct clk *clks[IMX8MM_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static struct clk ** const uart_clks[] __initconst = {
+	&clks[IMX8MM_CLK_UART1_ROOT],
+	&clks[IMX8MM_CLK_UART2_ROOT],
+	&clks[IMX8MM_CLK_UART3_ROOT],
+	&clks[IMX8MM_CLK_UART4_ROOT],
+	NULL
+};
+
+static int imx8mm_clocks_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	void __iomem *base;
+	int ret = 0;
+
+	clks[IMX8MM_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+	clks[IMX8MM_CLK_24M] = of_clk_get_by_name(np, "osc_24m");
+	clks[IMX8MM_CLK_32K] = of_clk_get_by_name(np, "osc_32k"); /* Check more */
+	clks[IMX8MM_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1");
+	clks[IMX8MM_CLK_EXT2] = of_clk_get_by_name(np, "clk_ext2");
+	clks[IMX8MM_CLK_EXT3] = of_clk_get_by_name(np, "clk_ext3");
+	clks[IMX8MM_CLK_EXT4] = of_clk_get_by_name(np, "clk_ext4");
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
+	base = of_iomap(np, 0);
+	if (WARN_ON(!base))
+		return -ENOMEM;
+
+	clks[IMX8MM_AUDIO_PLL1_REF_SEL] = imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_AUDIO_PLL2_REF_SEL] = imx_clk_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_VIDEO_PLL1_REF_SEL] = imx_clk_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_DRAM_PLL_REF_SEL] = imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_GPU_PLL_REF_SEL] = imx_clk_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_VPU_PLL_REF_SEL] = imx_clk_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_ARM_PLL_REF_SEL] = imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_SYS_PLL1_REF_SEL] = imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_SYS_PLL2_REF_SEL] = imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	clks[IMX8MM_SYS_PLL3_REF_SEL] = imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+	clks[IMX8MM_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx8mm_audio_pll);
+	clks[IMX8MM_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx8mm_audio_pll);
+	clks[IMX8MM_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx8mm_video_pll);
+	clks[IMX8MM_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx8mm_dram_pll);
+	clks[IMX8MM_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx8mm_gpu_pll);
+	clks[IMX8MM_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx8mm_vpu_pll);
+	clks[IMX8MM_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx8mm_arm_pll);
+	clks[IMX8MM_SYS_PLL1] = imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx8mm_sys_pll);
+	clks[IMX8MM_SYS_PLL2] = imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx8mm_sys_pll);
+	clks[IMX8MM_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mm_sys_pll);
+
+	/* PLL bypass out */
+	clks[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+	clks[IMX8MM_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+
+	/* unbypass all the plls */
+	clk_set_parent(clks[IMX8MM_AUDIO_PLL1_BYPASS], clks[IMX8MM_AUDIO_PLL1]);
+	clk_set_parent(clks[IMX8MM_AUDIO_PLL2_BYPASS], clks[IMX8MM_AUDIO_PLL2]);
+	clk_set_parent(clks[IMX8MM_VIDEO_PLL1_BYPASS], clks[IMX8MM_VIDEO_PLL1]);
+	clk_set_parent(clks[IMX8MM_DRAM_PLL_BYPASS], clks[IMX8MM_DRAM_PLL]);
+	clk_set_parent(clks[IMX8MM_GPU_PLL_BYPASS], clks[IMX8MM_GPU_PLL]);
+	clk_set_parent(clks[IMX8MM_VPU_PLL_BYPASS], clks[IMX8MM_VPU_PLL]);
+	clk_set_parent(clks[IMX8MM_ARM_PLL_BYPASS], clks[IMX8MM_ARM_PLL]);
+	clk_set_parent(clks[IMX8MM_SYS_PLL1_BYPASS], clks[IMX8MM_SYS_PLL1]);
+	clk_set_parent(clks[IMX8MM_SYS_PLL2_BYPASS], clks[IMX8MM_SYS_PLL2]);
+	clk_set_parent(clks[IMX8MM_SYS_PLL3_BYPASS], clks[IMX8MM_SYS_PLL3]);
+
+	/* PLL out gate */
+	clks[IMX8MM_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
+	clks[IMX8MM_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
+	clks[IMX8MM_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
+	clks[IMX8MM_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
+	clks[IMX8MM_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 13);
+	clks[IMX8MM_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 13);
+	clks[IMX8MM_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 13);
+	clks[IMX8MM_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 13);
+	clks[IMX8MM_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 13);
+	clks[IMX8MM_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 13);
+
+	/* SYS PLL fixed output */
+	clks[IMX8MM_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+	clks[IMX8MM_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+	clks[IMX8MM_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+	clks[IMX8MM_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+	clks[IMX8MM_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+	clks[IMX8MM_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+	clks[IMX8MM_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+	clks[IMX8MM_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+	clks[IMX8MM_SYS_PLL1_800M] = imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+	clks[IMX8MM_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+	clks[IMX8MM_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+	clks[IMX8MM_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+	clks[IMX8MM_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+	clks[IMX8MM_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+	clks[IMX8MM_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+	clks[IMX8MM_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+	clks[IMX8MM_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+	clks[IMX8MM_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+	np = dev->of_node;
+	base = of_iomap(np, 0);
+	if (WARN_ON(!base))
+		return -ENOMEM;
+
+	/* Core Slice */
+	clks[IMX8MM_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels));
+	clks[IMX8MM_CLK_M4_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, imx8mm_m4_sels, ARRAY_SIZE(imx8mm_m4_sels));
+	clks[IMX8MM_CLK_VPU_SRC] = imx_clk_mux2("vpu_src", base + 0x8100, 24, 3, imx8mm_vpu_sels, ARRAY_SIZE(imx8mm_vpu_sels));
+	clks[IMX8MM_CLK_GPU3D_SRC] = imx_clk_mux2("gpu3d_src", base + 0x8180, 24, 3,  imx8mm_gpu3d_sels, ARRAY_SIZE(imx8mm_gpu3d_sels));
+	clks[IMX8MM_CLK_GPU2D_SRC] = imx_clk_mux2("gpu2d_src", base + 0x8200, 24, 3, imx8mm_gpu2d_sels,  ARRAY_SIZE(imx8mm_gpu2d_sels));
+	clks[IMX8MM_CLK_A53_CG] = imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28);
+	clks[IMX8MM_CLK_M4_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
+	clks[IMX8MM_CLK_VPU_CG] = imx_clk_gate3("vpu_cg", "vpu_src", base + 0x8100, 28);
+	clks[IMX8MM_CLK_GPU3D_CG] = imx_clk_gate3("gpu3d_cg", "gpu3d_src", base + 0x8180, 28);
+	clks[IMX8MM_CLK_GPU2D_CG] = imx_clk_gate3("gpu2d_cg", "gpu2d_src", base + 0x8200, 28);
+
+	clks[IMX8MM_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
+	clks[IMX8MM_CLK_M4_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
+	clks[IMX8MM_CLK_VPU_DIV] = imx_clk_divider2("vpu_div", "vpu_cg", base + 0x8100, 0, 3);
+	clks[IMX8MM_CLK_GPU3D_DIV] = imx_clk_divider2("gpu3d_div", "gpu3d_cg", base + 0x8180, 0, 3);
+	clks[IMX8MM_CLK_GPU2D_DIV] = imx_clk_divider2("gpu2d_div", "gpu2d_cg", base + 0x8200, 0, 3);
+
+	/* BUS */
+	clks[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_composite_critical("main_axi",  imx8mm_main_axi_sels, base + 0x8800);
+	clks[IMX8MM_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
+	clks[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_composite_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
+	clks[IMX8MM_CLK_VPU_BUS] = imx8m_clk_composite("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
+	clks[IMX8MM_CLK_DISP_AXI] = imx8m_clk_composite("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
+	clks[IMX8MM_CLK_DISP_APB] = imx8m_clk_composite("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
+	clks[IMX8MM_CLK_DISP_RTRM] = imx8m_clk_composite("disp_rtrm", imx8mm_disp_rtrm_sels, base + 0x8b00);
+	clks[IMX8MM_CLK_USB_BUS] = imx8m_clk_composite("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
+	clks[IMX8MM_CLK_GPU_AXI] = imx8m_clk_composite("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
+	clks[IMX8MM_CLK_GPU_AHB] = imx8m_clk_composite("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
+	clks[IMX8MM_CLK_NOC] = imx8m_clk_composite_critical("noc", imx8mm_noc_sels, base + 0x8d00);
+	clks[IMX8MM_CLK_NOC_APB] = imx8m_clk_composite_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
+
+	/* AHB */
+	clks[IMX8MM_CLK_AHB] = imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
+	clks[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
+
+	/* IPG */
+	clks[IMX8MM_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
+	clks[IMX8MM_CLK_IPG_AUDIO_ROOT] = imx_clk_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
+
+	/* IP */
+	clks[IMX8MM_CLK_DRAM_ALT] = imx8m_clk_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000);
+	clks[IMX8MM_CLK_DRAM_APB] = imx8m_clk_composite("dram_apb", imx8mm_dram_apb_sels, base + 0xa080);
+	clks[IMX8MM_CLK_VPU_G1] = imx8m_clk_composite("vpu_g1", imx8mm_vpu_g1_sels, base + 0xa100);
+	clks[IMX8MM_CLK_VPU_G2] = imx8m_clk_composite("vpu_g2", imx8mm_vpu_g2_sels, base + 0xa180);
+	clks[IMX8MM_CLK_DISP_DTRC] = imx8m_clk_composite("disp_dtrc", imx8mm_disp_dtrc_sels, base + 0xa200);
+	clks[IMX8MM_CLK_DISP_DC8000] = imx8m_clk_composite("disp_dc8000", imx8mm_disp_dc8000_sels, base + 0xa280);
+	clks[IMX8MM_CLK_PCIE1_CTRL] = imx8m_clk_composite("pcie1_ctrl", imx8mm_pcie1_ctrl_sels, base + 0xa300);
+	clks[IMX8MM_CLK_PCIE1_PHY] = imx8m_clk_composite("pcie1_phy", imx8mm_pcie1_phy_sels, base + 0xa380);
+	clks[IMX8MM_CLK_PCIE1_AUX] = imx8m_clk_composite("pcie1_aux", imx8mm_pcie1_aux_sels, base + 0xa400);
+	clks[IMX8MM_CLK_DC_PIXEL] = imx8m_clk_composite("dc_pixel", imx8mm_dc_pixel_sels, base + 0xa480);
+	clks[IMX8MM_CLK_LCDIF_PIXEL] = imx8m_clk_composite("lcdif_pixel", imx8mm_lcdif_pixel_sels, base + 0xa500);
+	clks[IMX8MM_CLK_SAI1] = imx8m_clk_composite("sai1", imx8mm_sai1_sels, base + 0xa580);
+	clks[IMX8MM_CLK_SAI2] = imx8m_clk_composite("sai2", imx8mm_sai2_sels, base + 0xa600);
+	clks[IMX8MM_CLK_SAI3] = imx8m_clk_composite("sai3", imx8mm_sai3_sels, base + 0xa680);
+	clks[IMX8MM_CLK_SAI4] = imx8m_clk_composite("sai4", imx8mm_sai4_sels, base + 0xa700);
+	clks[IMX8MM_CLK_SAI5] = imx8m_clk_composite("sai5", imx8mm_sai5_sels, base + 0xa780);
+	clks[IMX8MM_CLK_SAI6] = imx8m_clk_composite("sai6", imx8mm_sai6_sels, base + 0xa800);
+	clks[IMX8MM_CLK_SPDIF1] = imx8m_clk_composite("spdif1", imx8mm_spdif1_sels, base + 0xa880);
+	clks[IMX8MM_CLK_SPDIF2] = imx8m_clk_composite("spdif2", imx8mm_spdif2_sels, base + 0xa900);
+	clks[IMX8MM_CLK_ENET_REF] = imx8m_clk_composite("enet_ref", imx8mm_enet_ref_sels, base + 0xa980);
+	clks[IMX8MM_CLK_ENET_TIMER] = imx8m_clk_composite("enet_timer", imx8mm_enet_timer_sels, base + 0xaa00);
+	clks[IMX8MM_CLK_ENET_PHY_REF] = imx8m_clk_composite("enet_phy", imx8mm_enet_phy_sels, base + 0xaa80);
+	clks[IMX8MM_CLK_NAND] = imx8m_clk_composite("nand", imx8mm_nand_sels, base + 0xab00);
+	clks[IMX8MM_CLK_QSPI] = imx8m_clk_composite("qspi", imx8mm_qspi_sels, base + 0xab80);
+	clks[IMX8MM_CLK_USDHC1] = imx8m_clk_composite("usdhc1", imx8mm_usdhc1_sels, base + 0xac00);
+	clks[IMX8MM_CLK_USDHC2] = imx8m_clk_composite("usdhc2", imx8mm_usdhc2_sels, base + 0xac80);
+	clks[IMX8MM_CLK_I2C1] = imx8m_clk_composite("i2c1", imx8mm_i2c1_sels, base + 0xad00);
+	clks[IMX8MM_CLK_I2C2] = imx8m_clk_composite("i2c2", imx8mm_i2c2_sels, base + 0xad80);
+	clks[IMX8MM_CLK_I2C3] = imx8m_clk_composite("i2c3", imx8mm_i2c3_sels, base + 0xae00);
+	clks[IMX8MM_CLK_I2C4] = imx8m_clk_composite("i2c4", imx8mm_i2c4_sels, base + 0xae80);
+	clks[IMX8MM_CLK_UART1] = imx8m_clk_composite("uart1", imx8mm_uart1_sels, base + 0xaf00);
+	clks[IMX8MM_CLK_UART2] = imx8m_clk_composite("uart2", imx8mm_uart2_sels, base + 0xaf80);
+	clks[IMX8MM_CLK_UART3] = imx8m_clk_composite("uart3", imx8mm_uart3_sels, base + 0xb000);
+	clks[IMX8MM_CLK_UART4] = imx8m_clk_composite("uart4", imx8mm_uart4_sels, base + 0xb080);
+	clks[IMX8MM_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mm_usb_core_sels, base + 0xb100);
+	clks[IMX8MM_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mm_usb_phy_sels, base + 0xb180);
+	clks[IMX8MM_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mm_ecspi1_sels, base + 0xb280);
+	clks[IMX8MM_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mm_ecspi2_sels, base + 0xb300);
+	clks[IMX8MM_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mm_pwm1_sels, base + 0xb380);
+	clks[IMX8MM_CLK_PWM2] = imx8m_clk_composite("pwm2", imx8mm_pwm2_sels, base + 0xb400);
+	clks[IMX8MM_CLK_PWM3] = imx8m_clk_composite("pwm3", imx8mm_pwm3_sels, base + 0xb480);
+	clks[IMX8MM_CLK_PWM4] = imx8m_clk_composite("pwm4", imx8mm_pwm4_sels, base + 0xb500);
+	clks[IMX8MM_CLK_GPT1] = imx8m_clk_composite("gpt1", imx8mm_gpt1_sels, base + 0xb580);
+	clks[IMX8MM_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mm_wdog_sels, base + 0xb900);
+	clks[IMX8MM_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mm_wrclk_sels, base + 0xb980);
+	clks[IMX8MM_CLK_CLKO1] = imx8m_clk_composite("clko1", imx8mm_clko1_sels, base + 0xba00);
+	clks[IMX8MM_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mm_dsi_core_sels, base + 0xbb00);
+	clks[IMX8MM_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mm_dsi_phy_sels, base + 0xbb80);
+	clks[IMX8MM_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mm_dsi_dbi_sels, base + 0xbc00);
+	clks[IMX8MM_CLK_USDHC3] = imx8m_clk_composite("usdhc3", imx8mm_usdhc3_sels, base + 0xbc80);
+	clks[IMX8MM_CLK_CSI1_CORE] = imx8m_clk_composite("csi1_core", imx8mm_csi1_core_sels, base + 0xbd00);
+	clks[IMX8MM_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mm_csi1_phy_sels, base + 0xbd80);
+	clks[IMX8MM_CLK_CSI1_ESC] = imx8m_clk_composite("csi1_esc", imx8mm_csi1_esc_sels, base + 0xbe00);
+	clks[IMX8MM_CLK_CSI2_CORE] = imx8m_clk_composite("csi2_core", imx8mm_csi2_core_sels, base + 0xbe80);
+	clks[IMX8MM_CLK_CSI2_PHY_REF] = imx8m_clk_composite("csi2_phy_ref", imx8mm_csi2_phy_sels, base + 0xbf00);
+	clks[IMX8MM_CLK_CSI2_ESC] = imx8m_clk_composite("csi2_esc", imx8mm_csi2_esc_sels, base + 0xbf80);
+	clks[IMX8MM_CLK_PCIE2_CTRL] = imx8m_clk_composite("pcie2_ctrl", imx8mm_pcie2_ctrl_sels, base + 0xc000);
+	clks[IMX8MM_CLK_PCIE2_PHY] = imx8m_clk_composite("pcie2_phy", imx8mm_pcie2_phy_sels, base + 0xc080);
+	clks[IMX8MM_CLK_PCIE2_AUX] = imx8m_clk_composite("pcie2_aux", imx8mm_pcie2_aux_sels, base + 0xc100);
+	clks[IMX8MM_CLK_ECSPI3] = imx8m_clk_composite("ecspi3", imx8mm_ecspi3_sels, base + 0xc180);
+	clks[IMX8MM_CLK_PDM] = imx8m_clk_composite("pdm", imx8mm_pdm_sels, base + 0xc200);
+	clks[IMX8MM_CLK_VPU_H1] = imx8m_clk_composite("vpu_h1", imx8mm_vpu_h1_sels, base + 0xc280);
+
+	/* CCGR */
+	clks[IMX8MM_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0);
+	clks[IMX8MM_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0);
+	clks[IMX8MM_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0);
+	clks[IMX8MM_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0);
+	clks[IMX8MM_CLK_GPT1_ROOT] = imx_clk_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0);
+	clks[IMX8MM_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0);
+	clks[IMX8MM_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0);
+	clks[IMX8MM_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0);
+	clks[IMX8MM_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0);
+	clks[IMX8MM_CLK_MU_ROOT] = imx_clk_gate4("mu_root_clk", "ipg_root", base + 0x4210, 0);
+	clks[IMX8MM_CLK_OCOTP_ROOT] = imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0);
+	clks[IMX8MM_CLK_PCIE1_ROOT] = imx_clk_gate4("pcie1_root_clk", "pcie1_ctrl", base + 0x4250, 0);
+	clks[IMX8MM_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0);
+	clks[IMX8MM_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0);
+	clks[IMX8MM_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0);
+	clks[IMX8MM_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0);
+	clks[IMX8MM_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0);
+	clks[IMX8MM_CLK_NAND_ROOT] = imx_clk_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0, &share_count_nand);
+	clks[IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", base + 0x4300, 0, &share_count_nand);
+	clks[IMX8MM_CLK_SAI1_ROOT] = imx_clk_gate2_shared2("sai1_root_clk", "sai1", base + 0x4330, 0, &share_count_sai1);
+	clks[IMX8MM_CLK_SAI1_IPG] = imx_clk_gate2_shared2("sai1_ipg_clk", "ipg_audio_root", base + 0x4330, 0, &share_count_sai1);
+	clks[IMX8MM_CLK_SAI2_ROOT] = imx_clk_gate2_shared2("sai2_root_clk", "sai2", base + 0x4340, 0, &share_count_sai2);
+	clks[IMX8MM_CLK_SAI2_IPG] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_audio_root", base + 0x4340, 0, &share_count_sai2);
+	clks[IMX8MM_CLK_SAI3_ROOT] = imx_clk_gate2_shared2("sai3_root_clk", "sai3", base + 0x4350, 0, &share_count_sai3);
+	clks[IMX8MM_CLK_SAI3_IPG] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_audio_root", base + 0x4350, 0, &share_count_sai3);
+	clks[IMX8MM_CLK_SAI4_ROOT] = imx_clk_gate2_shared2("sai4_root_clk", "sai4", base + 0x4360, 0, &share_count_sai4);
+	clks[IMX8MM_CLK_SAI4_IPG] = imx_clk_gate2_shared2("sai4_ipg_clk", "ipg_audio_root", base + 0x4360, 0, &share_count_sai4);
+	clks[IMX8MM_CLK_SAI5_ROOT] = imx_clk_gate2_shared2("sai5_root_clk", "sai5", base + 0x4370, 0, &share_count_sai5);
+	clks[IMX8MM_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5);
+	clks[IMX8MM_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6);
+	clks[IMX8MM_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6);
+	clks[IMX8MM_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0);
+	clks[IMX8MM_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
+	clks[IMX8MM_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
+	clks[IMX8MM_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
+	clks[IMX8MM_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0);
+	clks[IMX8MM_CLK_GPU3D_ROOT] = imx_clk_gate4("gpu3d_root_clk", "gpu3d_div", base + 0x44f0, 0);
+	clks[IMX8MM_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
+	clks[IMX8MM_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0);
+	clks[IMX8MM_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0);
+	clks[IMX8MM_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0);
+	clks[IMX8MM_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0);
+	clks[IMX8MM_CLK_VPU_G1_ROOT] = imx_clk_gate4("vpu_g1_root_clk", "vpu_g1", base + 0x4560, 0);
+	clks[IMX8MM_CLK_GPU_BUS_ROOT] = imx_clk_gate4("gpu_root_clk", "gpu_axi", base + 0x4570, 0);
+	clks[IMX8MM_CLK_VPU_H1_ROOT] = imx_clk_gate4("vpu_h1_root_clk", "vpu_h1", base + 0x4590, 0);
+	clks[IMX8MM_CLK_VPU_G2_ROOT] = imx_clk_gate4("vpu_g2_root_clk", "vpu_g2", base + 0x45a0, 0);
+	clks[IMX8MM_CLK_PDM_ROOT] = imx_clk_gate2_shared2("pdm_root_clk", "pdm", base + 0x45b0, 0, &share_count_pdm);
+	clks[IMX8MM_CLK_PDM_IPG]  = imx_clk_gate2_shared2("pdm_ipg_clk", "ipg_audio_root", base + 0x45b0, 0, &share_count_pdm);
+	clks[IMX8MM_CLK_DISP_ROOT] = imx_clk_gate2_shared2("disp_root_clk", "disp_dc8000", base + 0x45d0, 0, &share_count_dcss);
+	clks[IMX8MM_CLK_DISP_AXI_ROOT]  = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_dcss);
+	clks[IMX8MM_CLK_DISP_APB_ROOT]  = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_dcss);
+	clks[IMX8MM_CLK_DISP_RTRM_ROOT] = imx_clk_gate2_shared2("disp_rtrm_root_clk", "disp_rtrm", base + 0x45d0, 0, &share_count_dcss);
+	clks[IMX8MM_CLK_USDHC3_ROOT] = imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0);
+	clks[IMX8MM_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0);
+	clks[IMX8MM_CLK_VPU_DEC_ROOT] = imx_clk_gate4("vpu_dec_root_clk", "vpu_bus", base + 0x4630, 0);
+	clks[IMX8MM_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0);
+	clks[IMX8MM_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0);
+	clks[IMX8MM_CLK_SDMA3_ROOT] = imx_clk_gate4("sdma3_clk", "ipg_audio_root", base + 0x45f0, 0);
+	clks[IMX8MM_CLK_GPU2D_ROOT] = imx_clk_gate4("gpu2d_root_clk", "gpu2d_div", base + 0x4660, 0);
+	clks[IMX8MM_CLK_CSI1_ROOT] = imx_clk_gate4("csi1_root_clk", "csi1_core", base + 0x4650, 0);
+
+	clks[IMX8MM_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc_24m", 1, 8);
+
+	clks[IMX8MM_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
+	clks[IMX8MM_CLK_DRAM_CORE] = imx_clk_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mm_dram_core_sels, ARRAY_SIZE(imx8mm_dram_core_sels), CLK_IS_CRITICAL);
+
+	clks[IMX8MM_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_div",
+					   clks[IMX8MM_CLK_A53_DIV],
+					   clks[IMX8MM_CLK_A53_SRC],
+					   clks[IMX8MM_ARM_PLL_OUT],
+					   clks[IMX8MM_CLK_24M]);
+
+	imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+	clk_data.clks = clks;
+	clk_data.clk_num = ARRAY_SIZE(clks);
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	if (ret < 0) {
+		dev_err(dev, "failed to register clks for i.MX8MM\n");
+		return -EINVAL;
+	}
+
+	imx_register_uart_clocks(uart_clks);
+
+	pr_info("i.MX8MM clock driver init done\n");
+
+	return 0;
+}
+
+static const struct of_device_id imx8mm_clk_of_match[] = {
+	{ .compatible = "fsl,imx8mm-ccm" },
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx8mm_clk_of_match);
+
+static struct platform_driver imx8mm_clk_driver = {
+	.probe = imx8mm_clocks_probe,
+	.driver = {
+		.name = "imx8mm-ccm",
+		.of_match_table = of_match_ptr(imx8mm_clk_of_match),
+	},
+};
+module_platform_driver(imx8mm_clk_driver);
-- 
1.9.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] clk: imx: Add clock driver support for imx8mm
  2019-01-08  9:01 ` [PATCH 3/3] clk: imx: Add clock driver support " Jacky Bai
@ 2019-01-09 20:32   ` Stephen Boyd
  2019-01-10  2:14     ` Jacky Bai
  0 siblings, 1 reply; 10+ messages in thread
From: Stephen Boyd @ 2019-01-09 20:32 UTC (permalink / raw)
  To: mturquette, robh+dt, shawnguo, Jacky Bai
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

Quoting Jacky Bai (2019-01-08 01:01:04)
> +
> +static int imx8mm_clocks_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       void __iomem *base;
> +       int ret = 0;

Please don't assign ret here. Just let it be assigned later on.

> +
> +       clks[IMX8MM_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
> +       clks[IMX8MM_CLK_24M] = of_clk_get_by_name(np, "osc_24m");
> +       clks[IMX8MM_CLK_32K] = of_clk_get_by_name(np, "osc_32k"); /* Check more */
> +       clks[IMX8MM_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1");
> +       clks[IMX8MM_CLK_EXT2] = of_clk_get_by_name(np, "clk_ext2");
> +       clks[IMX8MM_CLK_EXT3] = of_clk_get_by_name(np, "clk_ext3");
> +       clks[IMX8MM_CLK_EXT4] = of_clk_get_by_name(np, "clk_ext4");
> +
> +       np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
> +       base = of_iomap(np, 0);
> +       if (WARN_ON(!base))
> +               return -ENOMEM;

Why do we need to reach into some other node to get the memory region to
map?

> +
> +       clks[IMX8MM_AUDIO_PLL1_REF_SEL] = imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +       clks[IMX8MM_AUDIO_PLL2_REF_SEL] = imx_clk_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +       clks[IMX8MM_VIDEO_PLL1_REF_SEL] = imx_clk_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +       clks[IMX8MM_DRAM_PLL_REF_SEL] = imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
[...]
> +       clks[IMX8MM_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
> +       clks[IMX8MM_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
> +       clks[IMX8MM_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
> +
> +       np = dev->of_node;
> +       base = of_iomap(np, 0);
> +       if (WARN_ON(!base))
> +               return -ENOMEM;

This can surely use the platform device APIs to map and retrieve memory
regions.

> +
[...]
> +
> +       imx_check_clocks(clks, ARRAY_SIZE(clks));
> +
> +       clk_data.clks = clks;
> +       clk_data.clk_num = ARRAY_SIZE(clks);
> +       ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +       if (ret < 0) {
> +               dev_err(dev, "failed to register clks for i.MX8MM\n");
> +               return -EINVAL;
> +       }
> +
> +       imx_register_uart_clocks(uart_clks);
> +
> +       pr_info("i.MX8MM clock driver init done\n");

Please no "I"m alive" messages.

> +
> +       return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc
  2019-01-08  9:00 [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Jacky Bai
  2019-01-08  9:00 ` [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm Jacky Bai
  2019-01-08  9:01 ` [PATCH 3/3] clk: imx: Add clock driver support " Jacky Bai
@ 2019-01-09 20:35 ` Stephen Boyd
  2019-01-10  2:09   ` Jacky Bai
  2 siblings, 1 reply; 10+ messages in thread
From: Stephen Boyd @ 2019-01-09 20:35 UTC (permalink / raw)
  To: mturquette, robh+dt, shawnguo, Jacky Bai
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

Quoting Jacky Bai (2019-01-08 01:00:45)
> diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
> new file mode 100644
> index 0000000..c9f83fd
> --- /dev/null
> +++ b/drivers/clk/imx/clk-pll14xx.c
> @@ -0,0 +1,409 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2017-2018 NXP.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/jiffies.h>
> +
> +#include "clk.h"
> +
> +#define GNRL_CTL       0x0
> +#define DIV_CTL                0x4
> +#define LOCK_STATUS    BIT(31)
> +#define LOCK_SEL_MASK  BIT(29)
> +#define CLKE_MASK      BIT(11)
> +#define RST_MASK       BIT(9)
> +#define BYPASS_MASK    BIT(4)
> +#define MDIV_SHIFT     12
> +#define MDIV_MASK      GENMASK(21, 12)
> +#define PDIV_SHIFT     4
> +#define PDIV_MASK      GENMASK(9, 4)
> +#define SDIV_SHIFT     0
> +#define SDIV_MASK      GENMASK(2, 0)
> +#define KDIV_SHIFT     0
> +#define KDIV_MASK      GENMASK(15, 0)
> +
> +struct clk_pll14xx {
> +       struct clk_hw                   hw;
> +       void __iomem                    *base;
> +       enum imx_pll14xx_type           type;
> +       struct imx_pll14xx_rate_table   *rate_table;
> +       int rate_count;
> +};
> +
> +#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
> +
> +static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
> +               struct clk_pll14xx *pll, unsigned long rate)
> +{
> +       const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
> +       int i;
> +
> +       for (i = 0; i < pll->rate_count; i++) {
> +               if (rate == rate_table[i].rate)
> +                       return &rate_table[i];
> +       }

Nitpick: Drop the brackets.

> +
> +       return NULL;
> +}
> +
> +static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
> +                       unsigned long *prate)
> +{
> +       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
> +       const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
> +       int i;
> +
> +       /* Assumming rate_table is in descending order */
> +       for (i = 0; i < pll->rate_count; i++) {
> +               if (rate >= rate_table[i].rate)
> +                       return rate_table[i].rate;
> +       }
> +       /* return minimum supported value */
> +       return rate_table[i - 1].rate;
> +}
> +
> +static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
> +                                                 unsigned long parent_rate)
> +{
> +       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
> +       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div;
> +       u64 fvco = parent_rate;
> +
> +       pll_gnrl = readl_relaxed(pll->base);
> +       pll_div = readl_relaxed(pll->base + 4);
> +       mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
> +       pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
> +       sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
> +
> +       fvco *= mdiv;
> +       do_div(fvco, pdiv << sdiv);
> +
> +       return (unsigned long)fvco;

Nitpick: Drop the cast.

> +}
> +
> +static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
> +                                                 unsigned long parent_rate)
> +{
> +       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
> +       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1;
> +       short int kdiv;
> +       u64 fvco = parent_rate;
> +
> +       pll_gnrl = readl_relaxed(pll->base);
> +       pll_div_ctl0 = readl_relaxed(pll->base + 4);
> +       pll_div_ctl1 = readl_relaxed(pll->base + 8);
> +       mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
> +       pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
> +       sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
> +       kdiv = pll_div_ctl1 & KDIV_MASK;
> +
> +       /* fvco = (m * 65536 + k) * Fin / (p * 65536) */
> +       fvco *= (mdiv * 65536 + kdiv);
> +       pdiv *= 65536;
> +
> +       do_div(fvco, pdiv << sdiv);
> +
> +       return (unsigned long)fvco;

Nitpick: Drop the cast.

> +}
> +
> +static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
> +                                         u32 pll_div)
> +{
> +       u32 old_mdiv, old_pdiv;
> +
> +       old_mdiv = (pll_div >> MDIV_SHIFT) & MDIV_MASK;
> +       old_pdiv = (pll_div >> PDIV_SHIFT) & PDIV_MASK;
> +
> +       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
> +}
> +
> +static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
> +                                         u32 pll_div_ctl0, u32 pll_div_ctl1)
> +{
> +       u32 old_mdiv, old_pdiv, old_kdiv;
> +
> +       old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
> +       old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
> +       old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
> +
> +       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
> +               rate->kdiv != old_kdiv);
> +}
> +
> +static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
> +                                         u32 pll_div_ctl0, u32 pll_div_ctl1)
> +{
> +       u32 old_mdiv, old_pdiv, old_kdiv;
> +
> +       old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
> +       old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
> +       old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
> +
> +       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
> +               rate->kdiv != old_kdiv);

Nitpick: Please drop the parenthesis on all the returns above.

> +}
> +
> +static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
> +{
> +       unsigned long timeout = jiffies + msecs_to_jiffies(10);
> +
> +       /* Wait for PLL to lock */
> +       do {
> +               if (readl_relaxed(pll->base) & LOCK_STATUS)
> +                       break;
> +               if (time_after(jiffies, timeout))
> +                       break;
> +       } while (1);
> +
> +       return readl_relaxed(pll->base) & LOCK_STATUS ? 0 : -ETIMEDOUT;

Is this readl_poll_timeout()?

> +}
> +
[...]
> +
> +struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
> +                           void __iomem *base,
> +                           const struct imx_pll14xx_clk *pll_clk)
> +{
> +       struct clk_pll14xx *pll;
> +       struct clk *clk;
> +       struct clk_init_data init;
> +       int len;
> +
> +       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> +       if (!pll)
> +               return ERR_PTR(-ENOMEM);
> +
> +       init.name = name;
> +       init.flags = pll_clk->flags;
> +       init.parent_names = &parent_name;
> +       init.num_parents = 1;
> +
> +       if (pll_clk->rate_table) {
> +               for (len = 0; pll_clk->rate_table[len].rate != 0; )
> +                       len++;
> +
> +               pll->rate_count = len;
> +               pll->rate_table = kmemdup(pll_clk->rate_table,
> +                                         pll->rate_count *
> +                                         sizeof(struct imx_pll14xx_rate_table),

Is this struct_size()?

> +                                         GFP_KERNEL);
> +               WARN(!pll->rate_table, "%s : could not alloc rate table\n", __func__);

Allocations will fail with a loud message indicating as such, so this
WARN is not necessary.

> +       }
> +
> +       switch (pll_clk->type) {
> +       case PLL_1416X:
> +               if (!pll->rate_table)
> +                       init.ops = &clk_pll1416x_min_ops;
> +               else
> +                       init.ops = &clk_pll1416x_ops;
> +               break;
> +       case PLL_1443X:

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm
  2019-01-08  9:00 ` [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm Jacky Bai
@ 2019-01-09 20:36   ` Stephen Boyd
  2019-01-10  1:59     ` Jacky Bai
  2019-01-21 20:33   ` Rob Herring
  1 sibling, 1 reply; 10+ messages in thread
From: Stephen Boyd @ 2019-01-09 20:36 UTC (permalink / raw)
  To: mturquette, robh+dt, shawnguo, Jacky Bai
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

Quoting Jacky Bai (2019-01-08 01:00:58)
> Add the clock binding doc for i.MX8MM.
> 
> Signed-off-by: Bai Ping <ping.bai@nxp.com>
> ---
>  .../devicetree/bindings/clock/imx8mm-clock.txt     |  19 ++
>  include/dt-bindings/clock/imx8mm-clock.h           | 244 +++++++++++++++++++++
>  2 files changed, 263 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/imx8mm-clock.txt
>  create mode 100644 include/dt-bindings/clock/imx8mm-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> new file mode 100644
> index 0000000..034b6d4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> @@ -0,0 +1,19 @@
> +* Clock bindings for NXP i.MX8M Mini
> +
> +Required properties:
> +- compatible: Should be "fsl,imx8mm-ccm"
> +- reg: Address and length of the register set
> +- #clock-cells: Should be <1>
> +- clocks: list of clock specifiers, must contain an entry for each required
> +          entry in clock-names
> +- clock-names: should include the following entries:
> +    - "osc_32k"
> +    - "osc_24m"
> +    - "clk_ext1"
> +    - "clk_ext2"
> +    - "clk_ext3"
> +    - "clk_ext4"
> +
> +The clock consumer should specify the desired clock by having the clock
> +ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h
> +for the full list of i.MX8M Mini clock IDs.

Any example of this node? Not the clock consumer.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm
  2019-01-09 20:36   ` Stephen Boyd
@ 2019-01-10  1:59     ` Jacky Bai
  0 siblings, 0 replies; 10+ messages in thread
From: Jacky Bai @ 2019-01-10  1:59 UTC (permalink / raw)
  To: Stephen Boyd, mturquette, robh+dt, shawnguo
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

> Subject: Re: [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm
> 
> Quoting Jacky Bai (2019-01-08 01:00:58)
> > Add the clock binding doc for i.MX8MM.
> >
> > Signed-off-by: Bai Ping <ping.bai@nxp.com>
> > ---
> >  .../devicetree/bindings/clock/imx8mm-clock.txt     |  19 ++
> >  include/dt-bindings/clock/imx8mm-clock.h           | 244
> +++++++++++++++++++++
> >  2 files changed, 263 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> >  create mode 100644 include/dt-bindings/clock/imx8mm-clock.h
> >
> > diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> > b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> > new file mode 100644
> > index 0000000..034b6d4
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> > @@ -0,0 +1,19 @@
> > +* Clock bindings for NXP i.MX8M Mini
> > +
> > +Required properties:
> > +- compatible: Should be "fsl,imx8mm-ccm"
> > +- reg: Address and length of the register set
> > +- #clock-cells: Should be <1>
> > +- clocks: list of clock specifiers, must contain an entry for each required
> > +          entry in clock-names
> > +- clock-names: should include the following entries:
> > +    - "osc_32k"
> > +    - "osc_24m"
> > +    - "clk_ext1"
> > +    - "clk_ext2"
> > +    - "clk_ext3"
> > +    - "clk_ext4"
> > +
> > +The clock consumer should specify the desired clock by having the
> > +clock ID in its "clocks" phandle cell. See
> > +include/dt-bindings/clock/imx8mm-clock.h
> > +for the full list of i.MX8M Mini clock IDs.
> 
> Any example of this node? Not the clock consumer.

Sure, I can add an example in V2.

BR
Jacky Bai

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc
  2019-01-09 20:35 ` [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Stephen Boyd
@ 2019-01-10  2:09   ` Jacky Bai
  0 siblings, 0 replies; 10+ messages in thread
From: Jacky Bai @ 2019-01-10  2:09 UTC (permalink / raw)
  To: Stephen Boyd, mturquette, robh+dt, shawnguo
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

> Subject: Re: [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc
> 
> Quoting Jacky Bai (2019-01-08 01:00:45)
> > diff --git a/drivers/clk/imx/clk-pll14xx.c
> > b/drivers/clk/imx/clk-pll14xx.c new file mode 100644 index
> > 0000000..c9f83fd
> > --- /dev/null
> > +++ b/drivers/clk/imx/clk-pll14xx.c
> > @@ -0,0 +1,409 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright 2017-2018 NXP.
> > + */
> > +
> > +#include <linux/bitops.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/delay.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/slab.h>
> > +#include <linux/jiffies.h>
> > +
> > +#include "clk.h"
> > +
> > +#define GNRL_CTL       0x0
> > +#define DIV_CTL                0x4
> > +#define LOCK_STATUS    BIT(31)
> > +#define LOCK_SEL_MASK  BIT(29)
> > +#define CLKE_MASK      BIT(11)
> > +#define RST_MASK       BIT(9)
> > +#define BYPASS_MASK    BIT(4)
> > +#define MDIV_SHIFT     12
> > +#define MDIV_MASK      GENMASK(21, 12)
> > +#define PDIV_SHIFT     4
> > +#define PDIV_MASK      GENMASK(9, 4)
> > +#define SDIV_SHIFT     0
> > +#define SDIV_MASK      GENMASK(2, 0)
> > +#define KDIV_SHIFT     0
> > +#define KDIV_MASK      GENMASK(15, 0)
> > +
> > +struct clk_pll14xx {
> > +       struct clk_hw                   hw;
> > +       void __iomem                    *base;
> > +       enum imx_pll14xx_type           type;
> > +       struct imx_pll14xx_rate_table   *rate_table;
> > +       int rate_count;
> > +};
> > +
> > +#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
> > +
> > +static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
> > +               struct clk_pll14xx *pll, unsigned long rate) {
> > +       const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
> > +       int i;
> > +
> > +       for (i = 0; i < pll->rate_count; i++) {
> > +               if (rate == rate_table[i].rate)
> > +                       return &rate_table[i];
> > +       }
> 
> Nitpick: Drop the brackets.
> 
Thanks, will fix it in V2.

> > +
> > +       return NULL;
> > +}
> > +
> > +static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
> > +                       unsigned long *prate) {
> > +       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
> > +       const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
> > +       int i;
> > +
> > +       /* Assumming rate_table is in descending order */
> > +       for (i = 0; i < pll->rate_count; i++) {
> > +               if (rate >= rate_table[i].rate)
> > +                       return rate_table[i].rate;
> > +       }
> > +       /* return minimum supported value */
> > +       return rate_table[i - 1].rate; }
> > +
> > +static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
> > +                                                 unsigned long
> > +parent_rate) {
> > +       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
> > +       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div;
> > +       u64 fvco = parent_rate;
> > +
> > +       pll_gnrl = readl_relaxed(pll->base);
> > +       pll_div = readl_relaxed(pll->base + 4);
> > +       mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
> > +       pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
> > +       sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
> > +
> > +       fvco *= mdiv;
> > +       do_div(fvco, pdiv << sdiv);
> > +
> > +       return (unsigned long)fvco;
> 
> Nitpick: Drop the cast.
> 

Thanks, will fix it in V2.

> > +}
> > +
> > +static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
> > +                                                 unsigned long
> > +parent_rate) {
> > +       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
> > +       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1;
> > +       short int kdiv;
> > +       u64 fvco = parent_rate;
> > +
> > +       pll_gnrl = readl_relaxed(pll->base);
> > +       pll_div_ctl0 = readl_relaxed(pll->base + 4);
> > +       pll_div_ctl1 = readl_relaxed(pll->base + 8);
> > +       mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
> > +       pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
> > +       sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
> > +       kdiv = pll_div_ctl1 & KDIV_MASK;
> > +
> > +       /* fvco = (m * 65536 + k) * Fin / (p * 65536) */
> > +       fvco *= (mdiv * 65536 + kdiv);
> > +       pdiv *= 65536;
> > +
> > +       do_div(fvco, pdiv << sdiv);
> > +
> > +       return (unsigned long)fvco;
> 
> Nitpick: Drop the cast.
> 

Will fix in V2.

> > +}
> > +
> > +static inline bool clk_pll1416x_mp_change(const struct
> imx_pll14xx_rate_table *rate,
> > +                                         u32 pll_div) {
> > +       u32 old_mdiv, old_pdiv;
> > +
> > +       old_mdiv = (pll_div >> MDIV_SHIFT) & MDIV_MASK;
> > +       old_pdiv = (pll_div >> PDIV_SHIFT) & PDIV_MASK;
> > +
> > +       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv); }
> > +
> > +static inline bool clk_pll1443x_mpk_change(const struct
> imx_pll14xx_rate_table *rate,
> > +                                         u32 pll_div_ctl0, u32
> > +pll_div_ctl1) {
> > +       u32 old_mdiv, old_pdiv, old_kdiv;
> > +
> > +       old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
> > +       old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
> > +       old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
> > +
> > +       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
> > +               rate->kdiv != old_kdiv); }
> > +
> > +static inline bool clk_pll1443x_mp_change(const struct
> imx_pll14xx_rate_table *rate,
> > +                                         u32 pll_div_ctl0, u32
> > +pll_div_ctl1) {
> > +       u32 old_mdiv, old_pdiv, old_kdiv;
> > +
> > +       old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
> > +       old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
> > +       old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
> > +
> > +       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
> > +               rate->kdiv != old_kdiv);
> 
> Nitpick: Please drop the parenthesis on all the returns above.
> 
Will fix in V2.

> > +}
> > +
> > +static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll) {
> > +       unsigned long timeout = jiffies + msecs_to_jiffies(10);
> > +
> > +       /* Wait for PLL to lock */
> > +       do {
> > +               if (readl_relaxed(pll->base) & LOCK_STATUS)
> > +                       break;
> > +               if (time_after(jiffies, timeout))
> > +                       break;
> > +       } while (1);
> > +
> > +       return readl_relaxed(pll->base) & LOCK_STATUS ? 0 :
> > + -ETIMEDOUT;
> 
> Is this readl_poll_timeout()?
> 

Yes, will fix it.

> > +}
> > +
> [...]
> > +
> > +struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
> > +                           void __iomem *base,
> > +                           const struct imx_pll14xx_clk *pll_clk) {
> > +       struct clk_pll14xx *pll;
> > +       struct clk *clk;
> > +       struct clk_init_data init;
> > +       int len;
> > +
> > +       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> > +       if (!pll)
> > +               return ERR_PTR(-ENOMEM);
> > +
> > +       init.name = name;
> > +       init.flags = pll_clk->flags;
> > +       init.parent_names = &parent_name;
> > +       init.num_parents = 1;
> > +
> > +       if (pll_clk->rate_table) {
> > +               for (len = 0; pll_clk->rate_table[len].rate != 0; )
> > +                       len++;
> > +
> > +               pll->rate_count = len;
> > +               pll->rate_table = kmemdup(pll_clk->rate_table,
> > +                                         pll->rate_count *
> > +                                         sizeof(struct
> > + imx_pll14xx_rate_table),
> 
> Is this struct_size()?

Will fix it in V2

> 
> > +                                         GFP_KERNEL);
> > +               WARN(!pll->rate_table, "%s : could not alloc rate
> > + table\n", __func__);
> 
> Allocations will fail with a loud message indicating as such, so this WARN is not
> necessary.
> 

Will fix in V2

BR

> > +       }
> > +
> > +       switch (pll_clk->type) {
> > +       case PLL_1416X:
> > +               if (!pll->rate_table)
> > +                       init.ops = &clk_pll1416x_min_ops;
> > +               else
> > +                       init.ops = &clk_pll1416x_ops;
> > +               break;
> > +       case PLL_1443X:

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 3/3] clk: imx: Add clock driver support for imx8mm
  2019-01-09 20:32   ` Stephen Boyd
@ 2019-01-10  2:14     ` Jacky Bai
  0 siblings, 0 replies; 10+ messages in thread
From: Jacky Bai @ 2019-01-10  2:14 UTC (permalink / raw)
  To: Stephen Boyd, mturquette, robh+dt, shawnguo
  Cc: Fabio Estevam, Aisheng Dong, dl-linux-imx, linux-clk, devicetree

> Subject: Re: [PATCH 3/3] clk: imx: Add clock driver support for imx8mm
> 
> Quoting Jacky Bai (2019-01-08 01:01:04)
> > +
> > +static int imx8mm_clocks_probe(struct platform_device *pdev) {
> > +       struct device *dev = &pdev->dev;
> > +       struct device_node *np = dev->of_node;
> > +       void __iomem *base;
> > +       int ret = 0;
> 
> Please don't assign ret here. Just let it be assigned later on.
> 

Sure.

> > +
> > +       clks[IMX8MM_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
> > +       clks[IMX8MM_CLK_24M] = of_clk_get_by_name(np, "osc_24m");
> > +       clks[IMX8MM_CLK_32K] = of_clk_get_by_name(np, "osc_32k");
> /* Check more */
> > +       clks[IMX8MM_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1");
> > +       clks[IMX8MM_CLK_EXT2] = of_clk_get_by_name(np, "clk_ext2");
> > +       clks[IMX8MM_CLK_EXT3] = of_clk_get_by_name(np, "clk_ext3");
> > +       clks[IMX8MM_CLK_EXT4] = of_clk_get_by_name(np, "clk_ext4");
> > +
> > +       np = of_find_compatible_node(NULL, NULL,
> "fsl,imx8mm-anatop");
> > +       base = of_iomap(np, 0);
> > +       if (WARN_ON(!base))
> > +               return -ENOMEM;
> 
> Why do we need to reach into some other node to get the memory region to
> map?
> 

The PLLs' config register is in a sperate memory region. As we registered all the PLLs clocks in this driver, the PLLs memory region
Need to be read out from its corresponding node. This is the method that we used on our all i.MX platform.

> > +
> > +       clks[IMX8MM_AUDIO_PLL1_REF_SEL] =
> imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels,
> ARRAY_SIZE(pll_ref_sels));
> > +       clks[IMX8MM_AUDIO_PLL2_REF_SEL] =
> imx_clk_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels,
> ARRAY_SIZE(pll_ref_sels));
> > +       clks[IMX8MM_VIDEO_PLL1_REF_SEL] =
> imx_clk_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels,
> ARRAY_SIZE(pll_ref_sels));
> > +       clks[IMX8MM_DRAM_PLL_REF_SEL] =
> > + imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels,
> > + ARRAY_SIZE(pll_ref_sels));
> [...]
> > +       clks[IMX8MM_SYS_PLL2_333M] =
> imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
> > +       clks[IMX8MM_SYS_PLL2_500M] =
> imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
> > +       clks[IMX8MM_SYS_PLL2_1000M] =
> > + imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
> > +
> > +       np = dev->of_node;
> > +       base = of_iomap(np, 0);
> > +       if (WARN_ON(!base))
> > +               return -ENOMEM;
> 
> This can surely use the platform device APIs to map and retrieve memory
> regions.
> 

Ok, will fix it

> > +
> [...]
> > +
> > +       imx_check_clocks(clks, ARRAY_SIZE(clks));
> > +
> > +       clk_data.clks = clks;
> > +       clk_data.clk_num = ARRAY_SIZE(clks);
> > +       ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> > +       if (ret < 0) {
> > +               dev_err(dev, "failed to register clks for i.MX8MM\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       imx_register_uart_clocks(uart_clks);
> > +
> > +       pr_info("i.MX8MM clock driver init done\n");
> 
> Please no "I"m alive" messages.

I will remove it in V2.

BR
> 
> > +
> > +       return 0;
> > +}
> > +

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm
  2019-01-08  9:00 ` [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm Jacky Bai
  2019-01-09 20:36   ` Stephen Boyd
@ 2019-01-21 20:33   ` Rob Herring
  1 sibling, 0 replies; 10+ messages in thread
From: Rob Herring @ 2019-01-21 20:33 UTC (permalink / raw)
  To: Jacky Bai
  Cc: sboyd, mturquette, shawnguo, Fabio Estevam, Aisheng Dong,
	dl-linux-imx, linux-clk, devicetree

On Tue, Jan 08, 2019 at 09:00:58AM +0000, Jacky Bai wrote:
> Add the clock binding doc for i.MX8MM.
> 
> Signed-off-by: Bai Ping <ping.bai@nxp.com>
> ---
>  .../devicetree/bindings/clock/imx8mm-clock.txt     |  19 ++
>  include/dt-bindings/clock/imx8mm-clock.h           | 244 +++++++++++++++++++++
>  2 files changed, 263 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/imx8mm-clock.txt
>  create mode 100644 include/dt-bindings/clock/imx8mm-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> new file mode 100644
> index 0000000..034b6d4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
> @@ -0,0 +1,19 @@
> +* Clock bindings for NXP i.MX8M Mini
> +
> +Required properties:
> +- compatible: Should be "fsl,imx8mm-ccm"
> +- reg: Address and length of the register set
> +- #clock-cells: Should be <1>
> +- clocks: list of clock specifiers, must contain an entry for each required
> +          entry in clock-names
> +- clock-names: should include the following entries:
> +    - "osc_32k"
> +    - "osc_24m"
> +    - "clk_ext1"
> +    - "clk_ext2"
> +    - "clk_ext3"
> +    - "clk_ext4"
> +
> +The clock consumer should specify the desired clock by having the clock
> +ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h
> +for the full list of i.MX8M Mini clock IDs.
> diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h
> new file mode 100644
> index 0000000..0301581
> --- /dev/null
> +++ b/include/dt-bindings/clock/imx8mm-clock.h
> @@ -0,0 +1,244 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2017-2018 NXP
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_IMX8MM_H
> +#define __DT_BINDINGS_CLOCK_IMX8MM_H
> +
> +#define	IMX8MM_CLK_DUMMY			0

Should be a space, not a tab after the #define.

> +#define	IMX8MM_CLK_32K				1
> +#define	IMX8MM_CLK_24M				2
> +#define	IMX8MM_OSC_HDMI_CLK			3
> +#define	IMX8MM_CLK_EXT1				4
> +#define	IMX8MM_CLK_EXT2				5
> +#define	IMX8MM_CLK_EXT3				6
> +#define	IMX8MM_CLK_EXT4				7
> +#define	IMX8MM_AUDIO_PLL1_REF_SEL		8
> +#define	IMX8MM_AUDIO_PLL2_REF_SEL		9
> +#define	IMX8MM_VIDEO_PLL1_REF_SEL		10
> +#define	IMX8MM_DRAM_PLL_REF_SEL			11
> +#define	IMX8MM_GPU_PLL_REF_SEL			12
> +#define	IMX8MM_VPU_PLL_REF_SEL			13
> +#define	IMX8MM_ARM_PLL_REF_SEL			14
> +#define	IMX8MM_SYS_PLL1_REF_SEL			15
> +#define	IMX8MM_SYS_PLL2_REF_SEL			16
> +#define	IMX8MM_SYS_PLL3_REF_SEL			17
> +#define	IMX8MM_AUDIO_PLL1			18
> +#define	IMX8MM_AUDIO_PLL2			19
> +#define	IMX8MM_VIDEO_PLL1			20
> +#define	IMX8MM_DRAM_PLL				21
> +#define	IMX8MM_GPU_PLL				22
> +#define	IMX8MM_VPU_PLL				23
> +#define	IMX8MM_ARM_PLL				24
> +#define	IMX8MM_SYS_PLL1				25
> +#define	IMX8MM_SYS_PLL2				26
> +#define	IMX8MM_SYS_PLL3				27
> +#define	IMX8MM_AUDIO_PLL1_BYPASS		28
> +#define	IMX8MM_AUDIO_PLL2_BYPASS		29
> +#define	IMX8MM_VIDEO_PLL1_BYPASS		30
> +#define	IMX8MM_DRAM_PLL_BYPASS			31
> +#define	IMX8MM_GPU_PLL_BYPASS			32
> +#define	IMX8MM_VPU_PLL_BYPASS			33
> +#define	IMX8MM_ARM_PLL_BYPASS			34
> +#define	IMX8MM_SYS_PLL1_BYPASS			35
> +#define	IMX8MM_SYS_PLL2_BYPASS			36
> +#define	IMX8MM_SYS_PLL3_BYPASS			37
> +#define	IMX8MM_AUDIO_PLL1_OUT			38
> +#define	IMX8MM_AUDIO_PLL2_OUT			39
> +#define	IMX8MM_VIDEO_PLL1_OUT			40
> +#define	IMX8MM_DRAM_PLL_OUT			41
> +#define	IMX8MM_GPU_PLL_OUT			42
> +#define	IMX8MM_VPU_PLL_OUT			43
> +#define	IMX8MM_ARM_PLL_OUT			44
> +#define	IMX8MM_SYS_PLL1_OUT			45
> +#define	IMX8MM_SYS_PLL2_OUT			46
> +#define	IMX8MM_SYS_PLL3_OUT			47
> +#define	IMX8MM_SYS_PLL1_40M			48
> +#define	IMX8MM_SYS_PLL1_80M			49
> +#define	IMX8MM_SYS_PLL1_100M			50
> +#define	IMX8MM_SYS_PLL1_133M			51
> +#define	IMX8MM_SYS_PLL1_160M			52
> +#define	IMX8MM_SYS_PLL1_200M			53
> +#define	IMX8MM_SYS_PLL1_266M			54
> +#define	IMX8MM_SYS_PLL1_400M			55
> +#define	IMX8MM_SYS_PLL1_800M			56
> +#define	IMX8MM_SYS_PLL2_50M			57
> +#define	IMX8MM_SYS_PLL2_100M			58
> +#define	IMX8MM_SYS_PLL2_125M			59
> +#define	IMX8MM_SYS_PLL2_166M			60
> +#define	IMX8MM_SYS_PLL2_200M			61
> +#define	IMX8MM_SYS_PLL2_250M			62
> +#define	IMX8MM_SYS_PLL2_333M			63
> +#define	IMX8MM_SYS_PLL2_500M			64
> +#define	IMX8MM_SYS_PLL2_1000M			65
> +
> +/* core */
> +#define	IMX8MM_CLK_A53_SRC			66
> +#define	IMX8MM_CLK_M4_SRC			67
> +#define	IMX8MM_CLK_VPU_SRC			68
> +#define	IMX8MM_CLK_GPU3D_SRC			69
> +#define	IMX8MM_CLK_GPU2D_SRC			70
> +#define	IMX8MM_CLK_A53_CG			71
> +#define	IMX8MM_CLK_M4_CG			72
> +#define	IMX8MM_CLK_VPU_CG			73
> +#define	IMX8MM_CLK_GPU3D_CG			74
> +#define	IMX8MM_CLK_GPU2D_CG			75
> +#define	IMX8MM_CLK_A53_DIV			76
> +#define	IMX8MM_CLK_M4_DIV			77
> +#define	IMX8MM_CLK_VPU_DIV			78
> +#define	IMX8MM_CLK_GPU3D_DIV			79
> +#define	IMX8MM_CLK_GPU2D_DIV			80
> +
> +/* bus */
> +#define	IMX8MM_CLK_MAIN_AXI			81
> +#define	IMX8MM_CLK_ENET_AXI			82
> +#define	IMX8MM_CLK_NAND_USDHC_BUS		83
> +#define	IMX8MM_CLK_VPU_BUS			84
> +#define	IMX8MM_CLK_DISP_AXI			85
> +#define	IMX8MM_CLK_DISP_APB			86
> +#define	IMX8MM_CLK_DISP_RTRM			87
> +#define	IMX8MM_CLK_USB_BUS			88
> +#define	IMX8MM_CLK_GPU_AXI			89
> +#define	IMX8MM_CLK_GPU_AHB			90
> +#define	IMX8MM_CLK_NOC				91
> +#define	IMX8MM_CLK_NOC_APB			92
> +
> +#define	IMX8MM_CLK_AHB				93
> +#define	IMX8MM_CLK_AUDIO_AHB			94
> +#define IMX8MM_CLK_IPG_ROOT			95
> +#define IMX8MM_CLK_IPG_AUDIO_ROOT		96
> +
> +#define	IMX8MM_CLK_DRAM_ALT			97
> +#define	IMX8MM_CLK_DRAM_APB			98
> +#define	IMX8MM_CLK_VPU_G1			99
> +#define	IMX8MM_CLK_VPU_G2			100
> +#define	IMX8MM_CLK_DISP_DTRC			101
> +#define	IMX8MM_CLK_DISP_DC8000			102
> +#define	IMX8MM_CLK_PCIE1_CTRL			103
> +#define	IMX8MM_CLK_PCIE1_PHY			104
> +#define	IMX8MM_CLK_PCIE1_AUX			105
> +#define	IMX8MM_CLK_DC_PIXEL			106
> +#define	IMX8MM_CLK_LCDIF_PIXEL			107
> +#define	IMX8MM_CLK_SAI1				108
> +#define	IMX8MM_CLK_SAI2				109
> +#define	IMX8MM_CLK_SAI3				110
> +#define	IMX8MM_CLK_SAI4				111
> +#define	IMX8MM_CLK_SAI5				112
> +#define	IMX8MM_CLK_SAI6				113
> +#define	IMX8MM_CLK_SPDIF1			114
> +#define	IMX8MM_CLK_SPDIF2			115
> +#define	IMX8MM_CLK_ENET_REF			116
> +#define	IMX8MM_CLK_ENET_TIMER			117
> +#define	IMX8MM_CLK_ENET_PHY_REF			118
> +#define	IMX8MM_CLK_NAND				119
> +#define	IMX8MM_CLK_QSPI				120
> +#define	IMX8MM_CLK_USDHC1			121
> +#define	IMX8MM_CLK_USDHC2			122
> +#define	IMX8MM_CLK_I2C1				123
> +#define	IMX8MM_CLK_I2C2				124
> +#define	IMX8MM_CLK_I2C3				125
> +#define	IMX8MM_CLK_I2C4				126
> +#define	IMX8MM_CLK_UART1			127
> +#define	IMX8MM_CLK_UART2			128
> +#define	IMX8MM_CLK_UART3			129
> +#define	IMX8MM_CLK_UART4			130
> +#define	IMX8MM_CLK_USB_CORE_REF			131
> +#define	IMX8MM_CLK_USB_PHY_REF			132
> +#define	IMX8MM_CLK_ECSPI1			133
> +#define	IMX8MM_CLK_ECSPI2			134
> +#define	IMX8MM_CLK_PWM1				135
> +#define	IMX8MM_CLK_PWM2				136
> +#define	IMX8MM_CLK_PWM3				137
> +#define	IMX8MM_CLK_PWM4				138
> +#define	IMX8MM_CLK_GPT1				139
> +#define	IMX8MM_CLK_WDOG				140
> +#define	IMX8MM_CLK_WRCLK			141
> +#define	IMX8MM_CLK_DSI_CORE			142
> +#define	IMX8MM_CLK_DSI_PHY_REF			143
> +#define	IMX8MM_CLK_DSI_DBI			144
> +#define	IMX8MM_CLK_USDHC3			145
> +#define	IMX8MM_CLK_CSI1_CORE			146
> +#define	IMX8MM_CLK_CSI1_PHY_REF			147
> +#define	IMX8MM_CLK_CSI1_ESC			148
> +#define	IMX8MM_CLK_CSI2_CORE			149
> +#define	IMX8MM_CLK_CSI2_PHY_REF			150
> +#define	IMX8MM_CLK_CSI2_ESC			151
> +#define	IMX8MM_CLK_PCIE2_CTRL			152
> +#define	IMX8MM_CLK_PCIE2_PHY			153
> +#define	IMX8MM_CLK_PCIE2_AUX			154
> +#define	IMX8MM_CLK_ECSPI3			155
> +#define	IMX8MM_CLK_PDM				156
> +#define	IMX8MM_CLK_VPU_H1			157
> +#define	IMX8MM_CLK_CLKO1			158
> +
> +#define	IMX8MM_CLK_ECSPI1_ROOT			159
> +#define	IMX8MM_CLK_ECSPI2_ROOT			160
> +#define	IMX8MM_CLK_ECSPI3_ROOT			161
> +#define	IMX8MM_CLK_ENET1_ROOT			162
> +#define	IMX8MM_CLK_GPT1_ROOT			163
> +#define	IMX8MM_CLK_I2C1_ROOT			164
> +#define	IMX8MM_CLK_I2C2_ROOT			165
> +#define	IMX8MM_CLK_I2C3_ROOT			166
> +#define	IMX8MM_CLK_I2C4_ROOT			167
> +#define	IMX8MM_CLK_OCOTP_ROOT			168
> +#define	IMX8MM_CLK_PCIE1_ROOT			169
> +#define	IMX8MM_CLK_PWM1_ROOT			170
> +#define	IMX8MM_CLK_PWM2_ROOT			171
> +#define	IMX8MM_CLK_PWM3_ROOT			172
> +#define	IMX8MM_CLK_PWM4_ROOT			173
> +#define	IMX8MM_CLK_QSPI_ROOT			174
> +#define	IMX8MM_CLK_NAND_ROOT			175
> +#define	IMX8MM_CLK_SAI1_ROOT			176
> +#define	IMX8MM_CLK_SAI1_IPG			177
> +#define	IMX8MM_CLK_SAI2_ROOT			178
> +#define	IMX8MM_CLK_SAI2_IPG			179
> +#define	IMX8MM_CLK_SAI3_ROOT			180
> +#define	IMX8MM_CLK_SAI3_IPG			181
> +#define	IMX8MM_CLK_SAI4_ROOT			182
> +#define	IMX8MM_CLK_SAI4_IPG			183
> +#define	IMX8MM_CLK_SAI5_ROOT			184
> +#define	IMX8MM_CLK_SAI5_IPG			185
> +#define	IMX8MM_CLK_SAI6_ROOT			186
> +#define	IMX8MM_CLK_SAI6_IPG			187
> +#define	IMX8MM_CLK_UART1_ROOT			188
> +#define	IMX8MM_CLK_UART2_ROOT			189
> +#define	IMX8MM_CLK_UART3_ROOT			190
> +#define	IMX8MM_CLK_UART4_ROOT			191
> +#define	IMX8MM_CLK_USB1_CTRL_ROOT		192
> +#define	IMX8MM_CLK_GPU3D_ROOT			193
> +#define	IMX8MM_CLK_USDHC1_ROOT			194
> +#define	IMX8MM_CLK_USDHC2_ROOT			195
> +#define	IMX8MM_CLK_WDOG1_ROOT			196
> +#define	IMX8MM_CLK_WDOG2_ROOT			197
> +#define	IMX8MM_CLK_WDOG3_ROOT			198
> +#define	IMX8MM_CLK_VPU_G1_ROOT			199
> +#define	IMX8MM_CLK_GPU_BUS_ROOT			200
> +#define	IMX8MM_CLK_VPU_H1_ROOT			201
> +#define	IMX8MM_CLK_VPU_G2_ROOT			202
> +#define	IMX8MM_CLK_PDM_ROOT			203
> +#define	IMX8MM_CLK_DISP_ROOT			204
> +#define	IMX8MM_CLK_DISP_AXI_ROOT		205
> +#define	IMX8MM_CLK_DISP_APB_ROOT		206
> +#define	IMX8MM_CLK_DISP_RTRM_ROOT		207
> +#define	IMX8MM_CLK_USDHC3_ROOT			208
> +#define	IMX8MM_CLK_TMU_ROOT			209
> +#define	IMX8MM_CLK_VPU_DEC_ROOT			210
> +#define	IMX8MM_CLK_SDMA1_ROOT			211
> +#define	IMX8MM_CLK_SDMA2_ROOT			212
> +#define	IMX8MM_CLK_SDMA3_ROOT			213
> +#define	IMX8MM_CLK_GPT_3M			214
> +#define	IMX8MM_CLK_ARM				215
> +#define	IMX8MM_CLK_PDM_IPG			216
> +#define	IMX8MM_CLK_GPU2D_ROOT			217
> +#define	IMX8MM_CLK_MU_ROOT			218
> +#define	IMX8MM_CLK_CSI1_ROOT			219
> +
> +#define IMX8MM_CLK_DRAM_CORE			220
> +#define IMX8MM_CLK_DRAM_ALT_ROOT		221
> +
> +#define IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK	222
> +
> +#define	IMX8MM_CLK_END				223
> +
> +#endif
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, back to index

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-08  9:00 [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Jacky Bai
2019-01-08  9:00 ` [PATCH 2/3] dt-bindings: imx: Add clock binding doc for imx8mm Jacky Bai
2019-01-09 20:36   ` Stephen Boyd
2019-01-10  1:59     ` Jacky Bai
2019-01-21 20:33   ` Rob Herring
2019-01-08  9:01 ` [PATCH 3/3] clk: imx: Add clock driver support " Jacky Bai
2019-01-09 20:32   ` Stephen Boyd
2019-01-10  2:14     ` Jacky Bai
2019-01-09 20:35 ` [PATCH 1/3] clk: imx: Add PLLs driver for imx8mm soc Stephen Boyd
2019-01-10  2:09   ` Jacky Bai

Linux-Clk Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-clk/0 linux-clk/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-clk linux-clk/ https://lore.kernel.org/linux-clk \
		linux-clk@vger.kernel.org linux-clk@archiver.kernel.org
	public-inbox-index linux-clk


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-clk


AGPL code for this site: git clone https://public-inbox.org/ public-inbox