[U-Boot,v2,3/7] clk: imx8: Update imx8 clock driver
diff mbox series

Message ID 1562147167-27330-3-git-send-email-ye.li@nxp.com
State New
Delegated to: Stefano Babic
Headers show
Series
  • [U-Boot,v2,1/7] imx8: Add lpcg driver for iMX8QM/QXP
Related show

Commit Message

Ye Li July 3, 2019, 9:46 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>
---
Changes in v2:
 - None

 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

Peng Fan Sept. 17, 2019, 6:52 a.m. UTC | #1
Hi All,

> Subject: [PATCH v2 3/7] clk: imx8: Update imx8 clock driver

Sorry to bring back this topic.

This patch is not converting to CCF following Linux, but it could
satisfy u-boot usage and make more feature work.

I checked Linux i.MX8 CCF recently, although Linux upstream has i.MX8
CCF support, but NXP downstream has significantly reimplement the code.
So we could not take code directly from Linux upstream, because this
would introduce efforts in U-Boot after NXP downstream clk code upstreamed.

I have also tried to converting to use NXP downstream Linux ccf code in u-boot,
but there is an issue is some clks are root clks, no parents. However u-boot ccf
always requires a parent for a clk. Anyway there is still long time to upstream
nxp Linux downstream clk code to Linux.

I would hear your voice about U-Boot part. Proceed with current patch
or promoting CCF with NXP downstream clk?

Thanks,
Peng.

> 
> 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>
> ---
> Changes in v2:
>  - None
> 
>  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,
> +};
> --
> 2.7.4
Lukasz Majewski Sept. 17, 2019, 7:28 a.m. UTC | #2
Hi Peng,

> Hi All,
> 
> > Subject: [PATCH v2 3/7] clk: imx8: Update imx8 clock driver  
> 
> Sorry to bring back this topic.
> 
> This patch is not converting to CCF following Linux, but it could
> satisfy u-boot usage and make more feature work.
> 
> I checked Linux i.MX8 CCF recently, although Linux upstream has i.MX8
> CCF support, but NXP downstream has significantly reimplement the
> code. So we could not take code directly from Linux upstream, because
> this would introduce efforts in U-Boot after NXP downstream clk code
> upstreamed.
> 
> I have also tried to converting to use NXP downstream Linux ccf code
> in u-boot, but there is an issue is some clks are root clks, no
> parents. However u-boot ccf always requires a parent for a clk.
> Anyway there is still long time to upstream nxp Linux downstream clk
> code to Linux.
> 
> I would hear your voice about U-Boot part. Proceed with current patch
> or promoting CCF with NXP downstream clk?

It depends.

One reason for using Linux clocks (backported from Linux) is that there
is a chance that this code would be maintained for a long time and
hence subsequent updates from Linux would have the chance to work.

With NXP downstream code - it may happen that we will end up with some
in-mainline version not being in sync with Linux and with future NXP
internal BSP releases.


My standpoint is as follows - if you feel like there is a pretty high
chance that NXP downstream clk code will be accepted to Linux _soon_,
then I don't mind to have it in U-Boot.

This is all the matter of active maintenance of the CLK code ...

> 
> Thanks,
> Peng.
> 
> > 
> > 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>
> > ---
> > Changes in v2:
> >  - None
> > 
> >  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,
> > +};
> > --
> > 2.7.4  
> 



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

Patch
diff mbox series

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