[U-Boot] [PATCH 3/5] clk: imx8: Update imx8 clock driver

Ye Li ye.li at nxp.com
Wed Jul 3 05:40:28 UTC 2019


Update imx8 clock driver to support LPCG and full clocks tree for some
modules aligned with kernel.

We classify the clock into serveral types: slice, fixed, lpcg, gpr and mux.
Generally slice and fixed clocks are the sources. lpcg, gpr and mux are
the downstream of those sources and are used for gating, muxing or dividing
functions.

This patch replaces the functions defined in imx8qm and imx8qxp with the clock
tables of different clock types. clk-imx8 use unified functions to process these
clock tables.

Note: since the clock depends on the power domain of its resource, must power
on the resource firstly, then we can get the clock. Otherwise, we can't access lpcg.
Thus, the clock dump only works for the slice clock.

Signed-off-by: Ye Li <ye.li at nxp.com>
---
 drivers/clk/imx/clk-imx8.c    | 304 +++++++++++++++++++++++++--
 drivers/clk/imx/clk-imx8.h    |  83 +++++++-
 drivers/clk/imx/clk-imx8qm.c  | 479 ++++++++++++++++--------------------------
 drivers/clk/imx/clk-imx8qxp.c | 432 +++++++++++++------------------------
 4 files changed, 689 insertions(+), 609 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8.c b/drivers/clk/imx/clk-imx8.c
index a755e26..afdb6ea 100644
--- a/drivers/clk/imx/clk-imx8.c
+++ b/drivers/clk/imx/clk-imx8.c
@@ -12,32 +12,294 @@
 #include <dt-bindings/clock/imx8qxp-clock.h>
 #include <dt-bindings/soc/imx_rsrc.h>
 #include <misc.h>
+#include <asm/arch/lpcg.h>
 
 #include "clk-imx8.h"
 
-__weak ulong imx8_clk_get_rate(struct clk *clk)
+struct imx8_clks_collect *soc_data[] = {
+#ifdef CONFIG_IMX8QXP
+	&imx8qxp_clk_collect,
+#endif
+#ifdef CONFIG_IMX8QM
+	&imx8qm_clk_collect,
+#endif
+};
+
+static ulong __imx8_clk_get_rate(struct udevice *dev, ulong id);
+static int __imx8_clk_enable(struct udevice *dev, ulong id, bool enable);
+static ulong __imx8_clk_set_rate(struct udevice *dev, ulong id, unsigned long rate);
+
+static struct imx8_clks_collect * find_clks_collect(struct udevice *dev)
+{
+	ulong data = (ulong)dev_get_driver_data(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(soc_data); i++) {
+		if (soc_data[i]->match_flag == data)
+			return soc_data[i];
+	}
+
+	return NULL;
+}
+
+static void * check_imx8_clk(struct udevice *dev, enum imx8_clk_type type, ulong id, u32 size_of_clk)
+{
+	u32 i, size;
+	struct imx8_clks_collect *clks_col = find_clks_collect(dev);
+	struct imx8_clk_header *hdr;
+	ulong clks;
+
+	if (!clks_col || !(clks_col->clks[type].type_clks)) {
+		printf("%s fails to get clks for type %d\n",
+		       __func__, type);
+		return NULL;
+	}
+
+	clks = (ulong)(clks_col->clks[type].type_clks);
+	size = clks_col->clks[type].num;
+
+	for (i = 0; i < size; i++) {
+		hdr = (struct imx8_clk_header *)clks;
+		if (id == hdr->id)
+			return (void *)hdr;
+
+		clks += size_of_clk;
+	}
+
+	return NULL;
+}
+
+static ulong imx8_get_rate_lpcg(struct udevice *dev, struct imx8_lpcg_clks *lpcg_clk)
+{
+	if (lpcg_clk->parent_id != 0) {
+		if (lpcg_is_clock_on(lpcg_clk->lpcg, lpcg_clk->bit_idx >> 2)) {
+			return __imx8_clk_get_rate(dev, lpcg_clk->parent_id);
+		} else {
+			return 0;
+		}
+	} else {
+		return -ENOSYS;
+	}
+}
+
+static ulong imx8_get_rate_slice(struct udevice *dev, struct imx8_clks *slice_clk)
+{
+	int ret;
+	u32 rate;
+
+	ret = sc_pm_get_clock_rate(-1, slice_clk->rsrc, slice_clk->pm_clk,
+				   (sc_pm_clock_rate_t *)&rate);
+	if (ret) {
+		printf("%s err %d\n", __func__, ret);
+		return ret;
+	}
+
+	return rate;
+}
+
+static ulong imx8_get_rate_fixed(struct udevice *dev, struct imx8_fixed_clks *fixed_clk)
+{
+	return fixed_clk->rate;
+}
+
+static ulong __imx8_clk_get_rate(struct udevice *dev, ulong id)
+{
+	void* clkdata;
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_LPCG, id, sizeof(struct imx8_lpcg_clks));
+	if (clkdata) {
+		return imx8_get_rate_lpcg(dev, (struct imx8_lpcg_clks *)clkdata);
+	}
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_SLICE, id, sizeof(struct imx8_clks));
+	if (clkdata) {
+		return imx8_get_rate_slice(dev, (struct imx8_clks *)clkdata);
+	}
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_FIXED, id, sizeof(struct imx8_fixed_clks));
+	if (clkdata) {
+		return imx8_get_rate_fixed(dev, (struct imx8_fixed_clks *)clkdata);
+	}
+
+	return -ENOSYS;
+}
+
+static ulong imx8_clk_get_rate(struct clk *clk)
+{
+	return __imx8_clk_get_rate(clk->dev, clk->id);
+}
+
+static ulong imx8_set_rate_lpcg(struct udevice *dev, struct imx8_lpcg_clks *lpcg_clk, unsigned long rate)
+{
+	if (lpcg_clk->parent_id != 0) {
+		return __imx8_clk_set_rate(dev, lpcg_clk->parent_id, rate);
+	} else {
+		return -ENOSYS;
+	}
+}
+
+static ulong imx8_set_rate_slice(struct udevice *dev, struct imx8_clks *slice_clk, unsigned long rate)
+{
+	int ret;
+	u32 new_rate = rate;
+
+	ret = sc_pm_set_clock_rate(-1, slice_clk->rsrc, slice_clk->pm_clk, &new_rate);
+	if (ret) {
+		printf("%s err %d\n", __func__, ret);
+		return ret;
+	}
+
+	return new_rate;
+}
+
+static ulong imx8_set_rate_gpr(struct udevice *dev, struct imx8_gpr_clks *gpr_clk, unsigned long rate)
 {
+	ulong parent_rate;
+	u32 val;
+	int ret;
+
+	if (gpr_clk->parent_id == 0)
+		return -ENOSYS;
+
+	parent_rate = __imx8_clk_get_rate(dev, gpr_clk->parent_id);
+	if (parent_rate > 0) {
+		val = (rate < parent_rate) ? 1 : 0;
+
+		ret = sc_misc_set_control(-1, gpr_clk->rsrc,
+			gpr_clk->gpr_id, val);
+		if (ret) {
+			printf("%s err %d\n", __func__, ret);
+			return ret;
+		}
+
+		return rate;
+	}
+
+	return -ENOSYS;
+}
+
+static ulong __imx8_clk_set_rate(struct udevice *dev, ulong id, unsigned long rate)
+{
+	void* clkdata;
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_SLICE, id, sizeof(struct imx8_clks));
+	if (clkdata) {
+		return imx8_set_rate_slice(dev, (struct imx8_clks *)clkdata, rate);
+	}
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_LPCG, id, sizeof(struct imx8_lpcg_clks));
+	if (clkdata) {
+		return imx8_set_rate_lpcg(dev, (struct imx8_lpcg_clks *)clkdata, rate);
+	}
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_GPR, id, sizeof(struct imx8_gpr_clks));
+	if (clkdata) {
+		return imx8_set_rate_gpr(dev, (struct imx8_gpr_clks *)clkdata, rate);
+	}
+
+	return -ENOSYS;
+}
+
+static ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return __imx8_clk_set_rate(clk->dev, clk->id, rate);
+
+}
+
+static int imx8_enable_slice(struct udevice *dev, struct imx8_clks *slice_clk, bool enable)
+{
+	int ret;
+
+	ret = sc_pm_clock_enable(-1, slice_clk->rsrc, slice_clk->pm_clk, enable, 0);
+	if (ret) {
+		printf("%s err %d\n", __func__, ret);
+		return ret;
+	}
+
 	return 0;
 }
 
-__weak ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
+static int imx8_enable_lpcg(struct udevice *dev, struct imx8_lpcg_clks *lpcg_clk, bool enable)
 {
+	if (enable) {
+		if (lpcg_clk->parent_id != 0) {
+			__imx8_clk_enable(dev, lpcg_clk->parent_id, enable);
+		}
+
+		lpcg_clock_on(lpcg_clk->lpcg, lpcg_clk->bit_idx >> 2);
+	} else {
+		lpcg_clock_off(lpcg_clk->lpcg, lpcg_clk->bit_idx >> 2);
+
+		if (lpcg_clk->parent_id != 0) {
+			__imx8_clk_enable(dev, lpcg_clk->parent_id, enable);
+		}
+	}
+
 	return 0;
 }
 
-__weak int __imx8_clk_enable(struct clk *clk, bool enable)
+static int __imx8_clk_enable(struct udevice *dev, ulong id, bool enable)
 {
-	return -ENOTSUPP;
+	void* clkdata;
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_LPCG, id, sizeof(struct imx8_lpcg_clks));
+	if (clkdata) {
+		return imx8_enable_lpcg(dev, (struct imx8_lpcg_clks *)clkdata, enable);
+	}
+
+	clkdata = check_imx8_clk(dev, IMX8_CLK_SLICE, id, sizeof(struct imx8_clks));
+	if (clkdata) {
+		return imx8_enable_slice(dev, (struct imx8_clks *)clkdata, enable);
+	}
+
+	return -ENOSYS;
 }
 
 static int imx8_clk_disable(struct clk *clk)
 {
-	return __imx8_clk_enable(clk, 0);
+	return __imx8_clk_enable(clk->dev, clk->id, 0);
 }
 
 static int imx8_clk_enable(struct clk *clk)
 {
-	return __imx8_clk_enable(clk, 1);
+	return __imx8_clk_enable(clk->dev, clk->id, 1);
+}
+
+static int imx8_set_parent_mux(struct udevice *dev, struct imx8_mux_clks *mux_clk, ulong pid)
+{
+	u32 i;
+	int ret;
+	struct imx8_clks *slice_clkdata;
+
+	slice_clkdata = check_imx8_clk(dev, IMX8_CLK_SLICE, mux_clk->slice_clk_id, sizeof(struct imx8_clks));
+	if (!slice_clkdata) {
+		printf("Error: fail to find slice clk %lu for this mux %lu\n", mux_clk->slice_clk_id, mux_clk->hdr.id);
+		return -EINVAL;
+	}
+
+	for (i = 0; i< CLK_IMX8_MAX_MUX_SEL; i++) {
+		if (pid == mux_clk->parent_clks[i]) {
+			ret = sc_pm_set_clock_parent(-1, slice_clkdata->rsrc,  slice_clkdata->pm_clk, i);
+			if (ret)
+				printf("Error: fail to set clock parent rsrc %d, pm_clk %d, parent clk %d\n",
+					slice_clkdata->rsrc,  slice_clkdata->pm_clk, i);
+			return ret;
+		}
+	}
+
+	return -ENOSYS;
+}
+
+static int imx8_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	void* clkdata;
+
+	clkdata = check_imx8_clk(clk->dev, IMX8_CLK_MUX, clk->id, sizeof(struct imx8_mux_clks));
+	if (clkdata) {
+		return imx8_set_parent_mux(clk->dev, (struct imx8_mux_clks *)clkdata, parent->id);
+	}
+
+	return -ENOSYS;
 }
 
 #if CONFIG_IS_ENABLED(CMD_CLK)
@@ -47,6 +309,9 @@ int soc_clk_dump(void)
 	struct clk clk;
 	unsigned long rate;
 	int i, ret;
+	u32 size;
+	struct imx8_clks *clks;
+	struct imx8_clks_collect *clks_col;
 
 	ret = uclass_get_device_by_driver(UCLASS_CLK,
 					  DM_GET_DRIVER(imx8_clk), &dev);
@@ -55,8 +320,19 @@ int soc_clk_dump(void)
 
 	printf("Clk\t\tHz\n");
 
-	for (i = 0; i < num_clks; i++) {
-		clk.id = imx8_clk_names[i].id;
+	clks_col = find_clks_collect(dev);
+
+	if (!clks_col || !(clks_col->clks[IMX8_CLK_SLICE].type_clks)) {
+		printf("%s fails to get clks for type %d\n",
+		       __func__, IMX8_CLK_SLICE);
+		return -ENODEV;
+	}
+
+	clks = (struct imx8_clks *)(clks_col->clks[IMX8_CLK_SLICE].type_clks);
+	size = clks_col->clks[IMX8_CLK_SLICE].num;
+
+	for (i = 0; i < size; i++) {
+		clk.id = clks[i].hdr.id;
 		ret = clk_request(dev, &clk);
 		if (ret < 0) {
 			debug("%s clk_request() failed: %d\n", __func__, ret);
@@ -70,21 +346,22 @@ int soc_clk_dump(void)
 
 		if (ret == -ENOTSUPP) {
 			printf("clk ID %lu not supported yet\n",
-			       imx8_clk_names[i].id);
+			       clks[i].hdr.id);
 			continue;
 		}
 		if (ret < 0) {
 			printf("%s %lu: get_rate err: %d\n",
-			       __func__, imx8_clk_names[i].id, ret);
+			       __func__, clks[i].hdr.id, ret);
 			continue;
 		}
 
 		printf("%s(%3lu):\t%lu\n",
-		       imx8_clk_names[i].name, imx8_clk_names[i].id, rate);
+		       clks[i].hdr.name, clks[i].hdr.id, rate);
 	}
 
 	return 0;
 }
+
 #endif
 
 static struct clk_ops imx8_clk_ops = {
@@ -92,6 +369,7 @@ static struct clk_ops imx8_clk_ops = {
 	.get_rate = imx8_clk_get_rate,
 	.enable = imx8_clk_enable,
 	.disable = imx8_clk_disable,
+	.set_parent = imx8_clk_set_parent,
 };
 
 static int imx8_clk_probe(struct udevice *dev)
@@ -100,8 +378,8 @@ static int imx8_clk_probe(struct udevice *dev)
 }
 
 static const struct udevice_id imx8_clk_ids[] = {
-	{ .compatible = "fsl,imx8qxp-clk" },
-	{ .compatible = "fsl,imx8qm-clk" },
+	{ .compatible = "fsl,imx8qxp-clk", .data = FLAG_CLK_IMX8_IMX8QXP, },
+	{ .compatible = "fsl,imx8qm-clk", .data = FLAG_CLK_IMX8_IMX8QM, },
 	{ },
 };
 
diff --git a/drivers/clk/imx/clk-imx8.h b/drivers/clk/imx/clk-imx8.h
index 68ad675..c0566f8 100644
--- a/drivers/clk/imx/clk-imx8.h
+++ b/drivers/clk/imx/clk-imx8.h
@@ -4,16 +4,87 @@
  * Peng Fan <peng.fan at nxp.com>
  */
 
-struct imx8_clks {
+#define CLK_IMX8_MAX_MUX_SEL 5
+
+#define FLAG_CLK_IMX8_IMX8QM	BIT(0)
+#define FLAG_CLK_IMX8_IMX8QXP	BIT(1)
+
+struct imx8_clk_header {
 	ulong id;
+#if CONFIG_IS_ENABLED(CMD_CLK)
 	const char *name;
+#endif
+};
+
+struct imx8_clks {
+	struct imx8_clk_header hdr;
+	u16 rsrc;
+	sc_pm_clk_t pm_clk;
+};
+
+struct imx8_fixed_clks {
+	struct imx8_clk_header hdr;
+	ulong rate;
+};
+
+struct imx8_gpr_clks {
+	struct imx8_clk_header hdr;
+	u16 rsrc;
+	sc_ctrl_t gpr_id;
+	ulong parent_id;
+};
+
+struct imx8_lpcg_clks {
+	struct imx8_clk_header hdr;
+	u8 bit_idx;
+	u32 lpcg;
+	ulong parent_id;
+};
+
+struct imx8_mux_clks {
+	struct imx8_clk_header hdr;
+	ulong slice_clk_id;
+	ulong parent_clks[CLK_IMX8_MAX_MUX_SEL];
+};
+
+enum imx8_clk_type {
+	IMX8_CLK_SLICE 		= 0,
+	IMX8_CLK_FIXED 	= 1,
+	IMX8_CLK_GPR 		= 2,
+	IMX8_CLK_LPCG 		= 3,
+	IMX8_CLK_MUX 		= 4,
+	IMX8_CLK_END		= 5,
+};
+
+struct imx8_clk_pair {
+	void *type_clks;
+	u32 num;
+};
+
+struct imx8_clks_collect {
+	struct imx8_clk_pair clks[IMX8_CLK_END];
+	ulong match_flag;
 };
 
 #if CONFIG_IS_ENABLED(CMD_CLK)
-extern struct imx8_clks imx8_clk_names[];
-extern int num_clks;
+#define CLK_3(ID, NAME, MEM2) \
+	{ { ID, NAME, }, MEM2, }
+#define CLK_4(ID, NAME, MEM2, MEM3) \
+	{ { ID, NAME, }, MEM2, MEM3, }
+#define CLK_5(ID, NAME, MEM2, MEM3, MEM4) \
+	{ { ID, NAME, }, MEM2, MEM3, MEM4, }
+#define CLK_MUX(ID, NAME, MEM2, MUX0, MUX1, MUX2, MUX3, MUX4) \
+	{ { ID, NAME, }, MEM2, { MUX0, MUX1, MUX2, MUX3, MUX4} }
+#else
+#define CLK_3(ID, NAME, MEM2) \
+	{ { ID, }, MEM2, }
+#define CLK_4(ID, NAME, MEM2, MEM3) \
+	{ { ID, }, MEM2, MEM3, }
+#define CLK_5(ID, NAME, MEM2, MEM3, MEM4) \
+	{ { ID, }, MEM2, MEM3, MEM4, }
+#define CLK_MUX(ID, NAME, MEM2, MUX0, MUX1, MUX2, MUX3, MUX4) \
+	{ { ID, }, MEM2, { MUX0, MUX1, MUX2, MUX3, MUX4} }
 #endif
 
-ulong imx8_clk_get_rate(struct clk *clk);
-ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate);
-int __imx8_clk_enable(struct clk *clk, bool enable);
+extern struct imx8_clks_collect imx8qxp_clk_collect;
+extern struct imx8_clks_collect imx8qm_clk_collect;
diff --git a/drivers/clk/imx/clk-imx8qm.c b/drivers/clk/imx/clk-imx8qm.c
index a6b09d2..f4ee007 100644
--- a/drivers/clk/imx/clk-imx8qm.c
+++ b/drivers/clk/imx/clk-imx8qm.c
@@ -12,314 +12,189 @@
 #include <dt-bindings/clock/imx8qm-clock.h>
 #include <dt-bindings/soc/imx_rsrc.h>
 #include <misc.h>
+#include <asm/arch/lpcg.h>
 
 #include "clk-imx8.h"
 
-#if CONFIG_IS_ENABLED(CMD_CLK)
-struct imx8_clks imx8_clk_names[] = {
-	{ IMX8QM_A53_DIV, "A53_DIV" },
-	{ IMX8QM_UART0_CLK, "UART0" },
-	{ IMX8QM_UART1_CLK, "UART1" },
-	{ IMX8QM_UART2_CLK, "UART2" },
-	{ IMX8QM_UART3_CLK, "UART3" },
-	{ IMX8QM_SDHC0_CLK, "SDHC0" },
-	{ IMX8QM_SDHC1_CLK, "SDHC1" },
-	{ IMX8QM_SDHC2_CLK, "SDHC2" },
-	{ IMX8QM_ENET0_AHB_CLK, "ENET0_AHB" },
-	{ IMX8QM_ENET0_IPG_CLK, "ENET0_IPG" },
-	{ IMX8QM_ENET0_REF_DIV, "ENET0_REF" },
-	{ IMX8QM_ENET0_PTP_CLK, "ENET0_PTP" },
-	{ IMX8QM_ENET1_AHB_CLK, "ENET1_AHB" },
-	{ IMX8QM_ENET1_IPG_CLK, "ENET1_IPG" },
-	{ IMX8QM_ENET1_REF_DIV, "ENET1_REF" },
-	{ IMX8QM_ENET1_PTP_CLK, "ENET1_PTP" },
+static struct imx8_clks imx8qm_clks[] = {
+	CLK_4( IMX8QM_A53_DIV, "A53_DIV", SC_R_A53, SC_PM_CLK_CPU ),
+	CLK_4( IMX8QM_A72_DIV, "A72_DIV", SC_R_A72, SC_PM_CLK_CPU ),
+	CLK_4( IMX8QM_I2C0_DIV, "I2C0_DIV", SC_R_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_I2C1_DIV, "I2C1_DIV", SC_R_I2C_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_I2C2_DIV, "I2C2_DIV", SC_R_I2C_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_I2C3_DIV, "I2C3_DIV", SC_R_I2C_3, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_LVDS0_I2C0_DIV, "LVDS0 I2C0 DIV", SC_R_LVDS_0_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_LVDS0_I2C1_DIV, "LVDS0 I2C1 DIV", SC_R_LVDS_0_I2C_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_LVDS1_I2C0_DIV, "LVDS1 I2C0 DIV", SC_R_LVDS_1_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_LVDS1_I2C1_DIV, "LVDS1 I2C1 DIV", SC_R_LVDS_1_I2C_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_MIPI0_I2C0_DIV, "MIPI0 I2C0_DIV", SC_R_MIPI_0_I2C_0, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QM_MIPI0_I2C1_DIV, "MIPI0 I2C1_DIV", SC_R_MIPI_0_I2C_1, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QM_MIPI1_I2C0_DIV, "MIPI1 I2C0_DIV", SC_R_MIPI_1_I2C_0, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QM_MIPI1_I2C1_DIV, "MIPI1 I2C1_DIV", SC_R_MIPI_1_I2C_1, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QM_CSI0_I2C0_DIV, "CSI0 I2C0_DIV", SC_R_CSI_0_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_CSI1_I2C0_DIV, "CSI1 I2C0_DIV", SC_R_CSI_1_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_HDMI_I2C0_DIV, "HDMI I2C0_DIV", SC_R_HDMI_I2C_0, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QM_HDMI_IPG_CLK, "HDMI IPG_CLK", SC_R_HDMI, SC_PM_CLK_MISC ),
+	CLK_4( IMX8QM_HDMI_RX_I2C0_DIV, "HDMI RX I2C_DIV", SC_R_HDMI_RX_I2C_0, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QM_UART0_DIV, "UART0_DIV", SC_R_UART_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_UART1_DIV, "UART1_DIV", SC_R_UART_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_UART2_DIV, "UART2_DIV", SC_R_UART_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_UART3_DIV, "UART3_DIV", SC_R_UART_3, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_SDHC0_DIV, "SDHC0_DIV", SC_R_SDHC_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_SDHC1_DIV, "SDHC1_DIV", SC_R_SDHC_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_SDHC2_DIV, "SDHC2_DIV", SC_R_SDHC_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_ENET0_ROOT_DIV, "ENET0_ROOT_DIV", SC_R_ENET_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_ENET0_RGMII_DIV, "ENET0_RGMII_DIV", SC_R_ENET_0, SC_PM_CLK_MISC0 ),
+	CLK_4( IMX8QM_ENET1_ROOT_DIV, "ENET1_ROOT_DIV", SC_R_ENET_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_ENET1_RGMII_DIV, "ENET1_RGMII_DIV", SC_R_ENET_1, SC_PM_CLK_MISC0 ),
+
+	CLK_4( IMX8QM_USB3_ACLK_DIV, "USB3_ACLK_DIV", SC_R_USB_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QM_USB3_BUS_DIV, "USB3_BUS_DIV", SC_R_USB_2, SC_PM_CLK_MST_BUS ),
+	CLK_4( IMX8QM_USB3_LPM_DIV, "USB3_LPM_DIV", SC_R_USB_2, SC_PM_CLK_MISC ),
+
+	CLK_4( IMX8QM_FSPI0_DIV, "FSPI0_DIV", SC_R_FSPI_0, SC_PM_CLK_PER ),
+
+	CLK_4( IMX8QM_GPMI_BCH_IO_DIV, "GPMI_IO_DIV", SC_R_NAND, SC_PM_CLK_MST_BUS ),
+	CLK_4( IMX8QM_GPMI_BCH_DIV, "GPMI_BCH_DIV", SC_R_NAND, SC_PM_CLK_PER ),
 };
 
-int num_clks = ARRAY_SIZE(imx8_clk_names);
-#endif
-
-ulong imx8_clk_get_rate(struct clk *clk)
-{
-	sc_pm_clk_t pm_clk;
-	ulong rate;
-	u16 resource;
-	int ret;
-
-	debug("%s(#%lu)\n", __func__, clk->id);
-
-	switch (clk->id) {
-	case IMX8QM_A53_DIV:
-		resource = SC_R_A53;
-		pm_clk = SC_PM_CLK_CPU;
-		break;
-	case IMX8QM_I2C0_CLK:
-		resource = SC_R_I2C_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C1_CLK:
-		resource = SC_R_I2C_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C2_CLK:
-		resource = SC_R_I2C_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C3_CLK:
-		resource = SC_R_I2C_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC0_IPG_CLK:
-	case IMX8QM_SDHC0_CLK:
-	case IMX8QM_SDHC0_DIV:
-		resource = SC_R_SDHC_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC1_IPG_CLK:
-	case IMX8QM_SDHC1_CLK:
-	case IMX8QM_SDHC1_DIV:
-		resource = SC_R_SDHC_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC2_IPG_CLK:
-	case IMX8QM_SDHC2_CLK:
-	case IMX8QM_SDHC2_DIV:
-		resource = SC_R_SDHC_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART0_IPG_CLK:
-	case IMX8QM_UART0_CLK:
-		resource = SC_R_UART_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART1_CLK:
-		resource = SC_R_UART_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART2_CLK:
-		resource = SC_R_UART_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART3_CLK:
-		resource = SC_R_UART_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_ENET0_IPG_CLK:
-	case IMX8QM_ENET0_AHB_CLK:
-	case IMX8QM_ENET0_REF_DIV:
-	case IMX8QM_ENET0_PTP_CLK:
-		resource = SC_R_ENET_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_ENET1_IPG_CLK:
-	case IMX8QM_ENET1_AHB_CLK:
-	case IMX8QM_ENET1_REF_DIV:
-	case IMX8QM_ENET1_PTP_CLK:
-		resource = SC_R_ENET_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	default:
-		if (clk->id < IMX8QM_UART0_IPG_CLK ||
-		    clk->id >= IMX8QM_CLK_END) {
-			printf("%s(Invalid clk ID #%lu)\n",
-			       __func__, clk->id);
-			return -EINVAL;
-		}
-		return -ENOTSUPP;
-	};
-
-	ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
-				   (sc_pm_clock_rate_t *)&rate);
-	if (ret) {
-		printf("%s err %d\n", __func__, ret);
-		return ret;
-	}
-
-	return rate;
-}
-
-ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	sc_pm_clk_t pm_clk;
-	u32 new_rate = rate;
-	u16 resource;
-	int ret;
-
-	debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
-	switch (clk->id) {
-	case IMX8QM_I2C0_CLK:
-		resource = SC_R_I2C_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C1_CLK:
-		resource = SC_R_I2C_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C2_CLK:
-		resource = SC_R_I2C_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C3_CLK:
-		resource = SC_R_I2C_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART0_CLK:
-		resource = SC_R_UART_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART1_CLK:
-		resource = SC_R_UART_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART2_CLK:
-		resource = SC_R_UART_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART3_CLK:
-		resource = SC_R_UART_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC0_IPG_CLK:
-	case IMX8QM_SDHC0_CLK:
-	case IMX8QM_SDHC0_DIV:
-		resource = SC_R_SDHC_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC1_IPG_CLK:
-	case IMX8QM_SDHC1_CLK:
-	case IMX8QM_SDHC1_DIV:
-		resource = SC_R_SDHC_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC2_IPG_CLK:
-	case IMX8QM_SDHC2_CLK:
-	case IMX8QM_SDHC2_DIV:
-		resource = SC_R_SDHC_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_ENET0_IPG_CLK:
-	case IMX8QM_ENET0_AHB_CLK:
-	case IMX8QM_ENET0_REF_DIV:
-	case IMX8QM_ENET0_PTP_CLK:
-	case IMX8QM_ENET0_ROOT_DIV:
-		resource = SC_R_ENET_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_ENET1_IPG_CLK:
-	case IMX8QM_ENET1_AHB_CLK:
-	case IMX8QM_ENET1_REF_DIV:
-	case IMX8QM_ENET1_PTP_CLK:
-	case IMX8QM_ENET1_ROOT_DIV:
-		resource = SC_R_ENET_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	default:
-		if (clk->id < IMX8QM_UART0_IPG_CLK ||
-		    clk->id >= IMX8QM_CLK_END) {
-			printf("%s(Invalid clk ID #%lu)\n",
-			       __func__, clk->id);
-			return -EINVAL;
-		}
-		return -ENOTSUPP;
-	};
-
-	ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
-	if (ret) {
-		printf("%s err %d\n", __func__, ret);
-		return ret;
-	}
-
-	return new_rate;
-}
-
-int __imx8_clk_enable(struct clk *clk, bool enable)
-{
-	sc_pm_clk_t pm_clk;
-	u16 resource;
-	int ret;
+static struct imx8_fixed_clks imx8qm_fixed_clks[] = {
+	CLK_3( IMX8QM_IPG_CONN_CLK_ROOT, "IPG_CONN_CLK", SC_83MHZ ),
+	CLK_3( IMX8QM_AHB_CONN_CLK_ROOT, "AHB_CONN_CLK", SC_166MHZ ),
+	CLK_3( IMX8QM_AXI_CONN_CLK_ROOT, "AXI_CONN_CLK", SC_333MHZ ),
+	CLK_3( IMX8QM_IPG_DMA_CLK_ROOT, "IPG_DMA_CLK", SC_120MHZ ),
+	CLK_3( IMX8QM_IPG_MIPI_CSI_CLK_ROOT, "IPG_MIPI_CLK", SC_120MHZ ),
+	CLK_3( IMX8QM_LVDS_IPG_CLK, "IPG_LVDS_CLK", SC_24MHZ ),
+	CLK_3( IMX8QM_LSIO_BUS_CLK, "LSIO_BUS_CLK", SC_100MHZ ),
+	CLK_3( IMX8QM_LSIO_MEM_CLK, "LSIO_MEM_CLK", SC_200MHZ ),
+	CLK_3( IMX8QM_MIPI0_CLK_ROOT, "MIPI0_CLK", SC_120MHZ ),
+	CLK_3( IMX8QM_MIPI1_CLK_ROOT, "MIPI1_CLK", SC_120MHZ ),
+	CLK_3( IMX8QM_HDMI_RX_IPG_CLK, "HDMI_RX_IPG_CLK", SC_200MHZ ),
+};
 
-	debug("%s(#%lu)\n", __func__, clk->id);
+static struct imx8_gpr_clks imx8qm_gpr_clks[] = {
+	CLK_5( IMX8QM_ENET0_REF_DIV, "ENET0_REF_DIV", SC_R_ENET_0, SC_C_CLKDIV, IMX8QM_ENET0_ROOT_DIV ),
+	CLK_4( IMX8QM_ENET0_REF_25MHZ_125MHZ_SEL, "ENET0_REF_25_125", SC_R_ENET_0, SC_C_SEL_125 ),
+	CLK_4( IMX8QM_ENET0_RMII_TX_SEL, "ENET0_RMII_TX", SC_R_ENET_0, SC_C_TXCLK ),
+	CLK_4( IMX8QM_ENET0_REF_25MHZ_125MHZ_CLK, "ENET0_REF_25_125_CLK", SC_R_ENET_0, SC_C_DISABLE_125 ),
+	CLK_4( IMX8QM_ENET0_REF_50MHZ_CLK, "ENET0_REF_50", SC_R_ENET_0, SC_C_DISABLE_50 ),
+
+	CLK_5( IMX8QM_ENET1_REF_DIV, "ENET1_REF_DIV", SC_R_ENET_1, SC_C_CLKDIV, IMX8QM_ENET1_ROOT_DIV ),
+	CLK_4( IMX8QM_ENET1_REF_25MHZ_125MHZ_SEL, "ENET1_REF_25_125", SC_R_ENET_1, SC_C_SEL_125 ),
+	CLK_4( IMX8QM_ENET1_RMII_TX_SEL, "ENET1_RMII_TX", SC_R_ENET_1, SC_C_TXCLK ),
+	CLK_4( IMX8QM_ENET1_REF_25MHZ_125MHZ_CLK, "ENET1_REF_25_125_CLK", SC_R_ENET_1, SC_C_DISABLE_125 ),
+	CLK_4( IMX8QM_ENET1_REF_50MHZ_CLK, "ENET1_REF_50", SC_R_ENET_1, SC_C_DISABLE_50 ),
+};
 
-	switch (clk->id) {
-	case IMX8QM_I2C0_CLK:
-		resource = SC_R_I2C_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C1_CLK:
-		resource = SC_R_I2C_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C2_CLK:
-		resource = SC_R_I2C_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_I2C3_CLK:
-		resource = SC_R_I2C_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART0_CLK:
-		resource = SC_R_UART_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART1_CLK:
-		resource = SC_R_UART_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART2_CLK:
-		resource = SC_R_UART_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_UART3_CLK:
-		resource = SC_R_UART_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC0_IPG_CLK:
-	case IMX8QM_SDHC0_CLK:
-	case IMX8QM_SDHC0_DIV:
-		resource = SC_R_SDHC_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC1_IPG_CLK:
-	case IMX8QM_SDHC1_CLK:
-	case IMX8QM_SDHC1_DIV:
-		resource = SC_R_SDHC_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_SDHC2_IPG_CLK:
-	case IMX8QM_SDHC2_CLK:
-	case IMX8QM_SDHC2_DIV:
-		resource = SC_R_SDHC_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_ENET0_IPG_CLK:
-	case IMX8QM_ENET0_AHB_CLK:
-	case IMX8QM_ENET0_REF_DIV:
-	case IMX8QM_ENET0_PTP_CLK:
-		resource = SC_R_ENET_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QM_ENET1_IPG_CLK:
-	case IMX8QM_ENET1_AHB_CLK:
-	case IMX8QM_ENET1_REF_DIV:
-	case IMX8QM_ENET1_PTP_CLK:
-		resource = SC_R_ENET_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	default:
-		if (clk->id < IMX8QM_UART0_IPG_CLK ||
-		    clk->id >= IMX8QM_CLK_END) {
-			printf("%s(Invalid clk ID #%lu)\n",
-			       __func__, clk->id);
-			return -EINVAL;
-		}
-		return -ENOTSUPP;
-	}
+static struct imx8_lpcg_clks imx8qm_lpcg_clks[] = {
+	CLK_5( IMX8QM_I2C0_CLK, "I2C0_CLK", 0, LPI2C_0_LPCG, IMX8QM_I2C0_DIV ),
+	CLK_5( IMX8QM_I2C0_IPG_CLK, "I2C0_IPG", 16, LPI2C_0_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QM_I2C1_CLK, "I2C1_CLK", 0, LPI2C_1_LPCG, IMX8QM_I2C1_DIV ),
+	CLK_5( IMX8QM_I2C1_IPG_CLK, "I2C1_IPG", 16, LPI2C_1_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QM_I2C2_CLK, "I2C2_CLK", 0, LPI2C_2_LPCG, IMX8QM_I2C2_DIV ),
+	CLK_5( IMX8QM_I2C2_IPG_CLK, "I2C2_IPG", 16, LPI2C_2_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QM_I2C3_CLK, "I2C3_CLK", 0, LPI2C_3_LPCG, IMX8QM_I2C3_DIV ),
+	CLK_5( IMX8QM_I2C3_IPG_CLK, "I2C3_IPG", 16, LPI2C_3_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+
+	CLK_5( IMX8QM_LVDS0_I2C0_CLK, "LVDS0_I2C0_CLK", 0, DI_LVDS_0_LPCG + 0x10, IMX8QM_LVDS0_I2C0_DIV ),
+	CLK_5( IMX8QM_LVDS0_I2C0_IPG_CLK, "LVDS0_I2C0_IPG", 16, DI_LVDS_0_LPCG + 0x10, IMX8QM_LVDS_IPG_CLK ),
+	CLK_5( IMX8QM_LVDS0_I2C1_CLK, "LVDS0_I2C1_CLK", 0, DI_LVDS_0_LPCG + 0x14, IMX8QM_LVDS0_I2C1_DIV ),
+	CLK_5( IMX8QM_LVDS0_I2C1_IPG_CLK, "LVDS0_I2C1_IPG", 16, DI_LVDS_0_LPCG + 0x14, IMX8QM_LVDS_IPG_CLK ),
+	CLK_5( IMX8QM_LVDS1_I2C0_CLK, "LVDS1_I2C0_CLK", 0, DI_LVDS_1_LPCG + 0x10, IMX8QM_LVDS1_I2C0_DIV ),
+	CLK_5( IMX8QM_LVDS1_I2C0_IPG_CLK, "LVDS1_I2C0_IPG", 16, DI_LVDS_1_LPCG + 0x10, IMX8QM_LVDS_IPG_CLK ),
+	CLK_5( IMX8QM_LVDS1_I2C1_CLK, "LVDS1_I2C1_CLK", 0, DI_LVDS_1_LPCG + 0x14, IMX8QM_LVDS1_I2C1_DIV ),
+	CLK_5( IMX8QM_LVDS1_I2C1_IPG_CLK, "LVDS1_I2C1_IPG", 16, DI_LVDS_1_LPCG + 0x14, IMX8QM_LVDS_IPG_CLK ),
+
+	CLK_5( IMX8QM_MIPI0_I2C0_CLK, "MIPI0_I2C0_CLK", 0, MIPI_DSI_0_LPCG + 0x1c, IMX8QM_MIPI0_I2C0_DIV ),
+	CLK_5( IMX8QM_MIPI0_I2C0_IPG_CLK, "MIPI0_I2C0_IPG", 0, MIPI_DSI_0_LPCG + 0x14,  IMX8QM_MIPI0_I2C0_IPG_S_CLK),
+	CLK_5( IMX8QM_MIPI0_I2C0_IPG_S_CLK, "MIPI0_I2C0_IPG_S", 0, MIPI_DSI_0_LPCG + 0x18, IMX8QM_MIPI0_CLK_ROOT ),
+	CLK_5( IMX8QM_MIPI0_I2C1_CLK, "MIPI0_I2C1_CLK", 0, MIPI_DSI_0_LPCG + 0x2c, IMX8QM_MIPI0_I2C1_DIV ),
+	CLK_5( IMX8QM_MIPI0_I2C1_IPG_CLK, "MIPI0_I2C1_IPG", 0, MIPI_DSI_0_LPCG + 0x24,  IMX8QM_MIPI0_I2C1_IPG_S_CLK),
+	CLK_5( IMX8QM_MIPI0_I2C1_IPG_S_CLK, "MIPI0_I2C1_IPG_S", 0, MIPI_DSI_0_LPCG + 0x28, IMX8QM_MIPI0_CLK_ROOT ),
+	CLK_5( IMX8QM_MIPI1_I2C0_CLK, "MIPI1_I2C0_CLK", 0, MIPI_DSI_1_LPCG + 0x1c, IMX8QM_MIPI1_I2C0_DIV ),
+	CLK_5( IMX8QM_MIPI1_I2C0_IPG_CLK, "MIPI1_I2C0_IPG", 0, MIPI_DSI_1_LPCG + 0x14, IMX8QM_MIPI1_I2C0_IPG_S_CLK),
+	CLK_5( IMX8QM_MIPI1_I2C0_IPG_S_CLK, "MIPI1_I2C0_IPG_S", 0, MIPI_DSI_1_LPCG + 0x18, IMX8QM_MIPI1_CLK_ROOT ),
+	CLK_5( IMX8QM_MIPI1_I2C1_CLK, "MIPI1_I2C1_CLK", 0, MIPI_DSI_1_LPCG + 0x2c, IMX8QM_MIPI1_I2C1_DIV ),
+	CLK_5( IMX8QM_MIPI1_I2C1_IPG_CLK, "MIPI1_I2C1_IPG", 0, MIPI_DSI_1_LPCG + 0x24, IMX8QM_MIPI1_I2C1_IPG_S_CLK),
+	CLK_5( IMX8QM_MIPI1_I2C1_IPG_S_CLK, "MIPI1_I2C1_IPG_S", 0, MIPI_DSI_1_LPCG + 0x28, IMX8QM_MIPI1_CLK_ROOT ),
+
+	CLK_5( IMX8QM_CSI0_I2C0_CLK, "CSI0_I2C0_CLK", 0, MIPI_CSI_0_LPCG + 0x14, IMX8QM_CSI0_I2C0_DIV ),
+	CLK_5( IMX8QM_CSI0_I2C0_IPG_CLK, "CSI0_I2C0_IPG", 16, MIPI_CSI_0_LPCG + 0x14, IMX8QM_IPG_MIPI_CSI_CLK_ROOT ),
+	CLK_5( IMX8QM_CSI1_I2C0_CLK, "CSI1_I2C0_CLK", 0, MIPI_CSI_1_LPCG + 0x14, IMX8QM_CSI1_I2C0_DIV ),
+	CLK_5( IMX8QM_CSI1_I2C0_IPG_CLK, "CSI1_I2C0_IPG", 16, MIPI_CSI_1_LPCG + 0x14, IMX8QM_IPG_MIPI_CSI_CLK_ROOT ),
+	CLK_5( IMX8QM_HDMI_I2C0_CLK, "HDMI_I2C0_CLK", 0, DI_HDMI_LPCG, IMX8QM_HDMI_I2C0_DIV ),
+	CLK_5( IMX8QM_HDMI_I2C_IPG_CLK, "HDMI_I2C0_IPG", 16, DI_HDMI_LPCG, IMX8QM_HDMI_IPG_CLK ),
+	CLK_5( IMX8QM_HDMI_RX_I2C_DIV_CLK, "HDMI RX_I2C_DIV_CLK", 0, MIPI_DSI_0_LPCG + 0x14, IMX8QM_MIPI0_I2C0_DIV ),
+	CLK_5( IMX8QM_HDMI_RX_I2C0_CLK, "HDMI RX_I2C_CLK", 0, MIPI_DSI_0_LPCG + 0x10, IMX8QM_HDMI_RX_I2C_DIV_CLK ),
+	CLK_5( IMX8QM_HDMI_RX_I2C_IPG_CLK, "HDMI_RX_I2C_IPG", 0, RX_HDMI_LPCG + 0x18,  IMX8QM_HDMI_RX_I2C_IPG_S_CLK),
+	CLK_5( IMX8QM_HDMI_RX_I2C_IPG_S_CLK, "HDMI_I2C_IPG_S", 0, RX_HDMI_LPCG + 0x1c, IMX8QM_HDMI_RX_IPG_CLK ),
+
+	CLK_5( IMX8QM_UART0_CLK, "UART0_CLK", 0, LPUART_0_LPCG, IMX8QM_UART0_DIV ),
+	CLK_5( IMX8QM_UART0_IPG_CLK, "UART0_IPG", 16, LPUART_0_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QM_UART1_CLK, "UART1_CLK", 0, LPUART_1_LPCG, IMX8QM_UART1_DIV ),
+	CLK_5( IMX8QM_UART1_IPG_CLK, "UART1_IPG", 16, LPUART_1_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QM_UART2_CLK, "UART2_CLK", 0, LPUART_2_LPCG, IMX8QM_UART2_DIV ),
+	CLK_5( IMX8QM_UART2_IPG_CLK, "UART2_IPG", 16, LPUART_2_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QM_UART3_CLK, "UART3_CLK", 0, LPUART_3_LPCG, IMX8QM_UART3_DIV ),
+	CLK_5( IMX8QM_UART3_IPG_CLK, "UART3_IPG", 16, LPUART_3_LPCG, IMX8QM_IPG_DMA_CLK_ROOT ),
+
+	CLK_5( IMX8QM_SDHC0_CLK, "SDHC0_CLK", 0, USDHC_0_LPCG, IMX8QM_SDHC0_DIV ),
+	CLK_5( IMX8QM_SDHC0_IPG_CLK, "SDHC0_IPG", 16, USDHC_0_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_SDHC1_CLK, "SDHC1_CLK", 0, USDHC_1_LPCG, IMX8QM_SDHC1_DIV ),
+	CLK_5( IMX8QM_SDHC1_IPG_CLK, "SDHC1_IPG", 16, USDHC_1_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_SDHC2_CLK, "SDHC2_CLK", 0, USDHC_2_LPCG, IMX8QM_SDHC2_DIV ),
+	CLK_5( IMX8QM_SDHC2_IPG_CLK, "SDHC2_IPG", 16, USDHC_2_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+
+	CLK_5( IMX8QM_ENET0_IPG_S_CLK, "ENET0_IPG_S", 20, ENET_0_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_ENET0_IPG_CLK, "ENET0_IPG", 16, ENET_0_LPCG, IMX8QM_ENET0_IPG_S_CLK ),
+	CLK_5( IMX8QM_ENET0_AHB_CLK, "ENET0_AHB", 8, ENET_0_LPCG, IMX8QM_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_ENET0_TX_CLK, "ENET0_TX", 4, ENET_0_LPCG, IMX8QM_ENET0_ROOT_DIV ),
+	CLK_5( IMX8QM_ENET0_PTP_CLK, "ENET0_PTP", 0, ENET_0_LPCG, IMX8QM_ENET0_ROOT_DIV  ),
+	CLK_5( IMX8QM_ENET0_RGMII_TX_CLK, "ENET0_RGMII_TX", 12, ENET_0_LPCG, IMX8QM_ENET0_RMII_TX_SEL  ),
+	CLK_5( IMX8QM_ENET0_RMII_RX_CLK, "ENET0_RMII_RX", 0, ENET_0_LPCG + 0x4, IMX8QM_ENET0_RGMII_DIV  ),
+
+	CLK_5( IMX8QM_ENET1_IPG_S_CLK, "ENET1_IPG_S", 20, ENET_1_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_ENET1_IPG_CLK, "ENET1_IPG", 16, ENET_1_LPCG, IMX8QM_ENET1_IPG_S_CLK ),
+	CLK_5( IMX8QM_ENET1_AHB_CLK, "ENET1_AHB", 8, ENET_1_LPCG, IMX8QM_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_ENET1_TX_CLK, "ENET1_TX", 4, ENET_1_LPCG, IMX8QM_ENET1_ROOT_DIV ),
+	CLK_5( IMX8QM_ENET1_PTP_CLK, "ENET1_PTP", 0, ENET_1_LPCG, IMX8QM_ENET1_ROOT_DIV  ),
+	CLK_5( IMX8QM_ENET1_RGMII_TX_CLK, "ENET1_RGMII_TX", 12, ENET_1_LPCG, IMX8QM_ENET1_RMII_TX_SEL  ),
+	CLK_5( IMX8QM_ENET1_RMII_RX_CLK, "ENET1_RMII_RX", 0, ENET_1_LPCG + 0x4, IMX8QM_ENET1_RGMII_DIV  ),
+
+	CLK_5( IMX8QM_FSPI0_IPG_S_CLK, "FSPI0_IPG_S", 0x18, FSPI_0_LPCG, IMX8QM_LSIO_BUS_CLK ),
+	CLK_5( IMX8QM_FSPI0_IPG_CLK, "FSPI0_IPG", 0x14, FSPI_0_LPCG, IMX8QM_FSPI0_IPG_S_CLK ),
+	CLK_5( IMX8QM_FSPI0_HCLK, "FSPI0_HCLK", 0x10, FSPI_0_LPCG, IMX8QM_LSIO_MEM_CLK ),
+	CLK_5( IMX8QM_FSPI0_CLK, "FSPI0_CLK", 0, FSPI_0_LPCG, IMX8QM_FSPI0_DIV ),
+
+	CLK_5( IMX8QM_USB2_OH_AHB_CLK, "USB2_OH_AHB", 24, USB_2_LPCG, IMX8QM_AHB_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_USB2_OH_IPG_S_CLK, "USB2_OH_IPG_S", 16, USB_2_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_USB2_OH_IPG_S_PL301_CLK, "USB2_OH_IPG_S_PL301", 20, USB_2_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_USB2_PHY_IPG_CLK, "USB2_PHY_IPG", 28, USB_2_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+
+	CLK_5( IMX8QM_USB3_IPG_CLK, "USB3_IPG", 16, USB_3_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_USB3_CORE_PCLK, "USB3_CORE", 20, USB_3_LPCG, IMX8QM_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_USB3_PHY_CLK, "USB3_PHY", 24, USB_3_LPCG, IMX8QM_USB3_IPG_CLK ),
+	CLK_5( IMX8QM_USB3_ACLK, "USB3_ACLK", 28, USB_3_LPCG, IMX8QM_USB3_ACLK_DIV ),
+	CLK_5( IMX8QM_USB3_BUS_CLK, "USB3_BUS", 0, USB_3_LPCG, IMX8QM_USB3_BUS_DIV ),
+	CLK_5( IMX8QM_USB3_LPM_CLK, "USB3_LPM", 4, USB_3_LPCG, IMX8QM_USB3_LPM_DIV ),
+
+	CLK_5( IMX8QM_GPMI_APB_CLK, "GPMI_APB", 16, NAND_LPCG, IMX8QM_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_GPMI_APB_BCH_CLK, "GPMI_APB_BCH", 20, NAND_LPCG, IMX8QM_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QM_GPMI_BCH_IO_CLK, "GPMI_IO_CLK", 4, NAND_LPCG, IMX8QM_GPMI_BCH_IO_DIV ),
+	CLK_5( IMX8QM_GPMI_BCH_CLK, "GPMI_BCH_CLK", 0, NAND_LPCG, IMX8QM_GPMI_BCH_DIV ),
+	CLK_5( IMX8QM_APBHDMA_CLK, "GPMI_CLK", 16, NAND_LPCG + 0x4, IMX8QM_AXI_CONN_CLK_ROOT ),
+};
 
-	ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
-	if (ret) {
-		printf("%s err %d\n", __func__, ret);
-		return ret;
-	}
+struct imx8_mux_clks imx8qm_mux_clks[] = {
+};
 
-	return 0;
-}
+struct imx8_clks_collect imx8qm_clk_collect = {
+	{
+		{&imx8qm_clks, ARRAY_SIZE(imx8qm_clks)},
+		{&imx8qm_fixed_clks, ARRAY_SIZE(imx8qm_fixed_clks)},
+		{&imx8qm_gpr_clks, ARRAY_SIZE(imx8qm_gpr_clks)},
+		{&imx8qm_lpcg_clks, ARRAY_SIZE(imx8qm_lpcg_clks)},
+		{&imx8qm_mux_clks, ARRAY_SIZE(imx8qm_mux_clks)},
+	},
+	FLAG_CLK_IMX8_IMX8QM,
+};
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
index 1fca36a..8181a97 100644
--- a/drivers/clk/imx/clk-imx8qxp.c
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -12,300 +12,156 @@
 #include <dt-bindings/clock/imx8qxp-clock.h>
 #include <dt-bindings/soc/imx_rsrc.h>
 #include <misc.h>
+#include <asm/arch/lpcg.h>
 
 #include "clk-imx8.h"
 
-#if CONFIG_IS_ENABLED(CMD_CLK)
-struct imx8_clks imx8_clk_names[] = {
-	{ IMX8QXP_A35_DIV, "A35_DIV" },
-	{ IMX8QXP_I2C0_CLK, "I2C0" },
-	{ IMX8QXP_I2C1_CLK, "I2C1" },
-	{ IMX8QXP_I2C2_CLK, "I2C2" },
-	{ IMX8QXP_I2C3_CLK, "I2C3" },
-	{ IMX8QXP_UART0_CLK, "UART0" },
-	{ IMX8QXP_UART1_CLK, "UART1" },
-	{ IMX8QXP_UART2_CLK, "UART2" },
-	{ IMX8QXP_UART3_CLK, "UART3" },
-	{ IMX8QXP_SDHC0_CLK, "SDHC0" },
-	{ IMX8QXP_SDHC1_CLK, "SDHC1" },
-	{ IMX8QXP_ENET0_AHB_CLK, "ENET0_AHB" },
-	{ IMX8QXP_ENET0_IPG_CLK, "ENET0_IPG" },
-	{ IMX8QXP_ENET0_REF_DIV, "ENET0_REF" },
-	{ IMX8QXP_ENET0_PTP_CLK, "ENET0_PTP" },
-	{ IMX8QXP_ENET1_AHB_CLK, "ENET1_AHB" },
-	{ IMX8QXP_ENET1_IPG_CLK, "ENET1_IPG" },
-	{ IMX8QXP_ENET1_REF_DIV, "ENET1_REF" },
-	{ IMX8QXP_ENET1_PTP_CLK, "ENET1_PTP" },
+static struct imx8_clks imx8qxp_clks[] = {
+	CLK_4( IMX8QXP_A35_DIV, "A35_DIV", SC_R_A35, SC_PM_CLK_CPU ),
+	CLK_4( IMX8QXP_I2C0_DIV, "I2C0_DIV", SC_R_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_I2C1_DIV, "I2C1_DIV", SC_R_I2C_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_I2C2_DIV, "I2C2_DIV", SC_R_I2C_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_I2C3_DIV, "I2C3_DIV", SC_R_I2C_3, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_MIPI0_I2C0_DIV, "MIPI0 I2C0_DIV", SC_R_MIPI_0_I2C_0, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QXP_MIPI0_I2C1_DIV, "MIPI0 I2C1_DIV", SC_R_MIPI_0_I2C_1, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QXP_MIPI1_I2C0_DIV, "MIPI1 I2C0_DIV", SC_R_MIPI_1_I2C_0, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QXP_MIPI1_I2C1_DIV, "MIPI1 I2C1_DIV", SC_R_MIPI_1_I2C_1, SC_PM_CLK_MISC2 ),
+	CLK_4( IMX8QXP_CSI0_I2C0_DIV, "CSI0 I2C0_DIV", SC_R_CSI_0_I2C_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_UART0_DIV, "UART0_DIV", SC_R_UART_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_UART1_DIV, "UART1_DIV", SC_R_UART_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_UART2_DIV, "UART2_DIV", SC_R_UART_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_UART3_DIV, "UART3_DIV", SC_R_UART_3, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_SDHC0_DIV, "SDHC0_DIV", SC_R_SDHC_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_SDHC1_DIV, "SDHC1_DIV", SC_R_SDHC_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_SDHC2_DIV, "SDHC2_DIV", SC_R_SDHC_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_ENET0_ROOT_DIV, "ENET0_ROOT_DIV", SC_R_ENET_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_ENET0_RGMII_DIV, "ENET0_RGMII_DIV", SC_R_ENET_0, SC_PM_CLK_MISC0 ),
+	CLK_4( IMX8QXP_ENET1_ROOT_DIV, "ENET1_ROOT_DIV", SC_R_ENET_1, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_ENET1_RGMII_DIV, "ENET1_RGMII_DIV", SC_R_ENET_1, SC_PM_CLK_MISC0 ),
+	CLK_4( IMX8QXP_USB3_ACLK_DIV, "USB3_ACLK_DIV", SC_R_USB_2, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_USB3_BUS_DIV, "USB3_BUS_DIV", SC_R_USB_2, SC_PM_CLK_MST_BUS ),
+	CLK_4( IMX8QXP_USB3_LPM_DIV, "USB3_LPM_DIV", SC_R_USB_2, SC_PM_CLK_MISC ),
+	CLK_4( IMX8QXP_LSIO_FSPI0_DIV, "FSPI0_DIV", SC_R_FSPI_0, SC_PM_CLK_PER ),
+	CLK_4( IMX8QXP_GPMI_BCH_IO_DIV, "GPMI_IO_DIV", SC_R_NAND, SC_PM_CLK_MST_BUS ),
+	CLK_4( IMX8QXP_GPMI_BCH_DIV, "GPMI_BCH_DIV", SC_R_NAND, SC_PM_CLK_PER ),
 };
 
-int num_clks = ARRAY_SIZE(imx8_clk_names);
-#endif
-
-ulong imx8_clk_get_rate(struct clk *clk)
-{
-	sc_pm_clk_t pm_clk;
-	ulong rate;
-	u16 resource;
-	int ret;
-
-	debug("%s(#%lu)\n", __func__, clk->id);
-
-	switch (clk->id) {
-	case IMX8QXP_A35_DIV:
-		resource = SC_R_A35;
-		pm_clk = SC_PM_CLK_CPU;
-		break;
-	case IMX8QXP_I2C0_CLK:
-		resource = SC_R_I2C_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C1_CLK:
-		resource = SC_R_I2C_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C2_CLK:
-		resource = SC_R_I2C_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C3_CLK:
-		resource = SC_R_I2C_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_SDHC0_IPG_CLK:
-	case IMX8QXP_SDHC0_CLK:
-	case IMX8QXP_SDHC0_DIV:
-		resource = SC_R_SDHC_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_SDHC1_IPG_CLK:
-	case IMX8QXP_SDHC1_CLK:
-	case IMX8QXP_SDHC1_DIV:
-		resource = SC_R_SDHC_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART0_IPG_CLK:
-	case IMX8QXP_UART0_CLK:
-		resource = SC_R_UART_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART1_CLK:
-		resource = SC_R_UART_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART2_CLK:
-		resource = SC_R_UART_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART3_CLK:
-		resource = SC_R_UART_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_ENET0_IPG_CLK:
-	case IMX8QXP_ENET0_AHB_CLK:
-	case IMX8QXP_ENET0_REF_DIV:
-	case IMX8QXP_ENET0_PTP_CLK:
-		resource = SC_R_ENET_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_ENET1_IPG_CLK:
-	case IMX8QXP_ENET1_AHB_CLK:
-	case IMX8QXP_ENET1_REF_DIV:
-	case IMX8QXP_ENET1_PTP_CLK:
-		resource = SC_R_ENET_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	default:
-		if (clk->id < IMX8QXP_UART0_IPG_CLK ||
-		    clk->id >= IMX8QXP_CLK_END) {
-			printf("%s(Invalid clk ID #%lu)\n",
-			       __func__, clk->id);
-			return -EINVAL;
-		}
-		return -ENOTSUPP;
-	};
-
-	ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
-				   (sc_pm_clock_rate_t *)&rate);
-	if (ret) {
-		printf("%s err %d\n", __func__, ret);
-		return ret;
-	}
-
-	return rate;
-}
-
-ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	sc_pm_clk_t pm_clk;
-	u32 new_rate = rate;
-	u16 resource;
-	int ret;
-
-	debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
-	switch (clk->id) {
-	case IMX8QXP_I2C0_CLK:
-		resource = SC_R_I2C_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C1_CLK:
-		resource = SC_R_I2C_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C2_CLK:
-		resource = SC_R_I2C_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C3_CLK:
-		resource = SC_R_I2C_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART0_CLK:
-		resource = SC_R_UART_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART1_CLK:
-		resource = SC_R_UART_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART2_CLK:
-		resource = SC_R_UART_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART3_CLK:
-		resource = SC_R_UART_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_SDHC0_IPG_CLK:
-	case IMX8QXP_SDHC0_CLK:
-	case IMX8QXP_SDHC0_DIV:
-		resource = SC_R_SDHC_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_SDHC1_SEL:
-	case IMX8QXP_SDHC0_SEL:
-		return 0;
-	case IMX8QXP_SDHC1_IPG_CLK:
-	case IMX8QXP_SDHC1_CLK:
-	case IMX8QXP_SDHC1_DIV:
-		resource = SC_R_SDHC_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_ENET0_IPG_CLK:
-	case IMX8QXP_ENET0_AHB_CLK:
-	case IMX8QXP_ENET0_REF_DIV:
-	case IMX8QXP_ENET0_PTP_CLK:
-		resource = SC_R_ENET_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_ENET1_IPG_CLK:
-	case IMX8QXP_ENET1_AHB_CLK:
-	case IMX8QXP_ENET1_REF_DIV:
-	case IMX8QXP_ENET1_PTP_CLK:
-		resource = SC_R_ENET_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	default:
-		if (clk->id < IMX8QXP_UART0_IPG_CLK ||
-		    clk->id >= IMX8QXP_CLK_END) {
-			printf("%s(Invalid clk ID #%lu)\n",
-			       __func__, clk->id);
-			return -EINVAL;
-		}
-		return -ENOTSUPP;
-	};
-
-	ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
-	if (ret) {
-		printf("%s err %d\n", __func__, ret);
-		return ret;
-	}
-
-	return new_rate;
-}
-
-int __imx8_clk_enable(struct clk *clk, bool enable)
-{
-	sc_pm_clk_t pm_clk;
-	u16 resource;
-	int ret;
+static struct imx8_fixed_clks imx8qxp_fixed_clks[] = {
+	CLK_3( IMX8QXP_IPG_CONN_CLK_ROOT, "IPG_CONN_CLK", SC_83MHZ ),
+	CLK_3( IMX8QXP_AHB_CONN_CLK_ROOT, "AHB_CONN_CLK", SC_166MHZ ),
+	CLK_3( IMX8QXP_AXI_CONN_CLK_ROOT, "AXI_CONN_CLK", SC_333MHZ ),
+	CLK_3( IMX8QXP_IPG_DMA_CLK_ROOT, "IPG_DMA_CLK", SC_120MHZ ),
+	CLK_3( IMX8QXP_MIPI_IPG_CLK, "IPG_MIPI_CLK", SC_120MHZ ),
+	CLK_3( IMX8QXP_LSIO_BUS_CLK, "LSIO_BUS_CLK", SC_100MHZ ),
+	CLK_3( IMX8QXP_LSIO_MEM_CLK, "LSIO_MEM_CLK", SC_200MHZ ),
+};
 
-	debug("%s(#%lu)\n", __func__, clk->id);
+static struct imx8_gpr_clks imx8qxp_gpr_clks[] = {
+	CLK_5( IMX8QXP_ENET0_REF_DIV, "ENET0_REF_DIV", SC_R_ENET_0, SC_C_CLKDIV, IMX8QXP_ENET0_ROOT_DIV ),
+	CLK_4( IMX8QXP_ENET0_REF_25MHZ_125MHZ_SEL, "ENET0_REF_25_125", SC_R_ENET_0, SC_C_SEL_125 ),
+	CLK_4( IMX8QXP_ENET0_RMII_TX_SEL, "ENET0_RMII_TX", SC_R_ENET_0, SC_C_TXCLK ),
+	CLK_4( IMX8QXP_ENET0_REF_25MHZ_125MHZ_CLK, "ENET0_REF_25_125_CLK", SC_R_ENET_0, SC_C_DISABLE_125 ),
+	CLK_4( IMX8QXP_ENET0_REF_50MHZ_CLK, "ENET0_REF_50", SC_R_ENET_0, SC_C_DISABLE_50 ),
+
+	CLK_5( IMX8QXP_ENET1_REF_DIV, "ENET1_REF_DIV", SC_R_ENET_1, SC_C_CLKDIV, IMX8QXP_ENET1_ROOT_DIV ),
+	CLK_4( IMX8QXP_ENET1_REF_25MHZ_125MHZ_SEL, "ENET1_REF_25_125", SC_R_ENET_1, SC_C_SEL_125 ),
+	CLK_4( IMX8QXP_ENET1_RMII_TX_SEL, "ENET1_RMII_TX", SC_R_ENET_1, SC_C_TXCLK ),
+	CLK_4( IMX8QXP_ENET1_REF_25MHZ_125MHZ_CLK, "ENET1_REF_25_125_CLK", SC_R_ENET_1, SC_C_DISABLE_125 ),
+	CLK_4( IMX8QXP_ENET1_REF_50MHZ_CLK, "ENET1_REF_50", SC_R_ENET_1, SC_C_DISABLE_50 ),
+};
 
-	switch (clk->id) {
-	case IMX8QXP_I2C0_CLK:
-		resource = SC_R_I2C_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C1_CLK:
-		resource = SC_R_I2C_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C2_CLK:
-		resource = SC_R_I2C_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_I2C3_CLK:
-		resource = SC_R_I2C_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART0_CLK:
-		resource = SC_R_UART_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART1_CLK:
-		resource = SC_R_UART_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART2_CLK:
-		resource = SC_R_UART_2;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_UART3_CLK:
-		resource = SC_R_UART_3;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_SDHC0_IPG_CLK:
-	case IMX8QXP_SDHC0_CLK:
-	case IMX8QXP_SDHC0_DIV:
-		resource = SC_R_SDHC_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_SDHC1_IPG_CLK:
-	case IMX8QXP_SDHC1_CLK:
-	case IMX8QXP_SDHC1_DIV:
-		resource = SC_R_SDHC_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_ENET0_IPG_CLK:
-	case IMX8QXP_ENET0_AHB_CLK:
-	case IMX8QXP_ENET0_REF_DIV:
-	case IMX8QXP_ENET0_PTP_CLK:
-		resource = SC_R_ENET_0;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	case IMX8QXP_ENET1_IPG_CLK:
-	case IMX8QXP_ENET1_AHB_CLK:
-	case IMX8QXP_ENET1_REF_DIV:
-	case IMX8QXP_ENET1_PTP_CLK:
-		resource = SC_R_ENET_1;
-		pm_clk = SC_PM_CLK_PER;
-		break;
-	default:
-		if (clk->id < IMX8QXP_UART0_IPG_CLK ||
-		    clk->id >= IMX8QXP_CLK_END) {
-			printf("%s(Invalid clk ID #%lu)\n",
-			       __func__, clk->id);
-			return -EINVAL;
-		}
-		return -ENOTSUPP;
-	}
+static struct imx8_lpcg_clks imx8qxp_lpcg_clks[] = {
+	CLK_5( IMX8QXP_I2C0_CLK, "I2C0_CLK", 0, LPI2C_0_LPCG, IMX8QXP_I2C0_DIV ),
+	CLK_5( IMX8QXP_I2C0_IPG_CLK, "I2C0_IPG", 16, LPI2C_0_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_I2C1_CLK, "I2C1_CLK", 0, LPI2C_1_LPCG, IMX8QXP_I2C1_DIV ),
+	CLK_5( IMX8QXP_I2C1_IPG_CLK, "I2C1_IPG", 16, LPI2C_1_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_I2C2_CLK, "I2C2_CLK", 0, LPI2C_2_LPCG, IMX8QXP_I2C2_DIV ),
+	CLK_5( IMX8QXP_I2C2_IPG_CLK, "I2C2_IPG", 16, LPI2C_2_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_I2C3_CLK, "I2C3_CLK", 0, LPI2C_3_LPCG, IMX8QXP_I2C3_DIV ),
+	CLK_5( IMX8QXP_I2C3_IPG_CLK, "I2C3_IPG", 16, LPI2C_3_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_MIPI0_I2C0_CLK, "MIPI0_I2C0_CLK", 0, DI_MIPI0_LPCG + 0x10, IMX8QXP_MIPI0_I2C0_DIV ),
+	CLK_5( IMX8QXP_MIPI0_I2C0_IPG_CLK, "MIPI0_I2C0_IPG", 16, DI_MIPI0_LPCG + 0x10, IMX8QXP_MIPI_IPG_CLK ),
+	CLK_5( IMX8QXP_MIPI0_I2C1_CLK, "MIPI0_I2C1_CLK", 0, DI_MIPI0_LPCG + 0x14, IMX8QXP_MIPI0_I2C1_DIV ),
+	CLK_5( IMX8QXP_MIPI0_I2C1_IPG_CLK, "MIPI0_I2C1_IPG", 16, DI_MIPI0_LPCG + 0x14, IMX8QXP_MIPI_IPG_CLK ),
+	CLK_5( IMX8QXP_MIPI1_I2C0_CLK, "MIPI1_I2C0_CLK", 0, DI_MIPI1_LPCG + 0x10, IMX8QXP_MIPI1_I2C0_DIV ),
+	CLK_5( IMX8QXP_MIPI1_I2C0_IPG_CLK, "MIPI1_I2C0_IPG", 16, DI_MIPI1_LPCG + 0x10, IMX8QXP_MIPI_IPG_CLK ),
+	CLK_5( IMX8QXP_MIPI1_I2C1_CLK, "MIPI1_I2C1_CLK", 0, DI_MIPI1_LPCG + 0x14, IMX8QXP_MIPI1_I2C1_DIV ),
+	CLK_5( IMX8QXP_MIPI1_I2C1_IPG_CLK, "MIPI1_I2C1_IPG", 16, DI_MIPI1_LPCG + 0x14, IMX8QXP_MIPI_IPG_CLK ),
+	CLK_5( IMX8QXP_CSI0_I2C0_CLK, "CSI0_I2C0_CLK", 0, MIPI_CSI_0_LPCG + 0x14, IMX8QXP_CSI0_I2C0_DIV ),
+	CLK_5( IMX8QXP_CSI0_I2C0_IPG_CLK, "CSI0_I2C0_IPG", 16, MIPI_CSI_0_LPCG + 0x14, IMX8QXP_MIPI_IPG_CLK ),
+
+	CLK_5( IMX8QXP_UART0_CLK, "UART0_CLK", 0, LPUART_0_LPCG, IMX8QXP_UART0_DIV ),
+	CLK_5( IMX8QXP_UART0_IPG_CLK, "UART0_IPG", 16, LPUART_0_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_UART1_CLK, "UART1_CLK", 0, LPUART_1_LPCG, IMX8QXP_UART1_DIV ),
+	CLK_5( IMX8QXP_UART1_IPG_CLK, "UART1_IPG", 16, LPUART_1_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_UART2_CLK, "UART2_CLK", 0, LPUART_2_LPCG, IMX8QXP_UART2_DIV ),
+	CLK_5( IMX8QXP_UART2_IPG_CLK, "UART2_IPG", 16, LPUART_2_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+	CLK_5( IMX8QXP_UART3_CLK, "UART3_CLK", 0, LPUART_3_LPCG, IMX8QXP_UART3_DIV ),
+	CLK_5( IMX8QXP_UART3_IPG_CLK, "UART3_IPG", 16, LPUART_3_LPCG, IMX8QXP_IPG_DMA_CLK_ROOT ),
+
+	CLK_5( IMX8QXP_SDHC0_CLK, "SDHC0_CLK", 0, USDHC_0_LPCG, IMX8QXP_SDHC0_DIV ),
+	CLK_5( IMX8QXP_SDHC0_IPG_CLK, "SDHC0_IPG", 16, USDHC_0_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_SDHC1_CLK, "SDHC1_CLK", 0, USDHC_1_LPCG, IMX8QXP_SDHC1_DIV ),
+	CLK_5( IMX8QXP_SDHC1_IPG_CLK, "SDHC1_IPG", 16, USDHC_1_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_SDHC2_CLK, "SDHC2_CLK", 0, USDHC_2_LPCG, IMX8QXP_SDHC2_DIV ),
+	CLK_5( IMX8QXP_SDHC2_IPG_CLK, "SDHC2_IPG", 16, USDHC_2_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+
+	CLK_5( IMX8QXP_ENET0_IPG_S_CLK, "ENET0_IPG_S", 20, ENET_0_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_ENET0_IPG_CLK, "ENET0_IPG", 16, ENET_0_LPCG, IMX8QXP_ENET0_IPG_S_CLK ),
+	CLK_5( IMX8QXP_ENET0_AHB_CLK, "ENET0_AHB", 8, ENET_0_LPCG, IMX8QXP_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_ENET0_TX_CLK, "ENET0_TX", 4, ENET_0_LPCG, IMX8QXP_ENET0_ROOT_DIV ),
+	CLK_5( IMX8QXP_ENET0_PTP_CLK, "ENET0_PTP", 0, ENET_0_LPCG, IMX8QXP_ENET0_ROOT_DIV  ),
+	CLK_5( IMX8QXP_ENET0_RGMII_TX_CLK, "ENET0_RGMII_TX", 12, ENET_0_LPCG, IMX8QXP_ENET0_RMII_TX_SEL  ),
+	CLK_5( IMX8QXP_ENET0_RMII_RX_CLK, "ENET0_RMII_RX", 0, ENET_0_LPCG + 0x4, IMX8QXP_ENET0_RGMII_DIV  ),
+
+	CLK_5( IMX8QXP_ENET1_IPG_S_CLK, "ENET1_IPG_S", 20, ENET_1_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_ENET1_IPG_CLK, "ENET1_IPG", 16, ENET_1_LPCG, IMX8QXP_ENET1_IPG_S_CLK ),
+	CLK_5( IMX8QXP_ENET1_AHB_CLK, "ENET1_AHB", 8, ENET_1_LPCG, IMX8QXP_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_ENET1_TX_CLK, "ENET1_TX", 4, ENET_1_LPCG, IMX8QXP_ENET1_ROOT_DIV ),
+	CLK_5( IMX8QXP_ENET1_PTP_CLK, "ENET1_PTP", 0, ENET_1_LPCG, IMX8QXP_ENET1_ROOT_DIV  ),
+	CLK_5( IMX8QXP_ENET1_RGMII_TX_CLK, "ENET1_RGMII_TX", 12, ENET_1_LPCG, IMX8QXP_ENET1_RMII_TX_SEL  ),
+	CLK_5( IMX8QXP_ENET1_RMII_RX_CLK, "ENET1_RMII_RX", 0, ENET_1_LPCG + 0x4, IMX8QXP_ENET1_RGMII_DIV  ),
+
+	CLK_5( IMX8QXP_LSIO_FSPI0_IPG_S_CLK, "FSPI0_IPG_S", 0x18, FSPI_0_LPCG, IMX8QXP_LSIO_BUS_CLK ),
+	CLK_5( IMX8QXP_LSIO_FSPI0_IPG_CLK, "FSPI0_IPG", 0x14, FSPI_0_LPCG, IMX8QXP_LSIO_FSPI0_IPG_S_CLK ),
+	CLK_5( IMX8QXP_LSIO_FSPI0_HCLK, "FSPI0_HCLK", 0x10, FSPI_0_LPCG, IMX8QXP_LSIO_MEM_CLK ),
+	CLK_5( IMX8QXP_LSIO_FSPI0_CLK, "FSPI0_CLK", 0, FSPI_0_LPCG, IMX8QXP_LSIO_FSPI0_DIV ),
+
+	CLK_5( IMX8QXP_USB2_OH_AHB_CLK, "USB2_OH_AHB", 24, USB_2_LPCG, IMX8QXP_AHB_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_USB2_OH_IPG_S_CLK, "USB2_OH_IPG_S", 16, USB_2_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_USB2_OH_IPG_S_PL301_CLK, "USB2_OH_IPG_S_PL301", 20, USB_2_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_USB2_PHY_IPG_CLK, "USB2_PHY_IPG", 28, USB_2_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+
+	CLK_5( IMX8QXP_USB3_IPG_CLK, "USB3_IPG", 16, USB_3_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_USB3_CORE_PCLK, "USB3_CORE", 20, USB_3_LPCG, IMX8QXP_IPG_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_USB3_PHY_CLK, "USB3_PHY", 24, USB_3_LPCG, IMX8QXP_USB3_IPG_CLK ),
+	CLK_5( IMX8QXP_USB3_ACLK, "USB3_ACLK", 28, USB_3_LPCG, IMX8QXP_USB3_ACLK_DIV ),
+	CLK_5( IMX8QXP_USB3_BUS_CLK, "USB3_BUS", 0, USB_3_LPCG, IMX8QXP_USB3_BUS_DIV ),
+	CLK_5( IMX8QXP_USB3_LPM_CLK, "USB3_LPM", 4, USB_3_LPCG, IMX8QXP_USB3_LPM_DIV ),
+
+	CLK_5( IMX8QXP_GPMI_APB_CLK, "GPMI_APB", 16, NAND_LPCG, IMX8QXP_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_GPMI_APB_BCH_CLK, "GPMI_APB_BCH", 20, NAND_LPCG, IMX8QXP_AXI_CONN_CLK_ROOT ),
+	CLK_5( IMX8QXP_GPMI_BCH_IO_CLK, "GPMI_IO_CLK", 4, NAND_LPCG, IMX8QXP_GPMI_BCH_IO_DIV ),
+	CLK_5( IMX8QXP_GPMI_BCH_CLK, "GPMI_BCH_CLK", 0, NAND_LPCG, IMX8QXP_GPMI_BCH_DIV ),
+	CLK_5( IMX8QXP_APBHDMA_CLK, "GPMI_CLK", 16, NAND_LPCG + 0x4, IMX8QXP_AXI_CONN_CLK_ROOT ),
+};
 
-	ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
-	if (ret) {
-		printf("%s err %d\n", __func__, ret);
-		return ret;
-	}
+struct imx8_mux_clks imx8qxp_mux_clks[] = {
+	CLK_MUX( IMX8QXP_SDHC0_SEL, "SDHC0_SEL", IMX8QXP_SDHC0_DIV, IMX8QXP_CLK_DUMMY, IMX8QXP_CONN_PLL0_CLK,
+		IMX8QXP_CONN_PLL1_CLK, IMX8QXP_CLK_DUMMY, IMX8QXP_CLK_DUMMY ),
+	CLK_MUX( IMX8QXP_SDHC1_SEL, "SDHC1_SEL", IMX8QXP_SDHC1_DIV, IMX8QXP_CLK_DUMMY, IMX8QXP_CONN_PLL0_CLK,
+		IMX8QXP_CONN_PLL1_CLK, IMX8QXP_CLK_DUMMY, IMX8QXP_CLK_DUMMY ),
+	CLK_MUX( IMX8QXP_SDHC2_SEL, "SDHC2_SEL", IMX8QXP_SDHC2_DIV, IMX8QXP_CLK_DUMMY, IMX8QXP_CONN_PLL0_CLK,
+		IMX8QXP_CONN_PLL1_CLK, IMX8QXP_CLK_DUMMY, IMX8QXP_CLK_DUMMY ),
+};
 
-	return 0;
-}
+struct imx8_clks_collect imx8qxp_clk_collect = {
+	{
+		{&imx8qxp_clks, ARRAY_SIZE(imx8qxp_clks)},
+		{&imx8qxp_fixed_clks, ARRAY_SIZE(imx8qxp_fixed_clks)},
+		{&imx8qxp_gpr_clks, ARRAY_SIZE(imx8qxp_gpr_clks)},
+		{&imx8qxp_lpcg_clks, ARRAY_SIZE(imx8qxp_lpcg_clks)},
+		{&imx8qxp_mux_clks, ARRAY_SIZE(imx8qxp_mux_clks)},
+	},
+	FLAG_CLK_IMX8_IMX8QXP,
+};
-- 
2.7.4



More information about the U-Boot mailing list