diff mbox series

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

Message ID 1562132399-114515-3-git-send-email-ye.li@nxp.com
State Superseded
Delegated to: Stefano Babic
Headers show
Series [U-Boot,1/5] imx8: Add lpcg driver for iMX8QM/QXP | expand

Commit Message

Ye Li July 3, 2019, 5:40 a.m. UTC
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@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(-)

Comments

Lukasz Majewski July 6, 2019, 11:07 p.m. UTC | #1
Hi Ye,

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

Is this code in sync with Linux kernel? Does the imx8 (in Linux kernel)
use the Common Clock Framework?

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


I've posted the Common Clock Framework v5 to the mailing list recently:
https://patchwork.ozlabs.org/cover/1121348/


So maybe this code could benefit from those patches and use this
infrastructure ?

> 
> 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@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@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,
> +};




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Ye Li July 10, 2019, 7:14 a.m. UTC | #2
Hi Lukasz,

> Hi Ye,
> 
>> 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.
> 
> Is this code in sync with Linux kernel? Does the imx8 (in Linux kernel)
> use the Common Clock Framework?
This patch syncs the tree architecture with kernel but not the codes. imx8 kernel clock
driver uses common clock framework.

> 
>> 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.
> 
> 
> I've posted the Common Clock Framework v5 to the mailing list recently:
> https://patchwork.ozlabs.org/cover/1121348/
> 
> 
> So maybe this code could benefit from those patches and use this
> infrastructure ?
> 
I think so. We will look into the CCF in u-boot and migrate it later. 
But now we prefer upstream this update first. This one has been tested in downstream. 
And we have some driver patches going for upstream depending on it, while 
a new driver using CCF may need more time to get ready.

Best regards,
Ye Li
>>
>> 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@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@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,
>> +};
> 
> 
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
>
Lukasz Majewski July 10, 2019, 7:34 a.m. UTC | #3
Hi Ye,

> Hi Lukasz,
> 
> > Hi Ye,
> >   
> >> 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.  
> > 
> > Is this code in sync with Linux kernel? Does the imx8 (in Linux
> > kernel) use the Common Clock Framework?  
> This patch syncs the tree architecture with kernel but not the codes.
> imx8 kernel clock driver uses common clock framework.
> 
> >   
> >> 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.  
> > 
> > 
> > I've posted the Common Clock Framework v5 to the mailing list
> > recently: https://patchwork.ozlabs.org/cover/1121348/
> > 
> > 
> > So maybe this code could benefit from those patches and use this
> > infrastructure ?
> >   
> I think so. We will look into the CCF in u-boot and migrate it later. 

Sorry, but I'm involved in the open source U-Boot developement for too
long to believe in such statements.

If the feature is not added from the outset, then it will not be
changed.

> But now we prefer upstream this update first. This one has been
> tested in downstream. And we have some driver patches going for
> upstream depending on it, while a new driver using CCF may need more
> time to get ready.
> 
> Best regards,
> Ye Li
> >>
> >> 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@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@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,
> >> +};  
> > 
> > 
> > 
> > 
> > Best regards,
> > 
> > Lukasz Majewski
> > 
> > --
> > 
> > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> > Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> > lukma@denx.de 
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Ye Li July 10, 2019, 8:25 a.m. UTC | #4
Hi Lukasz,

> Hi Ye,
> 
>> Hi Lukasz,
>>
>>> Hi Ye,
>>>   
>>>> 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.  
>>>
>>> Is this code in sync with Linux kernel? Does the imx8 (in Linux
>>> kernel) use the Common Clock Framework?  
>> This patch syncs the tree architecture with kernel but not the codes.
>> imx8 kernel clock driver uses common clock framework.
>>
>>>   
>>>> 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.  
>>>
>>>
>>> I've posted the Common Clock Framework v5 to the mailing list
>>> recently: https://patchwork.ozlabs.org/cover/1121348/
>>>
>>>
>>> So maybe this code could benefit from those patches and use this
>>> infrastructure ?
>>>   
>> I think so. We will look into the CCF in u-boot and migrate it later. 
> 
> Sorry, but I'm involved in the open source U-Boot developement for too
> long to believe in such statements.
> 
> If the feature is not added from the outset, then it will not be
> changed.
> 
So when will CCF be pushed? 

Best regards,
Ye Li
>> But now we prefer upstream this update first. This one has been
>> tested in downstream. And we have some driver patches going for
>> upstream depending on it, while a new driver using CCF may need more
>> time to get ready.
>>
>> Best regards,
>> Ye Li
>>>>
>>>> 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@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@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,
>>>> +};  
>>>
>>>
>>>
>>>
>>> Best regards,
>>>
>>> Lukasz Majewski
>>>
>>> --
>>>
>>> DENX Software Engineering GmbH,      Managing Director: Wolfgang
>>> Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
>>> Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
>>> lukma@denx.de 
>>
> 
> 
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
>
Lukasz Majewski July 10, 2019, 8:46 a.m. UTC | #5
On Wed, 10 Jul 2019 08:25:13 +0000
Ye Li <ye.li@nxp.com> wrote:

> Hi Lukasz,
> 
> > Hi Ye,
> >   
> >> Hi Lukasz,
> >>  
> >>> Hi Ye,
> >>>     
> >>>> 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.    
> >>>
> >>> Is this code in sync with Linux kernel? Does the imx8 (in Linux
> >>> kernel) use the Common Clock Framework?    
> >> This patch syncs the tree architecture with kernel but not the
> >> codes. imx8 kernel clock driver uses common clock framework.
> >>  
> >>>     
> >>>> 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.    
> >>>
> >>>
> >>> I've posted the Common Clock Framework v5 to the mailing list
> >>> recently: https://patchwork.ozlabs.org/cover/1121348/
> >>>
> >>>
> >>> So maybe this code could benefit from those patches and use this
> >>> infrastructure ?
> >>>     
> >> I think so. We will look into the CCF in u-boot and migrate it
> >> later.   
> > 
> > Sorry, but I'm involved in the open source U-Boot developement for
> > too long to believe in such statements.
> > 
> > If the feature is not added from the outset, then it will not be
> > changed.
> >   
> So when will CCF be pushed? 

It will be pulled when Simon ACKs it. It also may happen (and often
happens) that somebody from the community will lately jump in and we
would need to discuss it again.

> 
> Best regards,
> Ye Li
> >> But now we prefer upstream this update first. This one has been
> >> tested in downstream. And we have some driver patches going for
> >> upstream depending on it, while a new driver using CCF may need
> >> more time to get ready.
> >>
> >> Best regards,
> >> Ye Li  
> >>>>
> >>>> 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@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@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,
> >>>> +};    
> >>>
> >>>
> >>>
> >>>
> >>> Best regards,
> >>>
> >>> Lukasz Majewski
> >>>
> >>> --
> >>>
> >>> DENX Software Engineering GmbH,      Managing Director: Wolfgang
> >>> Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> >>> Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> >>> lukma@denx.de   
> >>  
> > 
> > 
> > 
> > 
> > Best regards,
> > 
> > Lukasz Majewski
> > 
> > --
> > 
> > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> > Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> > lukma@denx.de 
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
diff mbox series

Patch

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@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,
+};