• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1commit d3211978913e7ee651bf47cfb393daccb8be4fdb
2Author: zhaoxc0502 <zhaoxc0502@thundersoft.com>
3Date:   Wed Aug 10 11:43:26 2022 +0800
4
5    drivers_clk
6
7    Change-Id: Iad3fba6c51f290df25555d1136fd2cc4761d3324
8
9diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
10index c715d4681..3853ce51b 100644
11--- a/drivers/clk/Kconfig
12+++ b/drivers/clk/Kconfig
13@@ -374,6 +374,7 @@ source "drivers/clk/mvebu/Kconfig"
14 source "drivers/clk/qcom/Kconfig"
15 source "drivers/clk/renesas/Kconfig"
16 source "drivers/clk/rockchip/Kconfig"
17+source "drivers/clk/s32/Kconfig"
18 source "drivers/clk/samsung/Kconfig"
19 source "drivers/clk/sifive/Kconfig"
20 source "drivers/clk/sprd/Kconfig"
21diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
22index da8fcf147..8a52da49c 100644
23--- a/drivers/clk/Makefile
24+++ b/drivers/clk/Makefile
25@@ -102,6 +102,7 @@ obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
26 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
27 obj-y					+= renesas/
28 obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
29+obj-$(CONFIG_ARCH_S32)			+= s32/
30 obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
31 obj-$(CONFIG_CLK_SIFIVE)		+= sifive/
32 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
33diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
34index 61c78714c..18cfdbaab 100644
35--- a/drivers/clk/clk.c
36+++ b/drivers/clk/clk.c
37@@ -807,8 +807,7 @@ static void clk_core_unprepare(struct clk_core *core)
38 	if (!core)
39 		return;
40
41-	if (WARN(core->prepare_count == 0,
42-	    "%s already unprepared\n", core->name))
43+	if (core->prepare_count == 0)
44 		return;
45
46 	if (WARN(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL,
47@@ -949,7 +948,7 @@ static void clk_core_disable(struct clk_core *core)
48 	if (!core)
49 		return;
50
51-	if (WARN(core->enable_count == 0, "%s already disabled\n", core->name))
52+	if (core->enable_count == 0)
53 		return;
54
55 	if (WARN(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL,
56@@ -1008,8 +1007,7 @@ static int clk_core_enable(struct clk_core *core)
57 	if (!core)
58 		return 0;
59
60-	if (WARN(core->prepare_count == 0,
61-	    "Enabling unprepared %s\n", core->name))
62+	if (core->prepare_count == 0)
63 		return -ESHUTDOWN;
64
65 	if (core->enable_count == 0) {
66@@ -2495,7 +2493,8 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
67 	if (!core)
68 		return 0;
69
70-	if (core->parent == parent)
71+	if ((core->parent == parent) &&
72+		!(core->flags & CLK_SET_PARENT_NOCACHE))
73 		return 0;
74
75 	/* verify ops for multi-parent clks */
76diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
77index dd6a737d0..c4a188768 100644
78--- a/drivers/clk/imx/Makefile
79+++ b/drivers/clk/imx/Makefile
80@@ -23,12 +23,17 @@ obj-$(CONFIG_MXC_CLK) += mxc-clk.o
81
82 obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
83 obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
84-obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
85+obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-blk-ctrl.o
86 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
87
88 obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o
89-clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o
90+clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \
91+				     clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o \
92+				     clk-imx8dxl-rsrc.o
93 clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o
94+obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp-acm.o clk-imx8qm-acm.o clk-imx8dxl-acm.o clk-imx-acm-utils.o
95+
96+obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp.o
97
98 obj-$(CONFIG_CLK_IMX1)   += clk-imx1.o
99 obj-$(CONFIG_CLK_IMX25)  += clk-imx25.o
100diff --git a/drivers/clk/imx/clk-composite-7ulp.c b/drivers/clk/imx/clk-composite-7ulp.c
101index 7c4f31b31..6cc1b8bb8 100644
102--- a/drivers/clk/imx/clk-composite-7ulp.c
103+++ b/drivers/clk/imx/clk-composite-7ulp.c
104@@ -8,6 +8,7 @@
105 #include <linux/bits.h>
106 #include <linux/clk-provider.h>
107 #include <linux/err.h>
108+#include <linux/io.h>
109 #include <linux/slab.h>
110
111 #include "clk.h"
112@@ -22,17 +23,61 @@
113 #define PCG_PCD_WIDTH	3
114 #define PCG_PCD_MASK	0x7
115
116-struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
117+#define SW_RST		BIT(28)
118+
119+static int pcc_gate_enable(struct clk_hw *hw)
120+{
121+	struct clk_gate *gate = to_clk_gate(hw);
122+	unsigned long flags;
123+	u32 val;
124+	int ret;
125+
126+	ret = clk_gate_ops.enable(hw);
127+	if (ret)
128+		return ret;
129+
130+	spin_lock_irqsave(gate->lock, flags);
131+	/*
132+	 * release the sw reset for peripherals associated with
133+	 * with this pcc clock.
134+	 */
135+	val = readl(gate->reg);
136+	val |= SW_RST;
137+	writel(val, gate->reg);
138+
139+	spin_unlock_irqrestore(gate->lock, flags);
140+
141+	return 0;
142+}
143+
144+static void pcc_gate_disable(struct clk_hw *hw)
145+{
146+	clk_gate_ops.disable(hw);
147+}
148+
149+static int pcc_gate_is_enabled(struct clk_hw *hw)
150+{
151+	return clk_gate_ops.is_enabled(hw);
152+}
153+
154+static const struct clk_ops pcc_gate_ops = {
155+	.enable = pcc_gate_enable,
156+	.disable = pcc_gate_disable,
157+	.is_enabled = pcc_gate_is_enabled,
158+};
159+
160+static struct clk_hw *imx_ulp_clk_hw_composite(const char *name,
161 				     const char * const *parent_names,
162 				     int num_parents, bool mux_present,
163 				     bool rate_present, bool gate_present,
164-				     void __iomem *reg)
165+				     void __iomem *reg, bool has_swrst)
166 {
167 	struct clk_hw *mux_hw = NULL, *fd_hw = NULL, *gate_hw = NULL;
168 	struct clk_fractional_divider *fd = NULL;
169 	struct clk_gate *gate = NULL;
170 	struct clk_mux *mux = NULL;
171 	struct clk_hw *hw;
172+	u32 val;
173
174 	if (mux_present) {
175 		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
176@@ -42,6 +87,8 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
177 		mux->reg = reg;
178 		mux->shift = PCG_PCS_SHIFT;
179 		mux->mask = PCG_PCS_MASK;
180+		if (has_swrst)
181+			mux->lock = &imx_ccm_lock;
182 	}
183
184 	if (rate_present) {
185@@ -59,6 +106,8 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
186 		fd->nwidth = PCG_PCD_WIDTH;
187 		fd->nmask = PCG_PCD_MASK;
188 		fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
189+		if (has_swrst)
190+			fd->lock = &imx_ccm_lock;
191 	}
192
193 	if (gate_present) {
194@@ -71,13 +120,27 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
195 		gate_hw = &gate->hw;
196 		gate->reg = reg;
197 		gate->bit_idx = PCG_CGC_SHIFT;
198+		if (has_swrst)
199+			gate->lock = &imx_ccm_lock;
200+		/*
201+		 * make sure clock is gated during clock tree initialization,
202+		 * the HW ONLY allow clock parent/rate changed with clock gated,
203+		 * during clock tree initialization, clocks could be enabled
204+		 * by bootloader, so the HW status will mismatch with clock tree
205+		 * prepare count, then clock core driver will allow parent/rate
206+		 * change since the prepare count is zero, but HW actually
207+		 * prevent the parent/rate change due to the clock is enabled.
208+		 */
209+		val = readl_relaxed(reg);
210+		val &= ~(1 << PCG_CGC_SHIFT);
211+		writel_relaxed(val, reg);
212 	}
213
214 	hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
215 				       mux_hw, &clk_mux_ops, fd_hw,
216 				       &clk_fractional_divider_ops, gate_hw,
217-				       &clk_gate_ops, CLK_SET_RATE_GATE |
218-				       CLK_SET_PARENT_GATE);
219+				       has_swrst ? &pcc_gate_ops : &clk_gate_ops, CLK_SET_RATE_GATE |
220+				       CLK_SET_PARENT_GATE | CLK_SET_RATE_NO_REPARENT);
221 	if (IS_ERR(hw)) {
222 		kfree(mux);
223 		kfree(fd);
224@@ -86,3 +149,19 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
225
226 	return hw;
227 }
228+
229+struct clk_hw *imx7ulp_clk_hw_composite(const char *name, const char * const *parent_names,
230+				int num_parents, bool mux_present, bool rate_present,
231+				bool gate_present, void __iomem *reg)
232+{
233+	return imx_ulp_clk_hw_composite(name, parent_names, num_parents, mux_present, rate_present,
234+					gate_present, reg, false);
235+}
236+
237+struct clk_hw *imx8ulp_clk_hw_composite(const char *name, const char * const *parent_names,
238+				int num_parents, bool mux_present, bool rate_present,
239+				bool gate_present, void __iomem *reg, bool has_swrst)
240+{
241+	return imx_ulp_clk_hw_composite(name, parent_names, num_parents, mux_present, rate_present,
242+					gate_present, reg, has_swrst);
243+}
244diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
245index 04e728538..fec34169a 100644
246--- a/drivers/clk/imx/clk-composite-8m.c
247+++ b/drivers/clk/imx/clk-composite-8m.c
248@@ -223,14 +223,19 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
249 	div->lock = &imx_ccm_lock;
250 	div->flags = CLK_DIVIDER_ROUND_CLOSEST;
251
252-	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
253-	if (!gate)
254-		goto fail;
255-
256-	gate_hw = &gate->hw;
257-	gate->reg = reg;
258-	gate->bit_idx = PCG_CGC_SHIFT;
259-	gate->lock = &imx_ccm_lock;
260+	/* skip registering the gate ops if M4 is enabled */
261+	if (imx_src_is_m4_enabled()) {
262+		gate_hw = NULL;
263+	} else {
264+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
265+		if (!gate)
266+			goto fail;
267+
268+		gate_hw = &gate->hw;
269+		gate->reg = reg;
270+		gate->bit_idx = PCG_CGC_SHIFT;
271+		gate->lock = &imx_ccm_lock;
272+	}
273
274 	hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
275 			mux_hw, mux_ops, div_hw,
276diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
277index 7eed7083f..0f8fb0341 100644
278--- a/drivers/clk/imx/clk-gate2.c
279+++ b/drivers/clk/imx/clk-gate2.c
280@@ -8,11 +8,13 @@
281
282 #include <linux/clk-provider.h>
283 #include <linux/export.h>
284+#include <linux/imx_sema4.h>
285 #include <linux/module.h>
286 #include <linux/slab.h>
287 #include <linux/io.h>
288 #include <linux/err.h>
289 #include <linux/string.h>
290+#include <soc/imx/src.h>
291 #include "clk.h"
292
293 /**
294@@ -37,10 +39,54 @@ struct clk_gate2 {
295
296 #define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw)
297
298+static void clk_gate2_do_hardware(struct clk_gate2 *gate, bool enable)
299+{
300+	u32 reg;
301+
302+	reg = readl(gate->reg);
303+	if (enable)
304+		reg |= gate->cgr_val << gate->bit_idx;
305+	else
306+		reg &= ~(gate->cgr_val << gate->bit_idx);
307+	writel(reg, gate->reg);
308+}
309+
310+static void clk_gate2_do_shared_clks(struct clk_hw *hw, bool enable)
311+{
312+	struct clk_gate2 *gate = to_clk_gate2(hw);
313+
314+	if (imx_src_is_m4_enabled() && clk_on_imx6sx()) {
315+#ifdef CONFIG_SOC_IMX6SX
316+		if (!amp_power_mutex || !shared_mem) {
317+			if (enable)
318+				clk_gate2_do_hardware(gate, enable);
319+			return;
320+		}
321+
322+		imx_sema4_mutex_lock(amp_power_mutex);
323+		if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
324+			shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
325+			imx_sema4_mutex_unlock(amp_power_mutex);
326+			return;
327+		}
328+
329+		if (!imx_update_shared_mem(hw, enable)) {
330+			imx_sema4_mutex_unlock(amp_power_mutex);
331+			return;
332+		}
333+
334+		clk_gate2_do_hardware(gate, enable);
335+
336+		imx_sema4_mutex_unlock(amp_power_mutex);
337+#endif
338+	} else {
339+		clk_gate2_do_hardware(gate, enable);
340+	}
341+}
342+
343 static int clk_gate2_enable(struct clk_hw *hw)
344 {
345 	struct clk_gate2 *gate = to_clk_gate2(hw);
346-	u32 reg;
347 	unsigned long flags;
348 	int ret = 0;
349
350@@ -49,15 +95,7 @@ static int clk_gate2_enable(struct clk_hw *hw)
351 	if (gate->share_count && (*gate->share_count)++ > 0)
352 		goto out;
353
354-	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
355-		ret = clk_gate_ops.enable(hw);
356-	} else {
357-		reg = readl(gate->reg);
358-		reg &= ~(3 << gate->bit_idx);
359-		reg |= gate->cgr_val << gate->bit_idx;
360-		writel(reg, gate->reg);
361-	}
362-
363+	clk_gate2_do_shared_clks(hw, true);
364 out:
365 	spin_unlock_irqrestore(gate->lock, flags);
366
367@@ -67,7 +105,6 @@ static int clk_gate2_enable(struct clk_hw *hw)
368 static void clk_gate2_disable(struct clk_hw *hw)
369 {
370 	struct clk_gate2 *gate = to_clk_gate2(hw);
371-	u32 reg;
372 	unsigned long flags;
373
374 	spin_lock_irqsave(gate->lock, flags);
375@@ -79,23 +116,16 @@ static void clk_gate2_disable(struct clk_hw *hw)
376 			goto out;
377 	}
378
379-	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
380-		clk_gate_ops.disable(hw);
381-	} else {
382-		reg = readl(gate->reg);
383-		reg &= ~(3 << gate->bit_idx);
384-		writel(reg, gate->reg);
385-	}
386-
387+	clk_gate2_do_shared_clks(hw, false);
388 out:
389 	spin_unlock_irqrestore(gate->lock, flags);
390 }
391
392-static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx)
393+static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx, u8 cgr_val)
394 {
395 	u32 val = readl(reg);
396
397-	if (((val >> bit_idx) & 1) == 1)
398+	if (((val >> bit_idx) & cgr_val) == 1)
399 		return 1;
400
401 	return 0;
402@@ -104,29 +134,27 @@ static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx)
403 static int clk_gate2_is_enabled(struct clk_hw *hw)
404 {
405 	struct clk_gate2 *gate = to_clk_gate2(hw);
406+	unsigned long flags;
407+	int ret;
408
409-	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
410-		return clk_gate_ops.is_enabled(hw);
411+	spin_lock_irqsave(gate->lock, flags);
412+
413+	ret = clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx, gate->cgr_val);
414+
415+	spin_unlock_irqrestore(gate->lock, flags);
416
417-	return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
418+	return ret;
419 }
420
421 static void clk_gate2_disable_unused(struct clk_hw *hw)
422 {
423 	struct clk_gate2 *gate = to_clk_gate2(hw);
424 	unsigned long flags;
425-	u32 reg;
426-
427-	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
428-		return;
429
430 	spin_lock_irqsave(gate->lock, flags);
431
432-	if (!gate->share_count || *gate->share_count == 0) {
433-		reg = readl(gate->reg);
434-		reg &= ~(3 << gate->bit_idx);
435-		writel(reg, gate->reg);
436-	}
437+	if (!gate->share_count || *gate->share_count == 0)
438+		clk_gate2_do_shared_clks(hw, false);
439
440 	spin_unlock_irqrestore(gate->lock, flags);
441 }
442diff --git a/drivers/clk/imx/clk-imx-acm-utils.c b/drivers/clk/imx/clk-imx-acm-utils.c
443new file mode 100644
444index 000000000..b923e117d
445--- /dev/null
446+++ b/drivers/clk/imx/clk-imx-acm-utils.c
447@@ -0,0 +1,78 @@
448+// SPDX-License-Identifier: GPL-2.0+
449+// Copyright 2020 NXP
450+
451+#include <linux/pm_runtime.h>
452+#include <linux/pm_domain.h>
453+#include "clk-imx-acm-utils.h"
454+
455+/**
456+ * clk_imx_acm_attach_pm_domains
457+ */
458+int clk_imx_acm_attach_pm_domains(struct device *dev,
459+				  struct clk_imx_acm_pm_domains *dev_pm)
460+{
461+	int ret;
462+	int i;
463+
464+	dev_pm->num_domains = of_count_phandle_with_args(dev->of_node, "power-domains",
465+							 "#power-domain-cells");
466+	if (dev_pm->num_domains <= 1)
467+		return 0;
468+
469+	dev_pm->pd_dev = devm_kmalloc_array(dev, dev_pm->num_domains,
470+					    sizeof(*dev_pm->pd_dev),
471+					    GFP_KERNEL);
472+	if (!dev_pm->pd_dev)
473+		return -ENOMEM;
474+
475+	dev_pm->pd_dev_link = devm_kmalloc_array(dev,
476+						 dev_pm->num_domains,
477+						 sizeof(*dev_pm->pd_dev_link),
478+						 GFP_KERNEL);
479+	if (!dev_pm->pd_dev_link)
480+		return -ENOMEM;
481+
482+	for (i = 0; i < dev_pm->num_domains; i++) {
483+		dev_pm->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
484+		if (IS_ERR(dev_pm->pd_dev[i]))
485+			return PTR_ERR(dev_pm->pd_dev[i]);
486+
487+		dev_pm->pd_dev_link[i] = device_link_add(dev,
488+							 dev_pm->pd_dev[i],
489+							 DL_FLAG_STATELESS |
490+							 DL_FLAG_PM_RUNTIME |
491+							 DL_FLAG_RPM_ACTIVE);
492+		if (IS_ERR(dev_pm->pd_dev_link[i])) {
493+			dev_pm_domain_detach(dev_pm->pd_dev[i], false);
494+			ret = PTR_ERR(dev_pm->pd_dev_link[i]);
495+			goto detach_pm;
496+		}
497+	}
498+	return 0;
499+
500+detach_pm:
501+	while (--i >= 0) {
502+		device_link_del(dev_pm->pd_dev_link[i]);
503+		dev_pm_domain_detach(dev_pm->pd_dev[i], false);
504+	}
505+	return ret;
506+}
507+
508+/**
509+ * fsl_dev_detach_pm_domains
510+ */
511+int clk_imx_acm_detach_pm_domains(struct device *dev,
512+				  struct clk_imx_acm_pm_domains *dev_pm)
513+{
514+	int i;
515+
516+	if (dev_pm->num_domains <= 1)
517+		return 0;
518+
519+	for (i = 0; i < dev_pm->num_domains; i++) {
520+		device_link_del(dev_pm->pd_dev_link[i]);
521+		dev_pm_domain_detach(dev_pm->pd_dev[i], false);
522+	}
523+
524+	return 0;
525+}
526diff --git a/drivers/clk/imx/clk-imx-acm-utils.h b/drivers/clk/imx/clk-imx-acm-utils.h
527new file mode 100644
528index 000000000..662e0d123
529--- /dev/null
530+++ b/drivers/clk/imx/clk-imx-acm-utils.h
531@@ -0,0 +1,19 @@
532+/* SPDX-License-Identifier: GPL-2.0 */
533+/* Copyright 2020 NXP */
534+
535+#ifndef _CLK_IMX_ACM_UTILS_H
536+#define _CLK_IMX_ACM_UTILS_H
537+
538+#include <linux/device.h>
539+
540+struct clk_imx_acm_pm_domains {
541+	struct device **pd_dev;
542+	struct device_link **pd_dev_link;
543+	int    num_domains;
544+};
545+
546+int clk_imx_acm_attach_pm_domains(struct device *dev,
547+				  struct clk_imx_acm_pm_domains *dev_pm);
548+int clk_imx_acm_detach_pm_domains(struct device *dev,
549+				  struct clk_imx_acm_pm_domains *dev_pm);
550+#endif /* _CLK_IMX_ACM_UTILS_H */
551diff --git a/drivers/clk/imx/clk-imx8dxl-acm.c b/drivers/clk/imx/clk-imx8dxl-acm.c
552new file mode 100644
553index 000000000..b11254522
554--- /dev/null
555+++ b/drivers/clk/imx/clk-imx8dxl-acm.c
556@@ -0,0 +1,235 @@
557+// SPDX-License-Identifier: GPL-2.0+
558+/*
559+ * Copyright 2019~2020 NXP
560+ */
561+
562+#include <linux/clk-provider.h>
563+#include <linux/err.h>
564+#include <linux/io.h>
565+#include <linux/module.h>
566+#include <linux/of.h>
567+#include <linux/of_device.h>
568+#include <linux/platform_device.h>
569+#include <linux/slab.h>
570+#include <linux/pm_domain.h>
571+#include <linux/pm_runtime.h>
572+
573+#include "clk.h"
574+#include "clk-scu.h"
575+#include "clk-imx-acm-utils.h"
576+
577+#include <dt-bindings/clock/imx8-clock.h>
578+
579+struct imx8dxl_acm_priv {
580+	struct clk_imx_acm_pm_domains dev_pm;
581+	void __iomem *reg;
582+	u32 regs[0x20];
583+};
584+
585+static const char *aud_clk_sels[] = {
586+	"aud_rec_clk0_lpcg_clk",
587+	"aud_rec_clk1_lpcg_clk",
588+	"ext_aud_mclk0",
589+	"ext_aud_mclk1",
590+	"dummy",
591+	"dummy",
592+	"dummy",
593+	"dummy",
594+	"spdif0_rx",
595+	"sai0_rx_bclk",
596+	"sai0_tx_bclk",
597+	"sai1_rx_bclk",
598+	"sai1_tx_bclk",
599+	"sai2_rx_bclk",
600+	"sai3_rx_bclk",
601+};
602+
603+static const char *mclk_out_sels[] = {
604+	"aud_rec_clk0_lpcg_clk",
605+	"aud_rec_clk1_lpcg_clk",
606+	"dummy",
607+	"dummy",
608+	"spdif0_rx",
609+	"dummy",
610+	"dummy",
611+	"dummy",
612+};
613+
614+static const char *sai_mclk_sels[] = {
615+	"aud_pll_div_clk0_lpcg_clk",
616+	"aud_pll_div_clk1_lpcg_clk",
617+	"acm_aud_clk0_sel",
618+	"acm_aud_clk1_sel",
619+};
620+
621+static const char *spdif_mclk_sels[] = {
622+	"aud_pll_div_clk0_lpcg_clk",
623+	"aud_pll_div_clk1_lpcg_clk",
624+	"acm_aud_clk0_sel",
625+	"acm_aud_clk1_sel",
626+};
627+
628+static const char *mqs_mclk_sels[] = {
629+	"aud_pll_div_clk0_lpcg_clk",
630+	"aud_pll_div_clk1_lpcg_clk",
631+	"acm_aud_clk0_sel",
632+	"acm_aud_clk1_sel",
633+};
634+
635+static int imx8dxl_acm_clk_probe(struct platform_device *pdev)
636+{
637+	struct device *dev = &pdev->dev;
638+	struct device_node *np = dev->of_node;
639+	struct clk_onecell_data *clk_data;
640+	struct imx8dxl_acm_priv *priv;
641+	struct resource *res;
642+	struct clk **clks;
643+	void __iomem *base;
644+	int ret;
645+	int i;
646+
647+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
648+	base = devm_ioremap(dev, res->start, resource_size(res));
649+	if (!base)
650+		return -ENOMEM;
651+
652+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
653+	if (!priv)
654+		return -ENOMEM;
655+
656+	priv->reg = base;
657+
658+	platform_set_drvdata(pdev, priv);
659+
660+	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
661+	if (!clk_data)
662+		return -ENOMEM;
663+
664+	clk_data->clks = devm_kcalloc(&pdev->dev, IMX_ADMA_ACM_CLK_END,
665+					sizeof(*clk_data->clks), GFP_KERNEL);
666+	if (!clk_data->clks)
667+		return -ENOMEM;
668+
669+	clk_data->clk_num = IMX_ADMA_ACM_CLK_END;
670+
671+	clks = clk_data->clks;
672+
673+	ret = clk_imx_acm_attach_pm_domains(&pdev->dev, &priv->dev_pm);
674+	if (ret)
675+		return ret;
676+
677+	pm_runtime_enable(&pdev->dev);
678+	pm_runtime_get_sync(&pdev->dev);
679+
680+	clks[IMX_ADMA_EXT_AUD_MCLK0]     = imx_clk_fixed("ext_aud_mclk0", 0);
681+	clks[IMX_ADMA_EXT_AUD_MCLK1]     = imx_clk_fixed("ext_aud_mclk1", 0);
682+	clks[IMX_ADMA_SPDIF0_RX]         = imx_clk_fixed("spdif0_rx", 0);
683+	clks[IMX_ADMA_SAI0_RX_BCLK]      = imx_clk_fixed("sai0_rx_bclk", 0);
684+	clks[IMX_ADMA_SAI0_TX_BCLK]      = imx_clk_fixed("sai0_tx_bclk", 0);
685+	clks[IMX_ADMA_SAI1_RX_BCLK]      = imx_clk_fixed("sai1_rx_bclk", 0);
686+	clks[IMX_ADMA_SAI1_TX_BCLK]      = imx_clk_fixed("sai1_tx_bclk", 0);
687+	clks[IMX_ADMA_SAI2_RX_BCLK]      = imx_clk_fixed("sai2_rx_bclk", 0);
688+	clks[IMX_ADMA_SAI3_RX_BCLK]      = imx_clk_fixed("sai3_rx_bclk", 0);
689+
690+	clks[IMX_ADMA_ACM_AUD_CLK0_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk0_sel", base+0x000000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels));
691+	clks[IMX_ADMA_ACM_AUD_CLK1_SEL]	= imx_dev_clk_mux(dev, "acm_aud_clk1_sel", base+0x010000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels));
692+
693+	clks[IMX_ADMA_ACM_MCLKOUT0_SEL]	= imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels));
694+	clks[IMX_ADMA_ACM_MCLKOUT1_SEL]	= imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels));
695+
696+	clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
697+	clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
698+	clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
699+	clks[IMX_ADMA_ACM_SAI3_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai3_mclk_sel", base+0x110000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
700+
701+	clks[IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif0_mclk_sel", base+0x1A0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels));
702+	clks[IMX_ADMA_ACM_MQS_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_mqs_mclk_sel", base+0x1C0000, 0, 2, mqs_mclk_sels, ARRAY_SIZE(mqs_mclk_sels));
703+
704+	for (i = 0; i < clk_data->clk_num; i++) {
705+		if (IS_ERR(clks[i]))
706+			pr_warn("i.MX clk %u: register failed with %ld\n",
707+				i, PTR_ERR(clks[i]));
708+	}
709+
710+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
711+
712+	pm_runtime_put_sync(&pdev->dev);
713+
714+	return ret;
715+}
716+
717+static int imx8dxl_acm_clk_remove(struct platform_device *pdev)
718+{
719+	struct imx8dxl_acm_priv *priv = dev_get_drvdata(&pdev->dev);
720+
721+	pm_runtime_disable(&pdev->dev);
722+
723+	clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm);
724+
725+	return 0;
726+}
727+
728+static const struct of_device_id imx8dxl_acm_match[] = {
729+	{ .compatible = "nxp,imx8dxl-acm", },
730+	{ /* sentinel */ }
731+};
732+
733+static int __maybe_unused imx8dxl_acm_runtime_suspend(struct device *dev)
734+{
735+	struct imx8dxl_acm_priv *priv = dev_get_drvdata(dev);
736+
737+	priv->regs[0]  = readl_relaxed(priv->reg + 0x000000);
738+	priv->regs[1]  = readl_relaxed(priv->reg + 0x010000);
739+	priv->regs[2]  = readl_relaxed(priv->reg + 0x020000);
740+	priv->regs[3]  = readl_relaxed(priv->reg + 0x030000);
741+	priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000);
742+	priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000);
743+	priv->regs[16] = readl_relaxed(priv->reg + 0x100000);
744+	priv->regs[17] = readl_relaxed(priv->reg + 0x110000);
745+	priv->regs[26] = readl_relaxed(priv->reg + 0x1A0000);
746+	priv->regs[28] = readl_relaxed(priv->reg + 0x1C0000);
747+
748+	return 0;
749+}
750+
751+static int __maybe_unused imx8dxl_acm_runtime_resume(struct device *dev)
752+{
753+	struct imx8dxl_acm_priv *priv = dev_get_drvdata(dev);
754+
755+	writel_relaxed(priv->regs[0],  priv->reg + 0x000000);
756+	writel_relaxed(priv->regs[1],  priv->reg + 0x010000);
757+	writel_relaxed(priv->regs[2],  priv->reg + 0x020000);
758+	writel_relaxed(priv->regs[3],  priv->reg + 0x030000);
759+	writel_relaxed(priv->regs[14], priv->reg + 0x0E0000);
760+	writel_relaxed(priv->regs[15], priv->reg + 0x0F0000);
761+	writel_relaxed(priv->regs[16], priv->reg + 0x100000);
762+	writel_relaxed(priv->regs[17], priv->reg + 0x110000);
763+	writel_relaxed(priv->regs[26], priv->reg + 0x1A0000);
764+	writel_relaxed(priv->regs[28], priv->reg + 0x1C0000);
765+
766+	return 0;
767+}
768+
769+const struct dev_pm_ops imx8dxl_acm_pm_ops = {
770+	SET_RUNTIME_PM_OPS(imx8dxl_acm_runtime_suspend,
771+			   imx8dxl_acm_runtime_resume, NULL)
772+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
773+				      pm_runtime_force_resume)
774+};
775+
776+static struct platform_driver imx8dxl_acm_clk_driver = {
777+	.driver = {
778+		.name = "imx8dxl-acm",
779+		.of_match_table = imx8dxl_acm_match,
780+		.pm = &imx8dxl_acm_pm_ops,
781+		.suppress_bind_attrs = true,
782+	},
783+	.probe = imx8dxl_acm_clk_probe,
784+	.remove = imx8dxl_acm_clk_remove,
785+};
786+
787+static int __init imx8dxl_acm_init(void)
788+{
789+	return platform_driver_register(&imx8dxl_acm_clk_driver);
790+}
791+fs_initcall(imx8dxl_acm_init);
792diff --git a/drivers/clk/imx/clk-imx8dxl-rsrc.c b/drivers/clk/imx/clk-imx8dxl-rsrc.c
793new file mode 100644
794index 000000000..084bad519
795--- /dev/null
796+++ b/drivers/clk/imx/clk-imx8dxl-rsrc.c
797@@ -0,0 +1,65 @@
798+// SPDX-License-Identifier: GPL-2.0+
799+/*
800+ * Copyright 2019~2020 NXP
801+ */
802+
803+#include <dt-bindings/firmware/imx/rsrc.h>
804+
805+#include "clk-scu.h"
806+
807+/* Keep sorted in the ascending order */
808+static u32 imx8dxl_clk_scu_rsrc_table[] = {
809+	IMX_SC_R_SPI_0,
810+	IMX_SC_R_SPI_1,
811+	IMX_SC_R_SPI_2,
812+	IMX_SC_R_SPI_3,
813+	IMX_SC_R_UART_0,
814+	IMX_SC_R_UART_1,
815+	IMX_SC_R_UART_2,
816+	IMX_SC_R_UART_3,
817+	IMX_SC_R_I2C_0,
818+	IMX_SC_R_I2C_1,
819+	IMX_SC_R_I2C_2,
820+	IMX_SC_R_I2C_3,
821+	IMX_SC_R_ADC_0,
822+	IMX_SC_R_FTM_0,
823+	IMX_SC_R_FTM_1,
824+	IMX_SC_R_CAN_0,
825+	IMX_SC_R_LCD_0,
826+	IMX_SC_R_LCD_0_PWM_0,
827+	IMX_SC_R_PWM_0,
828+	IMX_SC_R_PWM_1,
829+	IMX_SC_R_PWM_2,
830+	IMX_SC_R_PWM_3,
831+	IMX_SC_R_PWM_4,
832+	IMX_SC_R_PWM_5,
833+	IMX_SC_R_PWM_6,
834+	IMX_SC_R_PWM_7,
835+	IMX_SC_R_GPT_0,
836+	IMX_SC_R_GPT_1,
837+	IMX_SC_R_GPT_2,
838+	IMX_SC_R_GPT_3,
839+	IMX_SC_R_GPT_4,
840+	IMX_SC_R_FSPI_0,
841+	IMX_SC_R_FSPI_1,
842+	IMX_SC_R_SDHC_0,
843+	IMX_SC_R_SDHC_1,
844+	IMX_SC_R_SDHC_2,
845+	IMX_SC_R_ENET_0,
846+	IMX_SC_R_ENET_1,
847+	IMX_SC_R_USB_1,
848+	IMX_SC_R_NAND,
849+	IMX_SC_R_M4_0_I2C,
850+	IMX_SC_R_M4_0_UART,
851+	IMX_SC_R_ELCDIF_PLL,
852+	IMX_SC_R_AUDIO_PLL_0,
853+	IMX_SC_R_AUDIO_PLL_1,
854+	IMX_SC_R_AUDIO_CLK_0,
855+	IMX_SC_R_AUDIO_CLK_1,
856+	IMX_SC_R_A35
857+};
858+
859+const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl = {
860+	.rsrc = imx8dxl_clk_scu_rsrc_table,
861+	.num = ARRAY_SIZE(imx8dxl_clk_scu_rsrc_table),
862+};
863diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
864index 711bd2294..61db2de25 100644
865--- a/drivers/clk/imx/clk-imx8mm.c
866+++ b/drivers/clk/imx/clk-imx8mm.c
867@@ -4,7 +4,9 @@
868  */
869
870 #include <dt-bindings/clock/imx8mm-clock.h>
871+#include <linux/clk.h>
872 #include <linux/clk-provider.h>
873+#include <linux/debugfs.h>
874 #include <linux/err.h>
875 #include <linux/io.h>
876 #include <linux/module.h>
877@@ -12,6 +14,7 @@
878 #include <linux/platform_device.h>
879 #include <linux/slab.h>
880 #include <linux/types.h>
881+#include <soc/imx/soc.h>
882
883 #include "clk.h"
884
885@@ -291,6 +294,34 @@ static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_
886 static struct clk_hw_onecell_data *clk_hw_data;
887 static struct clk_hw **hws;
888
889+static int imx_clk_init_on(struct device_node *np,
890+				  struct clk_hw * const clks[])
891+{
892+	u32 *array;
893+	int i, ret, elems;
894+
895+	elems = of_property_count_u32_elems(np, "init-on-array");
896+	if (elems < 0)
897+		return elems;
898+	array = kcalloc(elems, sizeof(elems), GFP_KERNEL);
899+	if (!array)
900+		return -ENOMEM;
901+
902+	ret = of_property_read_u32_array(np, "init-on-array", array, elems);
903+	if (ret)
904+		return ret;
905+
906+	for (i = 0; i < elems; i++) {
907+		ret = clk_prepare_enable(clks[array[i]]->clk);
908+		if (ret)
909+			pr_err("clk_prepare_enable failed %d\n", array[i]);
910+	}
911+
912+	kfree(array);
913+
914+	return 0;
915+}
916+
917 static int imx8mm_clocks_probe(struct platform_device *pdev)
918 {
919 	struct device *dev = &pdev->dev;
920@@ -298,6 +329,8 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
921 	void __iomem *base;
922 	int ret;
923
924+	check_m4_enabled();
925+
926 	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
927 					  IMX8MM_CLK_END), GFP_KERNEL);
928 	if (WARN_ON(!clk_hw_data))
929@@ -361,45 +394,29 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
930 	hws[IMX8MM_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11);
931
932 	/* SYS PLL1 fixed output */
933-	hws[IMX8MM_SYS_PLL1_40M_CG] = imx_clk_hw_gate("sys_pll1_40m_cg", "sys_pll1", base + 0x94, 27);
934-	hws[IMX8MM_SYS_PLL1_80M_CG] = imx_clk_hw_gate("sys_pll1_80m_cg", "sys_pll1", base + 0x94, 25);
935-	hws[IMX8MM_SYS_PLL1_100M_CG] = imx_clk_hw_gate("sys_pll1_100m_cg", "sys_pll1", base + 0x94, 23);
936-	hws[IMX8MM_SYS_PLL1_133M_CG] = imx_clk_hw_gate("sys_pll1_133m_cg", "sys_pll1", base + 0x94, 21);
937-	hws[IMX8MM_SYS_PLL1_160M_CG] = imx_clk_hw_gate("sys_pll1_160m_cg", "sys_pll1", base + 0x94, 19);
938-	hws[IMX8MM_SYS_PLL1_200M_CG] = imx_clk_hw_gate("sys_pll1_200m_cg", "sys_pll1", base + 0x94, 17);
939-	hws[IMX8MM_SYS_PLL1_266M_CG] = imx_clk_hw_gate("sys_pll1_266m_cg", "sys_pll1", base + 0x94, 15);
940-	hws[IMX8MM_SYS_PLL1_400M_CG] = imx_clk_hw_gate("sys_pll1_400m_cg", "sys_pll1", base + 0x94, 13);
941 	hws[IMX8MM_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11);
942
943-	hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20);
944-	hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10);
945-	hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8);
946-	hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6);
947-	hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5);
948-	hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4);
949-	hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3);
950-	hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2);
951+	hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
952+	hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
953+	hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
954+	hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
955+	hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
956+	hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
957+	hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
958+	hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
959 	hws[IMX8MM_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
960
961 	/* SYS PLL2 fixed output */
962-	hws[IMX8MM_SYS_PLL2_50M_CG] = imx_clk_hw_gate("sys_pll2_50m_cg", "sys_pll2", base + 0x104, 27);
963-	hws[IMX8MM_SYS_PLL2_100M_CG] = imx_clk_hw_gate("sys_pll2_100m_cg", "sys_pll2", base + 0x104, 25);
964-	hws[IMX8MM_SYS_PLL2_125M_CG] = imx_clk_hw_gate("sys_pll2_125m_cg", "sys_pll2", base + 0x104, 23);
965-	hws[IMX8MM_SYS_PLL2_166M_CG] = imx_clk_hw_gate("sys_pll2_166m_cg", "sys_pll2", base + 0x104, 21);
966-	hws[IMX8MM_SYS_PLL2_200M_CG] = imx_clk_hw_gate("sys_pll2_200m_cg", "sys_pll2", base + 0x104, 19);
967-	hws[IMX8MM_SYS_PLL2_250M_CG] = imx_clk_hw_gate("sys_pll2_250m_cg", "sys_pll2", base + 0x104, 17);
968-	hws[IMX8MM_SYS_PLL2_333M_CG] = imx_clk_hw_gate("sys_pll2_333m_cg", "sys_pll2", base + 0x104, 15);
969-	hws[IMX8MM_SYS_PLL2_500M_CG] = imx_clk_hw_gate("sys_pll2_500m_cg", "sys_pll2", base + 0x104, 13);
970 	hws[IMX8MM_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11);
971
972-	hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20);
973-	hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10);
974-	hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8);
975-	hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6);
976-	hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5);
977-	hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4);
978-	hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3);
979-	hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
980+	hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
981+	hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
982+	hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
983+	hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
984+	hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
985+	hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
986+	hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
987+	hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
988 	hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
989
990 	np = dev->of_node;
991@@ -437,7 +454,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
992 	/* BUS */
993 	hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi",  imx8mm_main_axi_sels, base + 0x8800);
994 	hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
995-	hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
996+	hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
997 	hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
998 	hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
999 	hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
1000@@ -565,7 +582,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
1001 	hws[IMX8MM_CLK_SAI5_IPG] = imx_clk_hw_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5);
1002 	hws[IMX8MM_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6);
1003 	hws[IMX8MM_CLK_SAI6_IPG] = imx_clk_hw_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6);
1004-	hws[IMX8MM_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0);
1005+	hws[IMX8MM_CLK_SNVS_ROOT] = imx_clk_hw_gate2_flags("snvs_root_clk", "ipg_root", base + 0x4470, 0, CLK_IS_CRITICAL);
1006 	hws[IMX8MM_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0);
1007 	hws[IMX8MM_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
1008 	hws[IMX8MM_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
1009@@ -615,6 +632,12 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
1010 		goto unregister_hws;
1011 	}
1012
1013+	imx_clk_init_on(np, hws);
1014+
1015+	clk_set_parent(hws[IMX8MM_CLK_CSI1_CORE]->clk, hws[IMX8MM_SYS_PLL2_1000M]->clk);
1016+	clk_set_parent(hws[IMX8MM_CLK_CSI1_PHY_REF]->clk, hws[IMX8MM_SYS_PLL2_1000M]->clk);
1017+	clk_set_parent(hws[IMX8MM_CLK_CSI1_ESC]->clk, hws[IMX8MM_SYS_PLL1_800M]->clk);
1018+
1019 	imx_register_uart_clocks(4);
1020
1021 	return 0;
1022@@ -645,6 +668,81 @@ static struct platform_driver imx8mm_clk_driver = {
1023 };
1024 module_platform_driver(imx8mm_clk_driver);
1025
1026+/*
1027+ * Debugfs interface for audio PLL K divider change dynamically.
1028+ * Monitor control for the Audio PLL K-Divider
1029+ */
1030+#ifdef CONFIG_DEBUG_FS
1031+
1032+#define KDIV_MASK	GENMASK(15, 0)
1033+#define MDIV_SHIFT	12
1034+#define MDIV_MASK	GENMASK(21, 12)
1035+#define PDIV_SHIFT	4
1036+#define PDIV_MASK	GENMASK(9, 4)
1037+#define SDIV_SHIFT	0
1038+#define SDIV_MASK	GENMASK(2, 0)
1039+
1040+static int pll_delta_k_set(void *data, u64 val)
1041+{
1042+	struct clk_hw *hw;
1043+	short int delta_k;
1044+
1045+	hw = data;
1046+	delta_k = (short int) (val & KDIV_MASK);
1047+
1048+	clk_set_delta_k(hw, val);
1049+
1050+	pr_debug("the delta k is %d\n", delta_k);
1051+	return 0;
1052+}
1053+DEFINE_DEBUGFS_ATTRIBUTE(delta_k_fops, NULL, pll_delta_k_set, "%lld\n");
1054+
1055+static int pll_setting_show(struct seq_file *s, void *data)
1056+{
1057+	struct clk_hw *hw;
1058+	u32 pll_div_ctrl0, pll_div_ctrl1;
1059+	u32 mdiv, pdiv, sdiv, kdiv;
1060+
1061+	hw = s->private;;
1062+
1063+	clk_get_pll_setting(hw, &pll_div_ctrl0, &pll_div_ctrl1);
1064+	mdiv = (pll_div_ctrl0 & MDIV_MASK) >> MDIV_SHIFT;
1065+	pdiv = (pll_div_ctrl0 & PDIV_MASK) >> PDIV_SHIFT;
1066+	sdiv = (pll_div_ctrl0 & SDIV_MASK) >> SDIV_SHIFT;
1067+	kdiv = (pll_div_ctrl1 & KDIV_MASK);
1068+
1069+	seq_printf(s, "Mdiv: 0x%x; Pdiv: 0x%x; Sdiv: 0x%x; Kdiv: 0x%x\n",
1070+		mdiv, pdiv, sdiv, kdiv);
1071+
1072+	return 0;
1073+}
1074+DEFINE_SHOW_ATTRIBUTE(pll_setting);
1075+
1076+static int __init pll_debug_init(void)
1077+{
1078+	struct dentry *root, *audio_pll1, *audio_pll2;
1079+
1080+	if (of_machine_is_compatible("fsl,imx8mm") && hws) {
1081+		/* create a root dir for audio pll monitor */
1082+		root = debugfs_create_dir("audio_pll_monitor", NULL);
1083+		audio_pll1 = debugfs_create_dir("audio_pll1", root);
1084+		audio_pll2 = debugfs_create_dir("audio_pll2", root);
1085+
1086+		debugfs_create_file_unsafe("delta_k", 0444, audio_pll1,
1087+			hws[IMX8MM_AUDIO_PLL1], &delta_k_fops);
1088+		debugfs_create_file("pll_parameter", 0x444, audio_pll1,
1089+			hws[IMX8MM_AUDIO_PLL1], &pll_setting_fops);
1090+		debugfs_create_file_unsafe("delta_k", 0444, audio_pll2,
1091+			hws[IMX8MM_AUDIO_PLL2], &delta_k_fops);
1092+		debugfs_create_file("pll_parameter", 0x444, audio_pll2,
1093+			hws[IMX8MM_AUDIO_PLL2], &pll_setting_fops);
1094+	}
1095+
1096+	return 0;
1097+}
1098+late_initcall(pll_debug_init);
1099+#endif /* CONFIG_DEBUG_FS */
1100+
1101 MODULE_AUTHOR("Bai Ping <ping.bai@nxp.com>");
1102 MODULE_DESCRIPTION("NXP i.MX8MM clock driver");
1103 MODULE_LICENSE("GPL v2");
1104diff --git a/drivers/clk/imx/clk-imx8qm-acm.c b/drivers/clk/imx/clk-imx8qm-acm.c
1105new file mode 100644
1106index 000000000..d531294e7
1107--- /dev/null
1108+++ b/drivers/clk/imx/clk-imx8qm-acm.c
1109@@ -0,0 +1,297 @@
1110+// SPDX-License-Identifier: GPL-2.0+
1111+/*
1112+ * Copyright 2018 NXP
1113+ *	Dong Aisheng <aisheng.dong@nxp.com>
1114+ */
1115+
1116+#include <linux/clk-provider.h>
1117+#include <linux/err.h>
1118+#include <linux/io.h>
1119+#include <linux/module.h>
1120+#include <linux/of.h>
1121+#include <linux/of_device.h>
1122+#include <linux/platform_device.h>
1123+#include <linux/slab.h>
1124+#include <linux/pm_domain.h>
1125+#include <linux/pm_runtime.h>
1126+
1127+#include "clk.h"
1128+#include "clk-scu.h"
1129+#include "clk-imx-acm-utils.h"
1130+
1131+#include <dt-bindings/clock/imx8-clock.h>
1132+
1133+struct imx8qm_acm_priv {
1134+	struct clk_imx_acm_pm_domains dev_pm;
1135+	void __iomem *reg;
1136+	u32 regs[32];
1137+};
1138+
1139+static const char *aud_clk_sels[] = {
1140+	"aud_rec_clk0_lpcg_clk",
1141+	"aud_rec_clk1_lpcg_clk",
1142+	"dummy",
1143+	"hdmi_rx_mclk",
1144+	"ext_aud_mclk0",
1145+	"ext_aud_mclk1",
1146+	"esai0_rx_clk",
1147+	"esai0_rx_hf_clk",
1148+	"esai0_tx_clk",
1149+	"esai0_tx_hf_clk",
1150+	"esai1_rx_clk",
1151+	"esai1_rx_hf_clk",
1152+	"esai1_tx_clk",
1153+	"esai1_tx_hf_clk",
1154+	"spdif0_rx",
1155+	"spdif1_rx",
1156+	"sai0_rx_bclk",
1157+	"sai0_tx_bclk",
1158+	"sai1_rx_bclk",
1159+	"sai1_tx_bclk",
1160+	"sai2_rx_bclk",
1161+	"sai3_rx_bclk",
1162+	"sai4_rx_bclk",
1163+};
1164+
1165+static const char *mclk_out_sels[] = {
1166+	"aud_rec_clk0_lpcg_clk",
1167+	"aud_rec_clk1_lpcg_clk",
1168+	"dummy",
1169+	"hdmi_rx_mclk",
1170+	"spdif0_rx",
1171+	"spdif1_rx",
1172+	"sai4_rx_bclk",
1173+	"sai6_rx_bclk",
1174+};
1175+
1176+static const char *sai_mclk_sels[] = {
1177+	"aud_pll_div_clk0_lpcg_clk",
1178+	"aud_pll_div_clk1_lpcg_clk",
1179+	"acm_aud_clk0_sel",
1180+	"acm_aud_clk1_sel",
1181+};
1182+
1183+static const char *asrc_mux_clk_sels[] = {
1184+	"sai4_rx_bclk",
1185+	"sai5_tx_bclk",
1186+	"dummy",
1187+	"dummy",
1188+};
1189+
1190+static const char *esai_mclk_sels[] = {
1191+	"aud_pll_div_clk0_lpcg_clk",
1192+	"aud_pll_div_clk1_lpcg_clk",
1193+	"acm_aud_clk0_sel",
1194+	"acm_aud_clk1_sel",
1195+};
1196+
1197+static const char *spdif_mclk_sels[] = {
1198+	"aud_pll_div_clk0_lpcg_clk",
1199+	"aud_pll_div_clk1_lpcg_clk",
1200+	"acm_aud_clk0_sel",
1201+	"acm_aud_clk1_sel",
1202+};
1203+
1204+static const char *mqs_mclk_sels[] = {
1205+	"aud_pll_div_clk0_lpcg_clk",
1206+	"aud_pll_div_clk1_lpcg_clk",
1207+	"acm_aud_clk0_sel",
1208+	"acm_aud_clk1_sel",
1209+};
1210+
1211+static int imx8qm_acm_clk_probe(struct platform_device *pdev)
1212+{
1213+	struct device *dev = &pdev->dev;
1214+	struct device_node *np = dev->of_node;
1215+	struct clk_onecell_data *clk_data;
1216+	struct imx8qm_acm_priv *priv;
1217+	struct resource *res;
1218+	struct clk **clks;
1219+	void __iomem *base;
1220+	int ret;
1221+	int i;
1222+
1223+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1224+	base = devm_ioremap(dev, res->start, resource_size(res));
1225+	if (!base)
1226+		return -ENOMEM;
1227+
1228+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1229+	if (!priv)
1230+		return -ENOMEM;
1231+
1232+	priv->reg = base;
1233+
1234+	platform_set_drvdata(pdev, priv);
1235+
1236+	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
1237+	if (!clk_data)
1238+		return -ENOMEM;
1239+
1240+	clk_data->clks = devm_kcalloc(&pdev->dev, IMX_ADMA_ACM_CLK_END,
1241+					sizeof(*clk_data->clks), GFP_KERNEL);
1242+	if (!clk_data->clks)
1243+		return -ENOMEM;
1244+
1245+	clk_data->clk_num = IMX_ADMA_ACM_CLK_END;
1246+
1247+	clks = clk_data->clks;
1248+
1249+	ret = clk_imx_acm_attach_pm_domains(&pdev->dev, &priv->dev_pm);
1250+	if (ret)
1251+		return ret;
1252+
1253+	pm_runtime_enable(&pdev->dev);
1254+	pm_runtime_get_sync(&pdev->dev);
1255+
1256+	clks[IMX_ADMA_EXT_AUD_MCLK0]     = imx_clk_fixed("ext_aud_mclk0", 0);
1257+	clks[IMX_ADMA_EXT_AUD_MCLK1]     = imx_clk_fixed("ext_aud_mclk1", 0);
1258+	clks[IMX_ADMA_ESAI0_RX_CLK]      = imx_clk_fixed("esai0_rx_clk", 0);
1259+	clks[IMX_ADMA_ESAI0_RX_HF_CLK]   = imx_clk_fixed("esai0_rx_hf_clk", 0);
1260+	clks[IMX_ADMA_ESAI0_TX_CLK]      = imx_clk_fixed("esai0_tx_clk", 0);
1261+	clks[IMX_ADMA_ESAI0_TX_HF_CLK]   = imx_clk_fixed("esai0_tx_hf_clk", 0);
1262+	clks[IMX_ADMA_ESAI1_RX_CLK]      = imx_clk_fixed("esai1_rx_clk", 0);
1263+	clks[IMX_ADMA_ESAI1_RX_HF_CLK]   = imx_clk_fixed("esai1_rx_hf_clk", 0);
1264+	clks[IMX_ADMA_ESAI1_TX_CLK]      = imx_clk_fixed("esai1_tx_clk", 0);
1265+	clks[IMX_ADMA_ESAI1_TX_HF_CLK]   = imx_clk_fixed("esai1_tx_hf_clk", 0);
1266+	clks[IMX_ADMA_SPDIF0_RX]         = imx_clk_fixed("spdif0_rx", 0);
1267+	clks[IMX_ADMA_SPDIF1_RX]         = imx_clk_fixed("spdif1_rx", 0);
1268+	clks[IMX_ADMA_SAI0_RX_BCLK]      = imx_clk_fixed("sai0_rx_bclk", 0);
1269+	clks[IMX_ADMA_SAI0_TX_BCLK]      = imx_clk_fixed("sai0_tx_bclk", 0);
1270+	clks[IMX_ADMA_SAI1_RX_BCLK]      = imx_clk_fixed("sai1_rx_bclk", 0);
1271+	clks[IMX_ADMA_SAI1_TX_BCLK]      = imx_clk_fixed("sai1_tx_bclk", 0);
1272+	clks[IMX_ADMA_SAI2_RX_BCLK]      = imx_clk_fixed("sai2_rx_bclk", 0);
1273+	clks[IMX_ADMA_SAI3_RX_BCLK]      = imx_clk_fixed("sai3_rx_bclk", 0);
1274+	clks[IMX_ADMA_SAI4_RX_BCLK]      = imx_clk_fixed("sai4_rx_bclk", 0);
1275+	clks[IMX_ADMA_SAI5_TX_BCLK]      = imx_clk_fixed("sai5_tx_bclk", 0);
1276+	clks[IMX_ADMA_SAI6_RX_BCLK]      = imx_clk_fixed("sai6_rx_bclk", 0);
1277+	clks[IMX_ADMA_HDMI_RX_MCLK]      = imx_clk_fixed("hdmi_rx_mclk", 0);
1278+
1279+
1280+	clks[IMX_ADMA_ACM_AUD_CLK0_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk0_sel", base+0x000000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels));
1281+	clks[IMX_ADMA_ACM_AUD_CLK1_SEL]	= imx_dev_clk_mux(dev, "acm_aud_clk1_sel", base+0x010000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels));
1282+
1283+	clks[IMX_ADMA_ACM_MCLKOUT0_SEL]	= imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels));
1284+	clks[IMX_ADMA_ACM_MCLKOUT1_SEL]	= imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels));
1285+
1286+	clks[IMX_ADMA_ACM_ASRC0_MUX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_asrc0_mclk_sel", base+0x040000, 0, 2, asrc_mux_clk_sels, ARRAY_SIZE(asrc_mux_clk_sels));
1287+
1288+	clks[IMX_ADMA_ACM_ESAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_esai0_mclk_sel", base+0x060000, 0, 2, esai_mclk_sels, ARRAY_SIZE(esai_mclk_sels));
1289+	clks[IMX_ADMA_ACM_ESAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_esai1_mclk_sel", base+0x070000, 0, 2, esai_mclk_sels, ARRAY_SIZE(esai_mclk_sels));
1290+	clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1291+	clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1292+	clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1293+	clks[IMX_ADMA_ACM_SAI3_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai3_mclk_sel", base+0x110000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1294+	clks[IMX_ADMA_ACM_SAI4_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai4_mclk_sel", base+0x120000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1295+	clks[IMX_ADMA_ACM_SAI5_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai5_mclk_sel", base+0x130000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1296+	clks[IMX_ADMA_ACM_SAI6_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai6_mclk_sel", base+0x140000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1297+	clks[IMX_ADMA_ACM_SAI7_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai7_mclk_sel", base+0x150000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1298+
1299+	clks[IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif0_mclk_sel", base+0x1A0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels));
1300+	clks[IMX_ADMA_ACM_SPDIF1_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif1_mclk_sel", base+0x1B0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels));
1301+	clks[IMX_ADMA_ACM_MQS_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_mqs_mclk_sel", base+0x1C0000, 0, 2, mqs_mclk_sels, ARRAY_SIZE(mqs_mclk_sels));
1302+
1303+	for (i = 0; i < clk_data->clk_num; i++) {
1304+		if (IS_ERR(clks[i]))
1305+			pr_warn("i.MX clk %u: register failed with %ld\n",
1306+				i, PTR_ERR(clks[i]));
1307+	}
1308+
1309+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
1310+
1311+	pm_runtime_put_sync(&pdev->dev);
1312+
1313+	return ret;
1314+}
1315+
1316+static int imx8qm_acm_clk_remove(struct platform_device *pdev)
1317+{
1318+	struct imx8qm_acm_priv *priv = dev_get_drvdata(&pdev->dev);
1319+
1320+	pm_runtime_disable(&pdev->dev);
1321+
1322+	clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm);
1323+
1324+	return 0;
1325+}
1326+
1327+static const struct of_device_id imx8qm_acm_match[] = {
1328+	{ .compatible = "nxp,imx8qm-acm", },
1329+	{ /* sentinel */ }
1330+};
1331+
1332+static int __maybe_unused imx8qm_acm_runtime_suspend(struct device *dev)
1333+{
1334+	struct imx8qm_acm_priv *priv = dev_get_drvdata(dev);
1335+
1336+	priv->regs[0]  = readl_relaxed(priv->reg + 0x000000);
1337+	priv->regs[1]  = readl_relaxed(priv->reg + 0x010000);
1338+	priv->regs[2]  = readl_relaxed(priv->reg + 0x020000);
1339+	priv->regs[3]  = readl_relaxed(priv->reg + 0x030000);
1340+	priv->regs[4]  = readl_relaxed(priv->reg + 0x040000);
1341+	priv->regs[6]  = readl_relaxed(priv->reg + 0x060000);
1342+	priv->regs[7]  = readl_relaxed(priv->reg + 0x070000);
1343+	priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000);
1344+	priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000);
1345+	priv->regs[16] = readl_relaxed(priv->reg + 0x100000);
1346+	priv->regs[17] = readl_relaxed(priv->reg + 0x110000);
1347+	priv->regs[18] = readl_relaxed(priv->reg + 0x120000);
1348+	priv->regs[19] = readl_relaxed(priv->reg + 0x130000);
1349+	priv->regs[20] = readl_relaxed(priv->reg + 0x140000);
1350+	priv->regs[21] = readl_relaxed(priv->reg + 0x150000);
1351+	priv->regs[26] = readl_relaxed(priv->reg + 0x1A0000);
1352+	priv->regs[27] = readl_relaxed(priv->reg + 0x1B0000);
1353+	priv->regs[28] = readl_relaxed(priv->reg + 0x1C0000);
1354+
1355+	return 0;
1356+}
1357+
1358+static int __maybe_unused imx8qm_acm_runtime_resume(struct device *dev)
1359+{
1360+	struct imx8qm_acm_priv *priv = dev_get_drvdata(dev);
1361+
1362+	writel_relaxed(priv->regs[0],  priv->reg + 0x000000);
1363+	writel_relaxed(priv->regs[1],  priv->reg + 0x010000);
1364+	writel_relaxed(priv->regs[2],  priv->reg + 0x020000);
1365+	writel_relaxed(priv->regs[3],  priv->reg + 0x030000);
1366+	writel_relaxed(priv->regs[4],  priv->reg + 0x040000);
1367+	writel_relaxed(priv->regs[6],  priv->reg + 0x060000);
1368+	writel_relaxed(priv->regs[7],  priv->reg + 0x070000);
1369+	writel_relaxed(priv->regs[14], priv->reg + 0x0E0000);
1370+	writel_relaxed(priv->regs[15], priv->reg + 0x0F0000);
1371+	writel_relaxed(priv->regs[16], priv->reg + 0x100000);
1372+	writel_relaxed(priv->regs[17], priv->reg + 0x110000);
1373+	writel_relaxed(priv->regs[18], priv->reg + 0x120000);
1374+	writel_relaxed(priv->regs[19], priv->reg + 0x130000);
1375+	writel_relaxed(priv->regs[20], priv->reg + 0x140000);
1376+	writel_relaxed(priv->regs[21], priv->reg + 0x150000);
1377+	writel_relaxed(priv->regs[26], priv->reg + 0x1A0000);
1378+	writel_relaxed(priv->regs[27], priv->reg + 0x1B0000);
1379+	writel_relaxed(priv->regs[28], priv->reg + 0x1C0000);
1380+
1381+	return 0;
1382+}
1383+
1384+static const struct dev_pm_ops imx8qm_acm_pm_ops = {
1385+	SET_RUNTIME_PM_OPS(imx8qm_acm_runtime_suspend,
1386+			   imx8qm_acm_runtime_resume, NULL)
1387+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1388+				      pm_runtime_force_resume)
1389+};
1390+
1391+static struct platform_driver imx8qm_acm_clk_driver = {
1392+	.driver = {
1393+		.name = "imx8qm-acm",
1394+		.of_match_table = imx8qm_acm_match,
1395+		.pm = &imx8qm_acm_pm_ops,
1396+		.suppress_bind_attrs = true,
1397+	},
1398+	.probe = imx8qm_acm_clk_probe,
1399+	.remove = imx8qm_acm_clk_remove,
1400+};
1401+
1402+static int __init imx8qm_acm_init(void)
1403+{
1404+	return platform_driver_register(&imx8qm_acm_clk_driver);
1405+}
1406+fs_initcall(imx8qm_acm_init);
1407diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c
1408new file mode 100644
1409index 000000000..5943f51c4
1410--- /dev/null
1411+++ b/drivers/clk/imx/clk-imx8qm-rsrc.c
1412@@ -0,0 +1,117 @@
1413+// SPDX-License-Identifier: GPL-2.0+
1414+/*
1415+ * Copyright 2019 NXP
1416+ *	Dong Aisheng <aisheng.dong@nxp.com>
1417+ */
1418+
1419+#include <dt-bindings/firmware/imx/rsrc.h>
1420+
1421+#include "clk-scu.h"
1422+
1423+/* Keep sorted in the ascending order */
1424+static u32 imx8qm_clk_scu_rsrc_table[] = {
1425+	IMX_SC_R_A53,
1426+	IMX_SC_R_A72,
1427+	IMX_SC_R_DC_0_VIDEO0,
1428+	IMX_SC_R_DC_0_VIDEO1,
1429+	IMX_SC_R_DC_0,
1430+	IMX_SC_R_DC_0_PLL_0,
1431+	IMX_SC_R_DC_0_PLL_1,
1432+	IMX_SC_R_DC_1_VIDEO0,
1433+	IMX_SC_R_DC_1_VIDEO1,
1434+	IMX_SC_R_DC_1,
1435+	IMX_SC_R_DC_1_PLL_0,
1436+	IMX_SC_R_DC_1_PLL_1,
1437+	IMX_SC_R_SPI_0,
1438+	IMX_SC_R_SPI_1,
1439+	IMX_SC_R_SPI_2,
1440+	IMX_SC_R_SPI_3,
1441+	IMX_SC_R_UART_0,
1442+	IMX_SC_R_UART_1,
1443+	IMX_SC_R_UART_2,
1444+	IMX_SC_R_UART_3,
1445+	IMX_SC_R_UART_4,
1446+	IMX_SC_R_EMVSIM_0,
1447+	IMX_SC_R_EMVSIM_1,
1448+	IMX_SC_R_I2C_0,
1449+	IMX_SC_R_I2C_1,
1450+	IMX_SC_R_I2C_2,
1451+	IMX_SC_R_I2C_3,
1452+	IMX_SC_R_I2C_4,
1453+	IMX_SC_R_ADC_0,
1454+	IMX_SC_R_ADC_1,
1455+	IMX_SC_R_FTM_0,
1456+	IMX_SC_R_FTM_1,
1457+	IMX_SC_R_CAN_0,
1458+	IMX_SC_R_CAN_1,
1459+	IMX_SC_R_CAN_2,
1460+	IMX_SC_R_GPU_0_PID0,
1461+	IMX_SC_R_GPU_1_PID0,
1462+	IMX_SC_R_PWM_0,
1463+	IMX_SC_R_PWM_1,
1464+	IMX_SC_R_PWM_2,
1465+	IMX_SC_R_PWM_3,
1466+	IMX_SC_R_PWM_4,
1467+	IMX_SC_R_PWM_5,
1468+	IMX_SC_R_PWM_6,
1469+	IMX_SC_R_PWM_7,
1470+	IMX_SC_R_GPT_0,
1471+	IMX_SC_R_GPT_1,
1472+	IMX_SC_R_GPT_2,
1473+	IMX_SC_R_GPT_3,
1474+	IMX_SC_R_GPT_4,
1475+	IMX_SC_R_FSPI_0,
1476+	IMX_SC_R_FSPI_1,
1477+	IMX_SC_R_SDHC_0,
1478+	IMX_SC_R_SDHC_1,
1479+	IMX_SC_R_SDHC_2,
1480+	IMX_SC_R_ENET_0,
1481+	IMX_SC_R_ENET_1,
1482+	IMX_SC_R_USB_2,
1483+	IMX_SC_R_NAND,
1484+	IMX_SC_R_LVDS_0,
1485+	IMX_SC_R_LVDS_0_PWM_0,
1486+	IMX_SC_R_LVDS_0_I2C_0,
1487+	IMX_SC_R_LVDS_0_I2C_1,
1488+	IMX_SC_R_LVDS_1,
1489+	IMX_SC_R_LVDS_1_PWM_0,
1490+	IMX_SC_R_LVDS_1_I2C_0,
1491+	IMX_SC_R_LVDS_1_I2C_1,
1492+	IMX_SC_R_M4_0_I2C,
1493+	IMX_SC_R_M4_1_I2C,
1494+	IMX_SC_R_AUDIO_PLL_0,
1495+	IMX_SC_R_VPU_UART,
1496+	IMX_SC_R_VPUCORE,
1497+	IMX_SC_R_MIPI_0,
1498+	IMX_SC_R_MIPI_0_PWM_0,
1499+	IMX_SC_R_MIPI_0_I2C_0,
1500+	IMX_SC_R_MIPI_0_I2C_1,
1501+	IMX_SC_R_MIPI_1,
1502+	IMX_SC_R_MIPI_1_PWM_0,
1503+	IMX_SC_R_MIPI_1_I2C_0,
1504+	IMX_SC_R_MIPI_1_I2C_1,
1505+	IMX_SC_R_CSI_0,
1506+	IMX_SC_R_CSI_0_PWM_0,
1507+	IMX_SC_R_CSI_0_I2C_0,
1508+	IMX_SC_R_CSI_1,
1509+	IMX_SC_R_CSI_1_PWM_0,
1510+	IMX_SC_R_CSI_1_I2C_0,
1511+	IMX_SC_R_HDMI,
1512+	IMX_SC_R_HDMI_I2S,
1513+	IMX_SC_R_HDMI_I2C_0,
1514+	IMX_SC_R_HDMI_PLL_0,
1515+	IMX_SC_R_HDMI_RX,
1516+	IMX_SC_R_HDMI_RX_BYPASS,
1517+	IMX_SC_R_HDMI_RX_I2C_0,
1518+	IMX_SC_R_AUDIO_PLL_1,
1519+	IMX_SC_R_AUDIO_CLK_0,
1520+	IMX_SC_R_AUDIO_CLK_1,
1521+	IMX_SC_R_HDMI_RX_PWM_0,
1522+	IMX_SC_R_HDMI_PLL_1,
1523+	IMX_SC_R_VPU,
1524+};
1525+
1526+const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm = {
1527+	.rsrc = imx8qm_clk_scu_rsrc_table,
1528+	.num = ARRAY_SIZE(imx8qm_clk_scu_rsrc_table),
1529+};
1530diff --git a/drivers/clk/imx/clk-imx8qxp-acm.c b/drivers/clk/imx/clk-imx8qxp-acm.c
1531new file mode 100644
1532index 000000000..8968061cf
1533--- /dev/null
1534+++ b/drivers/clk/imx/clk-imx8qxp-acm.c
1535@@ -0,0 +1,258 @@
1536+// SPDX-License-Identifier: GPL-2.0+
1537+/*
1538+ * Copyright 2018 NXP
1539+ *	Dong Aisheng <aisheng.dong@nxp.com>
1540+ */
1541+
1542+#include <linux/clk-provider.h>
1543+#include <linux/err.h>
1544+#include <linux/io.h>
1545+#include <linux/module.h>
1546+#include <linux/of.h>
1547+#include <linux/of_device.h>
1548+#include <linux/platform_device.h>
1549+#include <linux/slab.h>
1550+#include <linux/pm_domain.h>
1551+#include <linux/pm_runtime.h>
1552+
1553+#include "clk.h"
1554+#include "clk-scu.h"
1555+#include "clk-imx-acm-utils.h"
1556+
1557+#include <dt-bindings/clock/imx8-clock.h>
1558+
1559+struct imx8qxp_acm_priv {
1560+	struct clk_imx_acm_pm_domains dev_pm;
1561+	void __iomem *reg;
1562+	u32 regs[0x20];
1563+};
1564+
1565+static const char *aud_clk_sels[] = {
1566+	"aud_rec_clk0_lpcg_clk",
1567+	"aud_rec_clk1_lpcg_clk",
1568+	"ext_aud_mclk0",
1569+	"ext_aud_mclk1",
1570+	"esai0_rx_clk",
1571+	"esai0_rx_hf_clk",
1572+	"esai0_tx_clk",
1573+	"esai0_tx_hf_clk",
1574+	"spdif0_rx",
1575+	"sai0_rx_bclk",
1576+	"sai0_tx_bclk",
1577+	"sai1_rx_bclk",
1578+	"sai1_tx_bclk",
1579+	"sai2_rx_bclk",
1580+	"sai3_rx_bclk",
1581+};
1582+
1583+static const char *mclk_out_sels[] = {
1584+	"aud_rec_clk0_lpcg_clk",
1585+	"aud_rec_clk1_lpcg_clk",
1586+	"dummy",
1587+	"dummy",
1588+	"spdif0_rx",
1589+	"dummy",
1590+	"dummy",
1591+	"sai4_rx_bclk",
1592+};
1593+
1594+static const char *sai_mclk_sels[] = {
1595+	"aud_pll_div_clk0_lpcg_clk",
1596+	"aud_pll_div_clk1_lpcg_clk",
1597+	"acm_aud_clk0_sel",
1598+	"acm_aud_clk1_sel",
1599+};
1600+
1601+static const char *esai_mclk_sels[] = {
1602+	"aud_pll_div_clk0_lpcg_clk",
1603+	"aud_pll_div_clk1_lpcg_clk",
1604+	"acm_aud_clk0_sel",
1605+	"acm_aud_clk1_sel",
1606+};
1607+
1608+static const char *spdif_mclk_sels[] = {
1609+	"aud_pll_div_clk0_lpcg_clk",
1610+	"aud_pll_div_clk1_lpcg_clk",
1611+	"acm_aud_clk0_sel",
1612+	"acm_aud_clk1_sel",
1613+};
1614+
1615+static const char *mqs_mclk_sels[] = {
1616+	"aud_pll_div_clk0_lpcg_clk",
1617+	"aud_pll_div_clk1_lpcg_clk",
1618+	"acm_aud_clk0_sel",
1619+	"acm_aud_clk1_sel",
1620+};
1621+
1622+static int imx8qxp_acm_clk_probe(struct platform_device *pdev)
1623+{
1624+	struct device *dev = &pdev->dev;
1625+	struct device_node *np = dev->of_node;
1626+	struct clk_onecell_data *clk_data;
1627+	struct imx8qxp_acm_priv *priv;
1628+	struct resource *res;
1629+	struct clk **clks;
1630+	void __iomem *base;
1631+	int ret;
1632+	int i;
1633+
1634+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1635+	base = devm_ioremap(dev, res->start, resource_size(res));
1636+	if (!base)
1637+		return -ENOMEM;
1638+
1639+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1640+	if (!priv)
1641+		return -ENOMEM;
1642+
1643+	priv->reg = base;
1644+
1645+	platform_set_drvdata(pdev, priv);
1646+
1647+	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
1648+	if (!clk_data)
1649+		return -ENOMEM;
1650+
1651+	clk_data->clks = devm_kcalloc(&pdev->dev, IMX_ADMA_ACM_CLK_END,
1652+					sizeof(*clk_data->clks), GFP_KERNEL);
1653+	if (!clk_data->clks)
1654+		return -ENOMEM;
1655+
1656+	clk_data->clk_num = IMX_ADMA_ACM_CLK_END;
1657+
1658+	clks = clk_data->clks;
1659+
1660+	ret = clk_imx_acm_attach_pm_domains(&pdev->dev, &priv->dev_pm);
1661+	if (ret)
1662+		return ret;
1663+
1664+	pm_runtime_enable(&pdev->dev);
1665+	pm_runtime_get_sync(&pdev->dev);
1666+
1667+	clks[IMX_ADMA_EXT_AUD_MCLK0]     = imx_clk_fixed("ext_aud_mclk0", 0);
1668+	clks[IMX_ADMA_EXT_AUD_MCLK1]     = imx_clk_fixed("ext_aud_mclk1", 0);
1669+	clks[IMX_ADMA_ESAI0_RX_CLK]      = imx_clk_fixed("esai0_rx_clk", 0);
1670+	clks[IMX_ADMA_ESAI0_RX_HF_CLK]   = imx_clk_fixed("esai0_rx_hf_clk", 0);
1671+	clks[IMX_ADMA_ESAI0_TX_CLK]      = imx_clk_fixed("esai0_tx_clk", 0);
1672+	clks[IMX_ADMA_ESAI0_TX_HF_CLK]   = imx_clk_fixed("esai0_tx_hf_clk", 0);
1673+	clks[IMX_ADMA_SPDIF0_RX]         = imx_clk_fixed("spdif0_rx", 0);
1674+	clks[IMX_ADMA_SAI0_RX_BCLK]      = imx_clk_fixed("sai0_rx_bclk", 0);
1675+	clks[IMX_ADMA_SAI0_TX_BCLK]      = imx_clk_fixed("sai0_tx_bclk", 0);
1676+	clks[IMX_ADMA_SAI1_RX_BCLK]      = imx_clk_fixed("sai1_rx_bclk", 0);
1677+	clks[IMX_ADMA_SAI1_TX_BCLK]      = imx_clk_fixed("sai1_tx_bclk", 0);
1678+	clks[IMX_ADMA_SAI2_RX_BCLK]      = imx_clk_fixed("sai2_rx_bclk", 0);
1679+	clks[IMX_ADMA_SAI3_RX_BCLK]      = imx_clk_fixed("sai3_rx_bclk", 0);
1680+	clks[IMX_ADMA_SAI4_RX_BCLK]      = imx_clk_fixed("sai4_rx_bclk", 0);
1681+
1682+
1683+	clks[IMX_ADMA_ACM_AUD_CLK0_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk0_sel", base+0x000000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels));
1684+	clks[IMX_ADMA_ACM_AUD_CLK1_SEL]	= imx_dev_clk_mux(dev, "acm_aud_clk1_sel", base+0x010000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels));
1685+
1686+	clks[IMX_ADMA_ACM_MCLKOUT0_SEL]	= imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels));
1687+	clks[IMX_ADMA_ACM_MCLKOUT1_SEL]	= imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels));
1688+
1689+	clks[IMX_ADMA_ACM_ESAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_esai0_mclk_sel", base+0x060000, 0, 2, esai_mclk_sels, ARRAY_SIZE(esai_mclk_sels));
1690+	clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1691+	clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1692+	clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1693+	clks[IMX_ADMA_ACM_SAI3_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai3_mclk_sel", base+0x110000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1694+	clks[IMX_ADMA_ACM_SAI4_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai4_mclk_sel", base+0x140000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1695+	clks[IMX_ADMA_ACM_SAI5_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai5_mclk_sel", base+0x150000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels));
1696+
1697+	clks[IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif0_mclk_sel", base+0x1A0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels));
1698+	clks[IMX_ADMA_ACM_MQS_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_mqs_mclk_sel", base+0x1C0000, 0, 2, mqs_mclk_sels, ARRAY_SIZE(mqs_mclk_sels));
1699+
1700+	for (i = 0; i < clk_data->clk_num; i++) {
1701+		if (IS_ERR(clks[i]))
1702+			pr_warn("i.MX clk %u: register failed with %ld\n",
1703+				i, PTR_ERR(clks[i]));
1704+	}
1705+
1706+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
1707+
1708+	pm_runtime_put_sync(&pdev->dev);
1709+
1710+	return ret;
1711+}
1712+
1713+static int imx8qxp_acm_clk_remove(struct platform_device *pdev)
1714+{
1715+	struct imx8qxp_acm_priv *priv = dev_get_drvdata(&pdev->dev);
1716+
1717+	pm_runtime_disable(&pdev->dev);
1718+
1719+	clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm);
1720+
1721+	return 0;
1722+}
1723+
1724+static const struct of_device_id imx8qxp_acm_match[] = {
1725+	{ .compatible = "nxp,imx8qxp-acm", },
1726+	{ /* sentinel */ }
1727+};
1728+
1729+static int __maybe_unused imx8qxp_acm_runtime_suspend(struct device *dev)
1730+{
1731+	struct imx8qxp_acm_priv *priv = dev_get_drvdata(dev);
1732+
1733+	priv->regs[0]  = readl_relaxed(priv->reg + 0x000000);
1734+	priv->regs[1]  = readl_relaxed(priv->reg + 0x010000);
1735+	priv->regs[2]  = readl_relaxed(priv->reg + 0x020000);
1736+	priv->regs[3]  = readl_relaxed(priv->reg + 0x030000);
1737+	priv->regs[6]  = readl_relaxed(priv->reg + 0x060000);
1738+	priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000);
1739+	priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000);
1740+	priv->regs[16] = readl_relaxed(priv->reg + 0x100000);
1741+	priv->regs[17] = readl_relaxed(priv->reg + 0x110000);
1742+	priv->regs[20] = readl_relaxed(priv->reg + 0x140000);
1743+	priv->regs[21] = readl_relaxed(priv->reg + 0x150000);
1744+	priv->regs[26] = readl_relaxed(priv->reg + 0x1A0000);
1745+	priv->regs[28] = readl_relaxed(priv->reg + 0x1C0000);
1746+
1747+	return 0;
1748+}
1749+
1750+static int __maybe_unused imx8qxp_acm_runtime_resume(struct device *dev)
1751+{
1752+	struct imx8qxp_acm_priv *priv = dev_get_drvdata(dev);
1753+
1754+	writel_relaxed(priv->regs[0],  priv->reg + 0x000000);
1755+	writel_relaxed(priv->regs[1],  priv->reg + 0x010000);
1756+	writel_relaxed(priv->regs[2],  priv->reg + 0x020000);
1757+	writel_relaxed(priv->regs[3],  priv->reg + 0x030000);
1758+	writel_relaxed(priv->regs[6],  priv->reg + 0x060000);
1759+	writel_relaxed(priv->regs[14], priv->reg + 0x0E0000);
1760+	writel_relaxed(priv->regs[15], priv->reg + 0x0F0000);
1761+	writel_relaxed(priv->regs[16], priv->reg + 0x100000);
1762+	writel_relaxed(priv->regs[17], priv->reg + 0x110000);
1763+	writel_relaxed(priv->regs[20], priv->reg + 0x140000);
1764+	writel_relaxed(priv->regs[21], priv->reg + 0x150000);
1765+	writel_relaxed(priv->regs[26], priv->reg + 0x1A0000);
1766+	writel_relaxed(priv->regs[28], priv->reg + 0x1C0000);
1767+
1768+	return 0;
1769+}
1770+
1771+const struct dev_pm_ops imx8qxp_acm_pm_ops = {
1772+	SET_RUNTIME_PM_OPS(imx8qxp_acm_runtime_suspend,
1773+			   imx8qxp_acm_runtime_resume, NULL)
1774+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1775+				      pm_runtime_force_resume)
1776+};
1777+
1778+static struct platform_driver imx8qxp_acm_clk_driver = {
1779+	.driver = {
1780+		.name = "imx8qxp-acm",
1781+		.of_match_table = imx8qxp_acm_match,
1782+		.pm = &imx8qxp_acm_pm_ops,
1783+		.suppress_bind_attrs = true,
1784+	},
1785+	.probe = imx8qxp_acm_clk_probe,
1786+	.remove = imx8qxp_acm_clk_remove,
1787+};
1788+
1789+static int __init imx8qxp_acm_init(void)
1790+{
1791+	return platform_driver_register(&imx8qxp_acm_clk_driver);
1792+}
1793+fs_initcall(imx8qxp_acm_init);
1794diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
1795index 522c03a12..0b43a8345 100644
1796--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
1797+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
1798@@ -9,216 +9,106 @@
1799 #include <linux/io.h>
1800 #include <linux/module.h>
1801 #include <linux/of.h>
1802+#include <linux/of_address.h>
1803 #include <linux/of_device.h>
1804 #include <linux/platform_device.h>
1805+#include <linux/pm_runtime.h>
1806 #include <linux/slab.h>
1807
1808 #include "clk-scu.h"
1809-#include "clk-imx8qxp-lpcg.h"
1810
1811-#include <dt-bindings/clock/imx8-clock.h>
1812-
1813-/*
1814- * struct imx8qxp_lpcg_data - Description of one LPCG clock
1815- * @id: clock ID
1816- * @name: clock name
1817- * @parent: parent clock name
1818- * @flags: common clock flags
1819- * @offset: offset of this LPCG clock
1820- * @bit_idx: bit index of this LPCG clock
1821- * @hw_gate: whether supports HW autogate
1822- *
1823- * This structure describes one LPCG clock
1824- */
1825-struct imx8qxp_lpcg_data {
1826-	int id;
1827-	char *name;
1828-	char *parent;
1829-	unsigned long flags;
1830-	u32 offset;
1831-	u8 bit_idx;
1832-	bool hw_gate;
1833-};
1834-
1835-/*
1836- * struct imx8qxp_ss_lpcg - Description of one subsystem LPCG clocks
1837- * @lpcg: LPCG clocks array of one subsystem
1838- * @num_lpcg: the number of LPCG clocks
1839- * @num_max: the maximum number of LPCG clocks
1840- *
1841- * This structure describes each subsystem LPCG clocks information
1842- * which then will be used to create respective LPCGs clocks
1843- */
1844-struct imx8qxp_ss_lpcg {
1845-	const struct imx8qxp_lpcg_data *lpcg;
1846-	u8 num_lpcg;
1847-	u8 num_max;
1848-};
1849-
1850-static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
1851-	{ IMX_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
1852-	{ IMX_ADMA_LPCG_UART0_BAUD_CLK, "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
1853-	{ IMX_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
1854-	{ IMX_ADMA_LPCG_UART1_BAUD_CLK, "uart1_lpcg_baud_clk", "uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
1855-	{ IMX_ADMA_LPCG_UART2_IPG_CLK, "uart2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_2_LPCG, 16, 0, },
1856-	{ IMX_ADMA_LPCG_UART2_BAUD_CLK, "uart2_lpcg_baud_clk", "uart2_clk", 0, ADMA_LPUART_2_LPCG, 0, 0, },
1857-	{ IMX_ADMA_LPCG_UART3_IPG_CLK, "uart3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_3_LPCG, 16, 0, },
1858-	{ IMX_ADMA_LPCG_UART3_BAUD_CLK, "uart3_lpcg_baud_clk", "uart3_clk", 0, ADMA_LPUART_3_LPCG, 0, 0, },
1859-	{ IMX_ADMA_LPCG_I2C0_IPG_CLK, "i2c0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_0_LPCG, 16, 0, },
1860-	{ IMX_ADMA_LPCG_I2C0_CLK, "i2c0_lpcg_clk", "i2c0_clk", 0, ADMA_LPI2C_0_LPCG, 0, 0, },
1861-	{ IMX_ADMA_LPCG_I2C1_IPG_CLK, "i2c1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_1_LPCG, 16, 0, },
1862-	{ IMX_ADMA_LPCG_I2C1_CLK, "i2c1_lpcg_clk", "i2c1_clk", 0, ADMA_LPI2C_1_LPCG, 0, 0, },
1863-	{ IMX_ADMA_LPCG_I2C2_IPG_CLK, "i2c2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_2_LPCG, 16, 0, },
1864-	{ IMX_ADMA_LPCG_I2C2_CLK, "i2c2_lpcg_clk", "i2c2_clk", 0, ADMA_LPI2C_2_LPCG, 0, 0, },
1865-	{ IMX_ADMA_LPCG_I2C3_IPG_CLK, "i2c3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_3_LPCG, 16, 0, },
1866-	{ IMX_ADMA_LPCG_I2C3_CLK, "i2c3_lpcg_clk", "i2c3_clk", 0, ADMA_LPI2C_3_LPCG, 0, 0, },
1867-
1868-	{ IMX_ADMA_LPCG_DSP_CORE_CLK, "dsp_lpcg_core_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 28, 0, },
1869-	{ IMX_ADMA_LPCG_DSP_IPG_CLK, "dsp_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 20, 0, },
1870-	{ IMX_ADMA_LPCG_DSP_ADB_CLK, "dsp_lpcg_adb_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 16, 0, },
1871-	{ IMX_ADMA_LPCG_OCRAM_IPG_CLK, "ocram_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_OCRAM_LPCG, 16, 0, },
1872-};
1873-
1874-static const struct imx8qxp_ss_lpcg imx8qxp_ss_adma = {
1875-	.lpcg = imx8qxp_lpcg_adma,
1876-	.num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_adma),
1877-	.num_max = IMX_ADMA_LPCG_CLK_END,
1878-};
1879-
1880-static const struct imx8qxp_lpcg_data imx8qxp_lpcg_conn[] = {
1881-	{ IMX_CONN_LPCG_SDHC0_PER_CLK, "sdhc0_lpcg_per_clk", "sdhc0_clk", 0, CONN_USDHC_0_LPCG, 0, 0, },
1882-	{ IMX_CONN_LPCG_SDHC0_IPG_CLK, "sdhc0_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_0_LPCG, 16, 0, },
1883-	{ IMX_CONN_LPCG_SDHC0_HCLK, "sdhc0_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_0_LPCG, 20, 0, },
1884-	{ IMX_CONN_LPCG_SDHC1_PER_CLK, "sdhc1_lpcg_per_clk", "sdhc1_clk", 0, CONN_USDHC_1_LPCG, 0, 0, },
1885-	{ IMX_CONN_LPCG_SDHC1_IPG_CLK, "sdhc1_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_1_LPCG, 16, 0, },
1886-	{ IMX_CONN_LPCG_SDHC1_HCLK, "sdhc1_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_1_LPCG, 20, 0, },
1887-	{ IMX_CONN_LPCG_SDHC2_PER_CLK, "sdhc2_lpcg_per_clk", "sdhc2_clk", 0, CONN_USDHC_2_LPCG, 0, 0, },
1888-	{ IMX_CONN_LPCG_SDHC2_IPG_CLK, "sdhc2_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_2_LPCG, 16, 0, },
1889-	{ IMX_CONN_LPCG_SDHC2_HCLK, "sdhc2_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_2_LPCG, 20, 0, },
1890-	{ IMX_CONN_LPCG_ENET0_ROOT_CLK, "enet0_ipg_root_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 0, 0, },
1891-	{ IMX_CONN_LPCG_ENET0_TX_CLK, "enet0_tx_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 4, 0, },
1892-	{ IMX_CONN_LPCG_ENET0_AHB_CLK, "enet0_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_0_LPCG, 8, 0, },
1893-	{ IMX_CONN_LPCG_ENET0_IPG_S_CLK, "enet0_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_0_LPCG, 20, 0, },
1894-	{ IMX_CONN_LPCG_ENET0_IPG_CLK, "enet0_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_0_LPCG, 16, 0, },
1895-	{ IMX_CONN_LPCG_ENET1_ROOT_CLK, "enet1_ipg_root_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 0, 0, },
1896-	{ IMX_CONN_LPCG_ENET1_TX_CLK, "enet1_tx_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 4, 0, },
1897-	{ IMX_CONN_LPCG_ENET1_AHB_CLK, "enet1_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_1_LPCG, 8, 0, },
1898-	{ IMX_CONN_LPCG_ENET1_IPG_S_CLK, "enet1_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_1_LPCG, 20, 0, },
1899-	{ IMX_CONN_LPCG_ENET1_IPG_CLK, "enet1_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_1_LPCG, 16, 0, },
1900-};
1901-
1902-static const struct imx8qxp_ss_lpcg imx8qxp_ss_conn = {
1903-	.lpcg = imx8qxp_lpcg_conn,
1904-	.num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_conn),
1905-	.num_max = IMX_CONN_LPCG_CLK_END,
1906-};
1907-
1908-static const struct imx8qxp_lpcg_data imx8qxp_lpcg_lsio[] = {
1909-	{ IMX_LSIO_LPCG_PWM0_IPG_CLK, "pwm0_lpcg_ipg_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 0, 0, },
1910-	{ IMX_LSIO_LPCG_PWM0_IPG_HF_CLK, "pwm0_lpcg_ipg_hf_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 4, 0, },
1911-	{ IMX_LSIO_LPCG_PWM0_IPG_S_CLK, "pwm0_lpcg_ipg_s_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 16, 0, },
1912-	{ IMX_LSIO_LPCG_PWM0_IPG_SLV_CLK, "pwm0_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_0_LPCG, 20, 0, },
1913-	{ IMX_LSIO_LPCG_PWM0_IPG_MSTR_CLK, "pwm0_lpcg_ipg_mstr_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 24, 0, },
1914-	{ IMX_LSIO_LPCG_PWM1_IPG_CLK, "pwm1_lpcg_ipg_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 0, 0, },
1915-	{ IMX_LSIO_LPCG_PWM1_IPG_HF_CLK, "pwm1_lpcg_ipg_hf_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 4, 0, },
1916-	{ IMX_LSIO_LPCG_PWM1_IPG_S_CLK, "pwm1_lpcg_ipg_s_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 16, 0, },
1917-	{ IMX_LSIO_LPCG_PWM1_IPG_SLV_CLK, "pwm1_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_1_LPCG, 20, 0, },
1918-	{ IMX_LSIO_LPCG_PWM1_IPG_MSTR_CLK, "pwm1_lpcg_ipg_mstr_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 24, 0, },
1919-	{ IMX_LSIO_LPCG_PWM2_IPG_CLK, "pwm2_lpcg_ipg_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 0, 0, },
1920-	{ IMX_LSIO_LPCG_PWM2_IPG_HF_CLK, "pwm2_lpcg_ipg_hf_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 4, 0, },
1921-	{ IMX_LSIO_LPCG_PWM2_IPG_S_CLK, "pwm2_lpcg_ipg_s_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 16, 0, },
1922-	{ IMX_LSIO_LPCG_PWM2_IPG_SLV_CLK, "pwm2_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_2_LPCG, 20, 0, },
1923-	{ IMX_LSIO_LPCG_PWM2_IPG_MSTR_CLK, "pwm2_lpcg_ipg_mstr_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 24, 0, },
1924-	{ IMX_LSIO_LPCG_PWM3_IPG_CLK, "pwm3_lpcg_ipg_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 0, 0, },
1925-	{ IMX_LSIO_LPCG_PWM3_IPG_HF_CLK, "pwm3_lpcg_ipg_hf_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 4, 0, },
1926-	{ IMX_LSIO_LPCG_PWM3_IPG_S_CLK, "pwm3_lpcg_ipg_s_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 16, 0, },
1927-	{ IMX_LSIO_LPCG_PWM3_IPG_SLV_CLK, "pwm3_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_3_LPCG, 20, 0, },
1928-	{ IMX_LSIO_LPCG_PWM3_IPG_MSTR_CLK, "pwm3_lpcg_ipg_mstr_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 24, 0, },
1929-	{ IMX_LSIO_LPCG_PWM4_IPG_CLK, "pwm4_lpcg_ipg_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 0, 0, },
1930-	{ IMX_LSIO_LPCG_PWM4_IPG_HF_CLK, "pwm4_lpcg_ipg_hf_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 4, 0, },
1931-	{ IMX_LSIO_LPCG_PWM4_IPG_S_CLK, "pwm4_lpcg_ipg_s_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 16, 0, },
1932-	{ IMX_LSIO_LPCG_PWM4_IPG_SLV_CLK, "pwm4_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_4_LPCG, 20, 0, },
1933-	{ IMX_LSIO_LPCG_PWM4_IPG_MSTR_CLK, "pwm4_lpcg_ipg_mstr_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 24, 0, },
1934-	{ IMX_LSIO_LPCG_PWM5_IPG_CLK, "pwm5_lpcg_ipg_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 0, 0, },
1935-	{ IMX_LSIO_LPCG_PWM5_IPG_HF_CLK, "pwm5_lpcg_ipg_hf_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 4, 0, },
1936-	{ IMX_LSIO_LPCG_PWM5_IPG_S_CLK, "pwm5_lpcg_ipg_s_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 16, 0, },
1937-	{ IMX_LSIO_LPCG_PWM5_IPG_SLV_CLK, "pwm5_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_5_LPCG, 20, 0, },
1938-	{ IMX_LSIO_LPCG_PWM5_IPG_MSTR_CLK, "pwm5_lpcg_ipg_mstr_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 24, 0, },
1939-	{ IMX_LSIO_LPCG_PWM6_IPG_CLK, "pwm6_lpcg_ipg_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 0, 0, },
1940-	{ IMX_LSIO_LPCG_PWM6_IPG_HF_CLK, "pwm6_lpcg_ipg_hf_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 4, 0, },
1941-	{ IMX_LSIO_LPCG_PWM6_IPG_S_CLK, "pwm6_lpcg_ipg_s_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 16, 0, },
1942-	{ IMX_LSIO_LPCG_PWM6_IPG_SLV_CLK, "pwm6_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_6_LPCG, 20, 0, },
1943-	{ IMX_LSIO_LPCG_PWM6_IPG_MSTR_CLK, "pwm6_lpcg_ipg_mstr_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 24, 0, },
1944-};
1945-
1946-static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = {
1947-	.lpcg = imx8qxp_lpcg_lsio,
1948-	.num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_lsio),
1949-	.num_max = IMX_LSIO_LPCG_CLK_END,
1950-};
1951+#define IMX_LPCG_MAX_CLKS	8
1952
1953 static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
1954 {
1955-	struct device *dev = &pdev->dev;
1956-	struct device_node *np = dev->of_node;
1957+	struct device_node *np = pdev->dev.of_node;
1958+	const char *output_names[IMX_LPCG_MAX_CLKS];
1959+	const char *parent_names[IMX_LPCG_MAX_CLKS];
1960+	unsigned int bit_offset[IMX_LPCG_MAX_CLKS];
1961 	struct clk_hw_onecell_data *clk_data;
1962-	const struct imx8qxp_ss_lpcg *ss_lpcg;
1963-	const struct imx8qxp_lpcg_data *lpcg;
1964+	struct clk_hw **clk_hws;
1965 	struct resource *res;
1966-	struct clk_hw **clks;
1967 	void __iomem *base;
1968+	bool autogate;
1969+	int count;
1970+	int ret;
1971 	int i;
1972
1973-	ss_lpcg = of_device_get_match_data(dev);
1974-	if (!ss_lpcg)
1975-		return -ENODEV;
1976-
1977-	/*
1978-	 * Please don't replace this with devm_platform_ioremap_resource.
1979-	 *
1980-	 * devm_platform_ioremap_resource calls devm_ioremap_resource which
1981-	 * differs from devm_ioremap by also calling devm_request_mem_region
1982-	 * and preventing other mappings in the same area.
1983-	 *
1984-	 * On imx8 the LPCG nodes map entire subsystems and overlap
1985-	 * peripherals, this means that using devm_platform_ioremap_resource
1986-	 * will cause many devices to fail to probe including serial ports.
1987-	 */
1988 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1989-	if (!res)
1990+	base = devm_ioremap_resource(&pdev->dev, res);
1991+	if (IS_ERR(base))
1992+		return PTR_ERR(base);
1993+
1994+	count = of_property_count_u32_elems(np, "bit-offset");
1995+	if (count < 0) {
1996+		dev_err(&pdev->dev, "failed to count clocks\n");
1997 		return -EINVAL;
1998-	base = devm_ioremap(dev, res->start, resource_size(res));
1999-	if (!base)
2000-		return -ENOMEM;
2001+	}
2002
2003-	clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws,
2004-				ss_lpcg->num_max), GFP_KERNEL);
2005+	clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, count),
2006+				GFP_KERNEL);
2007 	if (!clk_data)
2008 		return -ENOMEM;
2009
2010-	clk_data->num = ss_lpcg->num_max;
2011-	clks = clk_data->hws;
2012+	clk_data->num = count;
2013+	clk_hws = clk_data->hws;
2014
2015-	for (i = 0; i < ss_lpcg->num_lpcg; i++) {
2016-		lpcg = ss_lpcg->lpcg + i;
2017-		clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name, lpcg->parent,
2018-						  lpcg->flags, base + lpcg->offset,
2019-						  lpcg->bit_idx, lpcg->hw_gate);
2020+	ret = of_property_read_u32_array(np, "bit-offset", bit_offset,
2021+					 clk_data->num);
2022+	if (ret < 0) {
2023+		dev_err(&pdev->dev, "failed to read clocks bit-offset\n");
2024+		return -EINVAL;
2025 	}
2026
2027+	ret = of_clk_parent_fill(np, parent_names, clk_data->num);
2028+	if (ret != clk_data->num) {
2029+		dev_err(&pdev->dev, "failed to get clock parent names\n");
2030+		return -EINVAL;
2031+	}
2032+
2033+	ret = of_property_read_string_array(np, "clock-output-names",
2034+					    output_names, clk_data->num);
2035+	if (ret != clk_data->num) {
2036+		dev_err(&pdev->dev, "failed to read clock-output-names\n");
2037+		return -EINVAL;
2038+	}
2039+
2040+	autogate = of_property_read_bool(np, "hw-autogate");
2041+
2042+	pm_runtime_get_noresume(&pdev->dev);
2043+	pm_runtime_set_active(&pdev->dev);
2044+	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
2045+	pm_runtime_use_autosuspend(&pdev->dev);
2046+	pm_runtime_enable(&pdev->dev);
2047+
2048 	for (i = 0; i < clk_data->num; i++) {
2049-		if (IS_ERR(clks[i]))
2050-			pr_warn("i.MX clk %u: register failed with %ld\n",
2051-				i, PTR_ERR(clks[i]));
2052+		if (bit_offset[i] > 31) {
2053+			dev_warn(&pdev->dev, "invalid bit offset of clock %d\n",
2054+				 i);
2055+			return -EINVAL;
2056+		}
2057+
2058+		clk_hws[i] = imx_clk_lpcg_scu_dev(&pdev->dev, output_names[i],
2059+						  parent_names[i], 0, base,
2060+						  bit_offset[i], autogate);
2061+		if (IS_ERR(clk_hws[i])) {
2062+			dev_warn(&pdev->dev, "failed to register clock %d\n",
2063+				 i);
2064+			return -EINVAL;
2065+		}
2066 	}
2067
2068-	return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
2069+	ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
2070+					  clk_data);
2071+
2072+	pm_runtime_mark_last_busy(&pdev->dev);
2073+	pm_runtime_put_autosuspend(&pdev->dev);
2074+
2075+	return ret;
2076 }
2077
2078 static const struct of_device_id imx8qxp_lpcg_match[] = {
2079-	{ .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
2080-	{ .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
2081-	{ .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
2082+	{ .compatible = "fsl,imx8qxp-lpcg", NULL },
2083 	{ /* sentinel */ }
2084 };
2085
2086@@ -226,6 +116,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = {
2087 	.driver = {
2088 		.name = "imx8qxp-lpcg-clk",
2089 		.of_match_table = imx8qxp_lpcg_match,
2090+		.pm = &imx_clk_lpcg_scu_pm_ops,
2091 		.suppress_bind_attrs = true,
2092 	},
2093 	.probe = imx8qxp_lpcg_clk_probe,
2094diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.h b/drivers/clk/imx/clk-imx8qxp-lpcg.h
2095index 2a37ce57c..e4458780e 100644
2096--- a/drivers/clk/imx/clk-imx8qxp-lpcg.h
2097+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.h
2098@@ -42,7 +42,6 @@
2099 #define CONN_ENET_0_LPCG		0x30000
2100 #define CONN_ENET_1_LPCG		0x40000
2101 #define CONN_DTCP_LPCG			0x50000
2102-#define CONN_MLB_LPCG			0x60000
2103 #define CONN_USB_2_LPCG			0x70000
2104 #define CONN_USB_3_LPCG			0x80000
2105 #define CONN_NAND_LPCG			0x90000
2106@@ -99,4 +98,49 @@
2107 #define ADMA_FLEXCAN_1_LPCG		0x1ce0000
2108 #define ADMA_FLEXCAN_2_LPCG		0x1cf0000
2109
2110+/* CM40 SS */
2111+#define CM40_I2C_LPCG			0x60000
2112+
2113+/* HSIO SS */
2114+#define HSIO_PCIEA_LPCG			0x00000
2115+#define HSIO_PCIEB_LPCG			0x10000
2116+#define HSIO_SATA0_LPCG			0x20000
2117+#define HSIO_PHYX2_LPCG			0x30000
2118+#define HSIO_PHYX1_LPCG			0x40000
2119+#define HSIO_CRR_0_LPCG			0x50000
2120+#define HSIO_CRR_1_LPCG			0x60000
2121+#define HSIO_CRR_2_LPCG			0x70000
2122+#define HSIO_CRR_3_LPCG			0x80000
2123+#define HSIO_CRR_4_LPCG			0x90000
2124+#define HSIO_CRR_5_LPCG			0xa0000
2125+#define HSIO_GPIO_LPCG			0xb0000
2126+
2127+/* IMG SS */
2128+#define IMG_PDMA0_LPCG			0x00000
2129+#define IMG_PDMA1_LPCG			0x10000
2130+#define IMG_PDMA2_LPCG			0x20000
2131+#define IMG_PDMA3_LPCG			0x30000
2132+#define IMG_PDMA4_LPCG			0x40000
2133+#define IMG_PDMA5_LPCG			0x50000
2134+#define IMG_PDMA6_LPCG			0x60000
2135+#define IMG_PDMA7_LPCG			0x70000
2136+#define IMG_MIPI_CSI0_LPCG		0x80000
2137+#define IMG_MIPI_CSI1_LPCG		0x90000
2138+
2139+/* CSI SS */
2140+#define CSI_CSI0_CORE_LPCG		0x18
2141+#define CSI_CSI0_ESC_LPCG		0x1C
2142+#define CSI_CSI0_I2C0_LPCG		0x14
2143+#define CSI_CSI1_CORE_LPCG		0x18
2144+#define CSI_CSI1_ESC_LPCG		0x1C
2145+#define CSI_CSI1_I2C0_LPCG		0x14
2146+
2147+/* Parallel Interface SS */
2148+#define PI_PI0_PIXEL_LPCG		0x18
2149+#define PI_PI0_IPG_LPCG			0x04
2150+#define PI_PI0_MISC_LPCG		0x1C
2151+
2152+/* DC0 SS */
2153+/* TODO: ADD DC LPCGs */
2154+
2155 #endif /* _IMX8QXP_LPCG_H */
2156diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c
2157new file mode 100644
2158index 000000000..947d5a64c
2159--- /dev/null
2160+++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c
2161@@ -0,0 +1,91 @@
2162+// SPDX-License-Identifier: GPL-2.0+
2163+/*
2164+ * Copyright 2019 NXP
2165+ *	Dong Aisheng <aisheng.dong@nxp.com>
2166+ */
2167+
2168+#include <dt-bindings/firmware/imx/rsrc.h>
2169+
2170+#include "clk-scu.h"
2171+
2172+/* Keep sorted in the ascending order */
2173+static u32 imx8qxp_clk_scu_rsrc_table[] = {
2174+	IMX_SC_R_DC_0_VIDEO0,
2175+	IMX_SC_R_DC_0_VIDEO1,
2176+	IMX_SC_R_DC_0,
2177+	IMX_SC_R_DC_0_PLL_0,
2178+	IMX_SC_R_DC_0_PLL_1,
2179+	IMX_SC_R_SPI_0,
2180+	IMX_SC_R_SPI_1,
2181+	IMX_SC_R_SPI_2,
2182+	IMX_SC_R_SPI_3,
2183+	IMX_SC_R_UART_0,
2184+	IMX_SC_R_UART_1,
2185+	IMX_SC_R_UART_2,
2186+	IMX_SC_R_UART_3,
2187+	IMX_SC_R_I2C_0,
2188+	IMX_SC_R_I2C_1,
2189+	IMX_SC_R_I2C_2,
2190+	IMX_SC_R_I2C_3,
2191+	IMX_SC_R_ADC_0,
2192+	IMX_SC_R_FTM_0,
2193+	IMX_SC_R_FTM_1,
2194+	IMX_SC_R_CAN_0,
2195+	IMX_SC_R_GPU_0_PID0,
2196+	IMX_SC_R_LCD_0,
2197+	IMX_SC_R_LCD_0_PWM_0,
2198+	IMX_SC_R_PWM_0,
2199+	IMX_SC_R_PWM_1,
2200+	IMX_SC_R_PWM_2,
2201+	IMX_SC_R_PWM_3,
2202+	IMX_SC_R_PWM_4,
2203+	IMX_SC_R_PWM_5,
2204+	IMX_SC_R_PWM_6,
2205+	IMX_SC_R_PWM_7,
2206+	IMX_SC_R_GPT_0,
2207+	IMX_SC_R_GPT_1,
2208+	IMX_SC_R_GPT_2,
2209+	IMX_SC_R_GPT_3,
2210+	IMX_SC_R_GPT_4,
2211+	IMX_SC_R_FSPI_0,
2212+	IMX_SC_R_FSPI_1,
2213+	IMX_SC_R_SDHC_0,
2214+	IMX_SC_R_SDHC_1,
2215+	IMX_SC_R_SDHC_2,
2216+	IMX_SC_R_ENET_0,
2217+	IMX_SC_R_ENET_1,
2218+	IMX_SC_R_USB_2,
2219+	IMX_SC_R_NAND,
2220+	IMX_SC_R_LVDS_0,
2221+	IMX_SC_R_LVDS_1,
2222+	IMX_SC_R_M4_0_UART,
2223+	IMX_SC_R_M4_0_I2C,
2224+	IMX_SC_R_ELCDIF_PLL,
2225+	IMX_SC_R_AUDIO_PLL_0,
2226+	IMX_SC_R_PI_0,
2227+	IMX_SC_R_PI_0_PWM_0,
2228+	IMX_SC_R_PI_0_I2C_0,
2229+	IMX_SC_R_PI_0_PLL,
2230+	IMX_SC_R_MIPI_0,
2231+	IMX_SC_R_MIPI_0_PWM_0,
2232+	IMX_SC_R_MIPI_0_I2C_0,
2233+	IMX_SC_R_MIPI_0_I2C_1,
2234+	IMX_SC_R_MIPI_1,
2235+	IMX_SC_R_MIPI_1_PWM_0,
2236+	IMX_SC_R_MIPI_1_I2C_0,
2237+	IMX_SC_R_MIPI_1_I2C_1,
2238+	IMX_SC_R_CSI_0,
2239+	IMX_SC_R_CSI_0_PWM_0,
2240+	IMX_SC_R_CSI_0_I2C_0,
2241+	IMX_SC_R_AUDIO_PLL_1,
2242+	IMX_SC_R_AUDIO_CLK_0,
2243+	IMX_SC_R_AUDIO_CLK_1,
2244+	IMX_SC_R_A35,
2245+	IMX_SC_R_VPU_DEC_0,
2246+	IMX_SC_R_VPU_ENC_0,
2247+};
2248+
2249+const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp = {
2250+	.rsrc = imx8qxp_clk_scu_rsrc_table,
2251+	.num = ARRAY_SIZE(imx8qxp_clk_scu_rsrc_table),
2252+};
2253diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
2254index 8c14e0bbe..29a8affda 100644
2255--- a/drivers/clk/imx/clk-imx8qxp.c
2256+++ b/drivers/clk/imx/clk-imx8qxp.c
2257@@ -9,139 +9,295 @@
2258 #include <linux/io.h>
2259 #include <linux/module.h>
2260 #include <linux/of.h>
2261+#include <linux/of_device.h>
2262 #include <linux/platform_device.h>
2263 #include <linux/slab.h>
2264
2265+#include <dt-bindings/firmware/imx/rsrc.h>
2266+
2267 #include "clk-scu.h"
2268
2269-#include <dt-bindings/clock/imx8-clock.h>
2270-#include <dt-bindings/firmware/imx/rsrc.h>
2271+static const char *pll0_sels[] = {
2272+	"clk_dummy",
2273+	"pi_dpll_clk",
2274+	"clk_dummy",
2275+	"clk_dummy",
2276+	"clk_dummy",
2277+};
2278+
2279+static const char *enet0_rgmii_txc_sels[] = {
2280+	"enet0_ref_div",
2281+	"clk_dummy",
2282+};
2283+
2284+static const char *enet1_rgmii_txc_sels[] __maybe_unused = {
2285+	"enet1_ref_div",
2286+	"clk_dummy",
2287+};
2288+
2289+static const char *dc0_sels[] = {
2290+	"clk_dummy",
2291+	"clk_dummy",
2292+	"dc0_pll0_clk",
2293+	"dc0_pll1_clk",
2294+	"dc0_bypass0_clk",
2295+};
2296+
2297+static const char *dc1_sels[] = {
2298+	"clk_dummy",
2299+	"clk_dummy",
2300+	"dc1_pll0_clk",
2301+	"dc1_pll1_clk",
2302+	"dc1_bypass0_clk",
2303+};
2304+
2305+static const char *hdmi_sels[] = {
2306+	"clk_dummy",
2307+	"hdmi_dig_pll_clk",
2308+	"clk_dummy",
2309+	"clk_dummy",
2310+	"hdmi_av_pll_clk",
2311+};
2312+
2313+static const char *hdmi_rx_sels[] = {
2314+	"clk_dummy",
2315+	"hdmi_rx_dig_pll_clk",
2316+	"clk_dummy",
2317+	"clk_dummy",
2318+	"hdmi_rx_bypass_clk",
2319+};
2320+
2321+static const char *lcd_pxl_sels[] = {
2322+	"dummy",
2323+	"dummy",
2324+	"dummy",
2325+	"dummy",
2326+	"lcd_pxl_bypass_div_clk",
2327+};
2328+
2329+static const char *mipi_sels[] = {
2330+	"dummy",
2331+	"dummy",
2332+	"mipi_pll_div2_clk",
2333+	"dummy",
2334+	"dummy",
2335+};
2336+
2337+static const char *lcd_sels[] = {
2338+	"clk_dummy",
2339+	"clk_dummy",
2340+	"clk_dummy",
2341+	"clk_dummy",
2342+	"elcdif_pll",
2343+};
2344+
2345+static const struct of_device_id imx8qxp_match[] = {
2346+	{ .compatible = "fsl,scu-clk", },
2347+	{ .compatible = "fsl,imx8qxp-clk", &imx_clk_scu_rsrc_imx8qxp, },
2348+	{ .compatible = "fsl,imx8qm-clk", &imx_clk_scu_rsrc_imx8qm, },
2349+	{ .compatible = "fsl,imx8dxl-clk", &imx_clk_scu_rsrc_imx8dxl, },
2350+	{ /* sentinel */ }
2351+};
2352
2353 static int imx8qxp_clk_probe(struct platform_device *pdev)
2354 {
2355+	const struct of_device_id *of_id =
2356+			of_match_device(imx8qxp_match, &pdev->dev);
2357 	struct device_node *ccm_node = pdev->dev.of_node;
2358-	struct clk_hw_onecell_data *clk_data;
2359-	struct clk_hw **clks;
2360-	int ret, i;
2361+	int ret;
2362
2363-	ret = imx_clk_scu_init();
2364+	ret = imx_clk_scu_init(ccm_node, of_id->data);
2365 	if (ret)
2366 		return ret;
2367
2368-	clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws,
2369-				IMX_SCU_CLK_END), GFP_KERNEL);
2370-	if (!clk_data)
2371-		return -ENOMEM;
2372-
2373-	clk_data->num = IMX_SCU_CLK_END;
2374-	clks = clk_data->hws;
2375-
2376-	/* Fixed clocks */
2377-	clks[IMX_CLK_DUMMY]		= clk_hw_register_fixed_rate(NULL, "dummy", NULL, 0, 0);
2378-	clks[IMX_ADMA_IPG_CLK_ROOT] 	= clk_hw_register_fixed_rate(NULL, "dma_ipg_clk_root", NULL, 0, 120000000);
2379-	clks[IMX_CONN_AXI_CLK_ROOT]	= clk_hw_register_fixed_rate(NULL, "conn_axi_clk_root", NULL, 0, 333333333);
2380-	clks[IMX_CONN_AHB_CLK_ROOT]	= clk_hw_register_fixed_rate(NULL, "conn_ahb_clk_root", NULL, 0, 166666666);
2381-	clks[IMX_CONN_IPG_CLK_ROOT]	= clk_hw_register_fixed_rate(NULL, "conn_ipg_clk_root", NULL, 0, 83333333);
2382-	clks[IMX_DC_AXI_EXT_CLK]	= clk_hw_register_fixed_rate(NULL, "dc_axi_ext_clk_root", NULL, 0, 800000000);
2383-	clks[IMX_DC_AXI_INT_CLK]	= clk_hw_register_fixed_rate(NULL, "dc_axi_int_clk_root", NULL, 0, 400000000);
2384-	clks[IMX_DC_CFG_CLK]		= clk_hw_register_fixed_rate(NULL, "dc_cfg_clk_root", NULL, 0, 100000000);
2385-	clks[IMX_MIPI_IPG_CLK]		= clk_hw_register_fixed_rate(NULL, "mipi_ipg_clk_root", NULL, 0, 120000000);
2386-	clks[IMX_IMG_AXI_CLK]		= clk_hw_register_fixed_rate(NULL, "img_axi_clk_root", NULL, 0, 400000000);
2387-	clks[IMX_IMG_IPG_CLK]		= clk_hw_register_fixed_rate(NULL, "img_ipg_clk_root", NULL, 0, 200000000);
2388-	clks[IMX_IMG_PXL_CLK]		= clk_hw_register_fixed_rate(NULL, "img_pxl_clk_root", NULL, 0, 600000000);
2389-	clks[IMX_HSIO_AXI_CLK]		= clk_hw_register_fixed_rate(NULL, "hsio_axi_clk_root", NULL, 0, 400000000);
2390-	clks[IMX_HSIO_PER_CLK]		= clk_hw_register_fixed_rate(NULL, "hsio_per_clk_root", NULL, 0, 133333333);
2391-	clks[IMX_LSIO_MEM_CLK]		= clk_hw_register_fixed_rate(NULL, "lsio_mem_clk_root", NULL, 0, 200000000);
2392-	clks[IMX_LSIO_BUS_CLK]		= clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000);
2393-
2394 	/* ARM core */
2395-	clks[IMX_A35_CLK]		= imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
2396+	imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
2397+	imx_clk_scu("a53_clk", IMX_SC_R_A53, IMX_SC_PM_CLK_CPU);
2398+	imx_clk_scu("a72_clk", IMX_SC_R_A72, IMX_SC_PM_CLK_CPU);
2399
2400 	/* LSIO SS */
2401-	clks[IMX_LSIO_PWM0_CLK]		= imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
2402-	clks[IMX_LSIO_PWM1_CLK]		= imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
2403-	clks[IMX_LSIO_PWM2_CLK]		= imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
2404-	clks[IMX_LSIO_PWM3_CLK]		= imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
2405-	clks[IMX_LSIO_PWM4_CLK]		= imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
2406-	clks[IMX_LSIO_PWM5_CLK]		= imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
2407-	clks[IMX_LSIO_PWM6_CLK]		= imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
2408-	clks[IMX_LSIO_PWM7_CLK]		= imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
2409-	clks[IMX_LSIO_GPT0_CLK]		= imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER);
2410-	clks[IMX_LSIO_GPT1_CLK]		= imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
2411-	clks[IMX_LSIO_GPT2_CLK]		= imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
2412-	clks[IMX_LSIO_GPT3_CLK]		= imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
2413-	clks[IMX_LSIO_GPT4_CLK]		= imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
2414-	clks[IMX_LSIO_FSPI0_CLK]	= imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
2415-	clks[IMX_LSIO_FSPI1_CLK]	= imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
2416-
2417-	/* ADMA SS */
2418-	clks[IMX_ADMA_UART0_CLK]	= imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
2419-	clks[IMX_ADMA_UART1_CLK]	= imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
2420-	clks[IMX_ADMA_UART2_CLK]	= imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
2421-	clks[IMX_ADMA_UART3_CLK]	= imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
2422-	clks[IMX_ADMA_SPI0_CLK]		= imx_clk_scu("spi0_clk",  IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
2423-	clks[IMX_ADMA_SPI1_CLK]		= imx_clk_scu("spi1_clk",  IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER);
2424-	clks[IMX_ADMA_SPI2_CLK]		= imx_clk_scu("spi2_clk",  IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
2425-	clks[IMX_ADMA_SPI3_CLK]		= imx_clk_scu("spi3_clk",  IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
2426-	clks[IMX_ADMA_CAN0_CLK]		= imx_clk_scu("can0_clk",  IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
2427-	clks[IMX_ADMA_I2C0_CLK]		= imx_clk_scu("i2c0_clk",  IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
2428-	clks[IMX_ADMA_I2C1_CLK]		= imx_clk_scu("i2c1_clk",  IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
2429-	clks[IMX_ADMA_I2C2_CLK]		= imx_clk_scu("i2c2_clk",  IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
2430-	clks[IMX_ADMA_I2C3_CLK]		= imx_clk_scu("i2c3_clk",  IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
2431-	clks[IMX_ADMA_FTM0_CLK]		= imx_clk_scu("ftm0_clk",  IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
2432-	clks[IMX_ADMA_FTM1_CLK]		= imx_clk_scu("ftm1_clk",  IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
2433-	clks[IMX_ADMA_ADC0_CLK]		= imx_clk_scu("adc0_clk",  IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
2434-	clks[IMX_ADMA_PWM_CLK]		= imx_clk_scu("pwm_clk",   IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
2435-	clks[IMX_ADMA_LCD_CLK]		= imx_clk_scu("lcd_clk",   IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
2436+	imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
2437+	imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
2438+	imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
2439+	imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
2440+	imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
2441+	imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
2442+	imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
2443+	imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
2444+	imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
2445+	imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
2446+	imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
2447+	imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
2448+	imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
2449+	imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
2450+
2451+	/* DMA SS */
2452+	imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
2453+	imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
2454+	imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
2455+	imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
2456+	imx_clk_scu("uart4_clk", IMX_SC_R_UART_4, IMX_SC_PM_CLK_PER);
2457+	imx_clk_scu("sim0_clk",  IMX_SC_R_EMVSIM_0, IMX_SC_PM_CLK_PER);
2458+	imx_clk_scu("spi0_clk",  IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
2459+	imx_clk_scu("spi1_clk",  IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER);
2460+	imx_clk_scu("spi2_clk",  IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
2461+	imx_clk_scu("spi3_clk",  IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
2462+	imx_clk_scu("can0_clk",  IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
2463+	imx_clk_scu("can1_clk",  IMX_SC_R_CAN_1, IMX_SC_PM_CLK_PER);
2464+	imx_clk_scu("can2_clk",  IMX_SC_R_CAN_2, IMX_SC_PM_CLK_PER);
2465+	imx_clk_scu("i2c0_clk",  IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
2466+	imx_clk_scu("i2c1_clk",  IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
2467+	imx_clk_scu("i2c2_clk",  IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
2468+	imx_clk_scu("i2c3_clk",  IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
2469+	imx_clk_scu("i2c4_clk",  IMX_SC_R_I2C_4, IMX_SC_PM_CLK_PER);
2470+	imx_clk_scu("ftm0_clk",  IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
2471+	imx_clk_scu("ftm1_clk",  IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
2472+	imx_clk_scu("adc0_clk",  IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
2473+	imx_clk_scu("pwm_clk",   IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
2474+	imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
2475+	imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
2476+	imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0);
2477+	imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS);
2478+
2479+
2480+	/* Audio SS */
2481+	imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL);
2482+	imx_clk_scu("audio_pll1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_PLL);
2483+	imx_clk_scu("audio_pll_div_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC0);
2484+	imx_clk_scu("audio_pll_div_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC0);
2485+	imx_clk_scu("audio_rec_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC1);
2486+	imx_clk_scu("audio_rec_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC1);
2487
2488 	/* Connectivity */
2489-	clks[IMX_CONN_SDHC0_CLK]	= imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
2490-	clks[IMX_CONN_SDHC1_CLK]	= imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
2491-	clks[IMX_CONN_SDHC2_CLK]	= imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
2492-	clks[IMX_CONN_ENET0_ROOT_CLK]	= imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
2493-	clks[IMX_CONN_ENET0_BYPASS_CLK]	= imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
2494-	clks[IMX_CONN_ENET0_RGMII_CLK]	= imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
2495-	clks[IMX_CONN_ENET1_ROOT_CLK]	= imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
2496-	clks[IMX_CONN_ENET1_BYPASS_CLK]	= imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
2497-	clks[IMX_CONN_ENET1_RGMII_CLK]	= imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
2498-	clks[IMX_CONN_GPMI_BCH_IO_CLK]	= imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
2499-	clks[IMX_CONN_GPMI_BCH_CLK]	= imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
2500-	clks[IMX_CONN_USB2_ACLK]	= imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
2501-	clks[IMX_CONN_USB2_BUS_CLK]	= imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
2502-	clks[IMX_CONN_USB2_LPM_CLK]	= imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
2503+	imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
2504+	imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
2505+	imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
2506+	if (of_id->data == &imx_clk_scu_rsrc_imx8dxl) {
2507+		imx_clk_divider_gpr_scu("enet0_ref_div", "conn_enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV);
2508+	} else {
2509+		imx_clk_scu("enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
2510+		imx_clk_divider_gpr_scu("enet0_ref_div", "enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV);
2511+	}
2512+	imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK);
2513+	imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
2514+	imx_clk_gate_gpr_scu("enet0_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_0, IMX_SC_C_DISABLE_50, true);
2515+	imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
2516+
2517+	if (of_id->data != &imx_clk_scu_rsrc_imx8dxl) {
2518+		imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
2519+		imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
2520+		imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV);
2521+		imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK);
2522+	}
2523+	imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
2524+	imx_clk_gate_gpr_scu("enet1_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_1, IMX_SC_C_DISABLE_50, true);
2525+	imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
2526+	imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
2527+	imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
2528+	imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
2529+	imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
2530
2531 	/* Display controller SS */
2532-	clks[IMX_DC0_DISP0_CLK]		= imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0);
2533-	clks[IMX_DC0_DISP1_CLK]		= imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
2534+	imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0);
2535+	imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
2536+	imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL);
2537+	imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL);
2538+	imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS);
2539+	imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS);
2540+
2541+	imx_clk_scu2("dc1_disp0_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC0);
2542+	imx_clk_scu2("dc1_disp1_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC1);
2543+	imx_clk_scu("dc1_pll0_clk", IMX_SC_R_DC_1_PLL_0, IMX_SC_PM_CLK_PLL);
2544+	imx_clk_scu("dc1_pll1_clk", IMX_SC_R_DC_1_PLL_1, IMX_SC_PM_CLK_PLL);
2545+	imx_clk_scu("dc1_bypass0_clk", IMX_SC_R_DC_1_VIDEO0, IMX_SC_PM_CLK_BYPASS);
2546+	imx_clk_scu("dc1_bypass1_clk", IMX_SC_R_DC_1_VIDEO1, IMX_SC_PM_CLK_BYPASS);
2547
2548 	/* MIPI-LVDS SS */
2549-	clks[IMX_MIPI0_I2C0_CLK]	= imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
2550-	clks[IMX_MIPI0_I2C1_CLK]	= imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
2551+	imx_clk_scu("mipi0_bypass_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_BYPASS);
2552+	imx_clk_scu("mipi0_pixel_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PER);
2553+	imx_clk_scu("lvds0_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2);
2554+	imx_clk_scu("lvds0_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS);
2555+	imx_clk_scu("lvds0_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3);
2556+	imx_clk_scu2("mipi0_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_MST_BUS);
2557+	imx_clk_scu2("mipi0_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_SLV_BUS);
2558+	imx_clk_scu2("mipi0_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PHY);
2559+	imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
2560+	imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
2561+	imx_clk_scu("mipi0_pwm_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER);
2562+
2563+	imx_clk_scu("mipi1_bypass_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_BYPASS);
2564+	imx_clk_scu("mipi1_pixel_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PER);
2565+	imx_clk_scu("lvds1_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2);
2566+	imx_clk_scu("lvds1_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS);
2567+	imx_clk_scu("lvds1_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3);
2568+	imx_clk_scu2("mipi1_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_MST_BUS);
2569+	imx_clk_scu2("mipi1_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_SLV_BUS);
2570+	imx_clk_scu2("mipi1_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PHY);
2571+	imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2);
2572+	imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2);
2573+	imx_clk_scu("mipi1_pwm_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER);
2574+
2575+	imx_clk_scu("lvds0_i2c0_clk", IMX_SC_R_LVDS_0_I2C_0, IMX_SC_PM_CLK_PER);
2576+	imx_clk_scu("lvds0_pwm0_clk", IMX_SC_R_LVDS_0_PWM_0, IMX_SC_PM_CLK_PER);
2577+
2578+	imx_clk_scu("lvds1_i2c0_clk", IMX_SC_R_LVDS_1_I2C_0, IMX_SC_PM_CLK_PER);
2579+	imx_clk_scu("lvds1_pwm0_clk", IMX_SC_R_LVDS_1_PWM_0, IMX_SC_PM_CLK_PER);
2580
2581 	/* MIPI CSI SS */
2582-	clks[IMX_CSI0_CORE_CLK]		= imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
2583-	clks[IMX_CSI0_ESC_CLK]		= imx_clk_scu("mipi_csi0_esc_clk",  IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
2584-	clks[IMX_CSI0_I2C0_CLK]		= imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
2585-	clks[IMX_CSI0_PWM0_CLK]		= imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
2586+	imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
2587+	imx_clk_scu("mipi_csi0_esc_clk",  IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
2588+	imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
2589+	imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
2590+	imx_clk_scu("mipi_csi1_core_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_PER);
2591+	imx_clk_scu("mipi_csi1_esc_clk",  IMX_SC_R_CSI_1, IMX_SC_PM_CLK_MISC);
2592+	imx_clk_scu("mipi_csi1_i2c0_clk", IMX_SC_R_CSI_1_I2C_0, IMX_SC_PM_CLK_PER);
2593+	imx_clk_scu("mipi_csi1_pwm0_clk", IMX_SC_R_CSI_1_PWM_0, IMX_SC_PM_CLK_PER);
2594+
2595+	/* Parallel Interface SS */
2596+	imx_clk_scu("pi_dpll_clk", IMX_SC_R_PI_0_PLL, IMX_SC_PM_CLK_PLL);
2597+	imx_clk_scu2("pi_per_div_clk", pll0_sels, ARRAY_SIZE(pll0_sels), IMX_SC_R_PI_0, IMX_SC_PM_CLK_PER);
2598+	imx_clk_scu("pi_mclk_div_clk", IMX_SC_R_PI_0, IMX_SC_PM_CLK_MISC0);
2599+	imx_clk_scu("pi_i2c0_div_clk", IMX_SC_R_PI_0_I2C_0, IMX_SC_PM_CLK_PER);
2600
2601 	/* GPU SS */
2602-	clks[IMX_GPU0_CORE_CLK]		= imx_clk_scu("gpu_core0_clk",	 IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
2603-	clks[IMX_GPU0_SHADER_CLK]	= imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
2604+	imx_clk_scu("gpu_core0_clk",	 IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
2605+	imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
2606
2607-	for (i = 0; i < clk_data->num; i++) {
2608-		if (IS_ERR(clks[i]))
2609-			pr_warn("i.MX clk %u: register failed with %ld\n",
2610-				i, PTR_ERR(clks[i]));
2611-	}
2612+	imx_clk_scu("gpu_core1_clk",	 IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_PER);
2613+	imx_clk_scu("gpu_shader1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_MISC);
2614+	 /* CM40 SS */
2615+	imx_clk_scu("cm40_i2c_div", IMX_SC_R_M4_0_I2C, IMX_SC_PM_CLK_PER);
2616+	imx_clk_scu("cm40_lpuart_div", IMX_SC_R_M4_0_UART, IMX_SC_PM_CLK_PER);
2617
2618-	return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
2619-}
2620+	 /* CM41 SS */
2621+	imx_clk_scu("cm41_i2c_div", IMX_SC_R_M4_1_I2C, IMX_SC_PM_CLK_PER);
2622
2623-static const struct of_device_id imx8qxp_match[] = {
2624-	{ .compatible = "fsl,scu-clk", },
2625-	{ .compatible = "fsl,imx8qxp-clk", },
2626-	{ /* sentinel */ }
2627-};
2628+	/* HDMI TX SS */
2629+	imx_clk_scu("hdmi_dig_pll_clk",  IMX_SC_R_HDMI_PLL_0, IMX_SC_PM_CLK_PLL);
2630+	imx_clk_scu("hdmi_av_pll_clk", IMX_SC_R_HDMI_PLL_1, IMX_SC_PM_CLK_PLL);
2631+	imx_clk_scu2("hdmi_pixel_mux_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC0);
2632+	imx_clk_scu2("hdmi_pixel_link_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC1);
2633+	imx_clk_scu("hdmi_ipg_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC4);
2634+	imx_clk_scu("hdmi_i2c0_clk", IMX_SC_R_HDMI_I2C_0, IMX_SC_PM_CLK_MISC2);
2635+	imx_clk_scu("hdmi_hdp_core_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC2);
2636+	imx_clk_scu2("hdmi_pxl_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC3);
2637+	imx_clk_scu("hdmi_i2s_bypass_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_BYPASS);
2638+	imx_clk_scu("hdmi_i2s_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_MISC0);
2639+
2640+	/* HDMI RX SS */
2641+	imx_clk_scu("hdmi_rx_i2s_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC0);
2642+	imx_clk_scu("hdmi_rx_spdif_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC1);
2643+	imx_clk_scu("hdmi_rx_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC2);
2644+	imx_clk_scu("hdmi_rx_i2c0_clk", IMX_SC_R_HDMI_RX_I2C_0, IMX_SC_PM_CLK_MISC2);
2645+	imx_clk_scu("hdmi_rx_pwm_clk", IMX_SC_R_HDMI_RX_PWM_0, IMX_SC_PM_CLK_MISC2);
2646+	imx_clk_scu("hdmi_rx_spdif_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC0);
2647+	imx_clk_scu2("hdmi_rx_hd_ref_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC1);
2648+	imx_clk_scu2("hdmi_rx_hd_core_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC2);
2649+	imx_clk_scu2("hdmi_rx_pxl_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC3);
2650+	imx_clk_scu("hdmi_rx_i2s_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC4);
2651+
2652+	return of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks);
2653+}
2654
2655 static struct platform_driver imx8qxp_clk_driver = {
2656 	.driver = {
2657@@ -151,7 +307,12 @@ static struct platform_driver imx8qxp_clk_driver = {
2658 	},
2659 	.probe = imx8qxp_clk_probe,
2660 };
2661-module_platform_driver(imx8qxp_clk_driver);
2662+
2663+static int __init imx8qxp_clk_driver_init(void)
2664+{
2665+	return platform_driver_register(&imx8qxp_clk_driver);
2666+}
2667+subsys_initcall_sync(imx8qxp_clk_driver_init);
2668
2669 MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>");
2670 MODULE_DESCRIPTION("NXP i.MX8QXP clock driver");
2671diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
2672index 1f0e44f92..a2a78a3df 100644
2673--- a/drivers/clk/imx/clk-lpcg-scu.c
2674+++ b/drivers/clk/imx/clk-lpcg-scu.c
2675@@ -6,6 +6,7 @@
2676
2677 #include <linux/bits.h>
2678 #include <linux/clk-provider.h>
2679+#include <linux/delay.h>
2680 #include <linux/err.h>
2681 #include <linux/io.h>
2682 #include <linux/slab.h>
2683@@ -34,10 +35,38 @@ struct clk_lpcg_scu {
2684 	void __iomem *reg;
2685 	u8 bit_idx;
2686 	bool hw_gate;
2687+
2688+	/* for state save&restore */
2689+	u32 state;
2690 };
2691
2692 #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
2693
2694+/* e10858 -LPCG clock gating register synchronization errata */
2695+static void do_lpcg_workaround(u32 rate, void __iomem *reg, u32 val)
2696+{
2697+	writel(val, reg);
2698+
2699+	if (rate >= 24000000 || rate == 0) {
2700+		u32 reg1;
2701+
2702+		/*
2703+		 * The time taken to access the LPCG registers from the AP core
2704+		 * through the interconnect is longer than the minimum delay
2705+		 * of 4 clock cycles required by the errata.
2706+		 * Adding a readl will provide sufficient delay to prevent
2707+		 * back-to-back writes.
2708+		 */
2709+		reg1 = readl(reg);
2710+	} else {
2711+		/*
2712+		 * For clocks running below 24MHz, wait a minimum of
2713+		 * 4 clock cycles.
2714+		 */
2715+		ndelay(4 * (DIV_ROUND_UP(1000000000, rate)));
2716+	}
2717+}
2718+
2719 static int clk_lpcg_scu_enable(struct clk_hw *hw)
2720 {
2721 	struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
2722@@ -54,7 +83,8 @@ static int clk_lpcg_scu_enable(struct clk_hw *hw)
2723 		val |= CLK_GATE_SCU_LPCG_HW_SEL;
2724
2725 	reg |= val << clk->bit_idx;
2726-	writel(reg, clk->reg);
2727+
2728+	do_lpcg_workaround(clk_hw_get_rate(hw), clk->reg, reg);
2729
2730 	spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
2731
2732@@ -71,7 +101,7 @@ static void clk_lpcg_scu_disable(struct clk_hw *hw)
2733
2734 	reg = readl_relaxed(clk->reg);
2735 	reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
2736-	writel(reg, clk->reg);
2737+	do_lpcg_workaround(clk_hw_get_rate(hw), clk->reg, reg);
2738
2739 	spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
2740 }
2741@@ -81,9 +111,9 @@ static const struct clk_ops clk_lpcg_scu_ops = {
2742 	.disable = clk_lpcg_scu_disable,
2743 };
2744
2745-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
2746-				unsigned long flags, void __iomem *reg,
2747-				u8 bit_idx, bool hw_gate)
2748+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
2749+				  const char *parent_name, unsigned long flags,
2750+				  void __iomem *reg, u8 bit_idx, bool hw_gate)
2751 {
2752 	struct clk_lpcg_scu *clk;
2753 	struct clk_init_data init;
2754@@ -107,11 +137,47 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
2755 	clk->hw.init = &init;
2756
2757 	hw = &clk->hw;
2758-	ret = clk_hw_register(NULL, hw);
2759+	ret = clk_hw_register(dev, hw);
2760 	if (ret) {
2761 		kfree(clk);
2762-		hw = ERR_PTR(ret);
2763+		return ERR_PTR(ret);
2764 	}
2765
2766+	if (dev)
2767+		dev_set_drvdata(dev, clk);
2768+
2769 	return hw;
2770 }
2771+
2772+int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev)
2773+{
2774+	struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
2775+
2776+	if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg")))
2777+		return 0;
2778+
2779+	clk->state = readl_relaxed(clk->reg);
2780+	dev_dbg(dev, "save lpcg state 0x%x\n", clk->state);
2781+
2782+	return 0;
2783+}
2784+
2785+int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
2786+{
2787+	struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
2788+
2789+	if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg")))
2790+		return 0;
2791+
2792+	/* FIXME: double write in case a failure */
2793+	writel(clk->state, clk->reg);
2794+	do_lpcg_workaround(0, clk->reg, clk->state);
2795+	dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
2796+
2797+	return 0;
2798+}
2799+
2800+const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = {
2801+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend,
2802+				      imx_clk_lpcg_scu_resume)
2803+};
2804diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c
2805index 5d2a9a3be..6c39b8c5a 100644
2806--- a/drivers/clk/imx/clk-pfd.c
2807+++ b/drivers/clk/imx/clk-pfd.c
2808@@ -5,9 +5,11 @@
2809  */
2810
2811 #include <linux/clk-provider.h>
2812+#include <linux/imx_sema4.h>
2813 #include <linux/io.h>
2814 #include <linux/slab.h>
2815 #include <linux/err.h>
2816+#include <soc/imx/src.h>
2817 #include "clk.h"
2818
2819 /**
2820@@ -32,20 +34,57 @@ struct clk_pfd {
2821 #define CLR	0x8
2822 #define OTG	0xc
2823
2824-static int clk_pfd_enable(struct clk_hw *hw)
2825+static void clk_pfd_do_hardware(struct clk_pfd *pfd, bool enable)
2826+{
2827+	if (enable)
2828+		writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR);
2829+	else
2830+		writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET);
2831+}
2832+
2833+static void clk_pfd_do_shared_clks(struct clk_hw *hw, bool enable)
2834 {
2835 	struct clk_pfd *pfd = to_clk_pfd(hw);
2836
2837-	writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR);
2838+	if (imx_src_is_m4_enabled() && clk_on_imx6sx()) {
2839+#ifdef CONFIG_SOC_IMX6SX
2840+		if (!amp_power_mutex || !shared_mem) {
2841+			if (enable)
2842+				clk_pfd_do_hardware(pfd, enable);
2843+			return;
2844+		}
2845+
2846+		imx_sema4_mutex_lock(amp_power_mutex);
2847+		if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
2848+			shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
2849+			imx_sema4_mutex_unlock(amp_power_mutex);
2850+			return;
2851+		}
2852+
2853+		if (!imx_update_shared_mem(hw, enable)) {
2854+			imx_sema4_mutex_unlock(amp_power_mutex);
2855+			return;
2856+		}
2857+
2858+		clk_pfd_do_hardware(pfd, enable);
2859+
2860+		imx_sema4_mutex_unlock(amp_power_mutex);
2861+#endif
2862+	} else {
2863+		clk_pfd_do_hardware(pfd, enable);
2864+	}
2865+}
2866+
2867+static int clk_pfd_enable(struct clk_hw *hw)
2868+{
2869+	clk_pfd_do_shared_clks(hw, true);
2870
2871 	return 0;
2872 }
2873
2874 static void clk_pfd_disable(struct clk_hw *hw)
2875 {
2876-	struct clk_pfd *pfd = to_clk_pfd(hw);
2877-
2878-	writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET);
2879+	clk_pfd_do_shared_clks(hw, false);
2880 }
2881
2882 static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
2883diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c
2884index 6b744c842..42505669c 100644
2885--- a/drivers/clk/imx/clk-pfdv2.c
2886+++ b/drivers/clk/imx/clk-pfdv2.c
2887@@ -161,8 +161,17 @@ static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate,
2888 	if (!rate)
2889 		return -EINVAL;
2890
2891-	/* PFD can NOT change rate without gating */
2892-	WARN_ON(clk_pfdv2_is_enabled(hw));
2893+	/*
2894+	 * PFD can NOT change rate without gating.
2895+	 * as the PFDs may enabled in HW by default but no
2896+	 * consumer used it, the enable count is '0', so the
2897+	 * 'SET_RATE_GATE' can NOT help on blocking the set_rate
2898+	 * ops especially for 'assigned-clock-xxx'. In order
2899+	 * to simplify the case, just disable the PFD if it is
2900+	 * enabled in HW but not in SW.
2901+	 */
2902+	if (clk_pfdv2_is_enabled(hw))
2903+		clk_pfdv2_disable(hw);
2904
2905 	tmp = tmp * 18 + rate / 2;
2906 	do_div(tmp, rate);
2907@@ -191,8 +200,8 @@ static const struct clk_ops clk_pfdv2_ops = {
2908 	.is_enabled     = clk_pfdv2_is_enabled,
2909 };
2910
2911-struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name,
2912-			     void __iomem *reg, u8 idx)
2913+struct clk_hw *imx_clk_hw_pfdv2(enum imx_pfdv2_type type, const char *name,
2914+			     const char *parent_name, void __iomem *reg, u8 idx)
2915 {
2916 	struct clk_init_data init;
2917 	struct clk_pfdv2 *pfd;
2918@@ -214,7 +223,10 @@ struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name,
2919 	init.ops = &clk_pfdv2_ops;
2920 	init.parent_names = &parent_name;
2921 	init.num_parents = 1;
2922-	init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
2923+	if (type == IMX_PFDV2_IMX7ULP)
2924+		init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
2925+	else
2926+		init.flags = CLK_SET_RATE_GATE;
2927
2928 	pfd->hw.init = &init;
2929
2930diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
2931index aba36e421..f7cfc5fea 100644
2932--- a/drivers/clk/imx/clk-pll14xx.c
2933+++ b/drivers/clk/imx/clk-pll14xx.c
2934@@ -137,9 +137,12 @@ static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
2935 						  unsigned long parent_rate)
2936 {
2937 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
2938+	const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
2939 	u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
2940 	short int kdiv;
2941 	u64 fvco = parent_rate;
2942+	long rate = 0;
2943+	int i;
2944
2945 	pll_div_ctl0 = readl_relaxed(pll->base + 4);
2946 	pll_div_ctl1 = readl_relaxed(pll->base + 8);
2947@@ -148,13 +151,25 @@ static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
2948 	sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
2949 	kdiv = pll_div_ctl1 & KDIV_MASK;
2950
2951+	/*
2952+	 * Sometimes, the recalculated rate has deviation due to
2953+	 * the frac part. So find the accurate pll rate from the table
2954+	 * first, if no match rate in the table, use the rate calculated
2955+	 * from the equation below.
2956+	 */
2957+	for (i = 0; i < pll->rate_count; i++) {
2958+		if (rate_table[i].pdiv == pdiv && rate_table[i].mdiv == mdiv &&
2959+		    rate_table[i].sdiv == sdiv && rate_table[i].kdiv == kdiv)
2960+			rate = rate_table[i].rate;
2961+	}
2962+
2963 	/* fvco = (m * 65536 + k) * Fin / (p * 65536) */
2964 	fvco *= (mdiv * 65536 + kdiv);
2965 	pdiv *= 65536;
2966
2967 	do_div(fvco, pdiv << sdiv);
2968
2969-	return fvco;
2970+	return rate ? (unsigned long) rate : (unsigned long)fvco;
2971 }
2972
2973 static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *rate,
2974@@ -360,6 +375,26 @@ static void clk_pll14xx_unprepare(struct clk_hw *hw)
2975 	writel_relaxed(val, pll->base + GNRL_CTL);
2976 }
2977
2978+void clk_set_delta_k(struct clk_hw *hw, short int delta_k)
2979+{
2980+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
2981+	short int k;
2982+	u32 val;
2983+
2984+	val = readl_relaxed(pll->base + 8);
2985+	k = (val & KDIV_MASK) + delta_k;
2986+	writel_relaxed(k << KDIV_SHIFT, pll->base + 8);
2987+}
2988+
2989+void clk_get_pll_setting(struct clk_hw *hw, u32 *pll_div_ctrl0,
2990+	u32 *pll_div_ctrl1)
2991+{
2992+	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
2993+
2994+	*pll_div_ctrl0 = readl_relaxed(pll->base + 4);
2995+	*pll_div_ctrl1 = readl_relaxed(pll->base + 8);
2996+}
2997+
2998 static const struct clk_ops clk_pll1416x_ops = {
2999 	.prepare	= clk_pll14xx_prepare,
3000 	.unprepare	= clk_pll14xx_unprepare,
3001diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
3002index 20ee9611b..5fd4765e6 100644
3003--- a/drivers/clk/imx/clk-pllv3.c
3004+++ b/drivers/clk/imx/clk-pllv3.c
3005@@ -8,9 +8,11 @@
3006 #include <linux/delay.h>
3007 #include <linux/io.h>
3008 #include <linux/iopoll.h>
3009+#include <linux/imx_sema4.h>
3010 #include <linux/slab.h>
3011 #include <linux/jiffies.h>
3012 #include <linux/err.h>
3013+#include <soc/imx/src.h>
3014 #include "clk.h"
3015
3016 #define PLL_NUM_OFFSET		0x10
3017@@ -65,36 +67,82 @@ static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
3018 	if ((pll->powerup_set && !val) || (!pll->powerup_set && val))
3019 		return 0;
3020
3021-	return readl_relaxed_poll_timeout(pll->base, val, val & BM_PLL_LOCK,
3022-					  500, PLL_LOCK_TIMEOUT);
3023+	if (!(imx_src_is_m4_enabled() && clk_on_imx6sx()))
3024+		return readl_relaxed_poll_timeout(pll->base, val, val & BM_PLL_LOCK,
3025+						  500, PLL_LOCK_TIMEOUT);
3026+	else
3027+		return readl_relaxed_poll_timeout_atomic(pll->base, val, val & BM_PLL_LOCK,
3028+						  10, PLL_LOCK_TIMEOUT);
3029 }
3030
3031-static int clk_pllv3_prepare(struct clk_hw *hw)
3032+static int clk_pllv3_do_hardware(struct clk_hw *hw, bool enable)
3033 {
3034 	struct clk_pllv3 *pll = to_clk_pllv3(hw);
3035+	int ret;
3036 	u32 val;
3037
3038 	val = readl_relaxed(pll->base);
3039-	if (pll->powerup_set)
3040-		val |= pll->power_bit;
3041-	else
3042-		val &= ~pll->power_bit;
3043-	writel_relaxed(val, pll->base);
3044+	if (enable) {
3045+		if (pll->powerup_set)
3046+			val |= pll->power_bit;
3047+		else
3048+			val &= ~pll->power_bit;
3049+		writel_relaxed(val, pll->base);
3050+
3051+		ret = clk_pllv3_wait_lock(pll);
3052+		if (ret)
3053+			return ret;
3054+	} else {
3055+		if (pll->powerup_set)
3056+			val &= ~pll->power_bit;
3057+		else
3058+			val |= pll->power_bit;
3059+		writel_relaxed(val, pll->base);
3060+	}
3061
3062-	return clk_pllv3_wait_lock(pll);
3063+	return 0;
3064 }
3065
3066-static void clk_pllv3_unprepare(struct clk_hw *hw)
3067+static void clk_pllv3_do_shared_clks(struct clk_hw *hw, bool enable)
3068 {
3069-	struct clk_pllv3 *pll = to_clk_pllv3(hw);
3070-	u32 val;
3071+	if (imx_src_is_m4_enabled() && clk_on_imx6sx()) {
3072+#ifdef CONFIG_SOC_IMX6SX
3073+		if (!amp_power_mutex || !shared_mem) {
3074+			if (enable)
3075+				clk_pllv3_do_hardware(hw, enable);
3076+			return;
3077+		}
3078+
3079+		imx_sema4_mutex_lock(amp_power_mutex);
3080+		if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
3081+			shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
3082+			imx_sema4_mutex_unlock(amp_power_mutex);
3083+			return;
3084+		}
3085+
3086+		if (!imx_update_shared_mem(hw, enable)) {
3087+			imx_sema4_mutex_unlock(amp_power_mutex);
3088+			return;
3089+		}
3090+		clk_pllv3_do_hardware(hw, enable);
3091+
3092+		imx_sema4_mutex_unlock(amp_power_mutex);
3093+#endif
3094+	} else {
3095+		clk_pllv3_do_hardware(hw, enable);
3096+	}
3097+}
3098
3099-	val = readl_relaxed(pll->base);
3100-	if (pll->powerup_set)
3101-		val &= ~pll->power_bit;
3102-	else
3103-		val |= pll->power_bit;
3104-	writel_relaxed(val, pll->base);
3105+static int clk_pllv3_prepare(struct clk_hw *hw)
3106+{
3107+	clk_pllv3_do_shared_clks(hw, true);
3108+
3109+	return 0;
3110+}
3111+
3112+static void clk_pllv3_unprepare(struct clk_hw *hw)
3113+{
3114+	clk_pllv3_do_shared_clks(hw, false);
3115 }
3116
3117 static int clk_pllv3_is_prepared(struct clk_hw *hw)
3118diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c
3119index 8ec703f27..3c750ccbe 100644
3120--- a/drivers/clk/imx/clk-pllv4.c
3121+++ b/drivers/clk/imx/clk-pllv4.c
3122@@ -23,14 +23,17 @@
3123
3124 /* PLL Configuration Register (xPLLCFG) */
3125 #define PLL_CFG_OFFSET		0x08
3126+#define IMX8ULP_PLL_CFG_OFFSET	0x10
3127 #define BP_PLL_MULT		16
3128 #define BM_PLL_MULT		(0x7f << 16)
3129
3130 /* PLL Numerator Register (xPLLNUM) */
3131 #define PLL_NUM_OFFSET		0x10
3132+#define IMX8ULP_PLL_NUM_OFFSET	0x1c
3133
3134 /* PLL Denominator Register (xPLLDENOM) */
3135 #define PLL_DENOM_OFFSET	0x14
3136+#define IMX8ULP_PLL_DENOM_OFFSET	0x18
3137
3138 #define MAX_MFD			0x3fffffff
3139 #define DEFAULT_MFD		1000000
3140@@ -38,6 +41,9 @@
3141 struct clk_pllv4 {
3142 	struct clk_hw	hw;
3143 	void __iomem	*base;
3144+	u32		cfg_offset;
3145+	u32		num_offset;
3146+	u32		denom_offset;
3147 };
3148
3149 /* Valid PLL MULT Table */
3150@@ -72,12 +78,12 @@ static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw,
3151 	u32 mult, mfn, mfd;
3152 	u64 temp64;
3153
3154-	mult = readl_relaxed(pll->base + PLL_CFG_OFFSET);
3155+	mult = readl_relaxed(pll->base + pll->cfg_offset);
3156 	mult &= BM_PLL_MULT;
3157 	mult >>= BP_PLL_MULT;
3158
3159-	mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
3160-	mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
3161+	mfn = readl_relaxed(pll->base + pll->num_offset);
3162+	mfd = readl_relaxed(pll->base + pll->denom_offset);
3163 	temp64 = parent_rate;
3164 	temp64 *= mfn;
3165 	do_div(temp64, mfd);
3166@@ -165,13 +171,13 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate,
3167 	do_div(temp64, parent_rate);
3168 	mfn = temp64;
3169
3170-	val = readl_relaxed(pll->base + PLL_CFG_OFFSET);
3171+	val = readl_relaxed(pll->base + pll->cfg_offset);
3172 	val &= ~BM_PLL_MULT;
3173 	val |= mult << BP_PLL_MULT;
3174-	writel_relaxed(val, pll->base + PLL_CFG_OFFSET);
3175+	writel_relaxed(val, pll->base + pll->cfg_offset);
3176
3177-	writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
3178-	writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
3179+	writel_relaxed(mfn, pll->base + pll->num_offset);
3180+	writel_relaxed(mfd, pll->base + pll->denom_offset);
3181
3182 	return 0;
3183 }
3184@@ -207,8 +213,8 @@ static const struct clk_ops clk_pllv4_ops = {
3185 	.is_prepared	= clk_pllv4_is_prepared,
3186 };
3187
3188-struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
3189-			  void __iomem *base)
3190+struct clk_hw *imx_clk_hw_pllv4(enum imx_pllv4_type type, const char *name,
3191+		 const char *parent_name, void __iomem *base)
3192 {
3193 	struct clk_pllv4 *pll;
3194 	struct clk_hw *hw;
3195@@ -221,6 +227,16 @@ struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
3196
3197 	pll->base = base;
3198
3199+	if (type == IMX_PLLV4_IMX8ULP) {
3200+		pll->cfg_offset = IMX8ULP_PLL_CFG_OFFSET;
3201+		pll->num_offset = IMX8ULP_PLL_NUM_OFFSET;
3202+		pll->denom_offset = IMX8ULP_PLL_DENOM_OFFSET;
3203+	} else {
3204+		pll->cfg_offset = PLL_CFG_OFFSET;
3205+		pll->num_offset = PLL_NUM_OFFSET;
3206+		pll->denom_offset = PLL_DENOM_OFFSET;
3207+	}
3208+
3209 	init.name = name;
3210 	init.ops = &clk_pllv4_ops;
3211 	init.parent_names = &parent_name;
3212diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
3213index b8b207274..bd71f24f8 100644
3214--- a/drivers/clk/imx/clk-scu.c
3215+++ b/drivers/clk/imx/clk-scu.c
3216@@ -6,16 +6,41 @@
3217
3218 #include <dt-bindings/firmware/imx/rsrc.h>
3219 #include <linux/arm-smccc.h>
3220+#include <linux/bsearch.h>
3221 #include <linux/clk-provider.h>
3222 #include <linux/err.h>
3223+#include <linux/firmware/imx/svc/rm.h>
3224+#include <linux/of_platform.h>
3225+#include <linux/platform_device.h>
3226+#include <linux/pm_domain.h>
3227+#include <linux/pm_runtime.h>
3228 #include <linux/slab.h>
3229+#include <linux/syscalls.h>
3230+#include <xen/xen.h>
3231
3232 #include "clk-scu.h"
3233
3234 #define IMX_SIP_CPUFREQ			0xC2000001
3235 #define IMX_SIP_SET_CPUFREQ		0x00
3236+#define MAX_CLUSTER_NUM			2
3237
3238 static struct imx_sc_ipc *ccm_ipc_handle;
3239+static const struct imx_clk_scu_rsrc_table *rsrc_table;
3240+struct device_node *pd_np;
3241+u32 clock_cells;
3242+
3243+struct imx_scu_clk_node {
3244+	const char *name;
3245+	u32 rsrc;
3246+	u8 clk_type;
3247+	const char * const *parents;
3248+	int num_parents;
3249+
3250+	struct clk_hw *hw;
3251+	struct list_head node;
3252+};
3253+
3254+struct list_head imx_scu_clks[IMX_SC_R_LAST];
3255
3256 /*
3257  * struct clk_scu - Description of one SCU clock
3258@@ -27,6 +52,26 @@ struct clk_scu {
3259 	struct clk_hw hw;
3260 	u16 rsrc_id;
3261 	u8 clk_type;
3262+
3263+	/* for state save&restore */
3264+	struct clk_hw *parent;
3265+	u8 parent_index;
3266+	bool is_enabled;
3267+	u32 rate;
3268+};
3269+
3270+/*
3271+ * struct clk_gpr_scu - Description of one gate SCU clock
3272+ * @hw: the common clk_hw
3273+ * @rsrc_id: resource ID of this SCU clock
3274+ * @gpr_id: GPR ID index to control the divider
3275+ */
3276+struct clk_gpr_scu {
3277+	struct clk_hw hw;
3278+	u16 rsrc_id;
3279+	u8 gpr_id;
3280+	u8 flags;
3281+	bool gate_invert;
3282 };
3283
3284 /*
3285@@ -54,6 +99,9 @@ struct resp_get_clock_rate {
3286 	__le32 rate;
3287 };
3288
3289+#define to_clk_mux_gpr_scu(_hw) container_of(_hw, struct clk_mux_gpr_scu, hw)
3290+#define to_clk_gpr_scu(_hw) container_of(_hw, struct clk_gpr_scu, hw)
3291+
3292 /*
3293  * struct imx_sc_msg_get_clock_rate - clock get rate protocol
3294  * @hdr: SCU protocol header
3295@@ -128,9 +176,48 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
3296 	return container_of(hw, struct clk_scu, hw);
3297 }
3298
3299-int imx_clk_scu_init(void)
3300+static int imx_scu_clk_search_cmp(const void *rsrc, const void *rsrc_p)
3301 {
3302-	return imx_scu_get_handle(&ccm_ipc_handle);
3303+	return *(u32 *)rsrc - *(u32 *)rsrc_p;
3304+}
3305+
3306+bool imx_scu_clk_is_valid(u32 rsrc_id)
3307+{
3308+	void *p;
3309+
3310+	if (!rsrc_table)
3311+		return true;
3312+
3313+        p = bsearch(&rsrc_id, rsrc_table->rsrc, rsrc_table->num,
3314+		    sizeof(rsrc_table->rsrc[0]), imx_scu_clk_search_cmp);
3315+	return p != NULL;
3316+}
3317+
3318+int imx_clk_scu_init(struct device_node *np, const void *data)
3319+{
3320+	struct platform_device *pd_dev;
3321+	int ret, i;
3322+
3323+	ret = imx_scu_get_handle(&ccm_ipc_handle);
3324+	if (ret)
3325+		return ret;
3326+
3327+	if (of_property_read_u32(np, "#clock-cells", &clock_cells))
3328+		return -EINVAL;
3329+
3330+	if (clock_cells == 2) {
3331+		for (i = 0; i < IMX_SC_R_LAST; i++)
3332+			INIT_LIST_HEAD(&imx_scu_clks[i]);
3333+
3334+		pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd");
3335+		pd_dev = of_find_device_by_node(pd_np);
3336+		if (!pd_dev || !device_is_bound(&pd_dev->dev))
3337+			return -EPROBE_DEFER;
3338+
3339+		rsrc_table = data;
3340+	}
3341+
3342+	return 0;
3343 }
3344
3345 /*
3346@@ -192,8 +279,10 @@ static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate,
3347 	struct arm_smccc_res res;
3348 	unsigned long cluster_id;
3349
3350-	if (clk->rsrc_id == IMX_SC_R_A35)
3351+	if (clk->rsrc_id == IMX_SC_R_A35 || clk->rsrc_id == IMX_SC_R_A53)
3352 		cluster_id = 0;
3353+	else if (clk->rsrc_id == IMX_SC_R_A72)
3354+		cluster_id = 1;
3355 	else
3356 		return -EINVAL;
3357
3358@@ -254,6 +343,8 @@ static u8 clk_scu_get_parent(struct clk_hw *hw)
3359 		return 0;
3360 	}
3361
3362+	clk->parent_index = msg.data.resp.parent;
3363+
3364 	return msg.data.resp.parent;
3365 }
3366
3367@@ -262,6 +353,7 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index)
3368 	struct clk_scu *clk = to_clk_scu(hw);
3369 	struct imx_sc_msg_set_clock_parent msg;
3370 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
3371+	int ret;
3372
3373 	hdr->ver = IMX_SC_RPC_VERSION;
3374 	hdr->svc = IMX_SC_RPC_SVC_PM;
3375@@ -272,7 +364,16 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index)
3376 	msg.clk = clk->clk_type;
3377 	msg.parent = index;
3378
3379-	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
3380+	ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
3381+	if (ret) {
3382+		pr_err("%s: failed to set clock parent %d\n",
3383+		       clk_hw_get_name(hw), ret);
3384+		return ret;
3385+	}
3386+
3387+	clk->parent_index = index;
3388+
3389+	return 0;
3390 }
3391
3392 static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource,
3393@@ -344,8 +445,15 @@ static const struct clk_ops clk_scu_cpu_ops = {
3394 	.unprepare = clk_scu_unprepare,
3395 };
3396
3397-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
3398-			     int num_parents, u32 rsrc_id, u8 clk_type)
3399+static const struct clk_ops clk_scu_pi_ops = {
3400+	.recalc_rate = clk_scu_recalc_rate,
3401+	.round_rate  = clk_scu_round_rate,
3402+	.set_rate    = clk_scu_set_rate,
3403+};
3404+
3405+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
3406+			     const char * const *parents, int num_parents,
3407+			     u32 rsrc_id, u8 clk_type)
3408 {
3409 	struct clk_init_data init;
3410 	struct clk_scu *clk;
3411@@ -361,8 +469,10 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
3412
3413 	init.name = name;
3414 	init.ops = &clk_scu_ops;
3415-	if (rsrc_id == IMX_SC_R_A35)
3416+	if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 || rsrc_id == IMX_SC_R_A72)
3417 		init.ops = &clk_scu_cpu_ops;
3418+	else if (rsrc_id == IMX_SC_R_PI_0_PLL)
3419+		init.ops = &clk_scu_pi_ops;
3420 	else
3421 		init.ops = &clk_scu_ops;
3422 	init.parent_names = parents;
3423@@ -375,14 +485,429 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
3424 	 * clock status from HW instead of using the possible invalid
3425 	 * cached rate.
3426 	 */
3427-	init.flags = CLK_GET_RATE_NOCACHE;
3428+	init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_PARENT_NOCACHE;
3429+	clk->hw.init = &init;
3430+
3431+	hw = &clk->hw;
3432+	ret = clk_hw_register(dev, hw);
3433+	if (ret) {
3434+		kfree(clk);
3435+		return ERR_PTR(ret);
3436+	}
3437+
3438+	if (dev)
3439+		dev_set_drvdata(dev, clk);
3440+
3441+	return hw;
3442+}
3443+
3444+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
3445+				      void *data)
3446+{
3447+	unsigned int rsrc = clkspec->args[0];
3448+	unsigned int idx = clkspec->args[1];
3449+	struct list_head *scu_clks = data;
3450+	struct imx_scu_clk_node *clk;
3451+
3452+	list_for_each_entry(clk, &scu_clks[rsrc], node) {
3453+		if (clk->clk_type == idx)
3454+			return clk->hw;
3455+	}
3456+
3457+	return ERR_PTR(-ENODEV);
3458+}
3459+
3460+static int imx_clk_scu_probe(struct platform_device *pdev)
3461+{
3462+	struct device *dev = &pdev->dev;
3463+	struct imx_scu_clk_node *clk = dev_get_platdata(dev);
3464+	struct clk_hw *hw;
3465+	int ret;
3466+
3467+       if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) ||
3468+           (clk->rsrc == IMX_SC_R_A72))) {
3469+		pm_runtime_set_suspended(dev);
3470+		pm_runtime_set_autosuspend_delay(dev, 50);
3471+		pm_runtime_use_autosuspend(&pdev->dev);
3472+		pm_runtime_enable(dev);
3473+
3474+		ret = pm_runtime_get_sync(dev);
3475+		if (ret) {
3476+			pm_genpd_remove_device(dev);
3477+			pm_runtime_disable(dev);
3478+			return ret;
3479+		}
3480+	}
3481+
3482+	hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents,
3483+			   clk->rsrc, clk->clk_type);
3484+	if (IS_ERR(hw)) {
3485+		pm_runtime_disable(dev);
3486+		return PTR_ERR(hw);
3487+	}
3488+
3489+	clk->hw = hw;
3490+	list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]);
3491+
3492+       if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) ||
3493+           (clk->rsrc == IMX_SC_R_A72))) {
3494+		pm_runtime_mark_last_busy(&pdev->dev);
3495+		pm_runtime_put_autosuspend(&pdev->dev);
3496+	}
3497+
3498+	dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc,
3499+		clk->clk_type);
3500+
3501+	return 0;
3502+}
3503+
3504+int __maybe_unused imx_clk_scu_suspend(struct device *dev)
3505+{
3506+	struct clk_scu *clk = dev_get_drvdata(dev);
3507+	u32 rsrc_id = clk->rsrc_id;
3508+
3509+	if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) ||
3510+	    (rsrc_id == IMX_SC_R_A72))
3511+		return 0;
3512+
3513+	clk->parent = clk_hw_get_parent(&clk->hw);
3514+
3515+	/* DC SS needs to handle bypass clock using non-cached clock rate */
3516+	if (clk->rsrc_id == IMX_SC_R_DC_0_VIDEO0 ||
3517+		clk->rsrc_id == IMX_SC_R_DC_0_VIDEO1 ||
3518+		clk->rsrc_id == IMX_SC_R_DC_1_VIDEO0 ||
3519+		clk->rsrc_id == IMX_SC_R_DC_1_VIDEO1)
3520+		clk->rate = clk_scu_recalc_rate(&clk->hw, 0);
3521+	else
3522+		clk->rate = clk_hw_get_rate(&clk->hw);
3523+
3524+	clk->is_enabled = clk_hw_is_enabled(&clk->hw);
3525+
3526+	if (clk->parent)
3527+		dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent),
3528+			clk->parent_index);
3529+
3530+	if (clk->rate)
3531+		dev_dbg(dev, "save rate %d\n", clk->rate);
3532+
3533+	if (clk->is_enabled)
3534+		dev_dbg(dev, "save enabled state\n");
3535+
3536+	return 0;
3537+}
3538+
3539+int __maybe_unused imx_clk_scu_resume(struct device *dev)
3540+{
3541+	struct clk_scu *clk = dev_get_drvdata(dev);
3542+	u32 rsrc_id = clk->rsrc_id;
3543+	int ret = 0;
3544+
3545+	if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) ||
3546+	    (rsrc_id == IMX_SC_R_A72))
3547+		return 0;
3548+
3549+	if (clk->parent) {
3550+		ret = clk_scu_set_parent(&clk->hw, clk->parent_index);
3551+		dev_dbg(dev, "restore parent %s idx %u %s\n",
3552+			clk_hw_get_name(clk->parent),
3553+			clk->parent_index, !ret ? "success" : "failed");
3554+	}
3555+
3556+	if (clk->rate) {
3557+		ret = clk_scu_set_rate(&clk->hw, clk->rate, 0);
3558+		dev_dbg(dev, "restore rate %d %s\n", clk->rate,
3559+			!ret ? "success" : "failed");
3560+	}
3561+
3562+	if (clk->is_enabled && rsrc_id != IMX_SC_R_PI_0_PLL) {
3563+		ret = clk_scu_prepare(&clk->hw);
3564+		dev_dbg(dev, "restore enabled state %s\n",
3565+			!ret ? "success" : "failed");
3566+	}
3567+
3568+	return ret;
3569+}
3570+
3571+const struct dev_pm_ops imx_clk_scu_pm_ops = {
3572+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend,
3573+				      imx_clk_scu_resume)
3574+};
3575+
3576+static struct platform_driver imx_clk_scu_driver = {
3577+	.driver = {
3578+		.name = "imx-scu-clk",
3579+		.suppress_bind_attrs = true,
3580+		.pm = &imx_clk_scu_pm_ops,
3581+	},
3582+	.probe = imx_clk_scu_probe,
3583+};
3584+
3585+static int __init imx_clk_scu_driver_init(void)
3586+{
3587+	return platform_driver_register(&imx_clk_scu_driver);
3588+}
3589+subsys_initcall_sync(imx_clk_scu_driver_init);
3590+
3591+static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
3592+{
3593+	struct of_phandle_args genpdspec = {
3594+		.np = pd_np,
3595+		.args_count = 1,
3596+		.args[0] = rsrc_id,
3597+	};
3598+
3599+	if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) ||
3600+	    (rsrc_id == IMX_SC_R_A72))
3601+		return 0;
3602+
3603+	/*
3604+	 * Temp fix to avoid the uart clk attached pd power off uart_0
3605+	 */
3606+	if (rsrc_id == IMX_SC_R_UART_0 && xen_initial_domain())
3607+			return 0;
3608+
3609+	return of_genpd_add_device(&genpdspec, dev);
3610+}
3611+
3612+static bool imx_clk_is_resource_owned(u32 rsrc)
3613+{
3614+	/*
3615+	 * A-core resources are special. SCFW reports they are not "owned" by
3616+	 * current partition but linux can still adjust them for cpufreq.
3617+	 *
3618+	 * So force this to return false when running as a VM guest and always
3619+	 * true otherwise.
3620+	 */
3621+	if (rsrc == IMX_SC_R_A53 || rsrc == IMX_SC_R_A72 ||
3622+	    rsrc == IMX_SC_R_A35) {
3623+		if (xen_domain() && !xen_initial_domain())
3624+			return false;
3625+		return true;
3626+	}
3627+
3628+	return imx_sc_rm_is_resource_owned(ccm_ipc_handle, rsrc);
3629+}
3630+
3631+struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
3632+				     const char * const *parents,
3633+				     int num_parents, u32 rsrc_id, u8 clk_type)
3634+{
3635+	struct imx_scu_clk_node clk = {
3636+		.name = name,
3637+		.rsrc = rsrc_id,
3638+		.clk_type = clk_type,
3639+		.parents = parents,
3640+		.num_parents = num_parents,
3641+	};
3642+	struct platform_device *pdev;
3643+	int ret;
3644+
3645+	if (!imx_scu_clk_is_valid(rsrc_id))
3646+		return NULL;
3647+
3648+	if (!imx_clk_is_resource_owned(rsrc_id))
3649+		return NULL;
3650+
3651+	pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
3652+	if (!pdev) {
3653+		pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
3654+		       name, rsrc_id, clk_type);
3655+		return ERR_PTR(-ENOMEM);
3656+	}
3657+
3658+	ret = platform_device_add_data(pdev, &clk, sizeof(clk));
3659+	if (ret) {
3660+		platform_device_put(pdev);
3661+		return ERR_PTR(-ENOMEM);
3662+	}
3663+
3664+	pdev->driver_override = "imx-scu-clk";
3665+
3666+	ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id);
3667+	if (ret)
3668+		pr_warn("%s: failed to attached the power domain %d\n",
3669+			name, ret);
3670+
3671+	platform_device_add(pdev);
3672+
3673+	/* For API backwards compatiblilty, simply return NULL for success */
3674+	return NULL;
3675+}
3676+
3677+static unsigned long clk_gpr_div_scu_recalc_rate(struct clk_hw *hw,
3678+						 unsigned long parent_rate)
3679+{
3680+	struct clk_gpr_scu *clk = to_clk_gpr_scu(hw);
3681+	unsigned long rate = 0;
3682+	u32 val;
3683+	int err;
3684+
3685+	err = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id,
3686+				      clk->gpr_id, &val);
3687+
3688+	rate  = val ? parent_rate / 2 : parent_rate;
3689+
3690+	return err ? 0 : rate;
3691+}
3692+
3693+static long clk_gpr_div_scu_round_rate(struct clk_hw *hw, unsigned long rate,
3694+				   unsigned long *prate)
3695+{
3696+	if (rate < *prate)
3697+		rate = *prate / 2;
3698+	else
3699+		rate = *prate;
3700+
3701+	return rate;
3702+}
3703+
3704+static int clk_gpr_div_scu_set_rate(struct clk_hw *hw, unsigned long rate,
3705+				unsigned long parent_rate)
3706+{
3707+	struct clk_gpr_scu *clk = to_clk_gpr_scu(hw);
3708+	uint32_t val;
3709+	int err;
3710+
3711+	val = (rate < parent_rate) ? 1 : 0;
3712+	err = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id,
3713+				      clk->gpr_id, val);
3714+
3715+	return err ? -EINVAL : 0;
3716+}
3717+
3718+static const struct clk_ops clk_gpr_div_scu_ops = {
3719+	.recalc_rate = clk_gpr_div_scu_recalc_rate,
3720+	.round_rate = clk_gpr_div_scu_round_rate,
3721+	.set_rate = clk_gpr_div_scu_set_rate,
3722+};
3723+
3724+static u8 clk_gpr_mux_scu_get_parent(struct clk_hw *hw)
3725+{
3726+	struct clk_gpr_scu *clk= to_clk_gpr_scu(hw);
3727+	u32 val = 0;
3728+
3729+	imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id,
3730+				clk->gpr_id, &val);
3731+
3732+	return (u8)val;
3733+}
3734+
3735+static int clk_gpr_mux_scu_set_parent(struct clk_hw *hw, u8 index)
3736+{
3737+	struct clk_gpr_scu *clk= to_clk_gpr_scu(hw);
3738+
3739+	imx_sc_misc_set_control(ccm_ipc_handle,	clk->rsrc_id,
3740+				clk->gpr_id, index);
3741+
3742+	return 0;
3743+}
3744+
3745+static const struct clk_ops clk_gpr_mux_scu_ops = {
3746+	.get_parent = clk_gpr_mux_scu_get_parent,
3747+	.set_parent = clk_gpr_mux_scu_set_parent,
3748+};
3749+
3750+static int clk_gpr_gate_scu_prepare(struct clk_hw *hw)
3751+{
3752+	struct clk_gpr_scu *clk = to_clk_gpr_scu(hw);
3753+
3754+	return imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id,
3755+				       clk->gpr_id, !clk->gate_invert);
3756+}
3757+
3758+static void clk_gpr_gate_scu_unprepare(struct clk_hw *hw)
3759+{
3760+	struct clk_gpr_scu *clk = to_clk_gpr_scu(hw);
3761+	int ret;
3762+
3763+	ret = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id,
3764+				      clk->gpr_id, clk->gate_invert);
3765+	if (ret)
3766+		pr_err("%s: clk unprepare failed %d\n", clk_hw_get_name(hw),
3767+		       ret);
3768+}
3769+
3770+static int clk_gpr_gate_scu_is_prepared(struct clk_hw *hw)
3771+{
3772+	struct clk_gpr_scu *clk= to_clk_gpr_scu(hw);
3773+	int ret;
3774+	u32 val;
3775+
3776+	ret = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id,
3777+				      clk->gpr_id, &val);
3778+	if (ret)
3779+		return ret;
3780+
3781+	return clk->gate_invert ? !val : val;
3782+}
3783+
3784+static struct clk_ops clk_gpr_gate_scu_ops = {
3785+	.prepare = clk_gpr_gate_scu_prepare,
3786+	.unprepare = clk_gpr_gate_scu_unprepare,
3787+	.is_prepared = clk_gpr_gate_scu_is_prepared,
3788+};
3789+
3790+struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name,
3791+				 int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags,
3792+				 bool invert)
3793+{
3794+	struct imx_scu_clk_node *clk_node;
3795+	struct clk_gpr_scu *clk;
3796+	struct clk_hw *hw;
3797+	struct clk_init_data init;
3798+	int ret;
3799+
3800+	if (rsrc_id >= IMX_SC_R_LAST)
3801+		return NULL;
3802+
3803+	if (gpr_id >= IMX_SC_C_LAST)
3804+		return NULL;
3805+
3806+	if (!imx_scu_clk_is_valid(rsrc_id))
3807+		return ERR_PTR(-EINVAL);
3808+
3809+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
3810+	if (!clk)
3811+		return ERR_PTR(-ENOMEM);
3812+
3813+	clk_node = kzalloc(sizeof(*clk_node), GFP_KERNEL);
3814+	if (!clk_node) {
3815+		kfree(clk);
3816+		return ERR_PTR(-ENOMEM);
3817+	};
3818+
3819+	/* struct clk_gate_scu assignments */
3820+	clk->rsrc_id = rsrc_id;
3821+	clk->gpr_id = gpr_id;
3822+	clk->flags = flags;
3823+	clk->gate_invert = invert;
3824+
3825+	if (flags & IMX_SCU_GPR_CLK_GATE)
3826+		init.ops = &clk_gpr_gate_scu_ops;
3827+
3828+	if (flags & IMX_SCU_GPR_CLK_DIV)
3829+		init.ops = &clk_gpr_div_scu_ops;
3830+
3831+	if (flags & IMX_SCU_GPR_CLK_MUX)
3832+		init.ops = &clk_gpr_mux_scu_ops;
3833+
3834+	init.flags = 0;
3835+	init.name = name;
3836+	init.parent_names = parent_name;
3837+	init.num_parents = num_parents;
3838+
3839 	clk->hw.init = &init;
3840
3841 	hw = &clk->hw;
3842 	ret = clk_hw_register(NULL, hw);
3843 	if (ret) {
3844 		kfree(clk);
3845+		kfree(clk_node);
3846 		hw = ERR_PTR(ret);
3847+	} else {
3848+		clk_node->hw = hw;
3849+		clk_node->clk_type = gpr_id;
3850+		list_add_tail(&clk_node->node, &imx_scu_clks[rsrc_id]);
3851 	}
3852
3853 	return hw;
3854diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
3855index 2bcfaf06a..50f883199 100644
3856--- a/drivers/clk/imx/clk-scu.h
3857+++ b/drivers/clk/imx/clk-scu.h
3858@@ -8,25 +8,95 @@
3859 #define __IMX_CLK_SCU_H
3860
3861 #include <linux/firmware/imx/sci.h>
3862+#include <linux/of.h>
3863
3864-int imx_clk_scu_init(void);
3865+#define IMX_SCU_GPR_CLK_GATE	BIT(0)
3866+#define IMX_SCU_GPR_CLK_DIV	BIT(1)
3867+#define IMX_SCU_GPR_CLK_MUX	BIT(2)
3868
3869-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
3870-			     int num_parents, u32 rsrc_id, u8 clk_type);
3871+struct imx_clk_scu_rsrc_table {
3872+	const u32 *rsrc;
3873+	u8 num;
3874+};
3875+
3876+extern u32 clock_cells;
3877+extern struct list_head imx_scu_clks[];
3878+extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops;
3879+extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp;
3880+extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm;
3881+extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl;
3882+
3883+int imx_clk_scu_init(struct device_node *np, const void *data);
3884+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
3885+				      void *data);
3886+struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
3887+				     const char * const *parents,
3888+				     int num_parents, u32 rsrc_id, u8 clk_type);
3889+
3890+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
3891+			     const char * const *parents, int num_parents,
3892+			     u32 rsrc_id, u8 clk_type);
3893+
3894+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
3895+				  const char *parent_name, unsigned long flags,
3896+				  void __iomem *reg, u8 bit_idx, bool hw_gate);
3897+
3898+struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name,
3899+				 int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags,
3900+				 bool invert);
3901
3902 static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
3903 					 u8 clk_type)
3904 {
3905-	return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
3906+	if (clock_cells == 2)
3907+		return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type);
3908+	else
3909+		return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type);
3910 }
3911
3912 static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
3913 					  int num_parents, u32 rsrc_id, u8 clk_type)
3914 {
3915-	return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
3916+	if (clock_cells == 2)
3917+		return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type);
3918+	else
3919+		return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type);
3920 }
3921
3922-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
3923-				unsigned long flags, void __iomem *reg,
3924-				u8 bit_idx, bool hw_gate);
3925+static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name,
3926+						  const char *parent_name, unsigned long flags,
3927+						  void __iomem *reg, u8 bit_idx, bool hw_gate)
3928+{
3929+	return __imx_clk_lpcg_scu(dev, name, parent_name, flags, reg,
3930+				  bit_idx, hw_gate);
3931+}
3932+
3933+static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
3934+					      unsigned long flags, void __iomem *reg,
3935+					      u8 bit_idx, bool hw_gate)
3936+{
3937+	return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg,
3938+				  bit_idx, hw_gate);
3939+}
3940+
3941+static inline struct clk_hw *imx_clk_gate_gpr_scu(const char *name, const char *parent_name,
3942+						  u32 rsrc_id, u8 gpr_id, bool invert)
3943+{
3944+	return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id,
3945+				 IMX_SCU_GPR_CLK_GATE, invert);
3946+}
3947+
3948+static inline struct clk_hw *imx_clk_divider_gpr_scu(const char *name, const char *parent_name,
3949+						     u32 rsrc_id, u8 gpr_id)
3950+{
3951+	return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id,
3952+				 IMX_SCU_GPR_CLK_DIV, 0);
3953+}
3954+
3955+static inline struct clk_hw *imx_clk_mux_gpr_scu(const char *name, const char * const *parent_names,
3956+						 int num_parents, u32 rsrc_id, u8 gpr_id)
3957+{
3958+	return __imx_clk_gpr_scu(name, parent_names, num_parents, rsrc_id,
3959+				 gpr_id, IMX_SCU_GPR_CLK_MUX, 0);
3960+}
3961 #endif
3962diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
3963index 7cc669934..c323ddbbb 100644
3964--- a/drivers/clk/imx/clk.c
3965+++ b/drivers/clk/imx/clk.c
3966@@ -17,6 +17,8 @@
3967 DEFINE_SPINLOCK(imx_ccm_lock);
3968 EXPORT_SYMBOL_GPL(imx_ccm_lock);
3969
3970+bool uart_from_osc;
3971+
3972 void imx_unregister_clocks(struct clk *clks[], unsigned int count)
3973 {
3974 	unsigned int i;
3975@@ -207,6 +209,14 @@ static int __init imx_clk_disable_uart(void)
3976 	return 0;
3977 }
3978 late_initcall_sync(imx_clk_disable_uart);
3979+
3980+static int __init setup_uart_clk(char *uart_rate)
3981+{
3982+       uart_from_osc = true;
3983+       return 1;
3984+}
3985+__setup("uart_from_osc", setup_uart_clk);
3986+
3987 #endif
3988
3989 MODULE_LICENSE("GPL v2");
3990diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
3991index c66e00e87..7f82eea83 100644
3992--- a/drivers/clk/imx/clk.h
3993+++ b/drivers/clk/imx/clk.h
3994@@ -5,8 +5,7 @@
3995 #include <linux/bits.h>
3996 #include <linux/spinlock.h>
3997 #include <linux/clk-provider.h>
3998-
3999-#define IMX_CLK_GATE2_SINGLE_BIT	1
4000+#include <soc/imx/src.h>
4001
4002 extern spinlock_t imx_ccm_lock;
4003
4004@@ -24,6 +23,9 @@ void imx_unregister_clocks(struct clk *clks[], unsigned int count);
4005 void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count);
4006
4007 extern void imx_cscmr1_fixup(u32 *val);
4008+extern struct imx_sema4_mutex *amp_power_mutex;
4009+extern struct imx_shared_mem *shared_mem;
4010+extern bool uart_from_osc;
4011
4012 enum imx_pllv1_type {
4013 	IMX_PLLV1_IMX1,
4014@@ -44,6 +46,16 @@ enum imx_pll14xx_type {
4015 	PLL_1443X,
4016 };
4017
4018+enum imx_pllv4_type {
4019+	IMX_PLLV4_IMX7ULP,
4020+	IMX_PLLV4_IMX8ULP,
4021+};
4022+
4023+enum imx_pfdv2_type {
4024+	IMX_PFDV2_IMX7ULP,
4025+	IMX_PFDV2_IMX8ULP,
4026+};
4027+
4028 /* NOTE: Rate table should be kept sorted in descending order. */
4029 struct imx_pll14xx_rate_table {
4030 	unsigned int rate;
4031@@ -173,6 +185,25 @@ enum imx_pllv3_type {
4032 	IMX_PLLV3_AV_IMX7,
4033 };
4034
4035+#define MAX_SHARED_CLK_NUMBER		100
4036+#define SHARED_MEM_MAGIC_NUMBER		0x12345678
4037+#define MCC_POWER_SHMEM_NUMBER		(6)
4038+
4039+struct imx_shared_clk {
4040+	struct clk *self;
4041+	struct clk *parent;
4042+	void *m4_clk;
4043+	void *m4_clk_parent;
4044+	u8 ca9_enabled;
4045+	u8 cm4_enabled;
4046+};
4047+
4048+struct imx_shared_mem {
4049+	u32 ca9_valid;
4050+	u32 cm4_valid;
4051+	struct imx_shared_clk imx_clk[MAX_SHARED_CLK_NUMBER];
4052+};
4053+
4054 struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name,
4055 		const char *parent_name, void __iomem *base, u32 div_mask);
4056
4057@@ -193,8 +224,8 @@ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name,
4058 		.kdiv	=	(_k),			\
4059 	}
4060
4061-struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
4062-			     void __iomem *base);
4063+struct clk_hw *imx_clk_hw_pllv4(enum imx_pllv4_type type, const char *name,
4064+		const char *parent_name, void __iomem *base);
4065
4066 struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
4067 		const char *parent_name, unsigned long flags,
4068@@ -217,8 +248,8 @@ struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
4069 struct clk_hw *imx_clk_hw_pfd(const char *name, const char *parent_name,
4070 		void __iomem *reg, u8 idx);
4071
4072-struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name,
4073-			     void __iomem *reg, u8 idx);
4074+struct clk_hw *imx_clk_hw_pfdv2(enum imx_pfdv2_type type, const char *name,
4075+	 const char *parent_name, void __iomem *reg, u8 idx);
4076
4077 struct clk_hw *imx_clk_hw_busy_divider(const char *name, const char *parent_name,
4078 				 void __iomem *reg, u8 shift, u8 width,
4079@@ -228,12 +259,25 @@ struct clk_hw *imx_clk_hw_busy_mux(const char *name, void __iomem *reg, u8 shift
4080 			     u8 width, void __iomem *busy_reg, u8 busy_shift,
4081 			     const char * const *parent_names, int num_parents);
4082
4083+int imx_update_shared_mem(struct clk_hw *hw, bool enable);
4084+
4085+static inline int clk_on_imx6sx(void)
4086+{
4087+	return of_machine_is_compatible("fsl,imx6sx");
4088+}
4089+
4090 struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
4091 				     const char * const *parent_names,
4092 				     int num_parents, bool mux_present,
4093 				     bool rate_present, bool gate_present,
4094 				     void __iomem *reg);
4095
4096+struct clk_hw *imx8ulp_clk_hw_composite(const char *name,
4097+				     const char * const *parent_names,
4098+				     int num_parents, bool mux_present,
4099+				     bool rate_present, bool gate_present,
4100+				     void __iomem *reg, bool has_swrst);
4101+
4102 struct clk_hw *imx_clk_hw_fixup_divider(const char *name, const char *parent,
4103 				  void __iomem *reg, u8 shift, u8 width,
4104 				  void (*fixup)(u32 *val));
4105@@ -286,6 +330,15 @@ static inline struct clk_hw *imx_clk_hw_divider(const char *name,
4106 				       reg, shift, width, 0, &imx_ccm_lock);
4107 }
4108
4109+static inline struct clk_hw *imx_clk_hw_divider_closest(const char *name,
4110+						const char *parent,
4111+						void __iomem *reg, u8 shift,
4112+						u8 width)
4113+{
4114+	return clk_hw_register_divider(NULL, name, parent, 0,
4115+				       reg, shift, width, CLK_DIVIDER_ROUND_CLOSEST, &imx_ccm_lock);
4116+}
4117+
4118 static inline struct clk_hw *imx_clk_hw_divider_flags(const char *name,
4119 						   const char *parent,
4120 						   void __iomem *reg, u8 shift,
4121@@ -383,10 +436,8 @@ static inline struct clk_hw *imx_dev_clk_hw_gate_shared(struct device *dev,
4122 				void __iomem *reg, u8 shift,
4123 				unsigned int *share_count)
4124 {
4125-	return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
4126-					CLK_OPS_PARENT_ENABLE, reg, shift, 0x3,
4127-					IMX_CLK_GATE2_SINGLE_BIT,
4128-					&imx_ccm_lock, share_count);
4129+	return clk_hw_register_gate2(dev, name, parent, CLK_SET_RATE_PARENT, reg,
4130+			shift, 0x1, 0, &imx_ccm_lock, share_count);
4131 }
4132
4133 static inline struct clk *imx_clk_gate2_cgr(const char *name,
4134@@ -399,7 +450,17 @@ static inline struct clk *imx_clk_gate2_cgr(const char *name,
4135 static inline struct clk_hw *imx_clk_hw_gate3(const char *name, const char *parent,
4136 		void __iomem *reg, u8 shift)
4137 {
4138-	return clk_hw_register_gate(NULL, name, parent,
4139+	/*
4140+	 * per design team's suggestion, clk root is NOT consuming
4141+	 * much power, and clk root enable/disable does NOT have domain
4142+	 * control, so they suggest to leave clk root always on when
4143+	 * M4 is enabled.
4144+	 */
4145+	if (imx_src_is_m4_enabled())
4146+		return clk_hw_register_fixed_factor(NULL, name, parent,
4147+						 CLK_SET_RATE_PARENT, 1, 1);
4148+	else
4149+		return clk_hw_register_gate(NULL, name, parent,
4150 			CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
4151 			reg, shift, 0, &imx_ccm_lock);
4152 }
4153@@ -454,6 +515,15 @@ static inline struct clk_hw *imx_dev_clk_hw_mux(struct device *dev,
4154 			reg, shift, width, 0, &imx_ccm_lock);
4155 }
4156
4157+static inline struct clk *imx_dev_clk_mux(struct device *dev, const char *name,
4158+			void __iomem *reg, u8 shift, u8 width,
4159+			const char * const *parents, int num_parents)
4160+{
4161+	return clk_register_mux(dev, name, parents, num_parents,
4162+			CLK_SET_RATE_NO_REPARENT | CLK_SET_PARENT_GATE,
4163+			reg, shift, width, 0, &imx_ccm_lock);
4164+}
4165+
4166 static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
4167 			u8 shift, u8 width, const char * const *parents,
4168 			int num_parents)
4169@@ -601,4 +671,7 @@ struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name
4170 		unsigned long flags, void __iomem *reg, u8 shift, u8 width,
4171 		u8 clk_divider_flags, const struct clk_div_table *table,
4172 		spinlock_t *lock);
4173+
4174+void clk_set_delta_k(struct clk_hw *hw, short int delta_k);
4175+void clk_get_pll_setting(struct clk_hw *hw, u32 *pll_div_ctrl0, u32 *pll_div_ctrl1);
4176 #endif
4177diff --git a/drivers/clk/s32/Kconfig b/drivers/clk/s32/Kconfig
4178new file mode 100644
4179index 000000000..c28bdbbfa
4180--- /dev/null
4181+++ b/drivers/clk/s32/Kconfig
4182@@ -0,0 +1,4 @@
4183+config ARCH_S32_CLK
4184+	bool "Enable S32 CLK Framework"
4185+	help
4186+	  Support for the Clock Framework on S32 SoCs.
4187diff --git a/drivers/clk/s32/Makefile b/drivers/clk/s32/Makefile
4188new file mode 100644
4189index 000000000..169b8b590
4190--- /dev/null
4191+++ b/drivers/clk/s32/Makefile
4192@@ -0,0 +1,2 @@
4193+obj-$(CONFIG_ARCH_S32_CLK) += clk-core.o
4194+obj-$(CONFIG_ARCH_S32_CLK) += s32v234/
4195diff --git a/drivers/clk/s32/clk-core.c b/drivers/clk/s32/clk-core.c
4196new file mode 100644
4197index 000000000..a8cca66f7
4198--- /dev/null
4199+++ b/drivers/clk/s32/clk-core.c
4200@@ -0,0 +1,53 @@
4201+// SPDX-License-Identifier: GPL-2.0-or-later
4202+/*
4203+ * Copyright 2015 Freescale Semiconductor, Inc.
4204+ * Copyright 2017 NXP
4205+ */
4206+
4207+#include <linux/clk.h>
4208+#include <linux/err.h>
4209+#include <linux/of.h>
4210+#include <linux/slab.h>
4211+#include <linux/spinlock.h>
4212+#include "clk.h"
4213+
4214+void __init s32_check_clocks(struct clk *clks[], unsigned int count)
4215+{
4216+	unsigned int i;
4217+
4218+	for (i = 0; i < count; i++)
4219+		if (IS_ERR(clks[i]))
4220+			pr_err("S32 clk %u: register failed with %ld\n",
4221+			       i, PTR_ERR(clks[i]));
4222+}
4223+
4224+static struct clk * __init s32_obtain_fixed_clock_from_dt(const char *name)
4225+{
4226+	struct of_phandle_args phandle;
4227+	struct clk *clk = ERR_PTR(-ENODEV);
4228+	char *path;
4229+
4230+	path = kasprintf(GFP_KERNEL, "/clocks/%s", name);
4231+	if (!path)
4232+		return ERR_PTR(-ENOMEM);
4233+
4234+	phandle.np = of_find_node_by_path(path);
4235+	kfree(path);
4236+
4237+	if (phandle.np) {
4238+		clk = of_clk_get_from_provider(&phandle);
4239+		of_node_put(phandle.np);
4240+	}
4241+	return clk;
4242+}
4243+
4244+struct clk * __init s32_obtain_fixed_clock(
4245+			const char *name, unsigned long rate)
4246+{
4247+	struct clk *clk;
4248+
4249+	clk = s32_obtain_fixed_clock_from_dt(name);
4250+	if (IS_ERR(clk))
4251+		clk = s32_clk_fixed(name, rate);
4252+	return clk;
4253+}
4254diff --git a/drivers/clk/s32/clk.h b/drivers/clk/s32/clk.h
4255new file mode 100644
4256index 000000000..831006411
4257--- /dev/null
4258+++ b/drivers/clk/s32/clk.h
4259@@ -0,0 +1,55 @@
4260+/* SPDX-License-Identifier: GPL-2.0-or-later */
4261+/*
4262+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
4263+ * Copyright 2017-2018 NXP
4264+ */
4265+
4266+#ifndef __MACH_S32_CLK_H
4267+#define __MACH_S32_CLK_H
4268+
4269+#include <linux/spinlock.h>
4270+#include <linux/clk-provider.h>
4271+
4272+#define PNAME(x) \
4273+	static const char *x[] __initconst
4274+
4275+void s32_check_clocks(struct clk *clks[], unsigned int count);
4276+
4277+struct clk *s32_obtain_fixed_clock(
4278+			const char *name, unsigned long rate);
4279+
4280+static inline struct clk *s32_clk_fixed(const char *name, unsigned long rate)
4281+{
4282+	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
4283+}
4284+
4285+static inline struct clk *s32_clk_divider(const char *name, const char *parent,
4286+					  void __iomem *reg, u8 shift, u8 width,
4287+					  spinlock_t *lock)
4288+{
4289+	struct clk *tmp_clk = clk_register_divider(NULL, name, parent,
4290+			      CLK_SET_RATE_PARENT,
4291+			      reg, shift, width, 0, lock);
4292+
4293+	return tmp_clk;
4294+}
4295+
4296+static inline struct clk *s32_clk_mux(const char *name, void __iomem *reg,
4297+				      u8 shift, u8 width, const char **parents,
4298+				      u8 num_parents, spinlock_t *lock)
4299+{
4300+	return clk_register_mux(NULL, name, parents, num_parents,
4301+			CLK_SET_RATE_NO_REPARENT, reg, shift,
4302+			width, 0, lock);
4303+}
4304+
4305+static inline struct clk *s32_clk_fixed_factor(const char *name,
4306+					       const char *parent,
4307+					       unsigned int mult,
4308+					       unsigned int div)
4309+{
4310+	return clk_register_fixed_factor(NULL, name, parent,
4311+			CLK_SET_RATE_PARENT, mult, div);
4312+}
4313+
4314+#endif
4315diff --git a/drivers/clk/s32/s32v234/Makefile b/drivers/clk/s32/s32v234/Makefile
4316new file mode 100644
4317index 000000000..7ddf9f4b5
4318--- /dev/null
4319+++ b/drivers/clk/s32/s32v234/Makefile
4320@@ -0,0 +1 @@
4321+obj-$(CONFIG_ARCH_S32_CLK) += clk.o clk-plldig.o clk-dfs.o
4322diff --git a/drivers/clk/s32/s32v234/clk-dfs.c b/drivers/clk/s32/s32v234/clk-dfs.c
4323new file mode 100644
4324index 000000000..2bd569e13
4325--- /dev/null
4326+++ b/drivers/clk/s32/s32v234/clk-dfs.c
4327@@ -0,0 +1,236 @@
4328+/*
4329+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
4330+ * Copyright 2017-2018 NXP
4331+ *
4332+ * The code contained herein is licensed under the GNU General Public
4333+ * License. You may obtain a copy of the GNU General Public License
4334+ * Version 2 or later at the following locations:
4335+ *
4336+ * http://www.opensource.org/licenses/gpl-license.html
4337+ * http://www.gnu.org/copyleft/gpl.html
4338+ */
4339+
4340+#include <linux/clk.h>
4341+#include <linux/clk-provider.h>
4342+#include <linux/io.h>
4343+#include <linux/slab.h>
4344+#include <linux/err.h>
4345+#include "clk.h"
4346+
4347+/**
4348+ * struct clk_dfs - S32 DFS clock
4349+ * @clk_hw:	clock source
4350+ * @reg:	DFS register address
4351+ * @idx:	the index of DFS encoded in the register
4352+ *
4353+ * DFS clock found on S32 series. Each register for DFS has 4 clk_dfs
4354+ * data encoded, and member idx is used to specify the one.
4355+ * Only ARMPLL(3 DFS), ENETPLL(4 DFS) and DDRPLL(3 DFS) has DFS outputs.
4356+ */
4357+struct clk_dfs {
4358+	struct clk_hw	hw;
4359+	void __iomem	*reg;
4360+	enum s32v234_plldig_type plltype;
4361+	u8		idx;
4362+	u32		mfn;
4363+};
4364+
4365+#define to_clk_dfs(_hw) container_of(_hw, struct clk_dfs, hw)
4366+
4367+static int get_pllx_dfs_nr(enum s32v234_plldig_type plltype)
4368+{
4369+	switch (plltype) {
4370+	case S32_PLLDIG_ARM:
4371+		return ARMPLL_DFS_NR;
4372+	case S32_PLLDIG_ENET:
4373+		return ENETPLL_DFS_NR;
4374+	case S32_PLLDIG_DDR:
4375+		return DDRPLL_DFS_NR;
4376+	case S32_PLLDIG_PERIPH:
4377+	case S32_PLLDIG_VIDEO:
4378+		pr_warn("Current selected PLL has no DFS\n");
4379+		break;
4380+	}
4381+
4382+	return -EINVAL;
4383+}
4384+static unsigned long get_pllx_dfsy_max_rate(enum s32v234_plldig_type plltype,
4385+					    int dfsno)
4386+{
4387+	switch (plltype) {
4388+	case S32_PLLDIG_ARM:
4389+		switch (dfsno) {
4390+		case 0:
4391+			return ARMPLL_DFS0_MAX_RATE;
4392+		case 1:
4393+			return ARMPLL_DFS1_MAX_RATE;
4394+		case 2:
4395+			return ARMPLL_DFS2_MAX_RATE;
4396+		}
4397+		break;
4398+	case S32_PLLDIG_ENET:
4399+		switch (dfsno) {
4400+		case 0:
4401+			return ENETPLL_DFS0_MAX_RATE;
4402+		case 1:
4403+			return ENETPLL_DFS1_MAX_RATE;
4404+		case 2:
4405+			return ENETPLL_DFS2_MAX_RATE;
4406+		case 3:
4407+			return ENETPLL_DFS3_MAX_RATE;
4408+		}
4409+		break;
4410+	case S32_PLLDIG_DDR:
4411+		switch (dfsno) {
4412+		case 0:
4413+			return DDRPLL_DFS0_MAX_RATE;
4414+		case 1:
4415+			return DDRPLL_DFS1_MAX_RATE;
4416+		case 2:
4417+			return DDRPLL_DFS2_MAX_RATE;
4418+		}
4419+		break;
4420+	case S32_PLLDIG_PERIPH:
4421+	case S32_PLLDIG_VIDEO:
4422+		pr_warn("Current selected PLL has no DFS.");
4423+		break;
4424+	default:
4425+		pr_warn("Unsupported PLL. Use %d or %d\n",
4426+			S32_PLLDIG_ARM,	S32_PLLDIG_VIDEO);
4427+		break;
4428+	}
4429+
4430+	return -EINVAL;
4431+}
4432+static int clk_dfs_enable(struct clk_hw *hw)
4433+{
4434+	/*
4435+	 * TODO: When SOC is available, this function
4436+	 * should be tested and implemented for DFS
4437+	 * if it is possible
4438+	 */
4439+	return 0;
4440+}
4441+
4442+static void clk_dfs_disable(struct clk_hw *hw)
4443+{
4444+	/*
4445+	 * TODO: When SOC is available, this function
4446+	 * should be tested and implemented for DFS
4447+	 * if it is possible
4448+	 */
4449+}
4450+
4451+static unsigned long clk_dfs_recalc_rate(struct clk_hw *hw,
4452+					 unsigned long parent_rate)
4453+{
4454+	struct clk_dfs *dfs = to_clk_dfs(hw);
4455+	u32 mfn, mfi, rate;
4456+	u32 dvport = readl_relaxed(DFS_DVPORTn(dfs->reg, dfs->idx));
4457+
4458+	mfn = (dvport & DFS_DVPORTn_MFN_MASK) >> DFS_DVPORTn_MFN_OFFSET;
4459+	mfi = (dvport & DFS_DVPORTn_MFI_MASK) >> DFS_DVPORTn_MFI_OFFSET;
4460+	mfi <<= 8;
4461+	rate = parent_rate / (mfi + mfn);
4462+	rate <<= 8;
4463+
4464+	return rate;
4465+}
4466+
4467+static long clk_dfs_round_rate(struct clk_hw *hw, unsigned long rate,
4468+			       unsigned long *prate)
4469+{
4470+	struct clk_dfs *dfs = to_clk_dfs(hw);
4471+	unsigned long max_allowed_rate;
4472+
4473+	max_allowed_rate = get_pllx_dfsy_max_rate(dfs->plltype, dfs->idx);
4474+
4475+	if (rate > max_allowed_rate)
4476+		rate = max_allowed_rate;
4477+
4478+	return rate;
4479+}
4480+
4481+static int clk_dfs_set_rate(struct clk_hw *hw, unsigned long rate,
4482+			    unsigned long parent_rate)
4483+{
4484+	struct clk_dfs *dfs = to_clk_dfs(hw);
4485+	u32 mfi;
4486+	u32 portreset = readl_relaxed(DFS_PORTRESET(dfs->reg));
4487+
4488+	writel_relaxed(DFS_CTRL_DLL_RESET, DFS_CTRL(dfs->reg));
4489+	writel_relaxed(portreset | ~DFS_PORTRESET_PORTRESET_SET(dfs->idx),
4490+			DFS_PORTRESET(dfs->reg));
4491+
4492+	mfi = parent_rate/rate;
4493+	writel_relaxed(DFS_DVPORTn_MFI_SET(mfi) |
4494+		       DFS_DVPORTn_MFN_SET(dfs->mfn),
4495+		       DFS_DVPORTn(dfs->reg, dfs->idx));
4496+
4497+	writel_relaxed(~DFS_CTRL_DLL_RESET, DFS_CTRL(dfs->reg));
4498+
4499+	while (readl_relaxed(DFS_PORTSR(dfs->reg)) & (1 << (dfs->idx)))
4500+		;
4501+
4502+	return 0;
4503+}
4504+
4505+static int clk_dfs_is_enabled(struct clk_hw *hw)
4506+{
4507+	struct clk_dfs *dfs = to_clk_dfs(hw);
4508+
4509+	/* Check if current DFS output port is locked */
4510+	if (readl_relaxed(DFS_PORTSR(dfs->reg)) & (1 << (dfs->idx)))
4511+		return 0;
4512+
4513+	return 1;
4514+}
4515+
4516+static const struct clk_ops clk_dfs_ops = {
4517+	.enable		= clk_dfs_enable,
4518+	.disable	= clk_dfs_disable,
4519+	.recalc_rate	= clk_dfs_recalc_rate,
4520+	.round_rate	= clk_dfs_round_rate,
4521+	.set_rate	= clk_dfs_set_rate,
4522+	.is_enabled	= clk_dfs_is_enabled,
4523+};
4524+
4525+struct clk *s32v234_clk_dfs(enum s32v234_plldig_type type, const char *name,
4526+			const char *parent_name, void __iomem *reg,
4527+			u8 idx, u32 mfn)
4528+{
4529+	struct clk_dfs *dfs;
4530+	struct clk *clk;
4531+	struct clk_init_data init;
4532+
4533+	/* PERIPH and VIDEO PLL do not have DFS */
4534+	if (type == S32_PLLDIG_PERIPH || type == S32_PLLDIG_VIDEO)
4535+		return ERR_PTR(-EINVAL);
4536+
4537+	/* check if DFS index is valid for current pll */
4538+	if (idx >= get_pllx_dfs_nr(type))
4539+		return ERR_PTR(-EINVAL);
4540+
4541+	dfs = kzalloc(sizeof(*dfs), GFP_KERNEL);
4542+	if (!dfs)
4543+		return ERR_PTR(-ENOMEM);
4544+
4545+	dfs->reg = reg;
4546+	dfs->idx = idx;
4547+	dfs->mfn = mfn;
4548+	dfs->plltype = type;
4549+
4550+	init.name = name;
4551+	init.ops = &clk_dfs_ops;
4552+	init.flags = 0;
4553+	init.parent_names = &parent_name;
4554+	init.num_parents = 1;
4555+
4556+	dfs->hw.init = &init;
4557+
4558+	clk = clk_register(NULL, &dfs->hw);
4559+	if (IS_ERR(clk))
4560+		kfree(dfs);
4561+
4562+	return clk;
4563+}
4564diff --git a/drivers/clk/s32/s32v234/clk-plldig.c b/drivers/clk/s32/s32v234/clk-plldig.c
4565new file mode 100644
4566index 000000000..6ed23974e
4567--- /dev/null
4568+++ b/drivers/clk/s32/s32v234/clk-plldig.c
4569@@ -0,0 +1,240 @@
4570+// SPDX-License-Identifier: GPL-2.0-or-later
4571+/*
4572+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
4573+ * Copyright 2017-2018 NXP
4574+ */
4575+
4576+#include <linux/clk.h>
4577+#include <linux/clk-provider.h>
4578+#include <linux/delay.h>
4579+#include <linux/io.h>
4580+#include <linux/slab.h>
4581+#include <linux/jiffies.h>
4582+#include <linux/err.h>
4583+#include "clk.h"
4584+
4585+/*
4586+ * struct clk_plldig - S32 PLLDIG clock
4587+ * @clk_hw:	   clock source
4588+ * @base:	   base address of PLL registers
4589+ * @plldv_mfd:	   multiplication loop factor divider
4590+ * @plldv_rfdphi:  PHI reduced frequency divider
4591+ * @plldv_rfdphi1: PHI reduced frequency divider
4592+ *
4593+ * PLLDIG clock version 1, found on S32 series.
4594+ */
4595+struct clk_plldig {
4596+	struct clk_hw	hw;
4597+	void __iomem	*base;
4598+	enum s32v234_plldig_type type;
4599+	u32		plldv_mfd;
4600+	u32		pllfd_mfn;
4601+	u32		plldv_rfdphi;
4602+	u32		plldv_rfdphi1;
4603+};
4604+
4605+#define to_clk_plldig(_hw) container_of(_hw, struct clk_plldig, hw)
4606+
4607+static unsigned long get_pllx_max_vco_rate(enum s32v234_plldig_type plltype)
4608+{
4609+	switch (plltype) {
4610+	case S32_PLLDIG_PERIPH:
4611+		return PERIPHPLL_MAX_VCO_RATE;
4612+	default:
4613+		pr_warn("Unsupported PLL.\n");
4614+			return -EINVAL;
4615+	}
4616+}
4617+
4618+static unsigned long get_pllx_phiy_max_rate(enum s32v234_plldig_type plltype,
4619+					    unsigned int phino)
4620+{
4621+	switch (plltype) {
4622+	case S32_PLLDIG_PERIPH:
4623+		switch (phino) {
4624+		case 0:
4625+			return PERIPHPLL_MAX_PHI0_MAX_RATE;
4626+		case 1:
4627+			return PERIPHPLL_MAX_PHI1_MAX_RATE;
4628+		default:
4629+			break;
4630+		}
4631+		break;
4632+	default:
4633+		pr_warn("Unsupported PLL.\n");
4634+		break;
4635+	}
4636+	return -EINVAL;
4637+}
4638+
4639+static int clk_plldig_prepare(struct clk_hw *hw)
4640+{
4641+	return 0;
4642+}
4643+
4644+static void clk_plldig_unprepare(struct clk_hw *hw)
4645+{
4646+}
4647+
4648+static unsigned long clk_plldig_recalc_rate(struct clk_hw *hw,
4649+					    unsigned long parent_rate)
4650+{
4651+	struct clk_plldig *pll = to_clk_plldig(hw);
4652+	u32 plldv = readl_relaxed(PLLDIG_PLLDV(pll->base));
4653+	u32 pllfd = readl_relaxed(PLLDIG_PLLFD(pll->base));
4654+	u32 prediv, mfd, mfn, vco;
4655+
4656+	prediv = (plldv & PLLDIG_PLLDV_PREDIV_MASK)
4657+			 >> PLLDIG_PLLDV_PREDIV_OFFSET;
4658+	mfd = (plldv & PLLDIG_PLLDV_MFD_MASK);
4659+
4660+	mfn = (pllfd & PLLDIG_PLLFD_MFN_MASK);
4661+
4662+	if (prediv == 0)
4663+		prediv = 1;
4664+
4665+	/*
4666+	 * This formula is from platform reference manual
4667+	 * (Rev. 1, 6/2015), PLLDIG chapter.
4668+	 */
4669+	vco = (parent_rate / prediv) * (mfd + mfn / 20480);
4670+
4671+	return vco;
4672+}
4673+
4674+static long clk_plldig_round_rate(struct clk_hw *hw, unsigned long rate,
4675+				  unsigned long *prate)
4676+{
4677+	struct clk_plldig *pll = to_clk_plldig(hw);
4678+	unsigned long max_allowed_rate = get_pllx_max_vco_rate(pll->type);
4679+
4680+	if (rate > max_allowed_rate)
4681+		rate = max_allowed_rate;
4682+	else if (rate < MIN_VCO_RATE)
4683+		rate = MIN_VCO_RATE;
4684+
4685+	return rate;
4686+}
4687+
4688+static int clk_plldig_set_rate(struct clk_hw *hw, unsigned long rate,
4689+			       unsigned long parent_rate)
4690+{
4691+	struct clk_plldig *pll = to_clk_plldig(hw);
4692+	u32 pllfd, prediv;
4693+
4694+	unsigned long max_allowed_rate = get_pllx_max_vco_rate(pll->type);
4695+	unsigned long phi0_max_rate =  get_pllx_phiy_max_rate(pll->type, 0);
4696+	unsigned long phi1_max_rate =  get_pllx_phiy_max_rate(pll->type, 1);
4697+
4698+	if (rate < MIN_VCO_RATE || rate > max_allowed_rate)
4699+		return -EINVAL;
4700+
4701+	if (((rate / pll->plldv_rfdphi) > phi0_max_rate) ||
4702+	    ((rate / pll->plldv_rfdphi) > phi1_max_rate))
4703+		return -EINVAL;
4704+
4705+	pllfd = readl_relaxed(PLLDIG_PLLFD(pll->base));
4706+	prediv = (parent_rate / rate) *
4707+		 (pll->plldv_mfd + pll->pllfd_mfn / 20480);
4708+
4709+	writel_relaxed(PLLDIG_PLLDV_RFDPHI1_SET(pll->plldv_rfdphi1) |
4710+			PLLDIG_PLLDV_RFDPHI_SET(pll->plldv_rfdphi) |
4711+			PLLDIG_PLLDV_PREDIV_SET(prediv) |
4712+			PLLDIG_PLLDV_MFD_SET(pll->plldv_mfd),
4713+			PLLDIG_PLLDV(pll->base));
4714+
4715+	writel_relaxed(pllfd | PLLDIG_PLLFD_MFN_SET(pll->pllfd_mfn),
4716+		       PLLDIG_PLLFD(pll->base));
4717+
4718+	/*
4719+	 * To be implemented the wait_lock or an equivalent state
4720+	 * return clk_plldig_wait_lock(pll);
4721+	 */
4722+	return 0;
4723+}
4724+
4725+static const struct clk_ops clk_plldig_ops = {
4726+	.prepare	= clk_plldig_prepare,
4727+	.unprepare	= clk_plldig_unprepare,
4728+	.recalc_rate	= clk_plldig_recalc_rate,
4729+	.round_rate	= clk_plldig_round_rate,
4730+	.set_rate	= clk_plldig_set_rate,
4731+};
4732+
4733+struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type,
4734+				   const char *name, const char *parent,
4735+				   void __iomem *base, u32 phi)
4736+{
4737+	u32 plldv, rfd_phi;
4738+
4739+	if (!base)
4740+		return ERR_PTR(-ENOMEM);
4741+
4742+	plldv = readl_relaxed(PLLDIG_PLLDV(base));
4743+
4744+	switch (phi) {
4745+	/* PHI0 */
4746+	case 0:
4747+		rfd_phi = (plldv & PLLDIG_PLLDV_RFDPHI_MASK)
4748+			  >> PLLDIG_PLLDV_RFDPHI_OFFSET;
4749+		break;
4750+	/* PHI1 */
4751+	case 1:
4752+		rfd_phi = (plldv & PLLDIG_PLLDV_RFDPHI1_MASK)
4753+			  >> PLLDIG_PLLDV_RFDPHI1_OFFSET;
4754+
4755+		if (rfd_phi == 0)
4756+			rfd_phi = 1;
4757+
4758+		break;
4759+	default:
4760+		return ERR_PTR(-EINVAL);
4761+	}
4762+
4763+	return clk_register_fixed_factor(NULL, name, parent,
4764+			CLK_SET_RATE_PARENT, 1, rfd_phi);
4765+}
4766+
4767+struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name,
4768+			       const char *parent_name, void __iomem *base,
4769+			       u32 plldv_mfd, u32 pllfd_mfn,
4770+			       u32 plldv_rfdphi, u32 plldv_rfdphi1)
4771+{
4772+	struct clk_plldig *pll;
4773+	const struct clk_ops *ops;
4774+	struct clk *clk;
4775+	struct clk_init_data init;
4776+
4777+	if (plldv_rfdphi > PLLDIG_PLLDV_RFDPHI_MAXVALUE)
4778+		return ERR_PTR(-EINVAL);
4779+
4780+	if (plldv_rfdphi1 > PLLDIG_PLLDV_RFDPHI1_MAXVALUE)
4781+		return ERR_PTR(-EINVAL);
4782+
4783+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
4784+	if (!pll)
4785+		return ERR_PTR(-ENOMEM);
4786+
4787+	ops = &clk_plldig_ops;
4788+
4789+	pll->base = base;
4790+	pll->type = type;
4791+	pll->plldv_mfd = plldv_mfd;
4792+	pll->pllfd_mfn = pllfd_mfn;
4793+	pll->plldv_rfdphi = plldv_rfdphi;
4794+	pll->plldv_rfdphi1 = plldv_rfdphi1;
4795+
4796+	init.name = name;
4797+	init.ops = ops;
4798+	init.flags = 0;
4799+	init.parent_names = &parent_name;
4800+	init.num_parents = 1;
4801+
4802+	pll->hw.init = &init;
4803+
4804+	clk = clk_register(NULL, &pll->hw);
4805+	if (IS_ERR(clk))
4806+		kfree(pll);
4807+
4808+	return clk;
4809+}
4810diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c
4811new file mode 100644
4812index 000000000..ad88c6b45
4813--- /dev/null
4814+++ b/drivers/clk/s32/s32v234/clk.c
4815@@ -0,0 +1,299 @@
4816+// SPDX-License-Identifier: GPL-2.0-or-later
4817+/*
4818+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
4819+ * Copyright 2017-2018 NXP
4820+ */
4821+
4822+#include <linux/of_address.h>
4823+#include <linux/clk.h>
4824+#include <dt-bindings/clock/s32v234-clock.h>
4825+
4826+#include "clk.h"
4827+
4828+static void __iomem *mc_cgm0_base;
4829+static void __iomem *mc_cgm1_base;
4830+static void __iomem *mc_cgm2_base;
4831+static void __iomem *mc_cgm3_base;
4832+static void __iomem *mc_me_base;
4833+static void __iomem *src_base;
4834+
4835+DEFINE_SPINLOCK(s32v234_lock);
4836+
4837+/* sources for multiplexer clocks, this is used multiple times */
4838+PNAME(osc_sels) = {"firc", "fxosc", };
4839+
4840+PNAME(sys_sels) = {"firc", "fxosc", "armpll_dfs0", };
4841+
4842+PNAME(can_sels) = {"firc", "fxosc", "dummy",
4843+		   "periphpll_phi0_div5", };
4844+
4845+PNAME(lin_sels) = {"firc", "fxosc", "dummy",
4846+		   "periphpll_phi0_div3", "dummy", "dummy",
4847+		   "dummy", "dummy", "sys6",};
4848+
4849+PNAME(sdhc_sels) = {"firc", "fxosc", "dummy", "dummy",
4850+		    "enetpll_dfs3",};
4851+
4852+PNAME(enet_sels) = {"firc", "fxosc", "dummy",
4853+		    "dummy", "enetpll_phi0",};
4854+
4855+PNAME(enet_time_sels) = {"firc", "fxosc", "dummy",
4856+			 "dummy", "enetpll_phi0",};
4857+
4858+static struct clk *clk[S32V234_CLK_END];
4859+static struct clk_onecell_data clk_data;
4860+
4861+static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node)
4862+{
4863+	struct device_node *np;
4864+
4865+	clk[S32V234_CLK_DUMMY] = s32_clk_fixed("dummy", 0);
4866+	clk[S32V234_CLK_FXOSC] = s32_obtain_fixed_clock("fxosc", 0);
4867+	clk[S32V234_CLK_FIRC] = s32_obtain_fixed_clock("firc", 0);
4868+
4869+	np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_me");
4870+	mc_me_base = of_iomap(np, 0);
4871+	if (WARN_ON(!mc_me_base))
4872+		return;
4873+
4874+	np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-src");
4875+	src_base = of_iomap(np, 0);
4876+	if (WARN_ON(!src_base))
4877+		return;
4878+
4879+	np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm1");
4880+	mc_cgm1_base = of_iomap(np, 0);
4881+	if (WARN_ON(!mc_cgm1_base))
4882+		return;
4883+
4884+	np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm2");
4885+	mc_cgm2_base = of_iomap(np, 0);
4886+	if (WARN_ON(!mc_cgm2_base))
4887+		return;
4888+
4889+	np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm3");
4890+	mc_cgm3_base = of_iomap(np, 0);
4891+	if (WARN_ON(!mc_cgm3_base))
4892+		return;
4893+
4894+	np = mc_cgm0_node;
4895+	mc_cgm0_base = of_iomap(np, 0);
4896+	if (WARN_ON(!mc_cgm0_base))
4897+		return;
4898+
4899+	enable_cpumodes_onperipheralconfig(mc_me_base, MC_ME_RUN_PCn_DRUN |
4900+					    MC_ME_RUN_PCn_RUN0 |
4901+					    MC_ME_RUN_PCn_RUN1 |
4902+					    MC_ME_RUN_PCn_RUN2 |
4903+					    MC_ME_RUN_PCn_RUN3,
4904+					    0);
4905+
4906+	/* turn on XOSC and FIRC */
4907+	enable_clocks_sources(MC_ME_MODE_MC_MVRON, MC_ME_MODE_MC_XOSCON |
4908+			      MC_ME_MODE_MC_FIRCON,
4909+			      MC_ME_RUNn_MC(mc_me_base, 0));
4910+
4911+	/* transition the core to RUN0 mode */
4912+	entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0);
4913+
4914+	clk[S32V234_CLK_ARMPLL_SRC_SEL] = s32_clk_mux("armpll_sel",
4915+		SRC_GPR1, SRC_GPR1_ARMPLL_SRC_SEL_OFFSET,
4916+		SRC_GPR1_XPLL_SRC_SEL_SIZE,
4917+		osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock);
4918+
4919+	clk[S32V234_CLK_PERIPHPLL_SRC_SEL] = s32_clk_mux("periphpll_sel",
4920+		SRC_GPR1, SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET,
4921+		SRC_GPR1_XPLL_SRC_SEL_SIZE,
4922+		osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock);
4923+
4924+	clk[S32V234_CLK_ENETPLL_SRC_SEL] = s32_clk_mux("enetpll_sel",
4925+		SRC_GPR1, SRC_GPR1_ENETPLL_SRC_SEL_OFFSET,
4926+		SRC_GPR1_XPLL_SRC_SEL_SIZE,
4927+		osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock);
4928+
4929+	/* ARM_PLL */
4930+	clk[S32V234_CLK_ARMPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_ARM,
4931+		"armpll_vco", "armpll_sel", ARMPLL_PLLDIG(mc_cgm0_base),
4932+		ARMPLL_PLLDIG_PLLDV_MFD, ARMPLL_PLLDIG_PLLDV_MFN,
4933+		ARMPLL_PLLDIG_PLLDV_RFDPHI0, ARMPLL_PLLDIG_PLLDV_RFDPHI1);
4934+
4935+	clk[S32V234_CLK_ARMPLL_PHI0] = s32v234_clk_plldig_phi(S32_PLLDIG_ARM,
4936+		"armpll_phi0", "armpll_vco",
4937+		ARMPLL_PLLDIG(mc_cgm0_base), 0);
4938+
4939+	clk[S32V234_CLK_ARMPLL_PHI1] = s32v234_clk_plldig_phi(S32_PLLDIG_ARM,
4940+		"armpll_phi1", "armpll_vco",
4941+		ARMPLL_PLLDIG(mc_cgm0_base), 1);
4942+
4943+	clk[S32V234_CLK_ARMPLL_DFS0] = s32v234_clk_dfs(S32_PLLDIG_ARM,
4944+		 "armpll_dfs0", "armpll_phi1",
4945+		 ARMPLL_PLLDIG_DFS(mc_cgm0_base), 0,
4946+		 ARMPLL_PLLDIG_DFS0_MFN);
4947+
4948+	clk[S32V234_CLK_ARMPLL_DFS1] = s32v234_clk_dfs(S32_PLLDIG_ARM,
4949+		 "armpll_dfs1", "armpll_phi1",
4950+		 ARMPLL_PLLDIG_DFS(mc_cgm0_base), 1,
4951+		 ARMPLL_PLLDIG_DFS1_MFN);
4952+
4953+	clk[S32V234_CLK_ARMPLL_DFS2] = s32v234_clk_dfs(S32_PLLDIG_ARM,
4954+		 "armpll_dfs2", "armpll_phi1",
4955+		 ARMPLL_PLLDIG_DFS(mc_cgm0_base), 2,
4956+		 ARMPLL_PLLDIG_DFS2_MFN);
4957+
4958+	clk[S32V234_CLK_SYS_SEL] = s32_clk_mux("sys_sel",
4959+		MC_ME_RUNn_MC(mc_me_base, 0),
4960+		MC_ME_MODE_MC_SYSCLK_OFFSET,
4961+		MC_ME_MODE_MC_SYSCLK_SIZE,
4962+		sys_sels, ARRAY_SIZE(sys_sels), &s32v234_lock);
4963+
4964+	clk[S32V234_CLK_SYS3] = s32_clk_divider("sys3", "sys_sel",
4965+		CGM_SC_DCn(mc_cgm0_base, 0), MC_CGM_SC_DCn_PREDIV_OFFSET,
4966+		MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock);
4967+
4968+	clk[S32V234_CLK_SYS6] = s32_clk_divider("sys6", "sys_sel",
4969+		CGM_SC_DCn(mc_cgm0_base, 1), MC_CGM_SC_DCn_PREDIV_OFFSET,
4970+		MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock);
4971+
4972+	clk[S32V234_CLK_SYS6_DIV2] = s32_clk_divider("sys6_div2", "sys_sel",
4973+		CGM_SC_DCn(mc_cgm0_base, 2), MC_CGM_SC_DCn_PREDIV_OFFSET,
4974+		MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock);
4975+
4976+	/* PERIPH_PLL */
4977+	clk[S32V234_CLK_PERIPHPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_PERIPH,
4978+		"periphpll_vco", "periphpll_sel",
4979+		PERIPHPLL_PLLDIG(mc_cgm0_base),
4980+		PERIPHPLL_PLLDIG_PLLDV_MFD, PERIPHPLL_PLLDIG_PLLDV_MFN,
4981+		PERIPHPLL_PLLDIG_PLLDV_RFDPHI0,
4982+		PERIPHPLL_PLLDIG_PLLDV_RFDPHI1);
4983+
4984+	clk[S32V234_CLK_PERIPHPLL_PHI0] =
4985+		s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH,
4986+		"periphpll_phi0", "periphpll_vco",
4987+		PERIPHPLL_PLLDIG(mc_cgm0_base), 0);
4988+
4989+	clk[S32V234_CLK_PERIPHPLL_PHI1] =
4990+		s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH,
4991+		"periphpll_phi1", "periphpll_vco",
4992+		PERIPHPLL_PLLDIG(mc_cgm0_base), 1);
4993+
4994+	clk[S32V234_CLK_PERIPHPLL_PHI0_DIV3] = s32_clk_fixed_factor(
4995+		"periphpll_phi0_div3", "periphpll_phi0", 1, 3);
4996+
4997+	clk[S32V234_CLK_PERIPHPLL_PHI0_DIV5] = s32_clk_fixed_factor(
4998+		"periphpll_phi0_div5", "periphpll_phi0", 1, 5);
4999+
5000+	clk[S32V234_CLK_CAN_SEL] = s32_clk_mux("can_sel",
5001+		CGM_ACn_SC(mc_cgm0_base, 6),
5002+		MC_CGM_ACn_SEL_OFFSET,
5003+		MC_CGM_ACn_SEL_SIZE,
5004+		can_sels, ARRAY_SIZE(can_sels), &s32v234_lock);
5005+
5006+	/* CAN Clock */
5007+	clk[S32V234_CLK_CAN] = s32_clk_divider("can", "can_sel",
5008+		CGM_ACn_DCm(mc_cgm0_base, 6, 0),
5009+		MC_CGM_ACn_DCm_PREDIV_OFFSET,
5010+		MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock);
5011+
5012+	/* Lin Clock */
5013+	clk[S32V234_CLK_LIN_SEL] = s32_clk_mux("lin_sel",
5014+		CGM_ACn_SC(mc_cgm0_base, 3),
5015+		MC_CGM_ACn_SEL_OFFSET,
5016+		MC_CGM_ACn_SEL_SIZE,
5017+		lin_sels, ARRAY_SIZE(lin_sels), &s32v234_lock);
5018+
5019+	clk[S32V234_CLK_LIN] = s32_clk_divider("lin", "lin_sel",
5020+		CGM_ACn_DCm(mc_cgm0_base, 3, 0),
5021+		MC_CGM_ACn_DCm_PREDIV_OFFSET,
5022+		MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock);
5023+
5024+	clk[S32V234_CLK_LIN_IPG] = s32_clk_fixed_factor("lin_ipg",
5025+		"lin", 1, 2);
5026+
5027+	/* enable PERIPHPLL */
5028+	enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL,
5029+			      MC_ME_RUNn_MC(mc_me_base, 0));
5030+
5031+	/* ENET_PLL */
5032+	clk[S32V234_CLK_ENETPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_ENET,
5033+		"enetpll_vco", "enetpll_sel", ENETPLL_PLLDIG(mc_cgm0_base),
5034+		ENETPLL_PLLDIG_PLLDV_MFD, ENETPLL_PLLDIG_PLLDV_MFN,
5035+		ENETPLL_PLLDIG_PLLDV_RFDPHI0, ENETPLL_PLLDIG_PLLDV_RFDPHI1);
5036+
5037+	clk[S32V234_CLK_ENETPLL_PHI0] = s32v234_clk_plldig_phi(S32_PLLDIG_ENET,
5038+		"enetpll_phi0", "enetpll_vco",
5039+		ENETPLL_PLLDIG(mc_cgm0_base), 0);
5040+
5041+	clk[S32V234_CLK_ENETPLL_PHI1] = s32v234_clk_plldig_phi(S32_PLLDIG_ENET,
5042+		"enetpll_phi1", "enetpll_vco",
5043+		ENETPLL_PLLDIG(mc_cgm0_base), 1);
5044+
5045+	clk[S32V234_CLK_ENETPLL_DFS0] = s32v234_clk_dfs(S32_PLLDIG_ENET,
5046+		 "enetpll_dfs0", "enetpll_phi1",
5047+		 ENETPLL_PLLDIG_DFS(mc_cgm0_base), 0,
5048+		 ENETPLL_PLLDIG_DFS0_MFN);
5049+
5050+	clk[S32V234_CLK_ENETPLL_DFS1] = s32v234_clk_dfs(S32_PLLDIG_ENET,
5051+		 "enetpll_dfs1", "enetpll_phi1",
5052+		 ENETPLL_PLLDIG_DFS(mc_cgm0_base), 1,
5053+		 ENETPLL_PLLDIG_DFS1_MFN);
5054+
5055+	clk[S32V234_CLK_ENETPLL_DFS2] = s32v234_clk_dfs(S32_PLLDIG_ENET,
5056+		 "enetpll_dfs2", "enetpll_phi1",
5057+		 ENETPLL_PLLDIG_DFS(mc_cgm0_base), 2,
5058+		 ENETPLL_PLLDIG_DFS2_MFN);
5059+
5060+	clk[S32V234_CLK_ENETPLL_DFS3] = s32v234_clk_dfs(S32_PLLDIG_ENET,
5061+		 "enetpll_dfs3", "enetpll_phi1",
5062+		 ENETPLL_PLLDIG_DFS(mc_cgm0_base), 3,
5063+		 ENETPLL_PLLDIG_DFS3_MFN);
5064+
5065+	/* ENET Clock */
5066+	clk[S32V234_CLK_ENET_SEL] = s32_clk_mux("enet_sel",
5067+		CGM_ACn_SC(mc_cgm2_base, 2),
5068+		MC_CGM_ACn_SEL_OFFSET,
5069+		MC_CGM_ACn_SEL_SIZE,
5070+		enet_sels, ARRAY_SIZE(enet_sels), &s32v234_lock);
5071+
5072+	clk[S32V234_CLK_ENET_TIME_SEL] = s32_clk_mux("enet_time_sel",
5073+		CGM_ACn_SC(mc_cgm0_base, 7),
5074+		MC_CGM_ACn_SEL_OFFSET,
5075+		MC_CGM_ACn_SEL_SIZE,
5076+		enet_time_sels, ARRAY_SIZE(enet_time_sels), &s32v234_lock);
5077+
5078+	clk[S32V234_CLK_ENET] = s32_clk_divider("enet", "enet_sel",
5079+		CGM_ACn_DCm(mc_cgm2_base, 2, 0),
5080+		MC_CGM_ACn_DCm_PREDIV_OFFSET,
5081+		MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock);
5082+
5083+	clk[S32V234_CLK_ENET_TIME] = s32_clk_divider("enet_time",
5084+		"enet_time_sel",
5085+		CGM_ACn_DCm(mc_cgm0_base, 7, 1),
5086+		MC_CGM_ACn_DCm_PREDIV_OFFSET,
5087+		MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock);
5088+
5089+	/* SDHC Clock */
5090+	clk[S32V234_CLK_SDHC_SEL] = s32_clk_mux("sdhc_sel",
5091+		CGM_ACn_SC(mc_cgm0_base, 15),
5092+		MC_CGM_ACn_SEL_OFFSET,
5093+		MC_CGM_ACn_SEL_SIZE,
5094+		sdhc_sels, ARRAY_SIZE(sdhc_sels), &s32v234_lock);
5095+
5096+	clk[S32V234_CLK_SDHC] = s32_clk_divider("sdhc", "sdhc_sel",
5097+		CGM_ACn_DCm(mc_cgm0_base, 15, 0),
5098+		MC_CGM_ACn_DCm_PREDIV_OFFSET,
5099+		MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock);
5100+
5101+	/* set the system clock */
5102+	enable_sysclock(MC_ME_MODE_MC_SYSCLK(0x2),
5103+			MC_ME_RUNn_MC(mc_me_base, 0));
5104+
5105+	/* transition the core to RUN0 mode */
5106+	entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0);
5107+
5108+	/* Add the clocks to provider list */
5109+	clk_data.clks = clk;
5110+	clk_data.clk_num = ARRAY_SIZE(clk);
5111+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
5112+}
5113+
5114+CLK_OF_DECLARE(S32V234, "fsl,s32v234-mc_cgm0", s32v234_clocks_init);
5115diff --git a/drivers/clk/s32/s32v234/clk.h b/drivers/clk/s32/s32v234/clk.h
5116new file mode 100644
5117index 000000000..82a222483
5118--- /dev/null
5119+++ b/drivers/clk/s32/s32v234/clk.h
5120@@ -0,0 +1,31 @@
5121+/* SPDX-License-Identifier: GPL-2.0-or-later */
5122+/*
5123+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
5124+ * Copyright 2017-2018 NXP
5125+ */
5126+
5127+#ifndef __MACH_S32V234_CLK_H
5128+#define __MACH_S32V234_CLK_H
5129+
5130+#include <linux/spinlock.h>
5131+#include <linux/clk-provider.h>
5132+#include "mc_cgm.h"
5133+#include "mc_me.h"
5134+#include "pll.h"
5135+#include "src.h"
5136+#include "dfs.h"
5137+#include "../clk.h"
5138+
5139+struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name,
5140+			       const char *parent_name, void __iomem *base,
5141+			       u32 plldv_mfd, u32 plldv_mfn,
5142+			       u32 plldv_rfdphi, u32 plldv_rfdphi1);
5143+
5144+struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type,
5145+				   const char *name, const char *parent,
5146+				   void __iomem *base, u32 phi);
5147+
5148+struct clk *s32v234_clk_dfs(enum s32v234_plldig_type type, const char *name,
5149+			    const char *parent_name,
5150+			    void __iomem *reg, u8 idx, u32 mfn);
5151+#endif
5152diff --git a/drivers/clk/s32/s32v234/dfs.h b/drivers/clk/s32/s32v234/dfs.h
5153new file mode 100644
5154index 000000000..be3104f7a
5155--- /dev/null
5156+++ b/drivers/clk/s32/s32v234/dfs.h
5157@@ -0,0 +1,78 @@
5158+/*
5159+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
5160+ * Copyright 2018 NXP
5161+ *
5162+ * This program is free software; you can redistribute it and/or modify
5163+ * it under the terms of the GNU General Public License as published by
5164+ * the Free Software Foundation; either version 2 of the License, or
5165+ * (at your option) any later version.
5166+ */
5167+#ifndef _DFS_S32V234_H
5168+#define _DFS_S32V234_H
5169+
5170+/* DFS Control Register (DFS_CTRL) */
5171+#define DFS_CTRL(base)		((base) + 0x00000018)
5172+#define DFS_CTRL_DLL_LOLIE	(1 << 0)
5173+#define DFS_CTRL_DLL_RESET	(1 << 1)
5174+
5175+/* DFS Port Status (DFS_PORTSR) */
5176+#define DFS_PORTSR(base)	((base) + 0x0000000C)
5177+#define DFS_PORTSR_MASK		(0x0000000F)
5178+#define DFS_PORTSR_OFFSET	(28)
5179+
5180+/* DFS Port Reset Register (DFS_PORTRESET) */
5181+#define DFS_PORTRESET(base)	((base) + 0x00000014)
5182+#define DFS_PORTRESET_PORTRESET_SET(val) \
5183+		(DFS_PORTRESET_PORTRESET_MASK | \
5184+		(((val) & DFS_PORTRESET_PORTRESET_MAXVAL) \
5185+		<< DFS_PORTRESET_PORTRESET_OFFSET))
5186+#define DFS_PORTRESET_PORTRESET_MAXVAL		(0xF)
5187+#define DFS_PORTRESET_PORTRESET_MASK		(0x0000000F)
5188+#define DFS_PORTRESET_PORTRESET_OFFSET		(28)
5189+
5190+/* DFS Divide Register Portn (DFS_DVPORTn) */
5191+#define DFS_DVPORTn(base, n)		((base) + (0x0000001C + \
5192+					((n) * sizeof(u32))))
5193+#define DFS_DVPORTn_MFI_SET(val)	(DFS_DVPORTn_MFI_MASK & \
5194+					(((val) & DFS_DVPORTn_MFI_MAXVAL) \
5195+					<< DFS_DVPORTn_MFI_OFFSET))
5196+#define DFS_DVPORTn_MFN_SET(val)	(DFS_DVPORTn_MFN_MASK & \
5197+					(((val) & DFS_DVPORTn_MFN_MAXVAL) \
5198+					<< DFS_DVPORTn_MFN_OFFSET))
5199+#define DFS_DVPORTn_MFI_MASK		(0x0000FF00)
5200+#define DFS_DVPORTn_MFN_MASK		(0x000000FF)
5201+#define DFS_DVPORTn_MFI_MAXVAL		(0xFF)
5202+#define DFS_DVPORTn_MFN_MAXVAL		(0xFF)
5203+#define DFS_DVPORTn_MFI_OFFSET		(8)
5204+#define DFS_DVPORTn_MFN_OFFSET		(0)
5205+#define DFS_MAXNUMBER			(4)
5206+
5207+/*
5208+ * Naming convention for PLL:
5209+ * ARMPLL - PLL0
5210+ * PERIPHPLL - PLL1
5211+ * ENETPLL - PLL2
5212+ * DDRPLL - PLL3
5213+ * VIDEOPLL - PLL4
5214+ */
5215+
5216+/* The max values for PLL DFS is in Hz */
5217+/* ARMPLL */
5218+#define ARMPLL_DFS0_MAX_RATE		(266000000)
5219+#define ARMPLL_DFS1_MAX_RATE		(600000000)
5220+#define ARMPLL_DFS2_MAX_RATE		(600000000)
5221+/* ENETPLL */
5222+#define ENETPLL_DFS0_MAX_RATE		(350000000)
5223+#define ENETPLL_DFS1_MAX_RATE		(350000000)
5224+#define ENETPLL_DFS2_MAX_RATE		(416000000)
5225+#define ENETPLL_DFS3_MAX_RATE		(104000000)
5226+/* DDRPLL */
5227+#define DDRPLL_DFS0_MAX_RATE		(500000000)
5228+#define DDRPLL_DFS1_MAX_RATE		(500000000)
5229+#define DDRPLL_DFS2_MAX_RATE		(350000000)
5230+
5231+#define ARMPLL_DFS_NR			(3)
5232+#define ENETPLL_DFS_NR			(4)
5233+#define DDRPLL_DFS_NR			(3)
5234+
5235+#endif
5236diff --git a/drivers/clk/s32/s32v234/mc_cgm.h b/drivers/clk/s32/s32v234/mc_cgm.h
5237new file mode 100644
5238index 000000000..aeac68771
5239--- /dev/null
5240+++ b/drivers/clk/s32/s32v234/mc_cgm.h
5241@@ -0,0 +1,70 @@
5242+/* SPDX-License-Identifier: GPL-2.0-or-later */
5243+/*
5244+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
5245+ * Copyright (C) 2017 NXP
5246+ */
5247+#ifndef _MC_CGM_H
5248+#define _MC_CGM_H
5249+
5250+#define ARMPLL_PLLDIG(mc_cgm)		(mc_cgm)
5251+#define ARMPLL_PLLDIG_DFS(mc_cgm)	((mc_cgm) + 0x40)
5252+#define ARMPLL_PLLDIG_PLLDV_MFD		(50)
5253+#define ARMPLL_PLLDIG_PLLDV_MFN		(0)
5254+#define ARMPLL_PLLDIG_PLLDV_RFDPHI0	(1)
5255+#define ARMPLL_PLLDIG_PLLDV_RFDPHI1	(1)
5256+#define ARMPLL_PLLDIG_DFS0_MFN		(195)
5257+#define ARMPLL_PLLDIG_DFS1_MFN		(171)
5258+#define ARMPLL_PLLDIG_DFS2_MFN		(171)
5259+
5260+#define PERIPHPLL_PLLDIG(mc_cgm)	((mc_cgm) + 0x80)
5261+#define PERIPHPLL_PLLDIG_PLLDV_MFD	(30)
5262+#define PERIPHPLL_PLLDIG_PLLDV_MFN	(0)
5263+#define PERIPHPLL_PLLDIG_PLLDV_RFDPHI0	(0x1)
5264+#define PERIPHPLL_PLLDIG_PLLDV_RFDPHI1	(0x1)
5265+
5266+#define ENETPLL_PLLDIG(mc_cgm)		((mc_cgm) + 0x100)
5267+#define ENETPLL_PLLDIG_DFS(mc_cgm)	((mc_cgm) + 0x100 + 0x40)
5268+#define ENETPLL_PLLDIG_PLLDV_MFD	(50)
5269+#define ENETPLL_PLLDIG_PLLDV_MFN	(0)
5270+#define ENETPLL_PLLDIG_PLLDV_RFDPHI0	(0x1)
5271+#define ENETPLL_PLLDIG_PLLDV_RFDPHI1	(0x1)
5272+#define ENETPLL_PLLDIG_DFS0_MFN		(220)
5273+#define ENETPLL_PLLDIG_DFS1_MFN		(220)
5274+#define ENETPLL_PLLDIG_DFS2_MFN		(33)
5275+#define ENETPLL_PLLDIG_DFS3_MFN		(1)
5276+
5277+/* MC_CGM_SC_SS */
5278+#define CGM_SC_SS(mc_cgm)		(((mc_cgm) + 0x7E4))
5279+
5280+/* MC_CGM_SC_DCn */
5281+#define CGM_SC_DCn(mc_cgm, dc)		(((mc_cgm) + 0x7E8) + ((dc) * 0x4))
5282+
5283+#define MC_CGM_SC_DCn_PREDIV_OFFSET	(16)
5284+#define MC_CGM_SC_DCn_PREDIV_SIZE	(3)
5285+#define MC_CGM_SC_DCn_DE		(1 << 31)
5286+#define MC_CGM_SC_SEL_OFFSET		(24)
5287+#define MC_CGM_SC_SEL_SIZE		(4)
5288+
5289+/* MC_CGM_ACn_DCm */
5290+#define CGM_ACn_DCm(mc_cgm, ac, dc)	(((mc_cgm) + 0x808) + ((ac) * 0x20)\
5291+					+ ((dc) * 0x4))
5292+
5293+#define MC_CGM_ACn_DCm_PREDIV(val)	(MC_CGM_ACn_DCm_PREDIV_MASK & \
5294+					((val) \
5295+					<< MC_CGM_ACn_DCm_PREDIV_OFFSET))
5296+#define MC_CGM_ACn_DCm_PREDIV_MASK	(0x001F0000)
5297+#define MC_CGM_ACn_DCm_PREDIV_OFFSET	(16)
5298+#define MC_CGM_ACn_DCm_PREDIV_SIZE	(5)
5299+#define MC_CGM_ACn_DCm_DE		(1 << 31)
5300+
5301+/* MC_CGM_ACn_SC/MC_CGM_ACn_SS */
5302+#define CGM_ACn_SC(mc_cgm, ac)		(((mc_cgm) + 0x800) + ((ac) * 0x20))
5303+#define CGM_ACn_SS(mc_cgm, ac)		(((mc_cgm) + 0x804) + ((ac) * 0x24))
5304+#define MC_CGM_ACn_SEL_MASK		(0x07000000)
5305+#define MC_CGM_ACn_SEL_SET(source)	(MC_CGM_ACn_SEL_MASK & \
5306+					(((source) & 0x7) \
5307+					<< MC_CGM_ACn_SEL_OFFSET))
5308+#define MC_CGM_ACn_SEL_OFFSET		(24)
5309+#define MC_CGM_ACn_SEL_SIZE		(4)
5310+
5311+#endif
5312diff --git a/drivers/clk/s32/s32v234/mc_me.h b/drivers/clk/s32/s32v234/mc_me.h
5313new file mode 100644
5314index 000000000..718f1d1a0
5315--- /dev/null
5316+++ b/drivers/clk/s32/s32v234/mc_me.h
5317@@ -0,0 +1,110 @@
5318+/* SPDX-License-Identifier: GPL-2.0-or-later */
5319+/*
5320+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
5321+ * Copyright (C) 2017 NXP
5322+ */
5323+
5324+#ifndef _MC_ME_H
5325+#define _MC_ME_H
5326+
5327+/* MC_ME registers definitions */
5328+/* MC_ME_GS */
5329+ #define MC_ME_GS(mc_me)                ((mc_me) + 0x00000000)
5330+
5331+/* MC_ME_MCTL */
5332+#define MC_ME_MCTL(mc_me)               ((mc_me) + 0x00000004)
5333+#define MC_ME_MCTL_RESET                (0x0 << 28)
5334+#define MC_ME_MCTL_TEST                 (0x1 << 28)
5335+#define MC_ME_MCTL_DRUN                 (0x3 << 28)
5336+#define MC_ME_MCTL_RUN0                 (0x4 << 28)
5337+#define MC_ME_MCTL_RUN1                 (0x5 << 28)
5338+#define MC_ME_MCTL_RUN2                 (0x6 << 28)
5339+#define MC_ME_MCTL_RUN3                 (0x7 << 28)
5340+
5341+#define MC_ME_GS_S_MTRANS               (1 << 27)
5342+
5343+#define MC_ME_MCTL_KEY                  (0x00005AF0)
5344+#define MC_ME_MCTL_INVERTEDKEY          (0x0000A50F)
5345+
5346+/*
5347+ * MC_ME_RESET_MC/MC_ME_TEST_MC
5348+ * MC_ME_DRUN_MC
5349+ * MC_ME_RUNn_MC
5350+ */
5351+#define MC_ME_RESET_MC(mc_me)           ((mc_me) + 0x00000020)
5352+#define MC_ME_TEST_MC(mc_me)            ((mc_me) + 0x00000024)
5353+#define MC_ME_DRUN_MC(mc_me)            ((mc_me) + 0x0000002C)
5354+#define MC_ME_RUNn_MC(mc_me, n)         ((mc_me) + 0x00000030 + 0x4 * (n))
5355+#define MC_ME_MODE_MC_SYSCLK_OFFSET     (0)
5356+#define MC_ME_MODE_MC_SYSCLK_SIZE       (0x3)
5357+#define MC_ME_MODE_MC_SYSCLK(val)       (MC_ME_MODE_MC_SYSCLK_MASK & (val))
5358+#define MC_ME_MODE_MC_SYSCLK_MASK       (0x0000000F)
5359+#define MC_ME_MODE_MC_FIRCON            (1 << 4)
5360+#define MC_ME_MODE_MC_XOSCON            (1 << 5)
5361+#define MC_ME_MODE_MC_ARMPLL            (1 << 6)
5362+#define MC_ME_MODE_MC_PERIPHPLL         (1 << 7)
5363+#define MC_ME_MODE_MC_ENETPLL           (1 << 8)
5364+#define MC_ME_MODE_MC_DDRPLL            (1 << 9)
5365+#define MC_ME_MODE_MC_VIDEOPLL          (1 << 10)
5366+#define MC_ME_MODE_MC_MVRON             (1 << 20)
5367+
5368+/* MC_ME_DRUN_SEC_CC_I */
5369+#define MC_ME_DRUN_SEC_CC_I(mc_me)              ((mc_me) + 0x260)
5370+/* MC_ME_RUNn_SEC_CC_I */
5371+#define MC_ME_RUNn_SEC_CC_I(mc_me, n)           ((mc_me) + 0x270 + (n) * 0x10)
5372+#define MC_ME_MODE_SEC_CC_I_SYSCLK1_OFFSET      (4)
5373+#define MC_ME_MODE_SEC_CC_I_SYSCLK2_OFFSET      (8)
5374+#define MC_ME_MODE_SEC_CC_I_SYSCLK3_OFFSET      (12)
5375+/* Consider only the defined clocks */
5376+#define MC_ME_MODE_SEC_CC_I_SYSCLK1_SIZE        (0x3)
5377+#define MC_ME_MODE_SEC_CC_I_SYSCLK2_SIZE        (0x3)
5378+#define MC_ME_MODE_SEC_CC_I_SYSCLK3_SIZE        (0x3)
5379+
5380+/* MC_ME_RUN_PCn */
5381+#define MC_ME_RUN_PCn(mc_me, n)         (mc_me + 0x00000080 + 0x4 * (n))
5382+
5383+#define MC_ME_RUN_PCn_MAX_IDX           (7)
5384+#define MC_ME_RUN_PCn_RESET             (1 << 0)
5385+#define MC_ME_RUN_PCn_TEST              (1 << 1)
5386+#define MC_ME_RUN_PCn_DRUN              (1 << 3)
5387+#define MC_ME_RUN_PCn_RUN0              (1 << 4)
5388+#define MC_ME_RUN_PCn_RUN1              (1 << 5)
5389+#define MC_ME_RUN_PCn_RUN2              (1 << 6)
5390+#define MC_ME_RUN_PCn_RUN3              (1 << 7)
5391+
5392+#define MC_ME_PCTLn(mc_me, n)           (mc_me + 0xC0 + 4 * (n >> 2) + \
5393+					(3 - (n) % 4))
5394+
5395+static inline void entry_to_target_mode(void __iomem *mc_me, u32 mode)
5396+{
5397+	writel_relaxed(mode | MC_ME_MCTL_KEY, MC_ME_MCTL(mc_me));
5398+	writel_relaxed(mode | MC_ME_MCTL_INVERTEDKEY, MC_ME_MCTL(mc_me));
5399+	while ((readl_relaxed(MC_ME_GS(mc_me)) &
5400+		MC_ME_GS_S_MTRANS) != 0x00000000)
5401+		;
5402+}
5403+
5404+static inline void enable_cpumodes_onperipheralconfig(void __iomem *mc_me,
5405+						      u32 modes, u32 run_pc_idx)
5406+{
5407+	WARN_ON(run_pc_idx > MC_ME_RUN_PCn_MAX_IDX);
5408+	if (run_pc_idx > MC_ME_RUN_PCn_MAX_IDX)
5409+		return;
5410+
5411+	writel_relaxed(modes, MC_ME_RUN_PCn(mc_me, run_pc_idx));
5412+}
5413+
5414+static inline void enable_clocks_sources(u32 flags, u32 clks,
5415+					 void __iomem *xrun_mc_addr)
5416+{
5417+	writel_relaxed(readl_relaxed(xrun_mc_addr) | flags | clks,
5418+		       xrun_mc_addr);
5419+}
5420+
5421+static inline void enable_sysclock(u32 clk, void __iomem *xrun_mc_addr)
5422+{
5423+	writel_relaxed(readl_relaxed(xrun_mc_addr) & clk,
5424+		       xrun_mc_addr);
5425+}
5426+
5427+#endif
5428diff --git a/drivers/clk/s32/s32v234/pll.h b/drivers/clk/s32/s32v234/pll.h
5429new file mode 100644
5430index 000000000..b7bcc50f0
5431--- /dev/null
5432+++ b/drivers/clk/s32/s32v234/pll.h
5433@@ -0,0 +1,78 @@
5434+/* SPDX-License-Identifier: GPL-2.0-or-later */
5435+/*
5436+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
5437+ * Copyright (C) 2017-2018 NXP
5438+ */
5439+#ifndef _PLL_S32V234_H
5440+#define _PLL_S32V234_H
5441+
5442+/* PLLDIG PLL Divider Register (PLLDIG_PLLDV) */
5443+#define PLLDIG_PLLDV(base)		((base) + 0x00000028)
5444+#define PLLDIG_PLLDV_MFD_SET(val)	(PLLDIG_PLLDV_MFD_MASK & (val))
5445+#define PLLDIG_PLLDV_MFD_MASK		(0x000000FF)
5446+
5447+#define PLLDIG_PLLDV_RFDPHI_SET(val)	(PLLDIG_PLLDV_RFDPHI_MASK & \
5448+					(((val) & \
5449+					PLLDIG_PLLDV_RFDPHI_MAXVALUE) \
5450+					<< PLLDIG_PLLDV_RFDPHI_OFFSET))
5451+#define PLLDIG_PLLDV_RFDPHI_MASK	(0x003F0000)
5452+#define PLLDIG_PLLDV_RFDPHI_MAXVALUE	(0x3F)
5453+
5454+#define PLLDIG_PLLDV_RFDPHI_OFFSET	(16)
5455+
5456+#define PLLDIG_PLLDV_RFDPHI1_SET(val)   (PLLDIG_PLLDV_RFDPHI1_MASK & \
5457+					(((val) & \
5458+					PLLDIG_PLLDV_RFDPHI1_MAXVALUE) \
5459+					<< PLLDIG_PLLDV_RFDPHI1_OFFSET))
5460+#define PLLDIG_PLLDV_RFDPHI1_MASK	(0x7E000000)
5461+#define PLLDIG_PLLDV_RFDPHI1_MAXVALUE	(0x3F)
5462+#define PLLDIG_PLLDV_RFDPHI1_OFFSET	(25)
5463+
5464+#define PLLDIG_PLLDV_PREDIV_SET(val)	(PLLDIG_PLLDV_PREDIV_MASK & \
5465+					(((val) & \
5466+					PLLDIG_PLLDV_PREDIV_MAXVALUE) \
5467+					<< PLLDIG_PLLDV_PREDIV_OFFSET))
5468+#define PLLDIG_PLLDV_PREDIV_MASK	(0x00007000)
5469+#define PLLDIG_PLLDV_PREDIV_MAXVALUE	(0x7)
5470+#define PLLDIG_PLLDV_PREDIV_OFFSET	(12)
5471+
5472+/* PLLDIG PLL Fractional  Divide Register (PLLDIG_PLLFD) */
5473+#define PLLDIG_PLLFD(base)		((base) + 0x00000030)
5474+#define PLLDIG_PLLFD_MFN_SET(val)	(PLLDIG_PLLFD_MFN_MASK & (val))
5475+#define PLLDIG_PLLFD_MFN_MASK		(0x00007FFF)
5476+
5477+/* PLL Calibration Register 1 (PLLDIG_PLLCAL1) */
5478+#define PLLDIG_PLLCAL1(base)	((base) + 0x00000038)
5479+#define PLLDIG_PLLCAL1_NDAC1_SET(val)	(PLLDIG_PLLCAL1_NDAC1_MASK & \
5480+					((val) \
5481+					 << PLLDIG_PLLCAL1_NDAC1_OFFSET))
5482+#define PLLDIG_PLLCAL1_NDAC1_OFFSET	(24)
5483+#define PLLDIG_PLLCAL1_NDAC1_MASK	(0x7F000000)
5484+
5485+/* Naming convention for PLL:
5486+ * ARMPLL - PLL0
5487+ * PERIPHPLL - PLL1
5488+ * ENETPLL - PLL2
5489+ * DDRPLL - PLL3
5490+ * VIDEOPLL - PLL4
5491+ */
5492+/* The min,max values for PLL VCO (Hz) */
5493+#define PERIPHPLL_MAX_VCO_RATE          (1200000000)
5494+
5495+/* The min,max values for PLL PHI0 and PHI1 outputs (Hz) */
5496+#define PERIPHPLL_MAX_PHI0_MAX_RATE	(400000000)
5497+#define PERIPHPLL_MAX_PHI1_MAX_RATE	(100000000)
5498+
5499+/* The maximum value for PLL VCO according to data sheet */
5500+#define MAX_VCO_RATE			(1300000000)
5501+#define MIN_VCO_RATE			(650000000)
5502+
5503+enum s32v234_plldig_type {
5504+	S32_PLLDIG_ARM,
5505+	S32_PLLDIG_PERIPH,
5506+	S32_PLLDIG_ENET,
5507+	S32_PLLDIG_DDR,
5508+	S32_PLLDIG_VIDEO,
5509+};
5510+
5511+#endif
5512diff --git a/drivers/clk/s32/s32v234/src.h b/drivers/clk/s32/s32v234/src.h
5513new file mode 100644
5514index 000000000..39fa973b7
5515--- /dev/null
5516+++ b/drivers/clk/s32/s32v234/src.h
5517@@ -0,0 +1,17 @@
5518+/* SPDX-License-Identifier: GPL-2.0-or-later */
5519+/*
5520+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
5521+ */
5522+#ifndef _SRC_H
5523+#define _SRC_H
5524+
5525+/* Source Reset Control: General Purpose Register 1 */
5526+#define SRC_GPR1                                (src_base + 0x100)
5527+#define SRC_GPR1_ARMPLL_SRC_SEL_OFFSET          (27)
5528+#define SRC_GPR1_ENETPLL_SRC_SEL_OFFSET         (28)
5529+#define SRC_GPR1_DDRPLL_SRC_SEL_OFFSET          (29)
5530+#define SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET       (30)
5531+#define SRC_GPR1_VIDEOPLL_SRC_SEL_OFFSET        (31)
5532+#define SRC_GPR1_XPLL_SRC_SEL_SIZE              (1)
5533+
5534+#endif
5535