blob: 7d3a4c01333f3dd11b66dd396b840c1cec893556 [file] [log] [blame]
Peng Fanbbcd2c42022-07-26 16:40:39 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2022 NXP
4 *
5 * Peng Fan <peng.fan@nxp.com>
6 */
7
8#include <common.h>
9#include <command.h>
10#include <asm/arch/clock.h>
11#include <asm/arch/imx-regs.h>
Peng Fan28b5cb52022-07-26 16:40:43 +080012#include <asm/arch/ccm_regs.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080013#include <asm/arch/sys_proto.h>
14#include <asm/global_data.h>
15#include <asm/io.h>
16#include <div64.h>
17#include <errno.h>
18#include <linux/bitops.h>
19#include <linux/delay.h>
20#include <log.h>
21
22DECLARE_GLOBAL_DATA_PTR;
23
Peng Fan28b5cb52022-07-26 16:40:43 +080024static struct anatop_reg *ana_regs = (struct anatop_reg *)ANATOP_BASE_ADDR;
25
26static struct imx_intpll_rate_table imx9_intpll_tbl[] = {
27 INT_PLL_RATE(1800000000U, 1, 150, 2), /* 1.8Ghz */
28 INT_PLL_RATE(1700000000U, 1, 141, 2), /* 1.7Ghz */
Peng Fan205286f2023-04-28 12:08:16 +080029 INT_PLL_RATE(1500000000U, 1, 125, 2), /* 1.5Ghz */
Peng Fan28b5cb52022-07-26 16:40:43 +080030 INT_PLL_RATE(1400000000U, 1, 175, 3), /* 1.4Ghz */
31 INT_PLL_RATE(1000000000U, 1, 166, 4), /* 1000Mhz */
32 INT_PLL_RATE(900000000U, 1, 150, 4), /* 900Mhz */
33};
34
35static struct imx_fracpll_rate_table imx9_fracpll_tbl[] = {
36 FRAC_PLL_RATE(1000000000U, 1, 166, 4, 2, 3), /* 1000Mhz */
37 FRAC_PLL_RATE(933000000U, 1, 155, 4, 1, 2), /* 933Mhz */
38 FRAC_PLL_RATE(700000000U, 1, 145, 5, 5, 6), /* 700Mhz */
Peng Fan205286f2023-04-28 12:08:16 +080039 FRAC_PLL_RATE(484000000U, 1, 121, 6, 0, 1),
40 FRAC_PLL_RATE(445333333U, 1, 167, 9, 0, 1),
Peng Fan28b5cb52022-07-26 16:40:43 +080041 FRAC_PLL_RATE(466000000U, 1, 155, 8, 1, 3), /* 466Mhz */
42 FRAC_PLL_RATE(400000000U, 1, 200, 12, 0, 1), /* 400Mhz */
Peng Fan205286f2023-04-28 12:08:16 +080043 FRAC_PLL_RATE(300000000U, 1, 150, 12, 0, 1),
Peng Fan28b5cb52022-07-26 16:40:43 +080044};
45
46/* return in khz */
47static u32 decode_pll_vco(struct ana_pll_reg *reg, bool fracpll)
48{
49 u32 ctrl;
50 u32 pll_status;
51 u32 div;
52 int rdiv, mfi, mfn, mfd;
53 int clk = 24000;
54
55 ctrl = readl(&reg->ctrl.reg);
56 pll_status = readl(&reg->pll_status);
57 div = readl(&reg->div.reg);
58
59 if (!(ctrl & PLL_CTRL_POWERUP))
60 return 0;
61
62 if (!(pll_status & PLL_STATUS_PLL_LOCK))
63 return 0;
64
65 mfi = (div & GENMASK(24, 16)) >> 16;
66 rdiv = (div & GENMASK(15, 13)) >> 13;
67
68 if (rdiv == 0)
69 rdiv = 1;
70
71 if (fracpll) {
72 mfn = (int)readl(&reg->num.reg);
73 mfn >>= 2;
74 mfd = (int)(readl(&reg->denom.reg) & GENMASK(29, 0));
75
76 clk = clk * (mfi * mfd + mfn) / mfd / rdiv;
77 } else {
78 clk = clk * mfi / rdiv;
79 }
80
81 return (u32)clk;
82}
83
84/* return in khz */
85static u32 decode_pll_out(struct ana_pll_reg *reg, bool fracpll)
86{
87 u32 ctrl = readl(&reg->ctrl.reg);
88 u32 div;
89
90 if (ctrl & PLL_CTRL_CLKMUX_BYPASS)
91 return 24000;
92
93 if (!(ctrl & PLL_CTRL_CLKMUX_EN))
94 return 0;
95
96 div = readl(&reg->div.reg);
97 div &= 0xff; /* odiv */
98
99 if (div == 0)
100 div = 2;
101 else if (div == 1)
102 div = 3;
103
104 return decode_pll_vco(reg, fracpll) / div;
105}
106
107/* return in khz */
108static u32 decode_pll_pfd(struct ana_pll_reg *reg, struct ana_pll_dfs *dfs_reg,
109 bool div2, bool fracpll)
110{
111 u32 pllvco = decode_pll_vco(reg, fracpll);
112 u32 dfs_ctrl = readl(&dfs_reg->dfs_ctrl.reg);
113 u32 dfs_div = readl(&dfs_reg->dfs_div.reg);
114 u32 mfn, mfi;
115 u32 output;
116
117 if (dfs_ctrl & PLL_DFS_CTRL_BYPASS)
118 return pllvco;
119
120 if (!(dfs_ctrl & PLL_DFS_CTRL_ENABLE) ||
121 (div2 && !(dfs_ctrl & PLL_DFS_CTRL_CLKOUT_DIV2)) ||
122 (!div2 && !(dfs_ctrl & PLL_DFS_CTRL_CLKOUT)))
123 return 0;
124
125 mfn = dfs_div & GENMASK(2, 0);
126 mfi = (dfs_div & GENMASK(15, 8)) >> 8;
127
128 if (mfn > 3)
129 return 0; /* valid mfn 0-3 */
130
131 if (mfi == 0 || mfi == 1)
132 return 0; /* valid mfi 2-255 */
133
134 output = (pllvco * 5) / (mfi * 5 + mfn);
135
136 if (div2)
137 return output >> 1;
138
139 return output;
140}
141
142static u32 decode_pll(enum ccm_clk_src pll)
143{
144 switch (pll) {
145 case ARM_PLL_CLK:
146 return decode_pll_out(&ana_regs->arm_pll, false);
147 case SYS_PLL_PG:
148 return decode_pll_out(&ana_regs->sys_pll, false);
149 case SYS_PLL_PFD0:
150 return decode_pll_pfd(&ana_regs->sys_pll,
151 &ana_regs->sys_pll.dfs[0], false, true);
152 case SYS_PLL_PFD0_DIV2:
153 return decode_pll_pfd(&ana_regs->sys_pll,
154 &ana_regs->sys_pll.dfs[0], true, true);
155 case SYS_PLL_PFD1:
156 return decode_pll_pfd(&ana_regs->sys_pll,
157 &ana_regs->sys_pll.dfs[1], false, true);
158 case SYS_PLL_PFD1_DIV2:
159 return decode_pll_pfd(&ana_regs->sys_pll,
160 &ana_regs->sys_pll.dfs[1], true, true);
161 case SYS_PLL_PFD2:
162 return decode_pll_pfd(&ana_regs->sys_pll,
163 &ana_regs->sys_pll.dfs[2], false, true);
164 case SYS_PLL_PFD2_DIV2:
165 return decode_pll_pfd(&ana_regs->sys_pll,
166 &ana_regs->sys_pll.dfs[2], true, true);
167 case AUDIO_PLL_CLK:
168 return decode_pll_out(&ana_regs->audio_pll, true);
169 case DRAM_PLL_CLK:
170 return decode_pll_out(&ana_regs->dram_pll, true);
171 case VIDEO_PLL_CLK:
172 return decode_pll_out(&ana_regs->video_pll, true);
173 default:
174 printf("Invalid clock source to decode\n");
175 break;
176 }
177
178 return 0;
179}
180
181int configure_intpll(enum ccm_clk_src pll, u32 freq)
182{
183 int i;
184 struct imx_intpll_rate_table *rate;
185 struct ana_pll_reg *reg;
186 u32 pll_status;
187
188 for (i = 0; i < ARRAY_SIZE(imx9_intpll_tbl); i++) {
189 if (freq == imx9_intpll_tbl[i].rate)
190 break;
191 }
192
193 if (i == ARRAY_SIZE(imx9_intpll_tbl)) {
194 debug("No matched freq table %u\n", freq);
195 return -EINVAL;
196 }
197
198 rate = &imx9_intpll_tbl[i];
199
200 /* ROM has configured SYS PLL and PFD, no need for it */
201 switch (pll) {
202 case ARM_PLL_CLK:
203 reg = &ana_regs->arm_pll;
204 break;
205 default:
206 return -EPERM;
207 }
208
209 /* Bypass the PLL to ref */
210 writel(PLL_CTRL_CLKMUX_BYPASS, &reg->ctrl.reg_set);
211
212 /* disable pll and output */
213 writel(PLL_CTRL_CLKMUX_EN | PLL_CTRL_POWERUP, &reg->ctrl.reg_clr);
214
215 /* Program the ODIV, RDIV, MFI */
216 writel((rate->odiv & GENMASK(7, 0)) | ((rate->rdiv << 13) & GENMASK(15, 13)) |
217 ((rate->mfi << 16) & GENMASK(24, 16)), &reg->div.reg);
218
219 /* wait 5us */
220 udelay(5);
221
222 /* power up the PLL and wait lock (max wait time 100 us) */
223 writel(PLL_CTRL_POWERUP, &reg->ctrl.reg_set);
224
225 udelay(100);
226
227 pll_status = readl(&reg->pll_status);
228 if (pll_status & PLL_STATUS_PLL_LOCK) {
229 writel(PLL_CTRL_CLKMUX_EN, &reg->ctrl.reg_set);
230
231 /* clear bypass */
232 writel(PLL_CTRL_CLKMUX_BYPASS, &reg->ctrl.reg_clr);
233
234 } else {
235 debug("Fail to lock PLL %u\n", pll);
236 return -EIO;
237 }
238
239 return 0;
240}
241
242int configure_fracpll(enum ccm_clk_src pll, u32 freq)
243{
244 struct imx_fracpll_rate_table *rate;
245 struct ana_pll_reg *reg;
246 u32 pll_status;
247 int i;
248
249 for (i = 0; i < ARRAY_SIZE(imx9_fracpll_tbl); i++) {
250 if (freq == imx9_fracpll_tbl[i].rate)
251 break;
252 }
253
254 if (i == ARRAY_SIZE(imx9_fracpll_tbl)) {
255 debug("No matched freq table %u\n", freq);
256 return -EINVAL;
257 }
258
259 rate = &imx9_fracpll_tbl[i];
260
261 switch (pll) {
262 case SYS_PLL_PG:
263 reg = &ana_regs->sys_pll;
264 break;
265 case DRAM_PLL_CLK:
266 reg = &ana_regs->dram_pll;
267 break;
268 case VIDEO_PLL_CLK:
269 reg = &ana_regs->video_pll;
270 break;
271 default:
272 return -EPERM;
273 }
274
275 /* Bypass the PLL to ref */
276 writel(PLL_CTRL_CLKMUX_BYPASS, &reg->ctrl.reg_set);
277
278 /* disable pll and output */
279 writel(PLL_CTRL_CLKMUX_EN | PLL_CTRL_POWERUP, &reg->ctrl.reg_clr);
280
281 /* Program the ODIV, RDIV, MFI */
282 writel((rate->odiv & GENMASK(7, 0)) | ((rate->rdiv << 13) & GENMASK(15, 13)) |
283 ((rate->mfi << 16) & GENMASK(24, 16)), &reg->div.reg);
284
285 /* Set SPREAD_SPECRUM enable to 0 */
286 writel(PLL_SS_EN, &reg->ss.reg_clr);
287
288 /* Program NUMERATOR and DENOMINATOR */
289 writel((rate->mfn << 2), &reg->num.reg);
290 writel((rate->mfd & GENMASK(29, 0)), &reg->denom.reg);
291
292 /* wait 5us */
293 udelay(5);
294
295 /* power up the PLL and wait lock (max wait time 100 us) */
296 writel(PLL_CTRL_POWERUP, &reg->ctrl.reg_set);
297
298 udelay(100);
299
300 pll_status = readl(&reg->pll_status);
301 if (pll_status & PLL_STATUS_PLL_LOCK) {
302 writel(PLL_CTRL_CLKMUX_EN, &reg->ctrl.reg_set);
303
304 /* check the MFN is updated */
305 pll_status = readl(&reg->pll_status);
306 if ((pll_status & ~0x3) != (rate->mfn << 2)) {
307 debug("MFN update not matched, pll_status 0x%x, mfn 0x%x\n",
308 pll_status, rate->mfn);
309 return -EIO;
310 }
311
312 /* clear bypass */
313 writel(PLL_CTRL_CLKMUX_BYPASS, &reg->ctrl.reg_clr);
314
315 } else {
316 debug("Fail to lock PLL %u\n", pll);
317 return -EIO;
318 }
319
320 return 0;
321}
322
323int configure_pll_pfd(enum ccm_clk_src pll_pfg, u32 mfi, u32 mfn, bool div2_en)
324{
325 struct ana_pll_dfs *dfs;
326 struct ana_pll_reg *reg;
327 u32 dfs_status;
328 u32 index;
329
330 if (mfn > 3)
331 return -EINVAL; /* valid mfn 0-3 */
332
333 if (mfi < 2 || mfi > 255)
334 return -EINVAL; /* valid mfi 2-255 */
335
336 switch (pll_pfg) {
337 case SYS_PLL_PFD0:
338 reg = &ana_regs->sys_pll;
339 index = 0;
340 break;
341 case SYS_PLL_PFD1:
342 reg = &ana_regs->sys_pll;
343 index = 1;
344 break;
345 case SYS_PLL_PFD2:
346 reg = &ana_regs->sys_pll;
347 index = 2;
348 break;
349 default:
350 return -EPERM;
351 }
352
353 dfs = &reg->dfs[index];
354
355 /* Bypass the DFS to PLL VCO */
356 writel(PLL_DFS_CTRL_BYPASS, &dfs->dfs_ctrl.reg_set);
357
358 /* disable DFS and output */
359 writel(PLL_DFS_CTRL_ENABLE | PLL_DFS_CTRL_CLKOUT |
360 PLL_DFS_CTRL_CLKOUT_DIV2, &dfs->dfs_ctrl.reg_clr);
361
362 writel(((mfi << 8) & GENMASK(15, 8)) | (mfn & GENMASK(2, 0)), &dfs->dfs_div.reg);
363
364 writel(PLL_DFS_CTRL_CLKOUT, &dfs->dfs_ctrl.reg_set);
365 if (div2_en)
366 writel(PLL_DFS_CTRL_CLKOUT_DIV2, &dfs->dfs_ctrl.reg_set);
367 writel(PLL_DFS_CTRL_ENABLE, &dfs->dfs_ctrl.reg_set);
368
369 /*
370 * As HW expert said: after enabling the DFS, clock will start
371 * coming after 6 cycles output clock period.
372 * 5us is much bigger than expected, so it will be safe
373 */
374 udelay(5);
375
376 dfs_status = readl(&reg->dfs_status);
377
378 if (!(dfs_status & (1 << index))) {
379 debug("DFS lock failed\n");
380 return -EIO;
381 }
382
383 /* Bypass the DFS to PLL VCO */
384 writel(PLL_DFS_CTRL_BYPASS, &dfs->dfs_ctrl.reg_clr);
385
386 return 0;
387}
388
389int update_fracpll_mfn(enum ccm_clk_src pll, int mfn)
390{
391 struct ana_pll_reg *reg;
392 bool repoll = false;
393 u32 pll_status;
394 int count = 20;
395
396 switch (pll) {
397 case AUDIO_PLL_CLK:
398 reg = &ana_regs->audio_pll;
399 break;
400 case DRAM_PLL_CLK:
401 reg = &ana_regs->dram_pll;
402 break;
403 case VIDEO_PLL_CLK:
404 reg = &ana_regs->video_pll;
405 break;
406 default:
407 printf("Invalid pll %u for update FRAC PLL MFN\n", pll);
408 return -EINVAL;
409 }
410
411 if (readl(&reg->pll_status) & PLL_STATUS_PLL_LOCK)
412 repoll = true;
413
414 mfn <<= 2;
415 writel(mfn, &reg->num);
416
417 if (repoll) {
418 do {
419 pll_status = readl(&reg->pll_status);
420 udelay(5);
421 count--;
422 } while (((pll_status & ~0x3) != (u32)mfn) && count > 0);
423
424 if (count <= 0) {
425 printf("update MFN timeout, pll_status 0x%x, mfn 0x%x\n", pll_status, mfn);
426 return -EIO;
427 }
428 }
429
430 return 0;
431}
432
433int update_pll_pfd_mfn(enum ccm_clk_src pll_pfd, u32 mfn)
434{
435 struct ana_pll_dfs *dfs;
436 u32 val;
437 u32 index;
438
439 switch (pll_pfd) {
440 case SYS_PLL_PFD0:
441 case SYS_PLL_PFD0_DIV2:
442 index = 0;
443 break;
444 case SYS_PLL_PFD1:
445 case SYS_PLL_PFD1_DIV2:
446 index = 1;
447 break;
448 case SYS_PLL_PFD2:
449 case SYS_PLL_PFD2_DIV2:
450 index = 2;
451 break;
452 default:
453 printf("Invalid pfd %u for update PLL PFD MFN\n", pll_pfd);
454 return -EINVAL;
455 }
456
457 dfs = &ana_regs->sys_pll.dfs[index];
458
459 val = readl(&dfs->dfs_div.reg);
460 val &= ~0x3;
461 val |= mfn & 0x3;
462 writel(val, &dfs->dfs_div.reg);
463
464 return 0;
465}
466
467/* return in khz */
468u32 get_clk_src_rate(enum ccm_clk_src source)
469{
470 u32 ctrl;
471 bool clk_on;
472
473 switch (source) {
474 case ARM_PLL_CLK:
475 ctrl = readl(&ana_regs->arm_pll.ctrl.reg);
476 case AUDIO_PLL_CLK:
477 ctrl = readl(&ana_regs->audio_pll.ctrl.reg);
478 break;
479 case DRAM_PLL_CLK:
480 ctrl = readl(&ana_regs->dram_pll.ctrl.reg);
481 break;
482 case VIDEO_PLL_CLK:
483 ctrl = readl(&ana_regs->video_pll.ctrl.reg);
484 break;
485 case SYS_PLL_PFD0:
486 case SYS_PLL_PFD0_DIV2:
487 ctrl = readl(&ana_regs->sys_pll.dfs[0].dfs_ctrl.reg);
488 break;
489 case SYS_PLL_PFD1:
490 case SYS_PLL_PFD1_DIV2:
491 ctrl = readl(&ana_regs->sys_pll.dfs[1].dfs_ctrl.reg);
492 break;
493 case SYS_PLL_PFD2:
494 case SYS_PLL_PFD2_DIV2:
495 ctrl = readl(&ana_regs->sys_pll.dfs[2].dfs_ctrl.reg);
496 break;
497 case OSC_24M_CLK:
498 return 24000;
499 default:
500 printf("Invalid clock source to get rate\n");
501 return 0;
502 }
503
504 if (ctrl & PLL_CTRL_HW_CTRL_SEL) {
505 /* When using HW ctrl, check OSCPLL */
506 clk_on = ccm_clk_src_is_clk_on(source);
507 if (clk_on)
508 return decode_pll(source);
509 else
510 return 0;
511 } else {
512 /* controlled by pll registers */
513 return decode_pll(source);
514 }
515}
516
517u32 get_arm_core_clk(void)
518{
519 u32 val;
520
521 ccm_shared_gpr_get(SHARED_GPR_A55_CLK, &val);
522
523 if (val & SHARED_GPR_A55_CLK_SEL_PLL)
524 return decode_pll(ARM_PLL_CLK) * 1000;
525
526 return ccm_clk_root_get_rate(ARM_A55_CLK_ROOT);
527}
528
529unsigned int mxc_get_clock(enum mxc_clock clk)
530{
531 switch (clk) {
532 case MXC_ARM_CLK:
533 return get_arm_core_clk();
534 case MXC_IPG_CLK:
535 return ccm_clk_root_get_rate(BUS_WAKEUP_CLK_ROOT);
536 case MXC_CSPI_CLK:
537 return ccm_clk_root_get_rate(LPSPI1_CLK_ROOT);
538 case MXC_ESDHC_CLK:
539 return ccm_clk_root_get_rate(USDHC1_CLK_ROOT);
540 case MXC_ESDHC2_CLK:
541 return ccm_clk_root_get_rate(USDHC2_CLK_ROOT);
542 case MXC_ESDHC3_CLK:
543 return ccm_clk_root_get_rate(USDHC3_CLK_ROOT);
544 case MXC_UART_CLK:
545 return ccm_clk_root_get_rate(LPUART1_CLK_ROOT);
546 case MXC_FLEXSPI_CLK:
547 return ccm_clk_root_get_rate(FLEXSPI1_CLK_ROOT);
548 default:
549 return -1;
550 };
551
552 return -1;
553};
554
555int enable_i2c_clk(unsigned char enable, u32 i2c_num)
556{
557 if (i2c_num > 7)
558 return -EINVAL;
559
560 if (enable) {
561 /* 24M */
562 ccm_lpcg_on(CCGR_I2C1 + i2c_num, false);
563 ccm_clk_root_cfg(LPI2C1_CLK_ROOT + i2c_num, OSC_24M_CLK, 1);
564 ccm_lpcg_on(CCGR_I2C1 + i2c_num, true);
565 } else {
566 ccm_lpcg_on(CCGR_I2C1 + i2c_num, false);
567 }
568
569 return 0;
570}
571
572u32 imx_get_i2cclk(u32 i2c_num)
573{
574 if (i2c_num > 7)
575 return -EINVAL;
576
577 return ccm_clk_root_get_rate(LPUART1_CLK_ROOT + i2c_num);
578}
579
Peng Fanbbcd2c42022-07-26 16:40:39 +0800580u32 get_lpuart_clk(void)
581{
Peng Fan28b5cb52022-07-26 16:40:43 +0800582 return mxc_get_clock(MXC_UART_CLK);
583}
584
585void init_uart_clk(u32 index)
586{
587 switch (index) {
588 case LPUART1_CLK_ROOT:
589 /* 24M */
590 ccm_lpcg_on(CCGR_URT1, false);
591 ccm_clk_root_cfg(LPUART1_CLK_ROOT, OSC_24M_CLK, 1);
592 ccm_lpcg_on(CCGR_URT1, true);
593 break;
594 default:
595 break;
596 }
597}
598
599void init_clk_usdhc(u32 index)
600{
601 /* 400 Mhz */
602 switch (index) {
603 case 0:
604 ccm_lpcg_on(CCGR_USDHC1, 0);
605 ccm_clk_root_cfg(USDHC1_CLK_ROOT, SYS_PLL_PFD1, 2);
606 ccm_lpcg_on(CCGR_USDHC1, 1);
607 break;
608 case 1:
609 ccm_lpcg_on(CCGR_USDHC2, 0);
610 ccm_clk_root_cfg(USDHC2_CLK_ROOT, SYS_PLL_PFD1, 2);
611 ccm_lpcg_on(CCGR_USDHC2, 1);
612 break;
613 case 2:
614 ccm_lpcg_on(CCGR_USDHC3, 0);
615 ccm_clk_root_cfg(USDHC3_CLK_ROOT, SYS_PLL_PFD1, 2);
616 ccm_lpcg_on(CCGR_USDHC3, 1);
617 break;
618 default:
619 return;
620 };
621}
622
623void enable_usboh3_clk(unsigned char enable)
624{
625 if (enable) {
626 ccm_clk_root_cfg(HSIO_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
627 ccm_lpcg_on(CCGR_USBC, 1);
628 } else {
629 ccm_lpcg_on(CCGR_USBC, 0);
630 }
631}
632
Ye Li327ecf92022-07-26 16:41:06 +0800633#ifdef CONFIG_SPL_BUILD
634void dram_pll_init(ulong pll_val)
635{
636 configure_fracpll(DRAM_PLL_CLK, pll_val);
637}
638
639void dram_enable_bypass(ulong clk_val)
640{
641 switch (clk_val) {
642 case MHZ(400):
643 ccm_clk_root_cfg(DRAM_ALT_CLK_ROOT, SYS_PLL_PFD1, 2);
644 break;
645 case MHZ(333):
646 ccm_clk_root_cfg(DRAM_ALT_CLK_ROOT, SYS_PLL_PFD0, 3);
647 break;
648 case MHZ(200):
649 ccm_clk_root_cfg(DRAM_ALT_CLK_ROOT, SYS_PLL_PFD1, 4);
650 break;
651 case MHZ(100):
652 ccm_clk_root_cfg(DRAM_ALT_CLK_ROOT, SYS_PLL_PFD1, 8);
653 break;
654 default:
655 printf("No matched freq table %lu\n", clk_val);
656 return;
657 }
658
659 /* Set DRAM APB to 133Mhz */
660 ccm_clk_root_cfg(DRAM_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
661 /* Switch from DRAM clock root from PLL to CCM */
662 ccm_shared_gpr_set(SHARED_GPR_DRAM_CLK, SHARED_GPR_DRAM_CLK_SEL_CCM);
663}
664
665void dram_disable_bypass(void)
666{
667 /* Set DRAM APB to 133Mhz */
668 ccm_clk_root_cfg(DRAM_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
669 /* Switch from DRAM clock root from CCM to PLL */
670 ccm_shared_gpr_set(SHARED_GPR_DRAM_CLK, SHARED_GPR_DRAM_CLK_SEL_PLL);
671}
Peng Fan10fde4e2022-07-26 16:41:11 +0800672
673void set_arm_clk(ulong freq)
674{
675 /* Increase ARM clock to 1.7Ghz */
676 ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_CCM);
677 configure_intpll(ARM_PLL_CLK, 1700000000);
678 ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_PLL);
679}
680
Ye Li327ecf92022-07-26 16:41:06 +0800681#endif
682
Peng Fan28b5cb52022-07-26 16:40:43 +0800683int clock_init(void)
684{
685 int i;
686
687 /* Set A55 periphal to 333M */
688 ccm_clk_root_cfg(ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD0, 3);
689 /* Set A55 mtr bus to 133M */
690 ccm_clk_root_cfg(ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
691
692 /* Sentinel to 200M */
693 ccm_clk_root_cfg(SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 2);
694 /* Bus_wakeup to 133M */
695 ccm_clk_root_cfg(BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
696 /* Bus_AON to 133M */
697 ccm_clk_root_cfg(BUS_AON_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
698 /* M33 to 200M */
699 ccm_clk_root_cfg(M33_CLK_ROOT, SYS_PLL_PFD1_DIV2, 2);
700 /*
701 * WAKEUP_AXI to 312.5M, because of FEC only can support to 320M for
702 * generating MII clock at 2.5M
703 */
704 ccm_clk_root_cfg(WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD2, 2);
705 /* SWO TRACE to 133M */
706 ccm_clk_root_cfg(SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
Peng Fan44b6f6b2023-04-28 12:08:15 +0800707 /* M33 systetick to 24M */
708 ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1);
Peng Fan28b5cb52022-07-26 16:40:43 +0800709 /* NIC to 400M */
710 ccm_clk_root_cfg(NIC_CLK_ROOT, SYS_PLL_PFD1, 2);
711 /* NIC_APB to 133M */
712 ccm_clk_root_cfg(NIC_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
713
714 /* allow for non-secure access */
715 for (i = 0; i < OSCPLL_END; i++)
716 ccm_clk_src_tz_access(i, true, false, false);
717
718 for (i = 0; i < CLK_ROOT_NUM; i++)
719 ccm_clk_root_tz_access(i, true, false, false);
720
721 for (i = 0; i < CCGR_NUM; i++)
722 ccm_lpcg_tz_access(i, true, false, false);
723
724 for (i = 0; i < SHARED_GPR_NUM; i++)
725 ccm_shared_gpr_tz_access(i, true, false, false);
726
727 return 0;
728}
729
730int set_clk_eqos(enum enet_freq type)
731{
732 u32 eqos_post_div;
733
734 switch (type) {
735 case ENET_125MHZ:
736 eqos_post_div = 2; /* 250M clock */
737 break;
738 case ENET_50MHZ:
739 eqos_post_div = 5; /* 100M clock */
740 break;
741 case ENET_25MHZ:
742 eqos_post_div = 10; /* 50M clock*/
743 break;
744 default:
745 return -EINVAL;
746 }
747
748 /* disable the clock first */
749 ccm_lpcg_on(CCGR_ENETQOS, false);
750
751 ccm_clk_root_cfg(ENET_CLK_ROOT, SYS_PLL_PFD0_DIV2, eqos_post_div);
752 ccm_clk_root_cfg(ENET_TIMER2_CLK_ROOT, SYS_PLL_PFD0_DIV2, 5);
753
754 /* enable clock */
755 ccm_lpcg_on(CCGR_ENETQOS, true);
756
757 return 0;
758}
759
760u32 imx_get_eqos_csr_clk(void)
761{
762 return ccm_clk_root_get_rate(WAKEUP_AXI_CLK_ROOT);
763}
764
765u32 imx_get_fecclk(void)
766{
767 return ccm_clk_root_get_rate(WAKEUP_AXI_CLK_ROOT);
768}
769
770int set_clk_enet(enum enet_freq type)
771{
772 u32 div;
773
774 /* disable the clock first */
775 ccm_lpcg_on(CCGR_ENET1, false);
776
777 switch (type) {
778 case ENET_125MHZ:
779 div = 2; /* 250Mhz */
780 break;
781 case ENET_50MHZ:
782 div = 5; /* 100Mhz */
783 break;
784 case ENET_25MHZ:
785 div = 10; /* 50Mhz */
786 break;
787 default:
788 return -EINVAL;
789 }
790
791 ccm_clk_root_cfg(ENET_REF_CLK_ROOT, SYS_PLL_PFD0_DIV2, div);
792 ccm_clk_root_cfg(ENET_TIMER1_CLK_ROOT, SYS_PLL_PFD0_DIV2, 5);
793
794#ifdef CONFIG_FEC_MXC_25M_REF_CLK
795 ccm_clk_root_cfg(ENET_REF_PHY_CLK_ROOT, SYS_PLL_PFD0_DIV2, 20);
796#endif
797
798 /* enable clock */
799 ccm_lpcg_on(CCGR_ENET1, true);
800
801 return 0;
802}
803
804/*
805 * Dump some clockes.
806 */
807#ifndef CONFIG_SPL_BUILD
808int do_showclocks(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
809{
810 u32 freq;
811
812 freq = decode_pll(ARM_PLL_CLK);
813 printf("ARM_PLL %8d MHz\n", freq / 1000);
814 freq = decode_pll(DRAM_PLL_CLK);
815 printf("DRAM_PLL %8d MHz\n", freq / 1000);
816 freq = decode_pll(SYS_PLL_PFD0);
817 printf("SYS_PLL_PFD0 %8d MHz\n", freq / 1000);
818 freq = decode_pll(SYS_PLL_PFD0_DIV2);
819 printf("SYS_PLL_PFD0_DIV2 %8d MHz\n", freq / 1000);
820 freq = decode_pll(SYS_PLL_PFD1);
821 printf("SYS_PLL_PFD1 %8d MHz\n", freq / 1000);
822 freq = decode_pll(SYS_PLL_PFD1_DIV2);
823 printf("SYS_PLL_PFD1_DIV2 %8d MHz\n", freq / 1000);
824 freq = decode_pll(SYS_PLL_PFD2);
825 printf("SYS_PLL_PFD2 %8d MHz\n", freq / 1000);
826 freq = decode_pll(SYS_PLL_PFD2_DIV2);
827 printf("SYS_PLL_PFD2_DIV2 %8d MHz\n", freq / 1000);
828 freq = mxc_get_clock(MXC_ARM_CLK);
829 printf("ARM CORE %8d MHz\n", freq / 1000000);
830 freq = mxc_get_clock(MXC_IPG_CLK);
831 printf("IPG %8d MHz\n", freq / 1000000);
832 freq = mxc_get_clock(MXC_UART_CLK);
833 printf("UART3 %8d MHz\n", freq / 1000000);
834 freq = mxc_get_clock(MXC_ESDHC_CLK);
835 printf("USDHC1 %8d MHz\n", freq / 1000000);
836 freq = mxc_get_clock(MXC_FLEXSPI_CLK);
837 printf("FLEXSPI %8d MHz\n", freq / 1000000);
838
839 return 0;
Peng Fanbbcd2c42022-07-26 16:40:39 +0800840}
Peng Fan28b5cb52022-07-26 16:40:43 +0800841
842U_BOOT_CMD(
843 clocks, CONFIG_SYS_MAXARGS, 1, do_showclocks,
844 "display clocks",
845 ""
846);
847#endif