diff options
Diffstat (limited to 'arch/arm/mach-imx/imx8m/clock.c')
-rw-r--r-- | arch/arm/mach-imx/imx8m/clock.c | 878 |
1 files changed, 878 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/imx8m/clock.c b/arch/arm/mach-imx/imx8m/clock.c new file mode 100644 index 0000000000..289b9417aa --- /dev/null +++ b/arch/arm/mach-imx/imx8m/clock.c | |||
@@ -0,0 +1,878 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright 2017 NXP | ||
4 | * | ||
5 | * Peng Fan <peng.fan@nxp.com> | ||
6 | */ | ||
7 | |||
8 | #include <common.h> | ||
9 | #include <asm/arch/clock.h> | ||
10 | #include <asm/arch/imx-regs.h> | ||
11 | #include <asm/io.h> | ||
12 | #include <asm/arch/sys_proto.h> | ||
13 | #include <errno.h> | ||
14 | #include <linux/iopoll.h> | ||
15 | |||
16 | static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; | ||
17 | |||
18 | static u32 decode_frac_pll(enum clk_root_src frac_pll) | ||
19 | { | ||
20 | u32 pll_cfg0, pll_cfg1, pllout; | ||
21 | u32 pll_refclk_sel, pll_refclk; | ||
22 | u32 divr_val, divq_val, divf_val, divff, divfi; | ||
23 | u32 pllout_div_shift, pllout_div_mask, pllout_div; | ||
24 | |||
25 | switch (frac_pll) { | ||
26 | case ARM_PLL_CLK: | ||
27 | pll_cfg0 = readl(&ana_pll->arm_pll_cfg0); | ||
28 | pll_cfg1 = readl(&ana_pll->arm_pll_cfg1); | ||
29 | pllout_div_shift = HW_FRAC_ARM_PLL_DIV_SHIFT; | ||
30 | pllout_div_mask = HW_FRAC_ARM_PLL_DIV_MASK; | ||
31 | break; | ||
32 | default: | ||
33 | printf("Frac PLL %d not supporte\n", frac_pll); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | pllout_div = readl(&ana_pll->frac_pllout_div_cfg); | ||
38 | pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift; | ||
39 | |||
40 | /* Power down */ | ||
41 | if (pll_cfg0 & FRAC_PLL_PD_MASK) | ||
42 | return 0; | ||
43 | |||
44 | /* output not enabled */ | ||
45 | if ((pll_cfg0 & FRAC_PLL_CLKE_MASK) == 0) | ||
46 | return 0; | ||
47 | |||
48 | pll_refclk_sel = pll_cfg0 & FRAC_PLL_REFCLK_SEL_MASK; | ||
49 | |||
50 | if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_25M) | ||
51 | pll_refclk = 25000000u; | ||
52 | else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_27M) | ||
53 | pll_refclk = 27000000u; | ||
54 | else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_HDMI_PHY_27M) | ||
55 | pll_refclk = 27000000u; | ||
56 | else | ||
57 | pll_refclk = 0; | ||
58 | |||
59 | if (pll_cfg0 & FRAC_PLL_BYPASS_MASK) | ||
60 | return pll_refclk; | ||
61 | |||
62 | divr_val = (pll_cfg0 & FRAC_PLL_REFCLK_DIV_VAL_MASK) >> | ||
63 | FRAC_PLL_REFCLK_DIV_VAL_SHIFT; | ||
64 | divq_val = pll_cfg0 & FRAC_PLL_OUTPUT_DIV_VAL_MASK; | ||
65 | |||
66 | divff = (pll_cfg1 & FRAC_PLL_FRAC_DIV_CTL_MASK) >> | ||
67 | FRAC_PLL_FRAC_DIV_CTL_SHIFT; | ||
68 | divfi = pll_cfg1 & FRAC_PLL_INT_DIV_CTL_MASK; | ||
69 | |||
70 | divf_val = 1 + divfi + divff / (1 << 24); | ||
71 | |||
72 | pllout = pll_refclk / (divr_val + 1) * 8 * divf_val / | ||
73 | ((divq_val + 1) * 2); | ||
74 | |||
75 | return pllout / (pllout_div + 1); | ||
76 | } | ||
77 | |||
78 | static u32 decode_sscg_pll(enum clk_root_src sscg_pll) | ||
79 | { | ||
80 | u32 pll_cfg0, pll_cfg1, pll_cfg2; | ||
81 | u32 pll_refclk_sel, pll_refclk; | ||
82 | u32 divr1, divr2, divf1, divf2, divq, div; | ||
83 | u32 sse; | ||
84 | u32 pll_clke; | ||
85 | u32 pllout_div_shift, pllout_div_mask, pllout_div; | ||
86 | u32 pllout; | ||
87 | |||
88 | switch (sscg_pll) { | ||
89 | case SYSTEM_PLL1_800M_CLK: | ||
90 | case SYSTEM_PLL1_400M_CLK: | ||
91 | case SYSTEM_PLL1_266M_CLK: | ||
92 | case SYSTEM_PLL1_200M_CLK: | ||
93 | case SYSTEM_PLL1_160M_CLK: | ||
94 | case SYSTEM_PLL1_133M_CLK: | ||
95 | case SYSTEM_PLL1_100M_CLK: | ||
96 | case SYSTEM_PLL1_80M_CLK: | ||
97 | case SYSTEM_PLL1_40M_CLK: | ||
98 | pll_cfg0 = readl(&ana_pll->sys_pll1_cfg0); | ||
99 | pll_cfg1 = readl(&ana_pll->sys_pll1_cfg1); | ||
100 | pll_cfg2 = readl(&ana_pll->sys_pll1_cfg2); | ||
101 | pllout_div_shift = HW_SSCG_SYSTEM_PLL1_DIV_SHIFT; | ||
102 | pllout_div_mask = HW_SSCG_SYSTEM_PLL1_DIV_MASK; | ||
103 | break; | ||
104 | case SYSTEM_PLL2_1000M_CLK: | ||
105 | case SYSTEM_PLL2_500M_CLK: | ||
106 | case SYSTEM_PLL2_333M_CLK: | ||
107 | case SYSTEM_PLL2_250M_CLK: | ||
108 | case SYSTEM_PLL2_200M_CLK: | ||
109 | case SYSTEM_PLL2_166M_CLK: | ||
110 | case SYSTEM_PLL2_125M_CLK: | ||
111 | case SYSTEM_PLL2_100M_CLK: | ||
112 | case SYSTEM_PLL2_50M_CLK: | ||
113 | pll_cfg0 = readl(&ana_pll->sys_pll2_cfg0); | ||
114 | pll_cfg1 = readl(&ana_pll->sys_pll2_cfg1); | ||
115 | pll_cfg2 = readl(&ana_pll->sys_pll2_cfg2); | ||
116 | pllout_div_shift = HW_SSCG_SYSTEM_PLL2_DIV_SHIFT; | ||
117 | pllout_div_mask = HW_SSCG_SYSTEM_PLL2_DIV_MASK; | ||
118 | break; | ||
119 | case SYSTEM_PLL3_CLK: | ||
120 | pll_cfg0 = readl(&ana_pll->sys_pll3_cfg0); | ||
121 | pll_cfg1 = readl(&ana_pll->sys_pll3_cfg1); | ||
122 | pll_cfg2 = readl(&ana_pll->sys_pll3_cfg2); | ||
123 | pllout_div_shift = HW_SSCG_SYSTEM_PLL3_DIV_SHIFT; | ||
124 | pllout_div_mask = HW_SSCG_SYSTEM_PLL3_DIV_MASK; | ||
125 | break; | ||
126 | case DRAM_PLL1_CLK: | ||
127 | pll_cfg0 = readl(&ana_pll->dram_pll_cfg0); | ||
128 | pll_cfg1 = readl(&ana_pll->dram_pll_cfg1); | ||
129 | pll_cfg2 = readl(&ana_pll->dram_pll_cfg2); | ||
130 | pllout_div_shift = HW_SSCG_DRAM_PLL_DIV_SHIFT; | ||
131 | pllout_div_mask = HW_SSCG_DRAM_PLL_DIV_MASK; | ||
132 | break; | ||
133 | default: | ||
134 | printf("sscg pll %d not supporte\n", sscg_pll); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | switch (sscg_pll) { | ||
139 | case DRAM_PLL1_CLK: | ||
140 | pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK; | ||
141 | div = 1; | ||
142 | break; | ||
143 | case SYSTEM_PLL3_CLK: | ||
144 | pll_clke = SSCG_PLL_PLL3_CLKE_MASK; | ||
145 | div = 1; | ||
146 | break; | ||
147 | case SYSTEM_PLL2_1000M_CLK: | ||
148 | case SYSTEM_PLL1_800M_CLK: | ||
149 | pll_clke = SSCG_PLL_CLKE_MASK; | ||
150 | div = 1; | ||
151 | break; | ||
152 | case SYSTEM_PLL2_500M_CLK: | ||
153 | case SYSTEM_PLL1_400M_CLK: | ||
154 | pll_clke = SSCG_PLL_DIV2_CLKE_MASK; | ||
155 | div = 2; | ||
156 | break; | ||
157 | case SYSTEM_PLL2_333M_CLK: | ||
158 | case SYSTEM_PLL1_266M_CLK: | ||
159 | pll_clke = SSCG_PLL_DIV3_CLKE_MASK; | ||
160 | div = 3; | ||
161 | break; | ||
162 | case SYSTEM_PLL2_250M_CLK: | ||
163 | case SYSTEM_PLL1_200M_CLK: | ||
164 | pll_clke = SSCG_PLL_DIV4_CLKE_MASK; | ||
165 | div = 4; | ||
166 | break; | ||
167 | case SYSTEM_PLL2_200M_CLK: | ||
168 | case SYSTEM_PLL1_160M_CLK: | ||
169 | pll_clke = SSCG_PLL_DIV5_CLKE_MASK; | ||
170 | div = 5; | ||
171 | break; | ||
172 | case SYSTEM_PLL2_166M_CLK: | ||
173 | case SYSTEM_PLL1_133M_CLK: | ||
174 | pll_clke = SSCG_PLL_DIV6_CLKE_MASK; | ||
175 | div = 6; | ||
176 | break; | ||
177 | case SYSTEM_PLL2_125M_CLK: | ||
178 | case SYSTEM_PLL1_100M_CLK: | ||
179 | pll_clke = SSCG_PLL_DIV8_CLKE_MASK; | ||
180 | div = 8; | ||
181 | break; | ||
182 | case SYSTEM_PLL2_100M_CLK: | ||
183 | case SYSTEM_PLL1_80M_CLK: | ||
184 | pll_clke = SSCG_PLL_DIV10_CLKE_MASK; | ||
185 | div = 10; | ||
186 | break; | ||
187 | case SYSTEM_PLL2_50M_CLK: | ||
188 | case SYSTEM_PLL1_40M_CLK: | ||
189 | pll_clke = SSCG_PLL_DIV20_CLKE_MASK; | ||
190 | div = 20; | ||
191 | break; | ||
192 | default: | ||
193 | printf("sscg pll %d not supporte\n", sscg_pll); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /* Power down */ | ||
198 | if (pll_cfg0 & SSCG_PLL_PD_MASK) | ||
199 | return 0; | ||
200 | |||
201 | /* output not enabled */ | ||
202 | if ((pll_cfg0 & pll_clke) == 0) | ||
203 | return 0; | ||
204 | |||
205 | pllout_div = readl(&ana_pll->sscg_pllout_div_cfg); | ||
206 | pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift; | ||
207 | |||
208 | pll_refclk_sel = pll_cfg0 & SSCG_PLL_REFCLK_SEL_MASK; | ||
209 | |||
210 | if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_25M) | ||
211 | pll_refclk = 25000000u; | ||
212 | else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_27M) | ||
213 | pll_refclk = 27000000u; | ||
214 | else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_HDMI_PHY_27M) | ||
215 | pll_refclk = 27000000u; | ||
216 | else | ||
217 | pll_refclk = 0; | ||
218 | |||
219 | /* We assume bypass1/2 are the same value */ | ||
220 | if ((pll_cfg0 & SSCG_PLL_BYPASS1_MASK) || | ||
221 | (pll_cfg0 & SSCG_PLL_BYPASS2_MASK)) | ||
222 | return pll_refclk; | ||
223 | |||
224 | divr1 = (pll_cfg2 & SSCG_PLL_REF_DIVR1_MASK) >> | ||
225 | SSCG_PLL_REF_DIVR1_SHIFT; | ||
226 | divr2 = (pll_cfg2 & SSCG_PLL_REF_DIVR2_MASK) >> | ||
227 | SSCG_PLL_REF_DIVR2_SHIFT; | ||
228 | divf1 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F1_MASK) >> | ||
229 | SSCG_PLL_FEEDBACK_DIV_F1_SHIFT; | ||
230 | divf2 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F2_MASK) >> | ||
231 | SSCG_PLL_FEEDBACK_DIV_F2_SHIFT; | ||
232 | divq = (pll_cfg2 & SSCG_PLL_OUTPUT_DIV_VAL_MASK) >> | ||
233 | SSCG_PLL_OUTPUT_DIV_VAL_SHIFT; | ||
234 | sse = pll_cfg1 & SSCG_PLL_SSE_MASK; | ||
235 | |||
236 | if (sse) | ||
237 | sse = 8; | ||
238 | else | ||
239 | sse = 2; | ||
240 | |||
241 | pllout = pll_refclk / (divr1 + 1) * sse * (divf1 + 1) / | ||
242 | (divr2 + 1) * (divf2 + 1) / (divq + 1); | ||
243 | |||
244 | return pllout / (pllout_div + 1) / div; | ||
245 | } | ||
246 | |||
247 | static u32 get_root_src_clk(enum clk_root_src root_src) | ||
248 | { | ||
249 | switch (root_src) { | ||
250 | case OSC_25M_CLK: | ||
251 | return 25000000; | ||
252 | case OSC_27M_CLK: | ||
253 | return 27000000; | ||
254 | case OSC_32K_CLK: | ||
255 | return 32768; | ||
256 | case ARM_PLL_CLK: | ||
257 | return decode_frac_pll(root_src); | ||
258 | case SYSTEM_PLL1_800M_CLK: | ||
259 | case SYSTEM_PLL1_400M_CLK: | ||
260 | case SYSTEM_PLL1_266M_CLK: | ||
261 | case SYSTEM_PLL1_200M_CLK: | ||
262 | case SYSTEM_PLL1_160M_CLK: | ||
263 | case SYSTEM_PLL1_133M_CLK: | ||
264 | case SYSTEM_PLL1_100M_CLK: | ||
265 | case SYSTEM_PLL1_80M_CLK: | ||
266 | case SYSTEM_PLL1_40M_CLK: | ||
267 | case SYSTEM_PLL2_1000M_CLK: | ||
268 | case SYSTEM_PLL2_500M_CLK: | ||
269 | case SYSTEM_PLL2_333M_CLK: | ||
270 | case SYSTEM_PLL2_250M_CLK: | ||
271 | case SYSTEM_PLL2_200M_CLK: | ||
272 | case SYSTEM_PLL2_166M_CLK: | ||
273 | case SYSTEM_PLL2_125M_CLK: | ||
274 | case SYSTEM_PLL2_100M_CLK: | ||
275 | case SYSTEM_PLL2_50M_CLK: | ||
276 | case SYSTEM_PLL3_CLK: | ||
277 | return decode_sscg_pll(root_src); | ||
278 | default: | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static u32 get_root_clk(enum clk_root_index clock_id) | ||
286 | { | ||
287 | enum clk_root_src root_src; | ||
288 | u32 post_podf, pre_podf, root_src_clk; | ||
289 | |||
290 | if (clock_root_enabled(clock_id) <= 0) | ||
291 | return 0; | ||
292 | |||
293 | if (clock_get_prediv(clock_id, &pre_podf) < 0) | ||
294 | return 0; | ||
295 | |||
296 | if (clock_get_postdiv(clock_id, &post_podf) < 0) | ||
297 | return 0; | ||
298 | |||
299 | if (clock_get_src(clock_id, &root_src) < 0) | ||
300 | return 0; | ||
301 | |||
302 | root_src_clk = get_root_src_clk(root_src); | ||
303 | |||
304 | return root_src_clk / (post_podf + 1) / (pre_podf + 1); | ||
305 | } | ||
306 | |||
307 | #ifdef CONFIG_MXC_OCOTP | ||
308 | void enable_ocotp_clk(unsigned char enable) | ||
309 | { | ||
310 | clock_enable(CCGR_OCOTP, !!enable); | ||
311 | } | ||
312 | #endif | ||
313 | |||
314 | int enable_i2c_clk(unsigned char enable, unsigned int i2c_num) | ||
315 | { | ||
316 | /* 0 - 3 is valid i2c num */ | ||
317 | if (i2c_num > 3) | ||
318 | return -EINVAL; | ||
319 | |||
320 | clock_enable(CCGR_I2C1 + i2c_num, !!enable); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | unsigned int mxc_get_clock(enum clk_root_index clk) | ||
326 | { | ||
327 | u32 val; | ||
328 | |||
329 | if (clk >= CLK_ROOT_MAX) | ||
330 | return 0; | ||
331 | |||
332 | if (clk == MXC_ARM_CLK) | ||
333 | return get_root_clk(ARM_A53_CLK_ROOT); | ||
334 | |||
335 | if (clk == MXC_IPG_CLK) { | ||
336 | clock_get_target_val(IPG_CLK_ROOT, &val); | ||
337 | val = val & 0x3; | ||
338 | return get_root_clk(AHB_CLK_ROOT) / (val + 1); | ||
339 | } | ||
340 | |||
341 | return get_root_clk(clk); | ||
342 | } | ||
343 | |||
344 | u32 imx_get_uartclk(void) | ||
345 | { | ||
346 | return mxc_get_clock(UART1_CLK_ROOT); | ||
347 | } | ||
348 | |||
349 | void mxs_set_lcdclk(u32 base_addr, u32 freq) | ||
350 | { | ||
351 | /* | ||
352 | * LCDIF_PIXEL_CLK: select 800MHz root clock, | ||
353 | * select pre divider 8, output is 100 MHz | ||
354 | */ | ||
355 | clock_set_target_val(LCDIF_PIXEL_CLK_ROOT, CLK_ROOT_ON | | ||
356 | CLK_ROOT_SOURCE_SEL(4) | | ||
357 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV8)); | ||
358 | } | ||
359 | |||
360 | void init_wdog_clk(void) | ||
361 | { | ||
362 | clock_enable(CCGR_WDOG1, 0); | ||
363 | clock_enable(CCGR_WDOG2, 0); | ||
364 | clock_enable(CCGR_WDOG3, 0); | ||
365 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | | ||
366 | CLK_ROOT_SOURCE_SEL(0)); | ||
367 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | | ||
368 | CLK_ROOT_SOURCE_SEL(0)); | ||
369 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | | ||
370 | CLK_ROOT_SOURCE_SEL(0)); | ||
371 | clock_enable(CCGR_WDOG1, 1); | ||
372 | clock_enable(CCGR_WDOG2, 1); | ||
373 | clock_enable(CCGR_WDOG3, 1); | ||
374 | } | ||
375 | |||
376 | void init_usb_clk(void) | ||
377 | { | ||
378 | if (!is_usb_boot()) { | ||
379 | clock_enable(CCGR_USB_CTRL1, 0); | ||
380 | clock_enable(CCGR_USB_CTRL2, 0); | ||
381 | clock_enable(CCGR_USB_PHY1, 0); | ||
382 | clock_enable(CCGR_USB_PHY2, 0); | ||
383 | /* 500MHz */ | ||
384 | clock_set_target_val(USB_BUS_CLK_ROOT, CLK_ROOT_ON | | ||
385 | CLK_ROOT_SOURCE_SEL(1)); | ||
386 | /* 100MHz */ | ||
387 | clock_set_target_val(USB_CORE_REF_CLK_ROOT, CLK_ROOT_ON | | ||
388 | CLK_ROOT_SOURCE_SEL(1)); | ||
389 | /* 100MHz */ | ||
390 | clock_set_target_val(USB_PHY_REF_CLK_ROOT, CLK_ROOT_ON | | ||
391 | CLK_ROOT_SOURCE_SEL(1)); | ||
392 | clock_enable(CCGR_USB_CTRL1, 1); | ||
393 | clock_enable(CCGR_USB_CTRL2, 1); | ||
394 | clock_enable(CCGR_USB_PHY1, 1); | ||
395 | clock_enable(CCGR_USB_PHY2, 1); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | void init_uart_clk(u32 index) | ||
400 | { | ||
401 | /* Set uart clock root 25M OSC */ | ||
402 | switch (index) { | ||
403 | case 0: | ||
404 | clock_enable(CCGR_UART1, 0); | ||
405 | clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON | | ||
406 | CLK_ROOT_SOURCE_SEL(0)); | ||
407 | clock_enable(CCGR_UART1, 1); | ||
408 | return; | ||
409 | case 1: | ||
410 | clock_enable(CCGR_UART2, 0); | ||
411 | clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON | | ||
412 | CLK_ROOT_SOURCE_SEL(0)); | ||
413 | clock_enable(CCGR_UART2, 1); | ||
414 | return; | ||
415 | case 2: | ||
416 | clock_enable(CCGR_UART3, 0); | ||
417 | clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON | | ||
418 | CLK_ROOT_SOURCE_SEL(0)); | ||
419 | clock_enable(CCGR_UART3, 1); | ||
420 | return; | ||
421 | case 3: | ||
422 | clock_enable(CCGR_UART4, 0); | ||
423 | clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON | | ||
424 | CLK_ROOT_SOURCE_SEL(0)); | ||
425 | clock_enable(CCGR_UART4, 1); | ||
426 | return; | ||
427 | default: | ||
428 | printf("Invalid uart index\n"); | ||
429 | return; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | void init_clk_usdhc(u32 index) | ||
434 | { | ||
435 | /* | ||
436 | * set usdhc clock root | ||
437 | * sys pll1 400M | ||
438 | */ | ||
439 | switch (index) { | ||
440 | case 0: | ||
441 | clock_enable(CCGR_USDHC1, 0); | ||
442 | clock_set_target_val(USDHC1_CLK_ROOT, CLK_ROOT_ON | | ||
443 | CLK_ROOT_SOURCE_SEL(1) | | ||
444 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); | ||
445 | clock_enable(CCGR_USDHC1, 1); | ||
446 | return; | ||
447 | case 1: | ||
448 | clock_enable(CCGR_USDHC2, 0); | ||
449 | clock_set_target_val(USDHC2_CLK_ROOT, CLK_ROOT_ON | | ||
450 | CLK_ROOT_SOURCE_SEL(1) | | ||
451 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); | ||
452 | clock_enable(CCGR_USDHC2, 1); | ||
453 | return; | ||
454 | default: | ||
455 | printf("Invalid usdhc index\n"); | ||
456 | return; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | int set_clk_qspi(void) | ||
461 | { | ||
462 | /* | ||
463 | * set qspi root | ||
464 | * sys pll1 100M | ||
465 | */ | ||
466 | clock_enable(CCGR_QSPI, 0); | ||
467 | clock_set_target_val(QSPI_CLK_ROOT, CLK_ROOT_ON | | ||
468 | CLK_ROOT_SOURCE_SEL(7)); | ||
469 | clock_enable(CCGR_QSPI, 1); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | #ifdef CONFIG_FEC_MXC | ||
475 | int set_clk_enet(enum enet_freq type) | ||
476 | { | ||
477 | u32 target; | ||
478 | u32 enet1_ref; | ||
479 | |||
480 | switch (type) { | ||
481 | case ENET_125MHZ: | ||
482 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; | ||
483 | break; | ||
484 | case ENET_50MHZ: | ||
485 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; | ||
486 | break; | ||
487 | case ENET_25MHZ: | ||
488 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; | ||
489 | break; | ||
490 | default: | ||
491 | return -EINVAL; | ||
492 | } | ||
493 | |||
494 | /* disable the clock first */ | ||
495 | clock_enable(CCGR_ENET1, 0); | ||
496 | clock_enable(CCGR_SIM_ENET, 0); | ||
497 | |||
498 | /* set enet axi clock 266Mhz */ | ||
499 | target = CLK_ROOT_ON | ENET_AXI_CLK_ROOT_FROM_SYS1_PLL_266M | | ||
500 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | | ||
501 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1); | ||
502 | clock_set_target_val(ENET_AXI_CLK_ROOT, target); | ||
503 | |||
504 | target = CLK_ROOT_ON | enet1_ref | | ||
505 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | | ||
506 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1); | ||
507 | clock_set_target_val(ENET_REF_CLK_ROOT, target); | ||
508 | |||
509 | target = CLK_ROOT_ON | | ||
510 | ENET1_TIME_CLK_ROOT_FROM_PLL_ENET_MAIN_100M_CLK | | ||
511 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | | ||
512 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4); | ||
513 | clock_set_target_val(ENET_TIMER_CLK_ROOT, target); | ||
514 | |||
515 | /* enable clock */ | ||
516 | clock_enable(CCGR_SIM_ENET, 1); | ||
517 | clock_enable(CCGR_ENET1, 1); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | u32 imx_get_fecclk(void) | ||
524 | { | ||
525 | return get_root_clk(ENET_AXI_CLK_ROOT); | ||
526 | } | ||
527 | |||
528 | static struct dram_bypass_clk_setting imx8mq_dram_bypass_tbl[] = { | ||
529 | DRAM_BYPASS_ROOT_CONFIG(MHZ(100), 2, CLK_ROOT_PRE_DIV1, 2, | ||
530 | CLK_ROOT_PRE_DIV2), | ||
531 | DRAM_BYPASS_ROOT_CONFIG(MHZ(250), 3, CLK_ROOT_PRE_DIV2, 2, | ||
532 | CLK_ROOT_PRE_DIV2), | ||
533 | DRAM_BYPASS_ROOT_CONFIG(MHZ(400), 1, CLK_ROOT_PRE_DIV2, 3, | ||
534 | CLK_ROOT_PRE_DIV2), | ||
535 | }; | ||
536 | |||
537 | void dram_enable_bypass(ulong clk_val) | ||
538 | { | ||
539 | int i; | ||
540 | struct dram_bypass_clk_setting *config; | ||
541 | |||
542 | for (i = 0; i < ARRAY_SIZE(imx8mq_dram_bypass_tbl); i++) { | ||
543 | if (clk_val == imx8mq_dram_bypass_tbl[i].clk) | ||
544 | break; | ||
545 | } | ||
546 | |||
547 | if (i == ARRAY_SIZE(imx8mq_dram_bypass_tbl)) { | ||
548 | printf("No matched freq table %lu\n", clk_val); | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | config = &imx8mq_dram_bypass_tbl[i]; | ||
553 | |||
554 | clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | | ||
555 | CLK_ROOT_SOURCE_SEL(config->alt_root_sel) | | ||
556 | CLK_ROOT_PRE_DIV(config->alt_pre_div)); | ||
557 | clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | | ||
558 | CLK_ROOT_SOURCE_SEL(config->apb_root_sel) | | ||
559 | CLK_ROOT_PRE_DIV(config->apb_pre_div)); | ||
560 | clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | | ||
561 | CLK_ROOT_SOURCE_SEL(1)); | ||
562 | } | ||
563 | |||
564 | void dram_disable_bypass(void) | ||
565 | { | ||
566 | clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | | ||
567 | CLK_ROOT_SOURCE_SEL(0)); | ||
568 | clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | | ||
569 | CLK_ROOT_SOURCE_SEL(4) | | ||
570 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5)); | ||
571 | } | ||
572 | |||
573 | #ifdef CONFIG_SPL_BUILD | ||
574 | void dram_pll_init(ulong pll_val) | ||
575 | { | ||
576 | u32 val; | ||
577 | void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; | ||
578 | void __iomem *pll_cfg_reg2 = &ana_pll->dram_pll_cfg2; | ||
579 | |||
580 | /* Bypass */ | ||
581 | setbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); | ||
582 | setbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); | ||
583 | |||
584 | switch (pll_val) { | ||
585 | case MHZ(800): | ||
586 | val = readl(pll_cfg_reg2); | ||
587 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | | ||
588 | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | ||
589 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | | ||
590 | SSCG_PLL_REF_DIVR2_MASK); | ||
591 | val |= SSCG_PLL_OUTPUT_DIV_VAL(0); | ||
592 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); | ||
593 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); | ||
594 | val |= SSCG_PLL_REF_DIVR2_VAL(29); | ||
595 | writel(val, pll_cfg_reg2); | ||
596 | break; | ||
597 | case MHZ(600): | ||
598 | val = readl(pll_cfg_reg2); | ||
599 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | | ||
600 | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | ||
601 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | | ||
602 | SSCG_PLL_REF_DIVR2_MASK); | ||
603 | val |= SSCG_PLL_OUTPUT_DIV_VAL(1); | ||
604 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(17); | ||
605 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); | ||
606 | val |= SSCG_PLL_REF_DIVR2_VAL(29); | ||
607 | writel(val, pll_cfg_reg2); | ||
608 | break; | ||
609 | case MHZ(400): | ||
610 | val = readl(pll_cfg_reg2); | ||
611 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | | ||
612 | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | ||
613 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | | ||
614 | SSCG_PLL_REF_DIVR2_MASK); | ||
615 | val |= SSCG_PLL_OUTPUT_DIV_VAL(1); | ||
616 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); | ||
617 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); | ||
618 | val |= SSCG_PLL_REF_DIVR2_VAL(29); | ||
619 | writel(val, pll_cfg_reg2); | ||
620 | break; | ||
621 | case MHZ(167): | ||
622 | val = readl(pll_cfg_reg2); | ||
623 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | | ||
624 | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | ||
625 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | | ||
626 | SSCG_PLL_REF_DIVR2_MASK); | ||
627 | val |= SSCG_PLL_OUTPUT_DIV_VAL(3); | ||
628 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(8); | ||
629 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(45); | ||
630 | val |= SSCG_PLL_REF_DIVR2_VAL(30); | ||
631 | writel(val, pll_cfg_reg2); | ||
632 | break; | ||
633 | default: | ||
634 | break; | ||
635 | } | ||
636 | |||
637 | /* Clear power down bit */ | ||
638 | clrbits_le32(pll_control_reg, SSCG_PLL_PD_MASK); | ||
639 | /* Eanble ARM_PLL/SYS_PLL */ | ||
640 | setbits_le32(pll_control_reg, SSCG_PLL_DRAM_PLL_CLKE_MASK); | ||
641 | |||
642 | /* Clear bypass */ | ||
643 | clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); | ||
644 | __udelay(100); | ||
645 | clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); | ||
646 | /* Wait lock */ | ||
647 | while (!(readl(pll_control_reg) & SSCG_PLL_LOCK_MASK)) | ||
648 | ; | ||
649 | } | ||
650 | |||
651 | int frac_pll_init(u32 pll, enum frac_pll_out_val val) | ||
652 | { | ||
653 | void __iomem *pll_cfg0, __iomem *pll_cfg1; | ||
654 | u32 val_cfg0, val_cfg1; | ||
655 | int ret; | ||
656 | |||
657 | switch (pll) { | ||
658 | case ANATOP_ARM_PLL: | ||
659 | pll_cfg0 = &ana_pll->arm_pll_cfg0; | ||
660 | pll_cfg1 = &ana_pll->arm_pll_cfg1; | ||
661 | |||
662 | if (val == FRAC_PLL_OUT_1000M) | ||
663 | val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(49); | ||
664 | else | ||
665 | val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(79); | ||
666 | val_cfg0 = FRAC_PLL_CLKE_MASK | FRAC_PLL_REFCLK_SEL_OSC_25M | | ||
667 | FRAC_PLL_LOCK_SEL_MASK | FRAC_PLL_NEWDIV_VAL_MASK | | ||
668 | FRAC_PLL_REFCLK_DIV_VAL(4) | | ||
669 | FRAC_PLL_OUTPUT_DIV_VAL(0); | ||
670 | break; | ||
671 | default: | ||
672 | return -EINVAL; | ||
673 | } | ||
674 | |||
675 | /* bypass the clock */ | ||
676 | setbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK); | ||
677 | /* Set the value */ | ||
678 | writel(val_cfg1, pll_cfg1); | ||
679 | writel(val_cfg0 | FRAC_PLL_BYPASS_MASK, pll_cfg0); | ||
680 | val_cfg0 = readl(pll_cfg0); | ||
681 | /* unbypass the clock */ | ||
682 | clrbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK); | ||
683 | ret = readl_poll_timeout(pll_cfg0, val_cfg0, | ||
684 | val_cfg0 & FRAC_PLL_LOCK_MASK, 1); | ||
685 | if (ret) | ||
686 | printf("%s timeout\n", __func__); | ||
687 | clrbits_le32(pll_cfg0, FRAC_PLL_NEWDIV_VAL_MASK); | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | int sscg_pll_init(u32 pll) | ||
693 | { | ||
694 | void __iomem *pll_cfg0, __iomem *pll_cfg1, __iomem *pll_cfg2; | ||
695 | u32 val_cfg0, val_cfg1, val_cfg2, val; | ||
696 | u32 bypass1_mask = 0x20, bypass2_mask = 0x10; | ||
697 | int ret; | ||
698 | |||
699 | switch (pll) { | ||
700 | case ANATOP_SYSTEM_PLL1: | ||
701 | pll_cfg0 = &ana_pll->sys_pll1_cfg0; | ||
702 | pll_cfg1 = &ana_pll->sys_pll1_cfg1; | ||
703 | pll_cfg2 = &ana_pll->sys_pll1_cfg2; | ||
704 | /* 800MHz */ | ||
705 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | | ||
706 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(3); | ||
707 | val_cfg1 = 0; | ||
708 | val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK | | ||
709 | SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK | | ||
710 | SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK | | ||
711 | SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK | | ||
712 | SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | | ||
713 | SSCG_PLL_REFCLK_SEL_OSC_25M; | ||
714 | break; | ||
715 | case ANATOP_SYSTEM_PLL2: | ||
716 | pll_cfg0 = &ana_pll->sys_pll2_cfg0; | ||
717 | pll_cfg1 = &ana_pll->sys_pll2_cfg1; | ||
718 | pll_cfg2 = &ana_pll->sys_pll2_cfg2; | ||
719 | /* 1000MHz */ | ||
720 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | | ||
721 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(4); | ||
722 | val_cfg1 = 0; | ||
723 | val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK | | ||
724 | SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK | | ||
725 | SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK | | ||
726 | SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK | | ||
727 | SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | | ||
728 | SSCG_PLL_REFCLK_SEL_OSC_25M; | ||
729 | break; | ||
730 | case ANATOP_SYSTEM_PLL3: | ||
731 | pll_cfg0 = &ana_pll->sys_pll3_cfg0; | ||
732 | pll_cfg1 = &ana_pll->sys_pll3_cfg1; | ||
733 | pll_cfg2 = &ana_pll->sys_pll3_cfg2; | ||
734 | /* 800MHz */ | ||
735 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | | ||
736 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(3); | ||
737 | val_cfg1 = 0; | ||
738 | val_cfg0 = SSCG_PLL_PLL3_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | | ||
739 | SSCG_PLL_REFCLK_SEL_OSC_25M; | ||
740 | break; | ||
741 | default: | ||
742 | return -EINVAL; | ||
743 | } | ||
744 | |||
745 | /*bypass*/ | ||
746 | setbits_le32(pll_cfg0, bypass1_mask | bypass2_mask); | ||
747 | /* set value */ | ||
748 | writel(val_cfg2, pll_cfg2); | ||
749 | writel(val_cfg1, pll_cfg1); | ||
750 | /*unbypass1 and wait 70us */ | ||
751 | writel(val_cfg0 | bypass2_mask, pll_cfg1); | ||
752 | |||
753 | __udelay(70); | ||
754 | |||
755 | /* unbypass2 and wait lock */ | ||
756 | writel(val_cfg0, pll_cfg1); | ||
757 | ret = readl_poll_timeout(pll_cfg0, val, val & SSCG_PLL_LOCK_MASK, 1); | ||
758 | if (ret) | ||
759 | printf("%s timeout\n", __func__); | ||
760 | |||
761 | return ret; | ||
762 | } | ||
763 | |||
764 | int clock_init(void) | ||
765 | { | ||
766 | u32 grade; | ||
767 | |||
768 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | | ||
769 | CLK_ROOT_SOURCE_SEL(0)); | ||
770 | |||
771 | /* | ||
772 | * 8MQ only supports two grades: consumer and industrial. | ||
773 | * We set ARM clock to 1Ghz for consumer, 800Mhz for industrial | ||
774 | */ | ||
775 | grade = get_cpu_temp_grade(NULL, NULL); | ||
776 | if (!grade) { | ||
777 | frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1000M); | ||
778 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | | ||
779 | CLK_ROOT_SOURCE_SEL(1) | | ||
780 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1)); | ||
781 | } else { | ||
782 | frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1600M); | ||
783 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | | ||
784 | CLK_ROOT_SOURCE_SEL(1) | | ||
785 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); | ||
786 | } | ||
787 | /* | ||
788 | * According to ANAMIX SPEC | ||
789 | * sys pll1 fixed at 800MHz | ||
790 | * sys pll2 fixed at 1GHz | ||
791 | * Here we only enable the outputs. | ||
792 | */ | ||
793 | setbits_le32(&ana_pll->sys_pll1_cfg0, SSCG_PLL_CLKE_MASK | | ||
794 | SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK | | ||
795 | SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK | | ||
796 | SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK | | ||
797 | SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK); | ||
798 | |||
799 | setbits_le32(&ana_pll->sys_pll2_cfg0, SSCG_PLL_CLKE_MASK | | ||
800 | SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK | | ||
801 | SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK | | ||
802 | SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK | | ||
803 | SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK); | ||
804 | |||
805 | clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON | | ||
806 | CLK_ROOT_SOURCE_SEL(1)); | ||
807 | |||
808 | init_wdog_clk(); | ||
809 | clock_enable(CCGR_TSENSOR, 1); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | #endif | ||
814 | |||
815 | /* | ||
816 | * Dump some clockes. | ||
817 | */ | ||
818 | #ifndef CONFIG_SPL_BUILD | ||
819 | int do_imx8m_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, | ||
820 | char * const argv[]) | ||
821 | { | ||
822 | u32 freq; | ||
823 | |||
824 | freq = decode_frac_pll(ARM_PLL_CLK); | ||
825 | printf("ARM_PLL %8d MHz\n", freq / 1000000); | ||
826 | freq = decode_sscg_pll(SYSTEM_PLL1_800M_CLK); | ||
827 | printf("SYS_PLL1_800 %8d MHz\n", freq / 1000000); | ||
828 | freq = decode_sscg_pll(SYSTEM_PLL1_400M_CLK); | ||
829 | printf("SYS_PLL1_400 %8d MHz\n", freq / 1000000); | ||
830 | freq = decode_sscg_pll(SYSTEM_PLL1_266M_CLK); | ||
831 | printf("SYS_PLL1_266 %8d MHz\n", freq / 1000000); | ||
832 | freq = decode_sscg_pll(SYSTEM_PLL1_200M_CLK); | ||
833 | printf("SYS_PLL1_200 %8d MHz\n", freq / 1000000); | ||
834 | freq = decode_sscg_pll(SYSTEM_PLL1_160M_CLK); | ||
835 | printf("SYS_PLL1_160 %8d MHz\n", freq / 1000000); | ||
836 | freq = decode_sscg_pll(SYSTEM_PLL1_133M_CLK); | ||
837 | printf("SYS_PLL1_133 %8d MHz\n", freq / 1000000); | ||
838 | freq = decode_sscg_pll(SYSTEM_PLL1_100M_CLK); | ||
839 | printf("SYS_PLL1_100 %8d MHz\n", freq / 1000000); | ||
840 | freq = decode_sscg_pll(SYSTEM_PLL1_80M_CLK); | ||
841 | printf("SYS_PLL1_80 %8d MHz\n", freq / 1000000); | ||
842 | freq = decode_sscg_pll(SYSTEM_PLL1_40M_CLK); | ||
843 | printf("SYS_PLL1_40 %8d MHz\n", freq / 1000000); | ||
844 | freq = decode_sscg_pll(SYSTEM_PLL2_1000M_CLK); | ||
845 | printf("SYS_PLL2_1000 %8d MHz\n", freq / 1000000); | ||
846 | freq = decode_sscg_pll(SYSTEM_PLL2_500M_CLK); | ||
847 | printf("SYS_PLL2_500 %8d MHz\n", freq / 1000000); | ||
848 | freq = decode_sscg_pll(SYSTEM_PLL2_333M_CLK); | ||
849 | printf("SYS_PLL2_333 %8d MHz\n", freq / 1000000); | ||
850 | freq = decode_sscg_pll(SYSTEM_PLL2_250M_CLK); | ||
851 | printf("SYS_PLL2_250 %8d MHz\n", freq / 1000000); | ||
852 | freq = decode_sscg_pll(SYSTEM_PLL2_200M_CLK); | ||
853 | printf("SYS_PLL2_200 %8d MHz\n", freq / 1000000); | ||
854 | freq = decode_sscg_pll(SYSTEM_PLL2_166M_CLK); | ||
855 | printf("SYS_PLL2_166 %8d MHz\n", freq / 1000000); | ||
856 | freq = decode_sscg_pll(SYSTEM_PLL2_125M_CLK); | ||
857 | printf("SYS_PLL2_125 %8d MHz\n", freq / 1000000); | ||
858 | freq = decode_sscg_pll(SYSTEM_PLL2_100M_CLK); | ||
859 | printf("SYS_PLL2_100 %8d MHz\n", freq / 1000000); | ||
860 | freq = decode_sscg_pll(SYSTEM_PLL2_50M_CLK); | ||
861 | printf("SYS_PLL2_50 %8d MHz\n", freq / 1000000); | ||
862 | freq = decode_sscg_pll(SYSTEM_PLL3_CLK); | ||
863 | printf("SYS_PLL3 %8d MHz\n", freq / 1000000); | ||
864 | freq = mxc_get_clock(UART1_CLK_ROOT); | ||
865 | printf("UART1 %8d MHz\n", freq / 1000000); | ||
866 | freq = mxc_get_clock(USDHC1_CLK_ROOT); | ||
867 | printf("USDHC1 %8d MHz\n", freq / 1000000); | ||
868 | freq = mxc_get_clock(QSPI_CLK_ROOT); | ||
869 | printf("QSPI %8d MHz\n", freq / 1000000); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | U_BOOT_CMD( | ||
874 | clocks, CONFIG_SYS_MAXARGS, 1, do_imx8m_showclocks, | ||
875 | "display clocks", | ||
876 | "" | ||
877 | ); | ||
878 | #endif | ||