All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP
@ 2019-07-03  9:46 Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 2/7] misc: scu_api: Add new APIs for clk-imx8 driver Ye Li
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

Each module may have one or more lpcg registers for SW/HW enabling its
clocks. Add lpcg register address and its driver for accessing lpcg.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
Changes in v2:
 - Fix license and blank line

 arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h  | 198 ++++++++++++++++++++++++++
 arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h | 192 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-imx8/lpcg.h         |  25 ++++
 arch/arm/mach-imx/imx8/Makefile               |   2 +-
 arch/arm/mach-imx/imx8/lpcg.c                 | 114 +++++++++++++++
 5 files changed, 530 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h
 create mode 100644 arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h
 create mode 100644 arch/arm/include/asm/arch-imx8/lpcg.h
 create mode 100644 arch/arm/mach-imx/imx8/lpcg.c

diff --git a/arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h b/arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h
new file mode 100644
index 0000000..718dac4
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#ifndef _SC_LPCG_H
+#define _SC_LPCG_H
+
+/*LSIO SS */
+#define		PWM_0_LPCG		0x5D400000
+#define		PWM_1_LPCG		0x5D410000
+#define		PWM_2_LPCG		0x5D420000
+#define		PWM_3_LPCG		0x5D430000
+#define		PWM_4_LPCG		0x5D440000
+#define		PWM_5_LPCG		0x5D450000
+#define		PWM_6_LPCG		0x5D460000
+#define		PWM_7_LPCG		0x5D470000
+#define		GPIO_0_LPCG		0x5D480000
+#define		GPIO_1_LPCG		0x5D490000
+#define		GPIO_2_LPCG		0x5D4A0000
+#define		GPIO_3_LPCG		0x5D4B0000
+#define		GPIO_4_LPCG		0x5D4C0000
+#define		GPIO_5_LPCG		0x5D4D0000
+#define		GPIO_6_LPCG		0x5D4E0000
+#define		GPIO_7_LPCG		0x5D4F0000
+#define		FSPI_0_LPCG		0x5D520000
+#define		FSPI_1_LPCG		0x5D530000
+#define		GPT_0_LPCG		0x5D540000
+#define		GPT_1_LPCG		0x5D550000
+#define		GPT_2_LPCG		0x5D560000
+#define		GPT_3_LPCG		0x5D570000
+#define		GPT_4_LPCG		0x5D580000
+#define		OCRAM_LPCG		0x5D590000
+#define		KPP_LPCG		0x5D5A0000
+#define		MU_5A_LPCG		0x5D600000
+#define		MU_6A_LPCG		0x5D610000
+#define		MU_7A_LPCG		0x5D620000
+#define		MU_8A_LPCG		0x5D630000
+#define		MU_9A_LPCG		0x5D640000
+#define		MU_10A_LPCG		0x5D650000
+#define		MU_11A_LPCG		0x5D660000
+#define		MU_12A_LPCG		0x5D670000
+#define		MU_13A_LPCG		0x5D680000
+
+/* HSIO SS */
+#define		CRR_5_LPCG		0x5F0F0000
+#define		CRR_4_LPCG		0x5F0E0000
+#define		CRR_3_LPCG		0x5F0D0000
+#define		CRR_2_LPCG		0x5F0C0000
+#define		CRR_1_LPCG		0x5F0B0000
+#define		CRR_0_LPCG		0x5F0A0000
+#define		PHY_1_LPCG		0x5F090000
+#define		PHY_2_LPCG		0x5F080000
+#define		SATA_0_LPCG		0x5F070000
+#define		PCIE_B_LPCG		0x5F060000
+#define		PCIE_A_LPCG		0x5F050000
+
+/* DMA SS */
+#define		FLEX_CAN_2_LPCG		0x5ACF0000
+#define		FLEX_CAN_1_LPCG		0x5ACE0000
+#define		FLEX_CAN_0_LPCG		0x5ACD0000
+#define		FTM_1_LPCG		0x5ACB0000
+#define		FTM_0_LPCG		0x5ACA0000
+#define		ADC_1_LPCG		0x5AC90000
+#define		ADC_0_LPCG		0x5AC80000
+#define		LPI2C_4_LPCG		0x5AC40000
+#define		LPI2C_3_LPCG		0x5AC30000
+#define		LPI2C_2_LPCG		0x5AC20000
+#define		LPI2C_1_LPCG		0x5AC10000
+#define		LPI2C_0_LPCG		0x5AC00000
+#define		EMVSIM_1_LPCG		0x5A4E0000
+#define		EMVSIM_0_LPCG		0x5A4D0000
+#define		LPUART_4_LPCG		0x5A4A0000
+#define		LPUART_3_LPCG		0x5A490000
+#define		LPUART_2_LPCG		0x5A480000
+#define		LPUART_1_LPCG		0x5A470000
+#define		LPUART_0_LPCG		0x5A460000
+#define		LPSPI_3_LPCG		0x5A430000
+#define		LPSPI_2_LPCG		0x5A420000
+#define		LPSPI_1_LPCG		0x5A410000
+#define		LPSPI_0_LPCG		0x5A400000
+
+/* Display SS */
+#define		DC_0_LPCG		0x56010000
+#define		DC_1_LPCG		0x57010000
+
+/* LVDS */
+#define		DI_LVDS_0_LPCG		0x56243000
+#define		DI_LVDS_1_LPCG		0x57243000
+
+/* DI HDMI */
+#define		DI_HDMI_LPCG		0x56263000
+
+/* RX-HDMI */
+#define		RX_HDMI_LPCG		0x58263000
+
+/* MIPI CSI SS */
+#define		MIPI_CSI_0_LPCG		0x58223000
+#define		MIPI_CSI_1_LPCG		0x58243000
+
+/* MIPI DSI SS */
+#define		MIPI_DSI_0_LPCG		0x56223000
+#define		MIPI_DSI_1_LPCG		0x57223000
+
+/* Imaging SS */
+#define IMG_JPEG_ENC_LPCG		0x585F0000
+#define IMG_JPEG_DEC_LPCG		0x585D0000
+#define IMG_PXL_LINK_DC1_LPCG	0x585C0000
+#define IMG_PXL_LINK_DC0_LPCG	0x585B0000
+#define IMG_PXL_LINK_HDMI_LPCG	0x585A0000
+#define IMG_PXL_LINK_CSI1_LPCG	0x58590000
+#define IMG_PXL_LINK_CSI0_LPCG	0x58580000
+#define IMG_PDMA_7_LPCG			0x58570000
+#define IMG_PDMA_6_LPCG			0x58560000
+#define IMG_PDMA_5_LPCG			0x58550000
+#define IMG_PDMA_4_LPCG			0x58540000
+#define IMG_PDMA_3_LPCG			0x58530000
+#define IMG_PDMA_2_LPCG			0x58520000
+#define IMG_PDMA_1_LPCG			0x58510000
+#define IMG_PDMA_0_LPCG			0x58500000
+
+/* HSIO SS */
+#define HSIO_GPIO_LPCG			0x5F100000
+#define HSIO_MISC_LPCG			0x5F0F0000
+#define HSIO_SATA_CRR4_LPCG		0x5F0E0000
+#define HSIO_PCIE_X1_CRR3_LPCG	0x5F0D0000
+#define HSIO_PCIE_X2_CRR2_LPCG	0x5F0C0000
+#define HSIO_PHY_X1_CRR1_LPCG	0x5F0B0000
+#define HSIO_PHY_X2_CRR0_LPCG	0x5F0A0000
+#define HSIO_PHY_X1_LPCG		0x5F090000
+#define HSIO_PHY_X2_LPCG		0x5F080000
+#define HSIO_SATA_LPCG			0x5F070000
+#define HSIO_PCIE_X1_LPCG		0x5F060000
+#define HSIO_PCIE_X2_LPCG		0x5F050000
+
+/* M4 SS */
+#define		M4_0_I2C_LPCG		0x37630000
+#define		M4_0_LPUART_LPCG	0x37620000
+#define		M4_0_LPIT_LPCG		0x37610000
+#define		M4_1_I2C_LPCG		0x3B630000
+#define		M4_1_LPUART_LPCG	0x3B620000
+#define		M4_1_LPIT_LPCG		0x3B610000
+
+/* Audio SS */
+#define     AUD_ASRC_0_LPCG         0x59400000
+#define     AUD_ESAI_0_LPCG         0x59410000
+#define     AUD_SPDIF_0_LPCG        0x59420000
+#define     AUD_SPDIF_1_LPCG        0x59430000
+#define     AUD_SAI_0_LPCG          0x59440000
+#define     AUD_SAI_1_LPCG          0x59450000
+#define     AUD_SAI_2_LPCG          0x59460000
+#define     AUD_SAI_3_LPCG          0x59470000
+#define     AUD_HDMI_RX_SAI_0_LPCG  0x59480000
+#define     AUD_HDMI_TX_SAI_0_LPCG  0x59490000
+#define     AUD_GPT_5_LPCG          0x594B0000
+#define     AUD_GPT_6_LPCG          0x594C0000
+#define     AUD_GPT_7_LPCG          0x594D0000
+#define     AUD_GPT_8_LPCG          0x594E0000
+#define     AUD_GPT_9_LPCG          0x594F0000
+#define     AUD_GPT_10_LPCG         0x59500000
+#define     AUD_DSP_LPCG            0x59580000
+#define     AUD_OCRAM_LPCG          0x59590000
+#define     AUD_EDMA_0_LPCG         0x595f0000
+#define     AUD_ASRC_1_LPCG         0x59c00000
+#define     AUD_ESAI_1_LPCG         0x59c10000
+#define     AUD_SAI_6_LPCG          0x59c20000
+#define     AUD_SAI_7_LPCG          0x59c30000
+#define     AUD_AMIX_LPCG           0x59c40000
+#define     AUD_MQS_LPCG            0x59c50000
+#define     AUD_ACM_LPCG            0x59c60000
+#define     AUD_REC_CLK0_LPCG       0x59d00000
+#define     AUD_REC_CLK1_LPCG       0x59d10000
+#define     AUD_PLL_CLK0_LPCG       0x59d20000
+#define     AUD_PLL_CLK1_LPCG       0x59d30000
+#define     AUD_MCLKOUT0_LPCG       0x59d50000
+#define     AUD_MCLKOUT1_LPCG       0x59d60000
+#define     AUD_EDMA_1_LPCG         0x59df0000
+
+/* Connectivity SS */
+#define     USDHC_0_LPCG        0x5B200000
+#define     USDHC_1_LPCG        0x5B210000
+#define     USDHC_2_LPCG        0x5B220000
+#define     ENET_0_LPCG         0x5B230000
+#define     ENET_1_LPCG         0x5B240000
+#define     DTCP_LPCG           0x5B250000
+#define     MLB_LPCG            0x5B260000
+#define     USB_2_LPCG          0x5B270000
+#define     USB_3_LPCG          0x5B280000
+#define     NAND_LPCG           0x5B290000
+#define     EDMA_LPCG           0x5B2A0000
+
+/* CM40 SS */
+#define	CM40_I2C_LPCG		0x37630000
+
+/* CM41 SS */
+#define	CM41_I2C_LPCG		0x3B630000
+
+#endif
diff --git a/arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h b/arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h
new file mode 100644
index 0000000..074b208
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#ifndef _SC_LPCG_H
+#define _SC_LPCG_H
+
+/*LSIO SS */
+#define		PWM_0_LPCG		0x5D400000
+#define		PWM_1_LPCG		0x5D410000
+#define		PWM_2_LPCG		0x5D420000
+#define		PWM_3_LPCG		0x5D430000
+#define		PWM_4_LPCG		0x5D440000
+#define		PWM_5_LPCG		0x5D450000
+#define		PWM_6_LPCG		0x5D460000
+#define		PWM_7_LPCG		0x5D470000
+#define		GPIO_0_LPCG		0x5D480000
+#define		GPIO_1_LPCG		0x5D490000
+#define		GPIO_2_LPCG		0x5D4A0000
+#define		GPIO_3_LPCG		0x5D4B0000
+#define		GPIO_4_LPCG		0x5D4C0000
+#define		GPIO_5_LPCG		0x5D4D0000
+#define		GPIO_6_LPCG		0x5D4E0000
+#define		GPIO_7_LPCG		0x5D4F0000
+#define		FSPI_0_LPCG		0x5D520000
+#define		FSPI_1_LPCG		0x5D530000
+#define		GPT_0_LPCG		0x5D540000
+#define		GPT_1_LPCG		0x5D550000
+#define		GPT_2_LPCG		0x5D560000
+#define		GPT_3_LPCG		0x5D570000
+#define		GPT_4_LPCG		0x5D580000
+#define		OCRAM_LPCG		0x5D590000
+#define		KPP_LPCG		0x5D5A0000
+#define		ROMCP_LPCG		0x5D500000
+#define		MU_5A_LPCG		0x5D600000
+#define		MU_6A_LPCG		0x5D610000
+#define		MU_7A_LPCG		0x5D620000
+#define		MU_8A_LPCG		0x5D630000
+#define		MU_9A_LPCG		0x5D640000
+#define		MU_10A_LPCG		0x5D650000
+#define		MU_11A_LPCG		0x5D660000
+#define		MU_12A_LPCG		0x5D670000
+#define		MU_13A_LPCG		0x5D680000
+
+/* HSIO SS */
+#define		CRR_5_LPCG		0x5F0F0000
+#define		CRR_4_LPCG		0x5F0E0000
+#define		CRR_3_LPCG		0x5F0D0000
+#define		CRR_2_LPCG		0x5F0C0000
+#define		CRR_1_LPCG		0x5F0B0000
+#define		CRR_0_LPCG		0x5F0A0000
+#define		PHY_1_LPCG		0x5F090000
+#define		PHY_2_LPCG		0x5F080000
+#define		SATA_0_LPCG		0x5F070000
+#define		PCIE_B_LPCG		0x5F060000
+#define		PCIE_A_LPCG		0x5F050000
+
+/* DMA SS */
+#define		FLEX_CAN_2_LPCG		0x5ACF0000
+#define		FLEX_CAN_1_LPCG		0x5ACE0000
+#define		FLEX_CAN_0_LPCG		0x5ACD0000
+#define		FTM_1_LPCG		0x5ACB0000
+#define		FTM_0_LPCG		0x5ACA0000
+#define		ADC_0_LPCG		0x5AC80000
+#define		LPI2C_3_LPCG		0x5AC30000
+#define		LPI2C_2_LPCG		0x5AC20000
+#define		LPI2C_1_LPCG		0x5AC10000
+#define		LPI2C_0_LPCG		0x5AC00000
+#define		PWM_LPCG		0x5A590000
+#define		LCD_LPCG		0x5A580000
+#define		LPUART_3_LPCG		0x5A490000
+#define		LPUART_2_LPCG		0x5A480000
+#define		LPUART_1_LPCG		0x5A470000
+#define		LPUART_0_LPCG		0x5A460000
+#define		LPSPI_3_LPCG		0x5A430000
+#define		LPSPI_2_LPCG		0x5A420000
+#define		LPSPI_1_LPCG		0x5A410000
+#define		LPSPI_0_LPCG		0x5A400000
+
+/* Display SS */
+#define		DC_0_LPCG		0x56010000
+#define		DC_1_LPCG		0x57010000
+
+/* LVDS */
+#define		DI_LVDS_0_LPCG		0x56243000
+#define		DI_LVDS_1_LPCG		0x57243000
+
+/* DI HDMI */
+#define		DI_HDMI_LPCG		0x56263000
+
+/* RX-HDMI */
+#define		RX_HDMI_LPCG		0x58263000
+
+/* MIPI CSI SS */
+#define		MIPI_CSI_0_LPCG		0x58223000
+#define		MIPI_CSI_1_LPCG		0x58243000
+
+/* PARALLEL CSI SS */
+#define		PARALLEL_CSI_LPCG	0x58263000
+
+/* Display MIPI SS */
+#define		DI_MIPI0_LPCG		0x56223000
+#define		DI_MIPI1_LPCG		0x56243000
+
+/* Imaging SS */
+#define IMG_JPEG_ENC_LPCG		0x585F0000
+#define IMG_JPEG_DEC_LPCG		0x585D0000
+#define IMG_PXL_LINK_DC1_LPCG	0x585C0000
+#define IMG_PXL_LINK_DC0_LPCG	0x585B0000
+#define IMG_PXL_LINK_HDMI_LPCG	0x585A0000
+#define IMG_PXL_LINK_CSI1_LPCG	0x58590000
+#define IMG_PXL_LINK_CSI0_LPCG	0x58580000
+#define IMG_PDMA_7_LPCG			0x58570000
+#define IMG_PDMA_6_LPCG			0x58560000
+#define IMG_PDMA_5_LPCG			0x58550000
+#define IMG_PDMA_4_LPCG			0x58540000
+#define IMG_PDMA_3_LPCG			0x58530000
+#define IMG_PDMA_2_LPCG			0x58520000
+#define IMG_PDMA_1_LPCG			0x58510000
+#define IMG_PDMA_0_LPCG			0x58500000
+
+/* HSIO SS */
+#define HSIO_GPIO_LPCG			0x5F100000
+#define HSIO_MISC_LPCG			0x5F0F0000
+#define HSIO_SATA_CRR4_LPCG		0x5F0E0000
+#define HSIO_PCIE_X1_CRR3_LPCG	0x5F0D0000
+#define HSIO_PCIE_X2_CRR2_LPCG	0x5F0C0000
+#define HSIO_PHY_X1_CRR1_LPCG	0x5F0B0000
+#define HSIO_PHY_X2_CRR0_LPCG	0x5F0A0000
+#define HSIO_PHY_X1_LPCG		0x5F090000
+#define HSIO_PHY_X2_LPCG		0x5F080000
+#define HSIO_SATA_LPCG			0x5F070000
+#define HSIO_PCIE_X1_LPCG		0x5F060000
+#define HSIO_PCIE_X2_LPCG		0x5F050000
+
+/* M4 SS */
+#define		M4_0_I2C_LPCG		0x37630000
+#define		M4_0_LPUART_LPCG	0x37620000
+#define		M4_0_LPIT_LPCG		0x37610000
+#define		M4_1_I2C_LPCG		0x3B630000
+#define		M4_1_LPUART_LPCG	0x3B620000
+#define		M4_1_LPIT_LPCG		0x3B610000
+
+/* Audio SS */
+#define     AUD_ASRC_0_LPCG         0x59400000
+#define     AUD_ESAI_0_LPCG         0x59410000
+#define     AUD_SPDIF_0_LPCG        0x59420000
+#define     AUD_SAI_0_LPCG          0x59440000
+#define     AUD_SAI_1_LPCG          0x59450000
+#define     AUD_SAI_2_LPCG          0x59460000
+#define     AUD_SAI_3_LPCG          0x59470000
+#define     AUD_GPT_5_LPCG          0x594B0000
+#define     AUD_GPT_6_LPCG          0x594C0000
+#define     AUD_GPT_7_LPCG          0x594D0000
+#define     AUD_GPT_8_LPCG          0x594E0000
+#define     AUD_GPT_9_LPCG          0x594F0000
+#define     AUD_GPT_10_LPCG         0x59500000
+#define     AUD_DSP_LPCG            0x59580000
+#define     AUD_OCRAM_LPCG          0x59590000
+#define     AUD_EDMA_0_LPCG         0x595f0000
+#define     AUD_ASRC_1_LPCG         0x59c00000
+#define     AUD_SAI_4_LPCG          0x59c20000
+#define     AUD_SAI_5_LPCG          0x59c30000
+#define     AUD_AMIX_LPCG           0x59c40000
+#define     AUD_MQS_LPCG            0x59c50000
+#define     AUD_ACM_LPCG            0x59c60000
+#define     AUD_REC_CLK0_LPCG       0x59d00000
+#define     AUD_REC_CLK1_LPCG       0x59d10000
+#define     AUD_PLL_CLK0_LPCG       0x59d20000
+#define     AUD_PLL_CLK1_LPCG       0x59d30000
+#define     AUD_MCLKOUT0_LPCG       0x59d50000
+#define     AUD_MCLKOUT1_LPCG       0x59d60000
+#define     AUD_EDMA_1_LPCG         0x59df0000
+
+/* Connectivity SS */
+#define     USDHC_0_LPCG        0x5B200000
+#define     USDHC_1_LPCG        0x5B210000
+#define     USDHC_2_LPCG        0x5B220000
+#define     ENET_0_LPCG         0x5B230000
+#define     ENET_1_LPCG         0x5B240000
+#define     DTCP_LPCG           0x5B250000
+#define     MLB_LPCG            0x5B260000
+#define     USB_2_LPCG          0x5B270000
+#define     USB_3_LPCG          0x5B280000
+#define     NAND_LPCG           0x5B290000
+#define     EDMA_LPCG           0x5B2A0000
+
+/* CM40 SS */
+#define     CM40_I2C_LPCG       0x37630000
+
+#endif
diff --git a/arch/arm/include/asm/arch-imx8/lpcg.h b/arch/arm/include/asm/arch-imx8/lpcg.h
new file mode 100644
index 0000000..9ba4bb4
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8/lpcg.h
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#ifndef __ASM_ARCH_IMX8_LPCG_H__
+#define __ASM_ARCH_IMX8_LPCG_H__
+
+#if defined(CONFIG_IMX8QM)
+#include "imx8qm_lpcg.h"
+#elif defined(CONFIG_IMX8QXP)
+#include "imx8qxp_lpcg.h"
+#else
+#error "No lpcg header"
+#endif
+
+void lpcg_clock_off(u32 lpcg_addr, u8 clk);
+void lpcg_clock_on(u32 lpcg_addr, u8 clk);
+void lpcg_clock_autogate(u32 lpcg_addr, u8 clk);
+bool lpcg_is_clock_on(u32 lpcg_addr, u8 clk);
+void lpcg_all_clock_off(u32 lpcg_addr);
+void lpcg_all_clock_on(u32 lpcg_addr);
+void lpcg_all_clock_autogate(u32 lpcg_addr);
+
+#endif	/* __ASM_ARCH_IMX8_LPCG_H__ */
diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile
index 31ad169..e23f84f 100644
--- a/arch/arm/mach-imx/imx8/Makefile
+++ b/arch/arm/mach-imx/imx8/Makefile
@@ -4,4 +4,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += cpu.o iomux.o
+obj-y += cpu.o iomux.o lpcg.o
diff --git a/arch/arm/mach-imx/imx8/lpcg.c b/arch/arm/mach-imx/imx8/lpcg.c
new file mode 100644
index 0000000..621b871
--- /dev/null
+++ b/arch/arm/mach-imx/imx8/lpcg.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/lpcg.h>
+
+#define LPCG_CLOCK_MASK         0x3U
+#define LPCG_CLOCK_OFF          0x0U
+#define LPCG_CLOCK_ON           0x2U
+#define LPCG_CLOCK_AUTO         0x3U
+#define LPCG_CLOCK_STOP         0x8U
+
+#define LPCG_ALL_CLOCK_OFF      0x00000000U
+#define LPCG_ALL_CLOCK_ON       0x22222222U
+#define LPCG_ALL_CLOCK_AUTO     0x33333333U
+#define LPCG_ALL_CLOCK_STOP     0x88888888U
+
+static inline void lpcg_write(u32 lpcgVal, ulong lpcg_addr)
+{
+	/*
+	* Write twice with 4x DSC clock cycles (40x IPS clock cycles) interval
+	* to work around LPCG issue
+	*/
+	writel(lpcgVal, lpcg_addr);
+	udelay(10); /* 10us is enough. Worst case is 40x IPS cycle (200Mhz) */
+	writel(lpcgVal, lpcg_addr);
+	udelay(10);
+}
+
+void lpcg_clock_off(u32 lpcg_addr, u8 clk)
+{
+	u32 lpcgVal;
+
+	/* Read from LPCG */
+	lpcgVal = readl((ulong)lpcg_addr);
+
+	/* Modify */
+	lpcgVal &= ~((u32)(LPCG_CLOCK_MASK) << (clk * 4U));
+	lpcgVal |= ((u32)(LPCG_CLOCK_OFF) << (clk * 4U));
+
+	/* Write to LPCG */
+	lpcg_write(lpcgVal, (ulong)lpcg_addr);
+}
+
+void lpcg_clock_on(u32 lpcg_addr, u8 clk)
+{
+	u32 lpcgVal;
+
+	/* Read from LPCG */
+	lpcgVal = readl((ulong)lpcg_addr);
+
+	/* Modify */
+	lpcgVal &= ~((u32)(LPCG_CLOCK_MASK) << (clk * 4U));
+	lpcgVal |= ((u32)(LPCG_CLOCK_ON) << (clk * 4U));
+
+	/* Write to LPCG */
+	lpcg_write(lpcgVal, (ulong)lpcg_addr);
+}
+
+bool lpcg_is_clock_on(u32 lpcg_addr, u8 clk)
+{
+	u32 lpcgVal;
+
+	/* Read from LPCG */
+	lpcgVal = readl((ulong)lpcg_addr);
+	lpcgVal = (lpcgVal >> (clk * 4U)) & (u32)(LPCG_CLOCK_MASK);
+
+	if (lpcgVal == LPCG_CLOCK_ON)
+		return true;
+
+	return false;
+}
+
+void lpcg_clock_autogate(u32 lpcg_addr, u8 clk)
+{
+	u32 lpcgVal;
+
+	/* Read from LPCG */
+	lpcgVal = readl((ulong)lpcg_addr);
+
+	/* Modify */
+	lpcgVal &= ~((u32)(LPCG_CLOCK_MASK) << (clk * 4U));
+	lpcgVal |= ((u32)(LPCG_CLOCK_AUTO) << (clk * 4U));
+
+	/* Write to LPCG */
+	lpcg_write(lpcgVal, (ulong)lpcg_addr);
+}
+
+void lpcg_all_clock_off(u32 lpcg_addr)
+{
+	/* Write to LPCG */
+	lpcg_write(LPCG_ALL_CLOCK_OFF, (ulong)lpcg_addr);
+}
+
+void lpcg_all_clock_on(u32 lpcg_addr)
+{
+	/* Write to LPCG */
+	lpcg_write(LPCG_ALL_CLOCK_ON, (ulong)lpcg_addr);
+
+	/* Wait for clocks to start */
+	while ((readl((ulong)lpcg_addr) & LPCG_ALL_CLOCK_STOP) != 0U)
+	{
+	}
+}
+
+void lpcg_all_clock_autogate(u32 lpcg_addr)
+{
+	/* Write to LPCG */
+	lpcg_write(LPCG_ALL_CLOCK_AUTO, (ulong)lpcg_addr);
+}
-- 
2.7.4

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

* [U-Boot] [PATCH v2 2/7] misc: scu_api: Add new APIs for clk-imx8 driver
  2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
@ 2019-07-03  9:46 ` Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver Ye Li
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

Add sc_misc_set_control to write the subsystem's DSC GPR registers,
and sc_pm_set_clock_parent to select parent clock source.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
Changes in v2:
 - None

 arch/arm/include/asm/arch-imx8/sci/sci.h        |  4 ++
 arch/arm/include/asm/arch-imx8/sci/svc/pm/api.h |  7 ++++
 arch/arm/include/asm/arch-imx8/sci/types.h      | 13 ++++++-
 drivers/misc/imx8/scu_api.c                     | 52 +++++++++++++++++++++++++
 include/dt-bindings/soc/imx_rsrc.h              |  2 +
 5 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-imx8/sci/sci.h b/arch/arm/include/asm/arch-imx8/sci/sci.h
index 9737769..52a3ac8 100644
--- a/arch/arm/include/asm/arch-imx8/sci/sci.h
+++ b/arch/arm/include/asm/arch-imx8/sci/sci.h
@@ -64,8 +64,12 @@ int sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
 			 sc_pm_clock_rate_t *rate);
 int sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
 		       sc_bool_t enable, sc_bool_t autog);
+int sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
+			sc_pm_clk_parent_t parent);
 
 /* MISC API */
+int sc_misc_set_control(sc_ipc_t ipc, sc_rsrc_t resource,
+			sc_ctrl_t ctrl, u32 val);
 int sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource, sc_ctrl_t ctrl,
 			u32 *val);
 void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *boot_dev);
diff --git a/arch/arm/include/asm/arch-imx8/sci/svc/pm/api.h b/arch/arm/include/asm/arch-imx8/sci/svc/pm/api.h
index 9008b85..109ec27 100644
--- a/arch/arm/include/asm/arch-imx8/sci/svc/pm/api.h
+++ b/arch/arm/include/asm/arch-imx8/sci/svc/pm/api.h
@@ -35,6 +35,13 @@
 #define SC_PM_CLK_MODE_AUTOGATE_HW	4U /* Clock is in HW autogate mode */
 #define SC_PM_CLK_MODE_AUTOGATE_SW_HW	5U /* Clock is in SW-HW autogate mode */
 
+/* Defines for sc_pm_clk_parent_t */
+#define SC_PM_PARENT_XTAL              0U    /*!< Parent is XTAL. */
+#define SC_PM_PARENT_PLL0              1U    /*!< Parent is PLL0 */
+#define SC_PM_PARENT_PLL1              2U    /*!< Parent is PLL1 or PLL0/2 */
+#define SC_PM_PARENT_PLL2              3U    /*!< Parent in PLL2 or PLL0/4 */
+#define SC_PM_PARENT_BYPS              4U    /*!< Parent is a bypass clock. */
+
 typedef u8 sc_pm_power_mode_t;
 typedef u8 sc_pm_clk_t;
 typedef u8 sc_pm_clk_mode_t;
diff --git a/arch/arm/include/asm/arch-imx8/sci/types.h b/arch/arm/include/asm/arch-imx8/sci/types.h
index 9eadc88..2d5912e 100644
--- a/arch/arm/include/asm/arch-imx8/sci/types.h
+++ b/arch/arm/include/asm/arch-imx8/sci/types.h
@@ -185,7 +185,18 @@ typedef u64 sc_ipc_t;
 #define SC_C_RST0                       43U
 #define SC_C_RST1                       44U
 #define SC_C_SEL0                       45U
-#define SC_C_LAST                       46U
+#define SC_C_CALIB0                     46U
+#define SC_C_CALIB1                     47U
+#define SC_C_CALIB2                     48U
+#define SC_C_IPG_DEBUG                  49U
+#define SC_C_IPG_DOZE                   50U
+#define SC_C_IPG_WAIT                   51U
+#define SC_C_IPG_STOP                   52U
+#define SC_C_IPG_STOP_MODE              53U
+#define SC_C_IPG_STOP_ACK               54U
+#define SC_C_SYNC_CTRL                  55U
+#define SC_C_LAST                       56U
+
 
 #define SC_P_ALL        ((sc_pad_t)UINT16_MAX)   /* All pads */
 
diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c
index d9c4d5d..cab8995 100644
--- a/drivers/misc/imx8/scu_api.c
+++ b/drivers/misc/imx8/scu_api.c
@@ -93,6 +93,31 @@ int sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk,
 	return ret;
 }
 
+int sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+    sc_pm_clk_t clk, sc_pm_clk_parent_t parent)
+{
+	struct udevice *dev = gd->arch.scu_dev;
+	int size = sizeof(struct sc_rpc_msg_s);
+	struct sc_rpc_msg_s msg;
+	int ret;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (u8)(SC_RPC_SVC_PM);
+	RPC_FUNC(&msg) = (u8)(PM_FUNC_SET_CLOCK_PARENT);
+	RPC_U16(&msg, 0U) = (u16)(resource);
+	RPC_U8(&msg, 2U) = (u8)(clk);
+	RPC_U8(&msg, 3U) = (u8)(parent);
+	RPC_SIZE(&msg) = 2U;
+
+	ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
+	if (ret)
+		printf("%s: resource:%d clk:%d: parent clk: %d, res:%d\n",
+		       __func__, resource, clk, parent, RPC_R8(&msg));
+
+	return ret;
+}
+
+
 int sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
 				  sc_pm_power_mode_t mode)
 {
@@ -146,6 +171,33 @@ int sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, u32 val)
 }
 
 /* MISC */
+int sc_misc_set_control(sc_ipc_t ipc, sc_rsrc_t resource,
+			sc_ctrl_t ctrl, u32 val)
+{
+	struct udevice *dev = gd->arch.scu_dev;
+	int size = sizeof(struct sc_rpc_msg_s);
+	struct sc_rpc_msg_s msg;
+	int ret;
+
+	if (!dev)
+		hang();
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (u8)(SC_RPC_SVC_MISC);
+	RPC_FUNC(&msg) = (u8)(MISC_FUNC_SET_CONTROL);
+	RPC_U32(&msg, 0U) = (u32)(ctrl);
+	RPC_U32(&msg, 4U) = (u32)(val);
+	RPC_U16(&msg, 8U) = (u16)(resource);
+	RPC_SIZE(&msg) = 4U;
+
+	ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
+	if (ret)
+		printf("%s: ctrl:%d resource:%d: res:%d\n",
+		       __func__, ctrl, resource, RPC_R8(&msg));
+
+	return ret;
+}
+
 int sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource, sc_ctrl_t ctrl,
 			u32 *val)
 {
diff --git a/include/dt-bindings/soc/imx_rsrc.h b/include/dt-bindings/soc/imx_rsrc.h
index 4870eb9..a1c3b1f 100644
--- a/include/dt-bindings/soc/imx_rsrc.h
+++ b/include/dt-bindings/soc/imx_rsrc.h
@@ -554,4 +554,6 @@
 #define SC_R_VPU                        540
 #define SC_R_LAST                       541
 
+#define SC_R_NONE                       0xFFF0
+
 #endif /* DT_BINDINGS_RSCRC_IMX_H */
-- 
2.7.4

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

* [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver
  2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 2/7] misc: scu_api: Add new APIs for clk-imx8 driver Ye Li
@ 2019-07-03  9:46 ` Ye Li
  2019-09-17  6:52   ` Peng Fan
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 4/7] imx8qm_mek: increase the size of early malloc pool Ye Li
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

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

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

* [U-Boot] [PATCH v2 4/7] imx8qm_mek: increase the size of early malloc pool
  2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 2/7] misc: scu_api: Add new APIs for clk-imx8 driver Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver Ye Li
@ 2019-07-03  9:46 ` Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 5/7] net: fec_mxc: Update driver to use full clks for iMX8 Ye Li
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

Encounter malloc failure in arch_cpu_init_dm when binding "fsl,imx8-mu" node
with imx8_scu driver. So increase the early malloc pool to fix the issue.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
Changes in v2:
 - None

 configs/imx8qm_mek_defconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configs/imx8qm_mek_defconfig b/configs/imx8qm_mek_defconfig
index 1c67b98..a4d2619 100644
--- a/configs/imx8qm_mek_defconfig
+++ b/configs/imx8qm_mek_defconfig
@@ -6,7 +6,7 @@ CONFIG_SYS_TEXT_BASE=0x80020000
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_TARGET_IMX8QM_MEK=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
-- 
2.7.4

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

* [U-Boot] [PATCH v2 5/7] net: fec_mxc: Update driver to use full clks for iMX8
  2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
                   ` (2 preceding siblings ...)
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 4/7] imx8qm_mek: increase the size of early malloc pool Ye Li
@ 2019-07-03  9:46 ` Ye Li
  2019-07-15 23:10   ` Joe Hershberger
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 6/7] imx8qm/imx8qxp: Power down the resources before SPL jump to u-boot Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 7/7] imx8qm/qxp: Enable UART0 LPCG clock for early serial Ye Li
  5 siblings, 1 reply; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

Add support for more clocks used by iMX8 from DTB:
ref_clock, tx_2x_clock, ahb_clock
And update get clock rate interface to support multiple fec ports.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
Changes in v2:
 - None

 drivers/net/fec_mxc.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 drivers/net/fec_mxc.h |  1 +
 2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index d7c0809..6d485f1 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -6,7 +6,6 @@
  * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
  * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
  */
-
 #include <common.h>
 #include <dm.h>
 #include <environment.h>
@@ -132,9 +131,9 @@ static int fec_get_clk_rate(void *udev, int idx)
 
 	dev = udev;
 	if (!dev) {
-		ret = uclass_get_device(UCLASS_ETH, idx, &dev);
+		ret = uclass_get_device_by_seq(UCLASS_ETH, idx, &dev);
 		if (ret < 0) {
-			debug("Can't get FEC udev: %d\n", ret);
+			debug("Can't get FEC udev%d: %d\n", idx, ret);
 			return ret;
 		}
 	}
@@ -149,7 +148,7 @@ static int fec_get_clk_rate(void *udev, int idx)
 #endif
 }
 
-static void fec_mii_setspeed(struct ethernet_regs *eth)
+static void fec_mii_setspeed(struct ethernet_regs *eth, int idx)
 {
 	/*
 	 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
@@ -171,7 +170,7 @@ static void fec_mii_setspeed(struct ethernet_regs *eth)
 	u32 hold;
 	int ret;
 
-	ret = fec_get_clk_rate(NULL, 0);
+	ret = fec_get_clk_rate(NULL, idx);
 	if (ret < 0) {
 		printf("Can't find FEC0 clk rate: %d\n", ret);
 		return;
@@ -593,7 +592,7 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
 	fec_reg_setup(fec);
 
 	if (fec->xcv_type != SEVENWIRE)
-		fec_mii_setspeed(fec->bus->priv);
+		fec_mii_setspeed(fec->bus->priv, fec->dev_id);
 
 	/* Set Opcode/Pause Duration Register */
 	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
@@ -1073,7 +1072,7 @@ struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
 		free(bus);
 		return NULL;
 	}
-	fec_mii_setspeed(eth);
+	fec_mii_setspeed(eth, dev_id);
 	return bus;
 }
 
@@ -1142,7 +1141,7 @@ static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
 	fec_set_dev_name(edev->name, dev_id);
 	fec->dev_id = (dev_id == -1) ? 0 : dev_id;
 	fec->bus = bus;
-	fec_mii_setspeed(bus->priv);
+	fec_mii_setspeed(bus->priv, fec->dev_id);
 #ifdef CONFIG_PHYLIB
 	fec->phydev = phydev;
 	phy_connect_dev(phydev, edev);
@@ -1324,6 +1323,7 @@ static int fecmxc_probe(struct udevice *dev)
 	int ret;
 
 	if (IS_ENABLED(CONFIG_IMX8)) {
+		struct clk ref_clk, clk_2x_txclk;
 		ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk);
 		if (ret < 0) {
 			debug("Can't get FEC ipg clk: %d\n", ret);
@@ -1335,6 +1335,35 @@ static int fecmxc_probe(struct udevice *dev)
 			return ret;
 		}
 
+		ret = clk_get_by_name(dev, "ahb", &priv->ahb_clk);
+		if (ret < 0) {
+			debug("Can't get FEC ahb clk: %d\n", ret);
+			return ret;
+		}
+		ret = clk_enable(&priv->ahb_clk);
+		if (ret < 0) {
+			debug("Can't enable FEC ahb clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_get_by_name(dev, "enet_clk_ref", &ref_clk);
+		if (ret >= 0) {
+			ret = clk_enable(&ref_clk);
+			if (ret < 0) {
+				debug("Can't enable FEC ref clk: %d\n", ret);
+				return ret;
+			}
+		}
+
+		ret = clk_get_by_name(dev, "enet_2x_txclk", &clk_2x_txclk);
+		if (ret >= 0) {
+			ret = clk_enable(&clk_2x_txclk);
+			if (ret < 0) {
+				debug("Can't enable FEC 2x_tx clk: %d\n", ret);
+				return ret;
+			}
+		}
+
 		priv->clk_rate = clk_get_rate(&priv->ipg_clk);
 	}
 
@@ -1368,7 +1397,6 @@ static int fecmxc_probe(struct udevice *dev)
 	}
 
 	fec_reg_setup(priv);
-
 	priv->dev_id = dev->seq;
 #ifdef CONFIG_FEC_MXC_MDIO_BASE
 	bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
@@ -1492,6 +1520,7 @@ static const struct udevice_id fecmxc_ids[] = {
 	{ .compatible = "fsl,imx53-fec" },
 	{ .compatible = "fsl,imx7d-fec" },
 	{ .compatible = "fsl,mvf600-fec" },
+	{ .compatible = "fsl,imx8qm-fec" },
 	{ }
 };
 
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index e5f2dd7..23180a6 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -264,6 +264,7 @@ struct fec_priv {
 	u32 interface;
 #endif
 	struct clk ipg_clk;
+	struct clk ahb_clk;
 	u32 clk_rate;
 };
 
-- 
2.7.4

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

* [U-Boot] [PATCH v2 6/7] imx8qm/imx8qxp: Power down the resources before SPL jump to u-boot
  2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
                   ` (3 preceding siblings ...)
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 5/7] net: fec_mxc: Update driver to use full clks for iMX8 Ye Li
@ 2019-07-03  9:46 ` Ye Li
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 7/7] imx8qm/qxp: Enable UART0 LPCG clock for early serial Ye Li
  5 siblings, 0 replies; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

Make sure that all devices that are powered up by SPL are powered down
before entering into the u-boot. Otherwise the subsystem/device will never
be powered down by SCFW, due to SPL and u-boot are in different partitions.

Benefiting from power domain driver, this patch implements the function
"power_off_pd_devices" to power off all active devices.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
Changes in v2:
 - New patch in v2 to fix clock set parent failure in u-boot, due to SPL does not
   power off the resource.
 
 arch/arm/include/asm/arch-imx8/sys_proto.h |  1 +
 arch/arm/mach-imx/imx8/cpu.c               | 34 ++++++++++++++++++++++++++++++
 board/freescale/imx8qm_mek/spl.c           |  6 ++++++
 board/freescale/imx8qxp_mek/spl.c          |  6 ++++++
 4 files changed, 47 insertions(+)

diff --git a/arch/arm/include/asm/arch-imx8/sys_proto.h b/arch/arm/include/asm/arch-imx8/sys_proto.h
index 73ffaba..fd00e8f 100644
--- a/arch/arm/include/asm/arch-imx8/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8/sys_proto.h
@@ -17,3 +17,4 @@ struct pass_over_info_t {
 
 enum boot_device get_boot_device(void);
 int print_bootinfo(void);
+void power_off_pd_devices(const char* permanent_on_devices[], int size);
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index f2fa262..f03729b 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -11,6 +11,9 @@
 #include <dm/lists.h>
 #include <dm/uclass.h>
 #include <errno.h>
+#include <power-domain.h>
+#include <dm/device.h>
+#include <dm/uclass-internal.h>
 #include <thermal.h>
 #include <asm/arch/sci/sci.h>
 #include <asm/arch/sys_proto.h>
@@ -696,3 +699,34 @@ U_BOOT_DRIVER(cpu_imx8_drv) = {
 	.flags		= DM_FLAG_PRE_RELOC,
 };
 #endif
+
+static bool check_device_power_off(struct udevice *dev,
+	const char* permanent_on_devices[], int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (!strcmp(dev->name, permanent_on_devices[i]))
+			return false;
+	}
+
+	return true;
+}
+
+void power_off_pd_devices(const char* permanent_on_devices[], int size)
+{
+	struct udevice *dev;
+	struct power_domain pd;
+
+	for (uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev); dev;
+		uclass_find_next_device(&dev)) {
+
+		if (device_active(dev)) {
+			/* Power off active pd devices except the permanent power on devices */
+			if (check_device_power_off(dev, permanent_on_devices, size)) {
+				pd.dev = dev;
+				power_domain_off(&pd);
+			}
+		}
+	}
+}
diff --git a/board/freescale/imx8qm_mek/spl.c b/board/freescale/imx8qm_mek/spl.c
index 95ce9f3..a3f2faa 100644
--- a/board/freescale/imx8qm_mek/spl.c
+++ b/board/freescale/imx8qm_mek/spl.c
@@ -12,6 +12,7 @@
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <asm/arch/sys_proto.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -53,6 +54,11 @@ void spl_board_init(void)
 	puts("Normal Boot\n");
 }
 
+void spl_board_prepare_for_boot(void)
+{
+	power_off_pd_devices(NULL, 0);
+}
+
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
diff --git a/board/freescale/imx8qxp_mek/spl.c b/board/freescale/imx8qxp_mek/spl.c
index cb4006e..f947838 100644
--- a/board/freescale/imx8qxp_mek/spl.c
+++ b/board/freescale/imx8qxp_mek/spl.c
@@ -12,6 +12,7 @@
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <asm/arch/sys_proto.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -37,6 +38,11 @@ void spl_board_init(void)
 	puts("Normal Boot\n");
 }
 
+void spl_board_prepare_for_boot(void)
+{
+	power_off_pd_devices(NULL, 0);
+}
+
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
-- 
2.7.4

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

* [U-Boot] [PATCH v2 7/7] imx8qm/qxp: Enable UART0 LPCG clock for early serial
  2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
                   ` (4 preceding siblings ...)
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 6/7] imx8qm/imx8qxp: Power down the resources before SPL jump to u-boot Ye Li
@ 2019-07-03  9:46 ` Ye Li
  5 siblings, 0 replies; 10+ messages in thread
From: Ye Li @ 2019-07-03  9:46 UTC (permalink / raw)
  To: u-boot

Enable the UART0 LPCG clock in board_early_init_f not depending on
the reset default value.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
Changes in v2:
 - New patch in v2, enable the UART0 LPCG since we added LPCG driver
 
 board/freescale/imx8qm_mek/imx8qm_mek.c   | 3 +++
 board/freescale/imx8qxp_mek/imx8qxp_mek.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/board/freescale/imx8qm_mek/imx8qm_mek.c b/board/freescale/imx8qm_mek/imx8qm_mek.c
index e69efc4..083b90a 100644
--- a/board/freescale/imx8qm_mek/imx8qm_mek.c
+++ b/board/freescale/imx8qm_mek/imx8qm_mek.c
@@ -14,6 +14,7 @@
 #include <asm/arch/imx8-pins.h>
 #include <asm/arch/iomux.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/arch/lpcg.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -52,6 +53,8 @@ int board_early_init_f(void)
 	if (ret)
 		return ret;
 
+	lpcg_all_clock_on(LPUART_0_LPCG);
+
 	setup_iomux_uart();
 
 	sc_pm_set_resource_power_mode(-1, SC_R_GPIO_5, SC_PM_PW_MODE_ON);
diff --git a/board/freescale/imx8qxp_mek/imx8qxp_mek.c b/board/freescale/imx8qxp_mek/imx8qxp_mek.c
index 63cd605..f9c9c23 100644
--- a/board/freescale/imx8qxp_mek/imx8qxp_mek.c
+++ b/board/freescale/imx8qxp_mek/imx8qxp_mek.c
@@ -15,6 +15,7 @@
 #include <asm/arch/imx8-pins.h>
 #include <asm/arch/iomux.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/arch/lpcg.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -58,6 +59,8 @@ int board_early_init_f(void)
 	if (ret)
 		return ret;
 
+	lpcg_all_clock_on(LPUART_0_LPCG);
+
 	setup_iomux_uart();
 
 	return 0;
-- 
2.7.4

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

* [U-Boot] [PATCH v2 5/7] net: fec_mxc: Update driver to use full clks for iMX8
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 5/7] net: fec_mxc: Update driver to use full clks for iMX8 Ye Li
@ 2019-07-15 23:10   ` Joe Hershberger
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Hershberger @ 2019-07-15 23:10 UTC (permalink / raw)
  To: u-boot

Hi Ye,

On Wed, Jul 3, 2019 at 4:52 AM Ye Li <ye.li@nxp.com> wrote:
>
> Add support for more clocks used by iMX8 from DTB:
> ref_clock, tx_2x_clock, ahb_clock
> And update get clock rate interface to support multiple fec ports.

It seems the feature to support multiple ports should be independent
of adding the extra needed clocks. I think they should be two separate
patches.

Thanks,
-Joe

>
> Signed-off-by: Ye Li <ye.li@nxp.com>
> ---
> Changes in v2:
>  - None
>
>  drivers/net/fec_mxc.c | 47 ++++++++++++++++++++++++++++++++++++++---------
>  drivers/net/fec_mxc.h |  1 +
>  2 files changed, 39 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index d7c0809..6d485f1 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -6,7 +6,6 @@
>   * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
>   * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
>   */
> -
>  #include <common.h>
>  #include <dm.h>
>  #include <environment.h>
> @@ -132,9 +131,9 @@ static int fec_get_clk_rate(void *udev, int idx)
>
>         dev = udev;
>         if (!dev) {
> -               ret = uclass_get_device(UCLASS_ETH, idx, &dev);
> +               ret = uclass_get_device_by_seq(UCLASS_ETH, idx, &dev);
>                 if (ret < 0) {
> -                       debug("Can't get FEC udev: %d\n", ret);
> +                       debug("Can't get FEC udev%d: %d\n", idx, ret);
>                         return ret;
>                 }
>         }
> @@ -149,7 +148,7 @@ static int fec_get_clk_rate(void *udev, int idx)
>  #endif
>  }
>
> -static void fec_mii_setspeed(struct ethernet_regs *eth)
> +static void fec_mii_setspeed(struct ethernet_regs *eth, int idx)
>  {
>         /*
>          * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
> @@ -171,7 +170,7 @@ static void fec_mii_setspeed(struct ethernet_regs *eth)
>         u32 hold;
>         int ret;
>
> -       ret = fec_get_clk_rate(NULL, 0);
> +       ret = fec_get_clk_rate(NULL, idx);
>         if (ret < 0) {
>                 printf("Can't find FEC0 clk rate: %d\n", ret);
>                 return;
> @@ -593,7 +592,7 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
>         fec_reg_setup(fec);
>
>         if (fec->xcv_type != SEVENWIRE)
> -               fec_mii_setspeed(fec->bus->priv);
> +               fec_mii_setspeed(fec->bus->priv, fec->dev_id);
>
>         /* Set Opcode/Pause Duration Register */
>         writel(0x00010020, &fec->eth->op_pause);        /* FIXME 0xffff0020; */
> @@ -1073,7 +1072,7 @@ struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
>                 free(bus);
>                 return NULL;
>         }
> -       fec_mii_setspeed(eth);
> +       fec_mii_setspeed(eth, dev_id);
>         return bus;
>  }
>
> @@ -1142,7 +1141,7 @@ static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
>         fec_set_dev_name(edev->name, dev_id);
>         fec->dev_id = (dev_id == -1) ? 0 : dev_id;
>         fec->bus = bus;
> -       fec_mii_setspeed(bus->priv);
> +       fec_mii_setspeed(bus->priv, fec->dev_id);
>  #ifdef CONFIG_PHYLIB
>         fec->phydev = phydev;
>         phy_connect_dev(phydev, edev);
> @@ -1324,6 +1323,7 @@ static int fecmxc_probe(struct udevice *dev)
>         int ret;
>
>         if (IS_ENABLED(CONFIG_IMX8)) {
> +               struct clk ref_clk, clk_2x_txclk;
>                 ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk);
>                 if (ret < 0) {
>                         debug("Can't get FEC ipg clk: %d\n", ret);
> @@ -1335,6 +1335,35 @@ static int fecmxc_probe(struct udevice *dev)
>                         return ret;
>                 }
>
> +               ret = clk_get_by_name(dev, "ahb", &priv->ahb_clk);
> +               if (ret < 0) {
> +                       debug("Can't get FEC ahb clk: %d\n", ret);
> +                       return ret;
> +               }
> +               ret = clk_enable(&priv->ahb_clk);
> +               if (ret < 0) {
> +                       debug("Can't enable FEC ahb clk: %d\n", ret);
> +                       return ret;
> +               }
> +
> +               ret = clk_get_by_name(dev, "enet_clk_ref", &ref_clk);
> +               if (ret >= 0) {
> +                       ret = clk_enable(&ref_clk);
> +                       if (ret < 0) {
> +                               debug("Can't enable FEC ref clk: %d\n", ret);
> +                               return ret;
> +                       }
> +               }
> +
> +               ret = clk_get_by_name(dev, "enet_2x_txclk", &clk_2x_txclk);
> +               if (ret >= 0) {
> +                       ret = clk_enable(&clk_2x_txclk);
> +                       if (ret < 0) {
> +                               debug("Can't enable FEC 2x_tx clk: %d\n", ret);
> +                               return ret;
> +                       }
> +               }
> +
>                 priv->clk_rate = clk_get_rate(&priv->ipg_clk);
>         }
>
> @@ -1368,7 +1397,6 @@ static int fecmxc_probe(struct udevice *dev)
>         }
>
>         fec_reg_setup(priv);
> -
>         priv->dev_id = dev->seq;
>  #ifdef CONFIG_FEC_MXC_MDIO_BASE
>         bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
> @@ -1492,6 +1520,7 @@ static const struct udevice_id fecmxc_ids[] = {
>         { .compatible = "fsl,imx53-fec" },
>         { .compatible = "fsl,imx7d-fec" },
>         { .compatible = "fsl,mvf600-fec" },
> +       { .compatible = "fsl,imx8qm-fec" },
>         { }
>  };
>
> diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
> index e5f2dd7..23180a6 100644
> --- a/drivers/net/fec_mxc.h
> +++ b/drivers/net/fec_mxc.h
> @@ -264,6 +264,7 @@ struct fec_priv {
>         u32 interface;
>  #endif
>         struct clk ipg_clk;
> +       struct clk ahb_clk;
>         u32 clk_rate;
>  };
>
> --
> 2.7.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

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

* [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver
  2019-07-03  9:46 ` [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver Ye Li
@ 2019-09-17  6:52   ` Peng Fan
  2019-09-17  7:28     ` Lukasz Majewski
  0 siblings, 1 reply; 10+ messages in thread
From: Peng Fan @ 2019-09-17  6:52 UTC (permalink / raw)
  To: u-boot

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

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

* [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver
  2019-09-17  6:52   ` Peng Fan
@ 2019-09-17  7:28     ` Lukasz Majewski
  0 siblings, 0 replies; 10+ messages in thread
From: Lukasz Majewski @ 2019-09-17  7:28 UTC (permalink / raw)
  To: u-boot

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 at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190917/157d2448/attachment.sig>

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

end of thread, other threads:[~2019-09-17  7:28 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-03  9:46 [U-Boot] [PATCH v2 1/7] imx8: Add lpcg driver for iMX8QM/QXP Ye Li
2019-07-03  9:46 ` [U-Boot] [PATCH v2 2/7] misc: scu_api: Add new APIs for clk-imx8 driver Ye Li
2019-07-03  9:46 ` [U-Boot] [PATCH v2 3/7] clk: imx8: Update imx8 clock driver Ye Li
2019-09-17  6:52   ` Peng Fan
2019-09-17  7:28     ` Lukasz Majewski
2019-07-03  9:46 ` [U-Boot] [PATCH v2 4/7] imx8qm_mek: increase the size of early malloc pool Ye Li
2019-07-03  9:46 ` [U-Boot] [PATCH v2 5/7] net: fec_mxc: Update driver to use full clks for iMX8 Ye Li
2019-07-15 23:10   ` Joe Hershberger
2019-07-03  9:46 ` [U-Boot] [PATCH v2 6/7] imx8qm/imx8qxp: Power down the resources before SPL jump to u-boot Ye Li
2019-07-03  9:46 ` [U-Boot] [PATCH v2 7/7] imx8qm/qxp: Enable UART0 LPCG clock for early serial Ye Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.