imx8m: add clk support for i.MX8MM

Introduce clk implementation for i.MX8MM, including pll configuration,
ccm configuration. Mostly will be done clk dm driver,
but such as DRAM part, we still use non clk dm driver, because we
have limited sram.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
diff --git a/arch/arm/include/asm/arch-imx8m/clock.h b/arch/arm/include/asm/arch-imx8m/clock.h
index 80245a2..dded6e0 100644
--- a/arch/arm/include/asm/arch-imx8m/clock.h
+++ b/arch/arm/include/asm/arch-imx8m/clock.h
@@ -9,6 +9,8 @@
 
 #ifdef CONFIG_IMX8MQ
 #include <asm/arch/clock_imx8mq.h>
+#elif defined(CONFIG_IMX8MM)
+#include <asm/arch/clock_imx8mm.h>
 #else
 #error "Error no clock.h"
 #endif
diff --git a/arch/arm/include/asm/arch-imx8m/clock_imx8mm.h b/arch/arm/include/asm/arch-imx8m/clock_imx8mm.h
new file mode 100644
index 0000000..305514a
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8m/clock_imx8mm.h
@@ -0,0 +1,387 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018-2019 NXP
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#ifndef _ASM_ARCH_IMX8MM_CLOCK_H
+#define _ASM_ARCH_IMX8MM_CLOCK_H
+
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k)			\
+	{							\
+		.rate	=	(_rate),			\
+		.mdiv	=	(_m),				\
+		.pdiv	=	(_p),				\
+		.sdiv	=	(_s),				\
+		.kdiv	=	(_k),				\
+	}
+
+#define LOCK_STATUS	BIT(31)
+#define LOCK_SEL_MASK	BIT(29)
+#define CLKE_MASK	BIT(11)
+#define RST_MASK	BIT(9)
+#define BYPASS_MASK	BIT(4)
+#define	MDIV_SHIFT	12
+#define	MDIV_MASK	GENMASK(21, 12)
+#define PDIV_SHIFT	4
+#define PDIV_MASK	GENMASK(9, 4)
+#define SDIV_SHIFT	0
+#define SDIV_MASK	GENMASK(2, 0)
+#define KDIV_SHIFT	0
+#define KDIV_MASK	GENMASK(15, 0)
+
+struct imx_int_pll_rate_table {
+	u32 rate;
+	int mdiv;
+	int pdiv;
+	int sdiv;
+	int kdiv;
+};
+
+enum pll_clocks {
+	ANATOP_ARM_PLL,
+	ANATOP_VPU_PLL,
+	ANATOP_GPU_PLL,
+	ANATOP_SYSTEM_PLL1,
+	ANATOP_SYSTEM_PLL2,
+	ANATOP_SYSTEM_PLL3,
+	ANATOP_AUDIO_PLL1,
+	ANATOP_AUDIO_PLL2,
+	ANATOP_VIDEO_PLL,
+	ANATOP_DRAM_PLL,
+};
+
+enum clk_root_index {
+	ARM_A53_CLK_ROOT		= 0,
+	ARM_M4_CLK_ROOT			= 1,
+	VPU_A53_CLK_ROOT		= 2,
+	GPU3D_CLK_ROOT			= 3,
+	GPU2D_CLK_ROOT			= 4,
+	MAIN_AXI_CLK_ROOT		= 16,
+	ENET_AXI_CLK_ROOT		= 17,
+	NAND_USDHC_BUS_CLK_ROOT		= 18,
+	VPU_BUS_CLK_ROOT		= 19,
+	DISPLAY_AXI_CLK_ROOT		= 20,
+	DISPLAY_APB_CLK_ROOT		= 21,
+	DISPLAY_RTRM_CLK_ROOT		= 22,
+	USB_BUS_CLK_ROOT		= 23,
+	GPU_AXI_CLK_ROOT		= 24,
+	GPU_AHB_CLK_ROOT		= 25,
+	NOC_CLK_ROOT			= 26,
+	NOC_APB_CLK_ROOT		= 27,
+	AHB_CLK_ROOT			= 32,
+	IPG_CLK_ROOT			= 33,
+	AUDIO_AHB_CLK_ROOT		= 34,
+	MIPI_DSI_ESC_RX_CLK_ROOT	= 36,
+	DRAM_SEL_CFG			= 48,
+	CORE_SEL_CFG			= 49,
+	DRAM_ALT_CLK_ROOT		= 64,
+	DRAM_APB_CLK_ROOT		= 65,
+	VPU_G1_CLK_ROOT			= 66,
+	VPU_G2_CLK_ROOT			= 67,
+	DISPLAY_DTRC_CLK_ROOT		= 68,
+	DISPLAY_DC8000_CLK_ROOT		= 69,
+	PCIE_CTRL_CLK_ROOT		= 70,
+	PCIE_PHY_CLK_ROOT		= 71,
+	PCIE_AUX_CLK_ROOT		= 72,
+	DC_PIXEL_CLK_ROOT		= 73,
+	LCDIF_PIXEL_CLK_ROOT		= 74,
+	SAI1_CLK_ROOT			= 75,
+	SAI2_CLK_ROOT			= 76,
+	SAI3_CLK_ROOT			= 77,
+	SAI4_CLK_ROOT			= 78,
+	SAI5_CLK_ROOT			= 79,
+	SAI6_CLK_ROOT			= 80,
+	SPDIF1_CLK_ROOT			= 81,
+	SPDIF2_CLK_ROOT			= 82,
+	ENET_REF_CLK_ROOT		= 83,
+	ENET_TIMER_CLK_ROOT		= 84,
+	ENET_PHY_REF_CLK_ROOT		= 85,
+	NAND_CLK_ROOT			= 86,
+	QSPI_CLK_ROOT			= 87,
+	USDHC1_CLK_ROOT			= 88,
+	USDHC2_CLK_ROOT			= 89,
+	I2C1_CLK_ROOT			= 90,
+	I2C2_CLK_ROOT			= 91,
+	I2C3_CLK_ROOT			= 92,
+	I2C4_CLK_ROOT			= 93,
+	UART1_CLK_ROOT			= 94,
+	UART2_CLK_ROOT			= 95,
+	UART3_CLK_ROOT			= 96,
+	UART4_CLK_ROOT			= 97,
+	USB_CORE_REF_CLK_ROOT		= 98,
+	USB_PHY_REF_CLK_ROOT		= 99,
+	GIC_CLK_ROOT			= 100,
+	ECSPI1_CLK_ROOT			= 101,
+	ECSPI2_CLK_ROOT			= 102,
+	PWM1_CLK_ROOT			= 103,
+	PWM2_CLK_ROOT			= 104,
+	PWM3_CLK_ROOT			= 105,
+	PWM4_CLK_ROOT			= 106,
+	GPT1_CLK_ROOT			= 107,
+	GPT2_CLK_ROOT			= 108,
+	GPT3_CLK_ROOT			= 109,
+	GPT4_CLK_ROOT			= 110,
+	GPT5_CLK_ROOT			= 111,
+	GPT6_CLK_ROOT			= 112,
+	TRACE_CLK_ROOT			= 113,
+	WDOG_CLK_ROOT			= 114,
+	WRCLK_CLK_ROOT			= 115,
+	IPP_DO_CLKO1			= 116,
+	IPP_DO_CLKO2			= 117,
+	MIPI_DSI_CORE_CLK_ROOT		= 118,
+	MIPI_DSI_PHY_REF_CLK_ROOT	= 119,
+	MIPI_DSI_DBI_CLK_ROOT		= 120,
+	USDHC3_CLK_ROOT			= 121,
+	MIPI_CSI1_CORE_CLK_ROOT		= 122,
+	MIPI_CSI1_PHY_REF_CLK_ROOT	= 123,
+	MIPI_CSI1_ESC_CLK_ROOT		= 124,
+	MIPI_CSI2_CORE_CLK_ROOT		= 125,
+	MIPI_CSI2_PHY_REF_CLK_ROOT	= 126,
+	MIPI_CSI2_ESC_CLK_ROOT		= 127,
+	PCIE2_CTRL_CLK_ROOT		= 128,
+	PCIE2_PHY_CLK_ROOT		= 129,
+	PCIE2_AUX_CLK_ROOT		= 130,
+	ECSPI3_CLK_ROOT			= 131,
+	PDM_CLK_ROOT			= 132,
+	VPU_H1_CLK_ROOT			= 133,
+	CLK_ROOT_MAX,
+};
+
+enum clk_root_src {
+	OSC_24M_CLK,
+	ARM_PLL_CLK,
+	DRAM_PLL1_CLK,
+	VIDEO_PLL2_CLK,
+	VPU_PLL_CLK,
+	GPU_PLL_CLK,
+	SYSTEM_PLL1_800M_CLK,
+	SYSTEM_PLL1_400M_CLK,
+	SYSTEM_PLL1_266M_CLK,
+	SYSTEM_PLL1_200M_CLK,
+	SYSTEM_PLL1_160M_CLK,
+	SYSTEM_PLL1_133M_CLK,
+	SYSTEM_PLL1_100M_CLK,
+	SYSTEM_PLL1_80M_CLK,
+	SYSTEM_PLL1_40M_CLK,
+	SYSTEM_PLL2_1000M_CLK,
+	SYSTEM_PLL2_500M_CLK,
+	SYSTEM_PLL2_333M_CLK,
+	SYSTEM_PLL2_250M_CLK,
+	SYSTEM_PLL2_200M_CLK,
+	SYSTEM_PLL2_166M_CLK,
+	SYSTEM_PLL2_125M_CLK,
+	SYSTEM_PLL2_100M_CLK,
+	SYSTEM_PLL2_50M_CLK,
+	SYSTEM_PLL3_CLK,
+	AUDIO_PLL1_CLK,
+	AUDIO_PLL2_CLK,
+	VIDEO_PLL_CLK,
+	OSC_32K_CLK,
+	EXT_CLK_1,
+	EXT_CLK_2,
+	EXT_CLK_3,
+	EXT_CLK_4,
+	OSC_HDMI_CLK
+};
+
+enum clk_ccgr_index {
+	CCGR_DVFS = 0,
+	CCGR_ANAMIX = 1,
+	CCGR_CPU = 2,
+	CCGR_CSU = 3,
+	CCGR_DEBUG = 4,
+	CCGR_DDR1 = 5,
+	CCGR_ECSPI1 = 7,
+	CCGR_ECSPI2 = 8,
+	CCGR_ECSPI3 = 9,
+	CCGR_ENET1 = 10,
+	CCGR_GPIO1 = 11,
+	CCGR_GPIO2 = 12,
+	CCGR_GPIO3 = 13,
+	CCGR_GPIO4 = 14,
+	CCGR_GPIO5 = 15,
+	CCGR_GPT1 = 16,
+	CCGR_GPT2 = 17,
+	CCGR_GPT3 = 18,
+	CCGR_GPT4 = 19,
+	CCGR_GPT5 = 20,
+	CCGR_GPT6 = 21,
+	CCGR_HS = 22,
+	CCGR_I2C1 = 23,
+	CCGR_I2C2 = 24,
+	CCGR_I2C3 = 25,
+	CCGR_I2C4 = 26,
+	CCGR_IOMUX = 27,
+	CCGR_IOMUX1 = 28,
+	CCGR_IOMUX2 = 29,
+	CCGR_IOMUX3 = 30,
+	CCGR_IOMUX4 = 31,
+	CCGR_SNVSMIX_IPG_CLK = 32,
+	CCGR_MU = 33,
+	CCGR_OCOTP = 34,
+	CCGR_OCRAM = 35,
+	CCGR_OCRAM_S = 36,
+	CCGR_PCIE = 37,
+	CCGR_PERFMON1 = 38,
+	CCGR_PERFMON2 = 39,
+	CCGR_PWM1 = 40,
+	CCGR_PWM2 = 41,
+	CCGR_PWM3 = 42,
+	CCGR_PWM4 = 43,
+	CCGR_QOS = 44,
+	CCGR_QOS_DISPMIX = 45,
+	CCGR_QOS_ETHENET = 46,
+	CCGR_QSPI = 47,
+	CCGR_RAWNAND = 48,
+	CCGR_RDC = 49,
+	CCGR_ROM = 50,
+	CCGR_SAI1 = 51,
+	CCGR_SAI2 = 52,
+	CCGR_SAI3 = 53,
+	CCGR_SAI4 = 54,
+	CCGR_SAI5 = 55,
+	CCGR_SAI6 = 56,
+	CCGR_SCTR = 57,
+	CCGR_SDMA1 = 58,
+	CCGR_SDMA2 = 59,
+	CCGR_SEC_DEBUG = 60,
+	CCGR_SEMA1 = 61,
+	CCGR_SEMA2 = 62,
+	CCGR_SIM_DISPLAY = 63,
+	CCGR_SIM_ENET = 64,
+	CCGR_SIM_M = 65,
+	CCGR_SIM_MAIN = 66,
+	CCGR_SIM_S = 67,
+	CCGR_SIM_WAKEUP = 68,
+	CCGR_SIM_HSIO = 69,
+	CCGR_SIM_VPU = 70,
+	CCGR_SNVS = 71,
+	CCGR_TRACE = 72,
+	CCGR_UART1 = 73,
+	CCGR_UART2 = 74,
+	CCGR_UART3 = 75,
+	CCGR_UART4 = 76,
+	CCGR_USB_MSCALE_PL301 = 77,
+	CCGR_GPU3D = 79,
+	CCGR_USDHC1 = 81,
+	CCGR_USDHC2 = 82,
+	CCGR_WDOG1 = 83,
+	CCGR_WDOG2 = 84,
+	CCGR_WDOG3 = 85,
+	CCGR_VPUG1 = 86,
+	CCGR_GPU_BUS = 87,
+	CCGR_VPUH1 = 89,
+	CCGR_VPUG2 = 90,
+	CCGR_PDM = 91,
+	CCGR_GIC = 92,
+	CCGR_DISPMIX = 93,
+	CCGR_USDHC3 = 94,
+	CCGR_SDMA3 = 95,
+	CCGR_XTAL = 96,
+	CCGR_PLL = 97,
+	CCGR_TEMP_SENSOR = 98,
+	CCGR_VPUMIX_BUS = 99,
+	CCGR_GPU2D = 102,
+	CCGR_MAX
+};
+
+enum clk_src_index {
+	CLK_SRC_CKIL_SYNC_REQ = 0,
+	CLK_SRC_ARM_PLL_EN = 1,
+	CLK_SRC_GPU_PLL_EN = 2,
+	CLK_SRC_VPU_PLL_EN = 3,
+	CLK_SRC_DRAM_PLL_EN = 4,
+	CLK_SRC_SYSTEM_PLL1_EN = 5,
+	CLK_SRC_SYSTEM_PLL2_EN = 6,
+	CLK_SRC_SYSTEM_PLL3_EN = 7,
+	CLK_SRC_AUDIO_PLL1_EN = 8,
+	CLK_SRC_AUDIO_PLL2_EN = 9,
+	CLK_SRC_VIDEO_PLL1_EN = 10,
+	CLK_SRC_RESERVED = 11,
+	CLK_SRC_ARM_PLL = 12,
+	CLK_SRC_GPU_PLL = 13,
+	CLK_SRC_VPU_PLL = 14,
+	CLK_SRC_DRAM_PLL = 15,
+	CLK_SRC_SYSTEM_PLL1_800M = 16,
+	CLK_SRC_SYSTEM_PLL1_400M = 17,
+	CLK_SRC_SYSTEM_PLL1_266M = 18,
+	CLK_SRC_SYSTEM_PLL1_200M = 19,
+	CLK_SRC_SYSTEM_PLL1_160M = 20,
+	CLK_SRC_SYSTEM_PLL1_133M = 21,
+	CLK_SRC_SYSTEM_PLL1_100M = 22,
+	CLK_SRC_SYSTEM_PLL1_80M = 23,
+	CLK_SRC_SYSTEM_PLL1_40M = 24,
+	CLK_SRC_SYSTEM_PLL2_1000M = 25,
+	CLK_SRC_SYSTEM_PLL2_500M = 26,
+	CLK_SRC_SYSTEM_PLL2_333M = 27,
+	CLK_SRC_SYSTEM_PLL2_250M = 28,
+	CLK_SRC_SYSTEM_PLL2_200M = 29,
+	CLK_SRC_SYSTEM_PLL2_166M = 30,
+	CLK_SRC_SYSTEM_PLL2_125M = 31,
+	CLK_SRC_SYSTEM_PLL2_100M = 32,
+	CLK_SRC_SYSTEM_PLL2_50M = 33,
+	CLK_SRC_SYSTEM_PLL3 = 34,
+	CLK_SRC_AUDIO_PLL1 = 35,
+	CLK_SRC_AUDIO_PLL2 = 36,
+	CLK_SRC_VIDEO_PLL1 = 37,
+};
+
+#define INTPLL_LOCK_MASK			BIT(31)
+#define INTPLL_LOCK_SEL_MASK			BIT(29)
+#define INTPLL_EXT_BYPASS_MASK			BIT(28)
+#define INTPLL_DIV20_CLKE_MASK			BIT(27)
+#define INTPLL_DIV20_CLKE_OVERRIDE_MASK		BIT(26)
+#define INTPLL_DIV10_CLKE_MASK			BIT(25)
+#define INTPLL_DIV10_CLKE_OVERRIDE_MASK		BIT(24)
+#define INTPLL_DIV8_CLKE_MASK			BIT(23)
+#define INTPLL_DIV8_CLKE_OVERRIDE_MASK		BIT(22)
+#define INTPLL_DIV6_CLKE_MASK			BIT(21)
+#define INTPLL_DIV6_CLKE_OVERRIDE_MASK		BIT(20)
+#define INTPLL_DIV5_CLKE_MASK			BIT(19)
+#define INTPLL_DIV5_CLKE_OVERRIDE_MASK		BIT(18)
+#define INTPLL_DIV4_CLKE_MASK			BIT(17)
+#define INTPLL_DIV4_CLKE_OVERRIDE_MASK		BIT(16)
+#define INTPLL_DIV3_CLKE_MASK			BIT(15)
+#define INTPLL_DIV3_CLKE_OVERRIDE_MASK		BIT(14)
+#define INTPLL_DIV2_CLKE_MASK			BIT(13)
+#define INTPLL_DIV2_CLKE_OVERRIDE_MASK		BIT(12)
+#define INTPLL_CLKE_MASK			BIT(11)
+#define INTPLL_CLKE_OVERRIDE_MASK		BIT(10)
+#define INTPLL_RST_MASK				BIT(9)
+#define INTPLL_RST_OVERRIDE_MASK		BIT(8)
+#define INTPLL_BYPASS_MASK			BIT(4)
+#define INTPLL_PAD_CLK_SEL_MASK			GENMASK(3, 2)
+#define INTPLL_REF_CLK_SEL_MASK			GENMASK(1, 0)
+
+#define INTPLL_MAIN_DIV_MASK		GENMASK(21, 12)
+#define INTPLL_MAIN_DIV_VAL(n)		((n << 12) & GENMASK(21, 12))
+#define INTPLL_MAIN_DIV_SHIFT		12
+#define INTPLL_PRE_DIV_MASK		GENMASK(9, 4)
+#define INTPLL_PRE_DIV_VAL(n)		((n << 4) & GENMASK(9, 4))
+#define INTPLL_PRE_DIV_SHIFT		4
+#define INTPLL_POST_DIV_MASK		GENMASK(2, 0)
+#define INTPLL_POST_DIV_VAL(n)		((n << 0) & GENMASK(2, 0))
+#define INTPLL_POST_DIV_SHIFT		0
+
+#define INTPLL_LOCK_CON_DLY_MASK	GENMASK(5, 4)
+#define INTPLL_LOCK_CON_DLY_SHIFT	4
+#define INTPLL_LOCK_CON_OUT_MASK	GENMASK(3, 2)
+#define INTPLL_LOCK_CON_OUT_SHIFT	2
+#define INTPLL_LOCK_CON_IN_MASK		GENMASK(1, 0)
+#define INTPLL_LOCK_CON_IN_SHIFT	0
+
+#define INTPLL_LRD_EN_MASK		BIT(21)
+#define INTPLL_FOUT_MASK		BIT(20)
+#define INTPLL_AFC_SEL_MASK		BIT(19)
+#define INTPLL_PBIAS_CTRL_MASK		BIT(18)
+#define INTPLL_PBIAS_CTRL_EN_MASK	BIT(17)
+#define INTPLL_AFCINIT_SEL_MASK		BIT(16)
+#define INTPLL_FSEL_MASK		BIT(14)
+#define INTPLL_FEED_EN_MASK		BIT(13)
+#define INTPLL_EXTAFC_MASK		GENMASK(7, 3)
+#define INTPLL_AFC_EN_MASK		BIT(2)
+#define INTPLL_ICP_MASK			GENMASK(1, 0)
+
+#endif
diff --git a/arch/arm/mach-imx/imx8m/Makefile b/arch/arm/mach-imx/imx8m/Makefile
index 42a1544..92184f3 100644
--- a/arch/arm/mach-imx/imx8m/Makefile
+++ b/arch/arm/mach-imx/imx8m/Makefile
@@ -5,3 +5,4 @@
 obj-y += lowlevel_init.o
 obj-y += clock_slice.o soc.o
 obj-$(CONFIG_IMX8MQ) += clock_imx8mq.o
+obj-$(CONFIG_IMX8MM) += clock_imx8mm.o
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
new file mode 100644
index 0000000..ee44ba7
--- /dev/null
+++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018-2019 NXP
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include <div64.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
+
+void enable_ocotp_clk(unsigned char enable)
+{
+	struct clk *clkp;
+	int ret;
+
+	ret = clk_get_by_id(IMX8MM_CLK_OCOTP_ROOT, &clkp);
+	if (ret) {
+		printf("%s: err: %d\n", __func__, ret);
+		return;
+	}
+
+	enable ? clk_enable(clkp) : clk_disable(clkp);
+}
+
+int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
+{
+	struct clk *clkp;
+	int ret;
+
+	ret = clk_get_by_id(IMX8MM_CLK_I2C1_ROOT + i2c_num, &clkp);
+	if (ret) {
+		printf("%s: err: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return enable ? clk_enable(clkp) : clk_disable(clkp);
+}
+
+#ifdef CONFIG_SPL_BUILD
+static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = {
+	PLL_1443X_RATE(800000000U, 300, 9, 0, 0),
+	PLL_1443X_RATE(750000000U, 250, 8, 0, 0),
+	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+	PLL_1443X_RATE(600000000U, 300, 3, 2, 0),
+	PLL_1443X_RATE(594000000U, 99, 1, 2, 0),
+	PLL_1443X_RATE(400000000U, 300, 9, 1, 0),
+	PLL_1443X_RATE(266666667U, 400, 9, 2, 0),
+	PLL_1443X_RATE(167000000U, 334, 3, 4, 0),
+	PLL_1443X_RATE(100000000U, 300, 9, 3, 0),
+};
+
+int fracpll_configure(enum pll_clocks pll, u32 freq)
+{
+	int i;
+	u32 tmp, div_val;
+	void *pll_base;
+	struct imx_int_pll_rate_table *rate;
+
+	for (i = 0; i < ARRAY_SIZE(imx8mm_fracpll_tbl); i++) {
+		if (freq == imx8mm_fracpll_tbl[i].rate)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(imx8mm_fracpll_tbl)) {
+		printf("No matched freq table %u\n", freq);
+		return -EINVAL;
+	}
+
+	rate = &imx8mm_fracpll_tbl[i];
+
+	switch (pll) {
+	case ANATOP_DRAM_PLL:
+		setbits_le32(GPC_BASE_ADDR + 0xEC, 1 << 7);
+		setbits_le32(GPC_BASE_ADDR + 0xF8, 1 << 5);
+		writel(SRC_DDR1_ENABLE_MASK, SRC_BASE_ADDR + 0x1004);
+
+		pll_base = &ana_pll->dram_pll_gnrl_ctl;
+		break;
+	case ANATOP_VIDEO_PLL:
+		pll_base = &ana_pll->video_pll1_gnrl_ctl;
+		break;
+	default:
+		return 0;
+	}
+	/* Bypass clock and set lock to pll output lock */
+	tmp = readl(pll_base);
+	tmp |= BYPASS_MASK;
+	writel(tmp, pll_base);
+
+	/* Enable RST */
+	tmp &= ~RST_MASK;
+	writel(tmp, pll_base);
+
+	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+		(rate->sdiv << SDIV_SHIFT);
+	writel(div_val, pll_base + 4);
+	writel(rate->kdiv << KDIV_SHIFT, pll_base + 8);
+
+	__udelay(100);
+
+	/* Disable RST */
+	tmp |= RST_MASK;
+	writel(tmp, pll_base);
+
+	/* Wait Lock*/
+	while (!(readl(pll_base) & LOCK_STATUS))
+		;
+
+	/* Bypass */
+	tmp &= ~BYPASS_MASK;
+	writel(tmp, pll_base);
+
+	return 0;
+}
+
+void dram_pll_init(ulong pll_val)
+{
+	fracpll_configure(ANATOP_DRAM_PLL, pll_val);
+}
+
+static struct dram_bypass_clk_setting imx8mm_dram_bypass_tbl[] = {
+	DRAM_BYPASS_ROOT_CONFIG(MHZ(100), 2, CLK_ROOT_PRE_DIV1, 2,
+				CLK_ROOT_PRE_DIV2),
+	DRAM_BYPASS_ROOT_CONFIG(MHZ(250), 3, CLK_ROOT_PRE_DIV2, 2,
+				CLK_ROOT_PRE_DIV2),
+	DRAM_BYPASS_ROOT_CONFIG(MHZ(400), 1, CLK_ROOT_PRE_DIV2, 3,
+				CLK_ROOT_PRE_DIV2),
+};
+
+void dram_enable_bypass(ulong clk_val)
+{
+	int i;
+	struct dram_bypass_clk_setting *config;
+
+	for (i = 0; i < ARRAY_SIZE(imx8mm_dram_bypass_tbl); i++) {
+		if (clk_val == imx8mm_dram_bypass_tbl[i].clk)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(imx8mm_dram_bypass_tbl)) {
+		printf("No matched freq table %lu\n", clk_val);
+		return;
+	}
+
+	config = &imx8mm_dram_bypass_tbl[i];
+
+	clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(config->alt_root_sel) |
+			     CLK_ROOT_PRE_DIV(config->alt_pre_div));
+	clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(config->apb_root_sel) |
+			     CLK_ROOT_PRE_DIV(config->apb_pre_div));
+	clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(1));
+}
+
+void dram_disable_bypass(void)
+{
+	clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(0));
+	clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(4) |
+			     CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5));
+}
+#endif
+
+void init_uart_clk(u32 index)
+{
+	/*
+	 * set uart clock root
+	 * 24M OSC
+	 */
+	switch (index) {
+	case 0:
+		clock_enable(CCGR_UART1, 0);
+		clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON |
+				     CLK_ROOT_SOURCE_SEL(0));
+		clock_enable(CCGR_UART1, 1);
+		return;
+	case 1:
+		clock_enable(CCGR_UART2, 0);
+		clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON |
+				     CLK_ROOT_SOURCE_SEL(0));
+		clock_enable(CCGR_UART2, 1);
+		return;
+	case 2:
+		clock_enable(CCGR_UART3, 0);
+		clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON |
+				     CLK_ROOT_SOURCE_SEL(0));
+		clock_enable(CCGR_UART3, 1);
+		return;
+	case 3:
+		clock_enable(CCGR_UART4, 0);
+		clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON |
+				     CLK_ROOT_SOURCE_SEL(0));
+		clock_enable(CCGR_UART4, 1);
+		return;
+	default:
+		printf("Invalid uart index\n");
+		return;
+	}
+}
+
+void init_wdog_clk(void)
+{
+	clock_enable(CCGR_WDOG1, 0);
+	clock_enable(CCGR_WDOG2, 0);
+	clock_enable(CCGR_WDOG3, 0);
+	clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(0));
+	clock_enable(CCGR_WDOG1, 1);
+	clock_enable(CCGR_WDOG2, 1);
+	clock_enable(CCGR_WDOG3, 1);
+}
+
+int clock_init(void)
+{
+	u32 val_cfg0;
+
+	/*
+	 * The gate is not exported to clk tree, so configure them here.
+	 * According to ANAMIX SPEC
+	 * sys pll1 fixed at 800MHz
+	 * sys pll2 fixed at 1GHz
+	 * Here we only enable the outputs.
+	 */
+	val_cfg0 = readl(&ana_pll->sys_pll1_gnrl_ctl);
+	val_cfg0 |= INTPLL_CLKE_MASK | INTPLL_DIV2_CLKE_MASK |
+		INTPLL_DIV3_CLKE_MASK | INTPLL_DIV4_CLKE_MASK |
+		INTPLL_DIV5_CLKE_MASK | INTPLL_DIV6_CLKE_MASK |
+		INTPLL_DIV8_CLKE_MASK | INTPLL_DIV10_CLKE_MASK |
+		INTPLL_DIV20_CLKE_MASK;
+	writel(val_cfg0, &ana_pll->sys_pll1_gnrl_ctl);
+
+	val_cfg0 = readl(&ana_pll->sys_pll2_gnrl_ctl);
+	val_cfg0 |= INTPLL_CLKE_MASK | INTPLL_DIV2_CLKE_MASK |
+		INTPLL_DIV3_CLKE_MASK | INTPLL_DIV4_CLKE_MASK |
+		INTPLL_DIV5_CLKE_MASK | INTPLL_DIV6_CLKE_MASK |
+		INTPLL_DIV8_CLKE_MASK | INTPLL_DIV10_CLKE_MASK |
+		INTPLL_DIV20_CLKE_MASK;
+	writel(val_cfg0, &ana_pll->sys_pll2_gnrl_ctl);
+
+	/* config GIC to sys_pll2_100m */
+	clock_enable(CCGR_GIC, 0);
+	clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(3));
+	clock_enable(CCGR_GIC, 1);
+
+	clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(1));
+
+	clock_enable(CCGR_DDR1, 0);
+	clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(1));
+	clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
+			     CLK_ROOT_SOURCE_SEL(1));
+	clock_enable(CCGR_DDR1, 1);
+
+	init_wdog_clk();
+
+	clock_enable(CCGR_TEMP_SENSOR, 1);
+
+	clock_enable(CCGR_SEC_DEBUG, 1);
+
+	return 0;
+};
+
+u32 imx_get_uartclk(void)
+{
+	return 24000000U;
+}
+
+u32 mxc_get_clock(enum mxc_clock clk)
+{
+	struct clk *clkp;
+	int ret;
+
+	switch (clk) {
+	case MXC_IPG_CLK:
+		ret = clk_get_by_id(IMX8MM_CLK_IPG_ROOT, &clkp);
+		if (ret)
+			return 0;
+		return clk_get_rate(clkp);
+	case MXC_ARM_CLK:
+		ret = clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp);
+		if (ret)
+			return 0;
+		return clk_get_rate(clkp);
+	default:
+		printf("%s: %d not supported\n", __func__, clk);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-imx/imx8m/clock_slice.c b/arch/arm/mach-imx/imx8m/clock_slice.c
index 1a67c62..780f643 100644
--- a/arch/arm/mach-imx/imx8m/clock_slice.c
+++ b/arch/arm/mach-imx/imx8m/clock_slice.c
@@ -13,6 +13,7 @@
 
 static struct ccm_reg *ccm_reg = (struct ccm_reg *)CCM_BASE_ADDR;
 
+#ifdef CONFIG_IMX8MQ
 static struct clk_root_map root_array[] = {
 	{ARM_A53_CLK_ROOT, CORE_CLOCK_SLICE, 0,
 	 {OSC_25M_CLK, ARM_PLL_CLK, SYSTEM_PLL2_500M_CLK,
@@ -474,6 +475,68 @@
 	 {DRAM_PLL1_CLK}
 	},
 };
+#elif defined(CONFIG_IMX8MM)
+static struct clk_root_map root_array[] = {
+	{NAND_USDHC_BUS_CLK_ROOT, BUS_CLOCK_SLICE, 2,
+	 {OSC_24M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
+	  SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_133M_CLK,
+	  SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL1_CLK}
+	},
+	{NOC_CLK_ROOT, BUS_CLOCK_SLICE, 10,
+	 {OSC_24M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL3_CLK,
+	  SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL2_500M_CLK,
+	  AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
+	},
+	{NOC_APB_CLK_ROOT, BUS_CLOCK_SLICE, 11,
+	 {OSC_24M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL3_CLK,
+	  SYSTEM_PLL2_333M_CLK, SYSTEM_PLL2_200M_CLK,
+	  SYSTEM_PLL1_800M_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK}
+	},
+	{DRAM_ALT_CLK_ROOT, IP_CLOCK_SLICE, 0,
+	 {OSC_24M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL1_100M_CLK,
+	  SYSTEM_PLL2_500M_CLK, SYSTEM_PLL2_1000M_CLK,
+	  SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, SYSTEM_PLL1_266M_CLK}
+	},
+	{DRAM_APB_CLK_ROOT, IP_CLOCK_SLICE, 1,
+	 {OSC_24M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
+	  SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_800M_CLK,
+	  SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL2_CLK}
+	},
+	{UART1_CLK_ROOT, IP_CLOCK_SLICE, 30,
+	 {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
+	  SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
+	  EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
+	},
+	{UART2_CLK_ROOT, IP_CLOCK_SLICE, 31,
+	 {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
+	  SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
+	  EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK}
+	},
+	{UART3_CLK_ROOT, IP_CLOCK_SLICE, 32,
+	 {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
+	  SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
+	  EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
+	},
+	{UART4_CLK_ROOT, IP_CLOCK_SLICE, 33,
+	 {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
+	  SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
+	  EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK}
+	},
+	{GIC_CLK_ROOT, IP_CLOCK_SLICE, 36,
+	 {OSC_24M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
+	  SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_800M_CLK,
+	  EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
+	},
+	{WDOG_CLK_ROOT, IP_CLOCK_SLICE, 50,
+	 {OSC_24M_CLK, SYSTEM_PLL1_133M_CLK, SYSTEM_PLL1_160M_CLK,
+	  VPU_PLL_CLK, SYSTEM_PLL2_125M_CLK,
+	  SYSTEM_PLL3_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_166M_CLK}
+	},
+	{DRAM_SEL_CFG, DRAM_SEL_CLOCK_SLICE, 0,
+	 {DRAM_PLL1_CLK}
+	},
+};
+#endif
 
 static int select(enum clk_root_index clock_id)
 {