1129203Scognet// SPDX-License-Identifier: GPL-2.0
2129203Scognet/*
3129203Scognet * Copyright 2019 NXP
4129203Scognet * Copyright 2022 Purism
5129203Scognet * Peng Fan <peng.fan@nxp.com>
6129203Scognet */
7129203Scognet
8129203Scognet#include <common.h>
9129203Scognet#include <clk.h>
10129203Scognet#include <clk-uclass.h>
11129203Scognet#include <dm.h>
12129203Scognet#include <log.h>
13129203Scognet#include <asm/arch/clock.h>
14129203Scognet#include <asm/arch/imx-regs.h>
15129203Scognet#include <dt-bindings/clock/imx8mq-clock.h>
16129203Scognet
17129203Scognet#include "clk.h"
18129203Scognet
19129203Scognetstatic const char *const pll_ref_sels[] = { "clock-osc-25m", "clock-osc-27m", "clock-phy-27m", "dummy", };
20129203Scognetstatic const char *const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
21129203Scognetstatic const char *const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
22129203Scognetstatic const char *const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
23129203Scognetstatic const char *const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
24129203Scognetstatic const char *const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
25129203Scognetstatic const char *const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
26129203Scognet
27129203Scognetstatic const char *const imx8mq_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
28129203Scognetstatic const char *const imx8mq_a53_sels[] = {"clock-osc-25m", "arm_pll_out", "sys_pll2_500m",
29129203Scognet					      "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
30129203Scognet					      "audio_pll1_out", "sys_pll3_out", };
31129203Scognet
32129203Scognetstatic const char *const imx8mq_ahb_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_800m",
33129203Scognet					      "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
34129203Scognet					      "audio_pll1_out", "video_pll1_out", };
35129203Scognet
36129203Scognetstatic const char *const imx8mq_dram_alt_sels[] = {"osc_25m", "sys_pll1_800m", "sys_pll1_100m",
37129203Scognet						   "sys_pll2_500m", "sys_pll2_250m",
38129203Scognet						   "sys_pll1_400m", "audio_pll1_out", "sys_pll1_266m", }  ;
39129203Scognet
40129203Scognetstatic const char * const imx8mq_dram_apb_sels[] = {"osc_25m", "sys_pll2_200m", "sys_pll1_40m",
41129203Scognet						    "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
42129203Scognet						    "sys_pll2_250m", "audio_pll2_out", };
43129203Scognet
44129203Scognetstatic const char *const imx8mq_enet_axi_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m",
45129203Scognet						   "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
46129203Scognet						   "video_pll1_out", "sys_pll3_out", };
47129203Scognet
48129203Scognetstatic const char *const imx8mq_enet_ref_sels[] = {"clock-osc-25m", "sys_pll2_125m", "sys_pll2_50m",
49129203Scognet						   "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
50129203Scognet						   "video_pll1_out", "clk_ext4", };
51129203Scognet
52129203Scognetstatic const char *const imx8mq_enet_timer_sels[] = {"clock-osc-25m", "sys_pll2_100m", "audio_pll1_out",
53129203Scognet						     "clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4",
54129203Scognet						     "video_pll1_out", };
55129203Scognet
56129203Scognetstatic const char *const imx8mq_enet_phy_sels[] = {"clock-osc-25m", "sys_pll2_50m", "sys_pll2_125m",
57129203Scognet						   "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out",
58129203Scognet						   "audio_pll2_out", };
59129203Scognet
60129203Scognetstatic const char *const imx8mq_nand_usdhc_sels[] = {"clock-osc-25m", "sys_pll1_266m", "sys_pll1_800m",
61129203Scognet						     "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
62129203Scognet						     "sys_pll2_250m", "audio_pll1_out", };
63129203Scognet
64static const char *const imx8mq_usb_bus_sels[] = {"clock-osc-25m", "sys_pll2_500m", "sys_pll1_800m",
65						  "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
66						  "clk_ext4", "audio_pll2_out", };
67
68static const char *const imx8mq_usdhc1_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m",
69						 "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
70						 "audio_pll2_out", "sys_pll1_100m", };
71
72static const char *const imx8mq_usdhc2_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll1_800m",
73						 "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
74						 "audio_pll2_out", "sys_pll1_100m", };
75
76static const char *const imx8mq_i2c1_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
77					       "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
78					       "audio_pll2_out", "sys_pll1_133m", };
79
80static const char *const imx8mq_i2c2_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
81					       "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
82					       "audio_pll2_out", "sys_pll1_133m", };
83
84static const char *const imx8mq_i2c3_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
85					       "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
86					       "audio_pll2_out", "sys_pll1_133m", };
87
88static const char *const imx8mq_i2c4_sels[] = {"clock-osc-25m", "sys_pll1_160m", "sys_pll2_50m",
89					       "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
90					       "audio_pll2_out", "sys_pll1_133m", };
91
92static const char *const imx8mq_uart1_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m",
93						"sys_pll2_100m", "sys_pll3_out", "clk_ext2",
94						"clk_ext4", "audio_pll2_out", };
95
96static const char *const imx8mq_uart2_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m",
97						"sys_pll2_100m", "sys_pll3_out", "clk_ext2",
98						"clk_ext3", "audio_pll2_out", };
99
100static const char *const imx8mq_uart3_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m",
101						"sys_pll2_100m", "sys_pll3_out", "clk_ext2",
102						"clk_ext4", "audio_pll2_out", };
103
104static const char *const imx8mq_uart4_sels[] = {"clock-osc-25m", "sys_pll1_80m", "sys_pll2_200m",
105						"sys_pll2_100m", "sys_pll3_out", "clk_ext2",
106						"clk_ext3", "audio_pll2_out", };
107
108static const char *const imx8mq_wdog_sels[] = {"clock-osc-25m", "sys_pll1_133m", "sys_pll1_160m",
109					       "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
110					       "sys_pll1_80m", "sys_pll2_166m", };
111
112static const char *const imx8mq_qspi_sels[] = {"clock-osc-25m", "sys_pll1_400m", "sys_pll2_333m",
113					       "sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
114					       "sys_pll3_out", "sys_pll1_100m", };
115
116static const char *const imx8mq_usb_core_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m",
117						   "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
118						   "clk_ext3", "audio_pll2_out", };
119
120static const char *const imx8mq_usb_phy_sels[] = {"clock-osc-25m", "sys_pll1_100m", "sys_pll1_40m",
121						  "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
122						  "clk_ext3", "audio_pll2_out", };
123
124static const char *const imx8mq_ecspi1_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
125						 "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
126						 "sys_pll2_250m", "audio_pll2_out", };
127
128static const char *const imx8mq_ecspi2_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
129						 "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
130						 "sys_pll2_250m", "audio_pll2_out", };
131
132static const char *const imx8mq_ecspi3_sels[] = {"clock-osc-25m", "sys_pll2_200m", "sys_pll1_40m",
133						 "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
134						 "sys_pll2_250m", "audio_pll2_out", };
135
136static const char *const imx8mq_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
137
138static const char *const pllout_monitor_sels[] = {"clock-osc-25m", "clock-osc-27m", "clock-phy-27m",
139						  "dummy", "clock-ckil", "audio_pll1_out_monitor",
140						  "audio_pll2_out_monitor", "gpu_pll_out_monitor",
141						  "vpu_pll_out_monitor", "video_pll1_out_monitor",
142						  "arm_pll_out_monitor", "sys_pll1_out_monitor",
143						  "sys_pll2_out_monitor", "sys_pll3_out_monitor",
144						  "video_pll2_out_monitor", "dram_pll_out_monitor", };
145
146static int imx8mq_clk_probe(struct udevice *dev)
147{
148	void __iomem *base;
149
150	base = (void *)ANATOP_BASE_ADDR;
151
152	clk_dm(IMX8MQ_CLK_32K, clk_register_fixed_rate(NULL, "ckil", 32768));
153	clk_dm(IMX8MQ_CLK_27M, clk_register_fixed_rate(NULL, "clock-osc-27m", 27000000));
154
155	clk_dm(IMX8MQ_DRAM_PLL1_REF_SEL,
156	       imx_clk_mux("dram_pll_ref_sel", base + 0x60, 0, 2,
157			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
158	clk_dm(IMX8MQ_ARM_PLL_REF_SEL,
159	       imx_clk_mux("arm_pll_ref_sel", base + 0x28, 0, 2,
160			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
161	clk_dm(IMX8MQ_GPU_PLL_REF_SEL,
162	       imx_clk_mux("gpu_pll_ref_sel", base + 0x18, 0, 2,
163			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
164	clk_dm(IMX8MQ_VPU_PLL_REF_SEL,
165	       imx_clk_mux("vpu_pll_ref_sel", base + 0x20, 0, 2,
166			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
167	clk_dm(IMX8MQ_SYS3_PLL1_REF_SEL,
168	       imx_clk_mux("sys3_pll_ref_sel", base + 0x48, 0, 2,
169			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
170	clk_dm(IMX8MQ_AUDIO_PLL1_REF_SEL,
171	       imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2,
172			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
173	clk_dm(IMX8MQ_AUDIO_PLL2_REF_SEL,
174	       imx_clk_mux("audio_pll2_ref_sel", base + 0x8, 0, 2,
175			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
176	clk_dm(IMX8MQ_VIDEO_PLL1_REF_SEL,
177	       imx_clk_mux("video_pll1_ref_sel", base + 0x10, 0, 2,
178			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
179	clk_dm(IMX8MQ_VIDEO2_PLL1_REF_SEL,
180	       imx_clk_mux("video_pll2_ref_sel", base + 0x54, 0, 2,
181			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
182
183	clk_dm(IMX8MQ_ARM_PLL,
184	       imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
185			       base + 0x28, &imx_1416x_pll));
186	clk_dm(IMX8MQ_GPU_PLL,
187	       imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel",
188			       base + 0x18, &imx_1416x_pll));
189	clk_dm(IMX8MQ_VPU_PLL,
190	       imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel",
191			       base + 0x20, &imx_1416x_pll));
192
193	clk_dm(IMX8MQ_SYS1_PLL1,
194	       clk_register_fixed_rate(NULL, "sys1_pll", 800000000));
195	clk_dm(IMX8MQ_SYS2_PLL1,
196	       clk_register_fixed_rate(NULL, "sys2_pll", 1000000000));
197	clk_dm(IMX8MQ_SYS2_PLL1,
198	       clk_register_fixed_rate(NULL, "sys3_pll", 1000000000));
199	clk_dm(IMX8MQ_AUDIO_PLL1,
200	       imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel",
201			       base + 0x0, &imx_1443x_pll));
202	clk_dm(IMX8MQ_AUDIO_PLL2,
203	       imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel",
204			       base + 0x8, &imx_1443x_pll));
205	clk_dm(IMX8MQ_VIDEO_PLL1,
206	       imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel",
207			       base + 0x10, &imx_1443x_pll));
208
209	/* PLL bypass out */
210	clk_dm(IMX8MQ_ARM_PLL_BYPASS,
211	       imx_clk_mux_flags("arm_pll_bypass", base + 0x28, 4, 1,
212				 arm_pll_bypass_sels,
213				 ARRAY_SIZE(arm_pll_bypass_sels),
214				 CLK_SET_RATE_PARENT));
215	clk_dm(IMX8MQ_GPU_PLL_BYPASS,
216	       imx_clk_mux_flags("gpu_pll_bypass", base + 0x18, 4, 1,
217				 gpu_pll_bypass_sels,
218				 ARRAY_SIZE(gpu_pll_bypass_sels),
219				 CLK_SET_RATE_PARENT));
220	clk_dm(IMX8MQ_VPU_PLL_BYPASS,
221	       imx_clk_mux_flags("vpu_pll_bypass", base + 0x20, 4, 1,
222				 vpu_pll_bypass_sels,
223				 ARRAY_SIZE(vpu_pll_bypass_sels),
224				 CLK_SET_RATE_PARENT));
225	clk_dm(IMX8MQ_AUDIO_PLL1_BYPASS,
226	       imx_clk_mux_flags("audio_pll1_bypass", base + 0x0, 4, 1,
227				 audio_pll1_bypass_sels,
228				 ARRAY_SIZE(audio_pll1_bypass_sels),
229				 CLK_SET_RATE_PARENT));
230	clk_dm(IMX8MQ_AUDIO_PLL2_BYPASS,
231	       imx_clk_mux_flags("audio_pll2_bypass", base + 0x8, 4, 1,
232				 audio_pll2_bypass_sels,
233				 ARRAY_SIZE(audio_pll2_bypass_sels),
234				 CLK_SET_RATE_PARENT));
235	clk_dm(IMX8MQ_VIDEO_PLL1_BYPASS,
236	       imx_clk_mux_flags("video_pll1_bypass", base + 0x10, 4, 1,
237				 video_pll1_bypass_sels,
238				 ARRAY_SIZE(video_pll1_bypass_sels),
239				 CLK_SET_RATE_PARENT));
240
241	/* PLL out gate */
242	clk_dm(IMX8MQ_DRAM_PLL_OUT,
243	       imx_clk_gate("dram_pll_out", "dram_pll_ref_sel",
244			    base + 0x60, 13));
245	clk_dm(IMX8MQ_ARM_PLL_OUT,
246	       imx_clk_gate("arm_pll_out", "arm_pll_bypass",
247			    base + 0x28, 11));
248	clk_dm(IMX8MQ_GPU_PLL_OUT,
249	       imx_clk_gate("gpu_pll_out", "gpu_pll_bypass",
250			    base + 0x18, 11));
251	clk_dm(IMX8MQ_VPU_PLL_OUT,
252	       imx_clk_gate("vpu_pll_out", "vpu_pll_bypass",
253			    base + 0x20, 11));
254	clk_dm(IMX8MQ_AUDIO_PLL1_OUT,
255	       imx_clk_gate("audio_pll1_out", "audio_pll1_bypass",
256			    base + 0x0, 11));
257	clk_dm(IMX8MQ_AUDIO_PLL2_OUT,
258	       imx_clk_gate("audio_pll2_out", "audio_pll2_bypass",
259			    base + 0x8, 11));
260	clk_dm(IMX8MQ_VIDEO_PLL1_OUT,
261	       imx_clk_gate("video_pll1_out", "video_pll1_bypass",
262			    base + 0x10, 11));
263
264	clk_dm(IMX8MQ_SYS1_PLL_OUT,
265	       imx_clk_gate("sys_pll1_out", "sys1_pll",
266			    base + 0x30, 11));
267	clk_dm(IMX8MQ_SYS2_PLL_OUT,
268	       imx_clk_gate("sys_pll2_out", "sys2_pll",
269			    base + 0x3c, 11));
270	clk_dm(IMX8MQ_SYS3_PLL_OUT,
271	       imx_clk_gate("sys_pll3_out", "sys3_pll",
272			    base + 0x48, 11));
273	clk_dm(IMX8MQ_VIDEO2_PLL_OUT,
274	       imx_clk_gate("video_pll2_out", "video_pll2_ref_sel",
275			    base + 0x54, 11));
276
277	/* SYS PLL fixed output */
278	clk_dm(IMX8MQ_SYS1_PLL_40M,
279	       imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20));
280	clk_dm(IMX8MQ_SYS1_PLL_80M,
281	       imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10));
282	clk_dm(IMX8MQ_SYS1_PLL_100M,
283	       imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8));
284	clk_dm(IMX8MQ_SYS1_PLL_133M,
285	       imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6));
286	clk_dm(IMX8MQ_SYS1_PLL_160M,
287	       imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5));
288	clk_dm(IMX8MQ_SYS1_PLL_200M,
289	       imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4));
290	clk_dm(IMX8MQ_SYS1_PLL_266M,
291	       imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3));
292	clk_dm(IMX8MQ_SYS1_PLL_400M,
293	       imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2));
294	clk_dm(IMX8MQ_SYS1_PLL_800M,
295	       imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1));
296
297	clk_dm(IMX8MQ_SYS2_PLL_50M,
298	       imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20));
299	clk_dm(IMX8MQ_SYS2_PLL_100M,
300	       imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10));
301	clk_dm(IMX8MQ_SYS2_PLL_125M,
302	       imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8));
303	clk_dm(IMX8MQ_SYS2_PLL_166M,
304	       imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6));
305	clk_dm(IMX8MQ_SYS2_PLL_200M,
306	       imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5));
307	clk_dm(IMX8MQ_SYS2_PLL_250M,
308	       imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4));
309	clk_dm(IMX8MQ_SYS2_PLL_333M,
310	       imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3));
311	clk_dm(IMX8MQ_SYS2_PLL_500M,
312	       imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2));
313	clk_dm(IMX8MQ_SYS2_PLL_1000M,
314	       imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1));
315
316	clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL1_DIV,
317	       imx_clk_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3));
318	clk_dm(IMX8MQ_CLK_MON_AUDIO_PLL2_DIV,
319	       imx_clk_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3));
320	clk_dm(IMX8MQ_CLK_MON_VIDEO_PLL1_DIV,
321	       imx_clk_divider("video_pll1_out_monitor", "video_pll1_bypass", base + 0x78, 8, 3));
322	clk_dm(IMX8MQ_CLK_MON_GPU_PLL_DIV,
323	       imx_clk_divider("gpu_pll_out_monitor", "gpu_pll_bypass", base + 0x78, 12, 3));
324	clk_dm(IMX8MQ_CLK_MON_VPU_PLL_DIV,
325	       imx_clk_divider("vpu_pll_out_monitor", "vpu_pll_bypass", base + 0x78, 16, 3));
326	clk_dm(IMX8MQ_CLK_MON_ARM_PLL_DIV,
327	       imx_clk_divider("arm_pll_out_monitor", "arm_pll_bypass", base + 0x78, 20, 3));
328	clk_dm(IMX8MQ_CLK_MON_SYS_PLL1_DIV,
329	       imx_clk_divider("sys_pll1_out_monitor", "sys_pll1_out", base + 0x7c, 0, 3));
330	clk_dm(IMX8MQ_CLK_MON_SYS_PLL2_DIV,
331	       imx_clk_divider("sys_pll2_out_monitor", "sys_pll2_out", base + 0x7c, 4, 3));
332	clk_dm(IMX8MQ_CLK_MON_SYS_PLL3_DIV,
333	       imx_clk_divider("sys_pll3_out_monitor", "sys_pll3_out", base + 0x7c, 8, 3));
334	clk_dm(IMX8MQ_CLK_MON_DRAM_PLL_DIV,
335	       imx_clk_divider("dram_pll_out_monitor", "dram_pll_out", base + 0x7c, 12, 3));
336	clk_dm(IMX8MQ_CLK_MON_VIDEO_PLL2_DIV,
337	       imx_clk_divider("video_pll2_out_monitor", "video_pll2_out", base + 0x7c, 16, 3));
338	clk_dm(IMX8MQ_CLK_MON_SEL,
339	       imx_clk_mux_flags("pllout_monitor_sel", base + 0x74, 0, 4,
340				 pllout_monitor_sels,
341				 ARRAY_SIZE(pllout_monitor_sels),
342				 CLK_SET_RATE_PARENT));
343	clk_dm(IMX8MQ_CLK_MON_CLK2_OUT,
344	       imx_clk_gate4("pllout_monitor_clk2", "pllout_monitor_sel", base + 0x74, 4));
345
346	base = dev_read_addr_ptr(dev);
347	if (!base) {
348		printf("%s : base failed\n", __func__);
349		return -EINVAL;
350	}
351
352	clk_dm(IMX8MQ_CLK_A53_SRC,
353	       imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
354			    imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels)));
355	clk_dm(IMX8MQ_CLK_A53_CG,
356	       imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28));
357	clk_dm(IMX8MQ_CLK_A53_DIV,
358	       imx_clk_divider2("arm_a53_div", "arm_a53_cg",
359				base + 0x8000, 0, 3));
360	clk_dm(IMX8MQ_CLK_A53_CORE,
361	       imx_clk_mux2("arm_a53_src", base + 0x9880, 24, 1,
362			    imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels)));
363
364	clk_dm(IMX8MQ_CLK_AHB,
365	       imx8m_clk_composite_critical("ahb", imx8mq_ahb_sels,
366					    base + 0x9000));
367	clk_dm(IMX8MQ_CLK_IPG_ROOT,
368	       imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
369
370	clk_dm(IMX8MQ_CLK_ENET_AXI,
371	       imx8m_clk_composite("enet_axi", imx8mq_enet_axi_sels,
372				   base + 0x8880));
373	clk_dm(IMX8MQ_CLK_NAND_USDHC_BUS,
374	       imx8m_clk_composite_critical("nand_usdhc_bus",
375					    imx8mq_nand_usdhc_sels,
376					    base + 0x8900));
377	clk_dm(IMX8MQ_CLK_USB_BUS,
378	       imx8m_clk_composite("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80));
379
380	/* DRAM */
381	clk_dm(IMX8MQ_CLK_DRAM_CORE,
382	       imx_clk_mux2("dram_core_clk", base + 0x9800, 24, 1,
383			    imx8mq_dram_core_sels, ARRAY_SIZE(imx8mq_dram_core_sels)));
384	clk_dm(IMX8MQ_CLK_DRAM_ALT,
385	       imx8m_clk_composite("dram_alt", imx8mq_dram_alt_sels, base + 0xa000));
386	clk_dm(IMX8MQ_CLK_DRAM_APB,
387	       imx8m_clk_composite_critical("dram_apb", imx8mq_dram_apb_sels, base + 0xa080));
388
389	/* IP */
390	clk_dm(IMX8MQ_CLK_USDHC1,
391	       imx8m_clk_composite("usdhc1", imx8mq_usdhc1_sels,
392				   base + 0xac00));
393	clk_dm(IMX8MQ_CLK_USDHC2,
394	       imx8m_clk_composite("usdhc2", imx8mq_usdhc2_sels,
395				   base + 0xac80));
396	clk_dm(IMX8MQ_CLK_I2C1,
397	       imx8m_clk_composite("i2c1", imx8mq_i2c1_sels, base + 0xad00));
398	clk_dm(IMX8MQ_CLK_I2C2,
399	       imx8m_clk_composite("i2c2", imx8mq_i2c2_sels, base + 0xad80));
400	clk_dm(IMX8MQ_CLK_I2C3,
401	       imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base + 0xae00));
402	clk_dm(IMX8MQ_CLK_I2C4,
403	       imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base + 0xae80));
404	clk_dm(IMX8MQ_CLK_WDOG,
405	       imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900));
406	clk_dm(IMX8MQ_CLK_UART1,
407	       imx8m_clk_composite("uart1", imx8mq_uart1_sels, base + 0xaf00));
408	clk_dm(IMX8MQ_CLK_UART2,
409	       imx8m_clk_composite("uart2", imx8mq_uart2_sels, base + 0xaf80));
410	clk_dm(IMX8MQ_CLK_UART3,
411	       imx8m_clk_composite("uart3", imx8mq_uart3_sels, base + 0xb000));
412	clk_dm(IMX8MQ_CLK_UART4,
413	       imx8m_clk_composite("uart4", imx8mq_uart4_sels, base + 0xb080));
414	clk_dm(IMX8MQ_CLK_QSPI,
415	       imx8m_clk_composite("qspi", imx8mq_qspi_sels, base + 0xab80));
416	clk_dm(IMX8MQ_CLK_USB_CORE_REF,
417	       imx8m_clk_composite("usb_core_ref", imx8mq_usb_core_sels, base + 0xb100));
418	clk_dm(IMX8MQ_CLK_USB_PHY_REF,
419	       imx8m_clk_composite("usb_phy_ref", imx8mq_usb_phy_sels, base + 0xb180));
420	clk_dm(IMX8MQ_CLK_ECSPI1,
421	       imx8m_clk_composite("ecspi1", imx8mq_ecspi1_sels, base + 0xb280));
422	clk_dm(IMX8MQ_CLK_ECSPI2,
423	       imx8m_clk_composite("ecspi2", imx8mq_ecspi2_sels, base + 0xb300));
424	clk_dm(IMX8MQ_CLK_ECSPI3,
425	       imx8m_clk_composite("ecspi3", imx8mq_ecspi3_sels, base + 0xc180));
426
427	clk_dm(IMX8MQ_CLK_ECSPI1_ROOT,
428	       imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0));
429	clk_dm(IMX8MQ_CLK_ECSPI2_ROOT,
430	       imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0));
431	clk_dm(IMX8MQ_CLK_ECSPI3_ROOT,
432	       imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0));
433	clk_dm(IMX8MQ_CLK_I2C1_ROOT,
434	       imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
435	clk_dm(IMX8MQ_CLK_I2C2_ROOT,
436	       imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
437	clk_dm(IMX8MQ_CLK_I2C3_ROOT,
438	       imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
439	clk_dm(IMX8MQ_CLK_I2C4_ROOT,
440	       imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
441	clk_dm(IMX8MQ_CLK_UART1_ROOT,
442	       imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0));
443	clk_dm(IMX8MQ_CLK_UART2_ROOT,
444	       imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0));
445	clk_dm(IMX8MQ_CLK_UART3_ROOT,
446	       imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0));
447	clk_dm(IMX8MQ_CLK_UART4_ROOT,
448	       imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0));
449	clk_dm(IMX8MQ_CLK_OCOTP_ROOT,
450	       imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0));
451	clk_dm(IMX8MQ_CLK_USDHC1_ROOT,
452	       imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0));
453	clk_dm(IMX8MQ_CLK_USDHC2_ROOT,
454	       imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0));
455	clk_dm(IMX8MQ_CLK_WDOG1_ROOT,
456	       imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
457	clk_dm(IMX8MQ_CLK_WDOG2_ROOT,
458	       imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
459	clk_dm(IMX8MQ_CLK_WDOG3_ROOT,
460	       imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
461	clk_dm(IMX8MQ_CLK_QSPI_ROOT,
462	       imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
463	clk_dm(IMX8MQ_CLK_USB1_CTRL_ROOT,
464	       imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0));
465	clk_dm(IMX8MQ_CLK_USB2_CTRL_ROOT,
466	       imx_clk_gate4("usb2_ctrl_root_clk", "usb_bus", base + 0x44e0, 0));
467	clk_dm(IMX8MQ_CLK_USB1_PHY_ROOT,
468	       imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0));
469	clk_dm(IMX8MQ_CLK_USB2_PHY_ROOT,
470	       imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base + 0x4500, 0));
471
472	clk_dm(IMX8MQ_CLK_ENET_REF,
473	       imx8m_clk_composite("enet_ref", imx8mq_enet_ref_sels,
474				   base + 0xa980));
475	clk_dm(IMX8MQ_CLK_ENET_TIMER,
476	       imx8m_clk_composite("enet_timer", imx8mq_enet_timer_sels,
477				   base + 0xaa00));
478	clk_dm(IMX8MQ_CLK_ENET_PHY_REF,
479	       imx8m_clk_composite("enet_phy", imx8mq_enet_phy_sels,
480				   base + 0xaa80));
481	clk_dm(IMX8MQ_CLK_ENET1_ROOT,
482	       imx_clk_gate4("enet1_root_clk", "enet_axi",
483			     base + 0x40a0, 0));
484
485	clk_dm(IMX8MQ_CLK_DRAM_ALT_ROOT,
486	       imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4));
487
488	return 0;
489}
490
491static const struct udevice_id imx8mq_clk_ids[] = {
492	{ .compatible = "fsl,imx8mq-ccm" },
493	{ },
494};
495
496U_BOOT_DRIVER(imx8mq_clk) = {
497	.name = "clk_imx8mq",
498	.id = UCLASS_CLK,
499	.of_match = imx8mq_clk_ids,
500	.ops = &ccf_clk_ops,
501	.probe = imx8mq_clk_probe,
502	.flags = DM_FLAG_PRE_RELOC,
503};
504