2 * Copyright (C) 2010 Freescale Semiconductor, Inc.
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 #include <asm/arch/mx50.h>
25 #include <asm/errno.h>
28 #ifdef CONFIG_CMD_CLOCK
29 #include <asm/clock.h>
32 #ifdef CONFIG_ARCH_CPU_INIT
33 #include <asm/cache-cp15.h>
37 PLL1_CLK = MXC_DPLL1_BASE,
38 PLL2_CLK = MXC_DPLL2_BASE,
39 PLL3_CLK = MXC_DPLL3_BASE,
48 #define AHB_CLK_ROOT 133333333
49 #define IPG_CLK_ROOT 66666666
50 #define IPG_PER_CLK_ROOT 40000000
52 #ifdef CONFIG_CMD_CLOCK
53 #define SZ_DEC_1M 1000000
54 #define PLL_PD_MAX 16 /* Actual pd+1 */
55 #define PLL_MFI_MAX 15
63 struct fixed_pll_mfd {
68 const struct fixed_pll_mfd fixed_mfd[4] = {
69 {0, 0}, /* reserved */
70 {0, 0}, /* reserved */
71 {CONFIG_MX50_HCLK_FREQ, 24 * 16}, /* 384 */
72 {0, 0}, /* reserved */
82 #define PLL_FREQ_MAX(_ref_clk_) \
83 (4 * _ref_clk_ * PLL_MFI_MAX)
84 #define PLL_FREQ_MIN(_ref_clk_) \
85 ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
86 #define MAX_DDR_CLK 420000000
87 #define AHB_CLK_MAX 133333333
88 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
89 #define NFC_CLK_MAX 25000000
90 #define HSP_CLK_MAX 133333333
93 static u32 __decode_pll(enum pll_clocks pll, u32 infreq)
95 long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
96 unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
99 dp_ctl = __REG(pll + MXC_PLL_DP_CTL);
100 pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
101 dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
104 dp_op = __REG(pll + MXC_PLL_DP_OP);
105 dp_mfd = __REG(pll + MXC_PLL_DP_MFD);
106 dp_mfn = __REG(pll + MXC_PLL_DP_MFN);
108 dp_op = __REG(pll + MXC_PLL_DP_HFS_OP);
109 dp_mfd = __REG(pll + MXC_PLL_DP_HFS_MFD);
110 dp_mfn = __REG(pll + MXC_PLL_DP_HFS_MFN);
112 pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
113 mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
114 mfi = (mfi <= 5) ? 5 : mfi;
115 mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
116 mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
117 /* Sign extend to 32-bits */
118 if (mfn >= 0x04000000) {
123 ref_clk = 2 * infreq;
127 ref_clk /= (pdf + 1);
128 temp = (u64) ref_clk * mfn_abs;
129 do_div(temp, mfd + 1);
132 temp = (ref_clk * mfi) + temp;
137 static u32 __get_mcu_main_clk(void)
140 reg = (__REG(MXC_CCM_CACRR) & MXC_CCM_CACRR_ARM_PODF_MASK) >>
141 MXC_CCM_CACRR_ARM_PODF_OFFSET;
142 freq = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
143 return freq / (reg + 1);
147 * This function returns the low power audio clock.
149 u32 __get_lp_apm(void)
152 u32 cbcmr = __REG(MXC_CCM_CBCMR);
154 if (((cbcmr >> MXC_CCM_CBCMR_LP_APM_SEL_OFFSET) & 0x1) == 0)
155 ret_val = CONFIG_MX50_HCLK_FREQ;
157 ret_val = ((32768 * 1024));
162 static u32 __get_periph_clk(void)
165 reg = __REG(MXC_CCM_CBCDR);
167 switch ((reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL_MASK) >>
168 MXC_CCM_CBCDR_PERIPH_CLK_SEL_OFFSET) {
170 return __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
172 return __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ);
174 return __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ);
176 return __get_lp_apm();
180 static u32 __get_ipg_clk(void)
182 u32 ahb_podf, ipg_podf;
184 ahb_podf = __REG(MXC_CCM_CBCDR);
185 ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
186 MXC_CCM_CBCDR_IPG_PODF_OFFSET;
187 ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
188 MXC_CCM_CBCDR_AHB_PODF_OFFSET;
189 return __get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1));
192 static u32 __get_ipg_per_clk(void)
194 u32 pred1, pred2, podf, clk;
195 if (__REG(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL)
196 return __get_ipg_clk();
198 clk = __REG(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL ?
199 __get_lp_apm() : __get_periph_clk();
201 podf = __REG(MXC_CCM_CBCDR);
202 pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
203 MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET;
204 pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
205 MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET;
206 podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
207 MXC_CCM_CBCDR_PERCLK_PODF_OFFSET;
209 return clk / ((pred1 + 1) * (pred2 + 1) * (podf + 1));
212 static u32 __get_uart_clk(void)
214 u32 freq = 0, reg, pred, podf;
215 reg = __REG(MXC_CCM_CSCMR1);
216 switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >>
217 MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) {
219 freq = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
222 freq = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ);
225 freq = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ);
228 freq = __get_lp_apm();
234 reg = __REG(MXC_CCM_CSCDR1);
236 pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
237 MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET;
239 podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
240 MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
241 freq /= (pred + 1) * (podf + 1);
247 static u32 __get_cspi_clk(void)
249 u32 ret_val = 0, pdf, pre_pdf, clk_sel, div;
250 u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
251 u32 cscdr2 = __REG(MXC_CCM_CSCDR2);
253 pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \
254 >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET;
255 pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \
256 >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET;
257 clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \
258 >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
260 div = (pre_pdf + 1) * (pdf + 1);
264 ret_val = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ) / div;
267 ret_val = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ) / div;
270 ret_val = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ) / div;
273 ret_val = __get_lp_apm() / div;
280 static u32 __get_axi_a_clk(void)
282 u32 cbcdr = __REG(MXC_CCM_CBCDR);
283 u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_A_PODF_MASK) \
284 >> MXC_CCM_CBCDR_AXI_A_PODF_OFFSET;
286 return __get_periph_clk() / (pdf + 1);
289 static u32 __get_axi_b_clk(void)
291 u32 cbcdr = __REG(MXC_CCM_CBCDR);
292 u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_B_PODF_MASK) \
293 >> MXC_CCM_CBCDR_AXI_B_PODF_OFFSET;
295 return __get_periph_clk() / (pdf + 1);
298 static u32 __get_ahb_clk(void)
300 u32 cbcdr = __REG(MXC_CCM_CBCDR);
301 u32 pdf = (cbcdr & MXC_CCM_CBCDR_AHB_PODF_MASK) \
302 >> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
304 return __get_periph_clk() / (pdf + 1);
308 static u32 __get_emi_slow_clk(void)
310 u32 cbcdr = __REG(MXC_CCM_CBCDR);
311 u32 emi_clk_sel = cbcdr & MXC_CCM_CBCDR_WEIM_CLK_SEL;
312 u32 pdf = (cbcdr & MXC_CCM_CBCDR_WEIM_PODF_MASK) \
313 >> MXC_CCM_CBCDR_WEIM_PODF_OFFSET;
316 return __get_ahb_clk() / (pdf + 1);
318 return __get_periph_clk() / (pdf + 1);
321 static u32 __get_sys_clk(void)
323 u32 ret_val = 0, clk, sys_pll_div;
324 u32 clkseq_bypass = __REG(MXC_CCM_CLKSEQ_BYPASS);
326 /* Fixme Not handle OSC and PFD1 mux */
327 if ((clkseq_bypass & MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_1) &&
328 clkseq_bypass & MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_0) {
329 sys_pll_div = __REG(MXC_CCM_CLK_SYS) \
330 & MXC_CCM_CLK_SYS_DIV_PLL_MASK;
331 clk = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
335 } else if ((clkseq_bypass & MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_0) == 0) {
336 ret_val = CONFIG_MX50_HCLK_FREQ; /* OSC */
339 printf("Warning, Fixme Not handle PFD1 mux\n");
345 static u32 __get_ddr_clk(void)
347 u32 ret_val = 0, clk, ddr_pll_div;
348 u32 clk_ddr = __REG(MXC_CCM_CLK_DDR);
349 u32 ddr_clk_sel = clk_ddr & MXC_CCM_CLK_DDR_DDR_PFD_SEL;
352 ddr_pll_div = clk_ddr & \
353 MXC_CCM_CLK_DDR_DDR_DIV_PLL_MASK;
354 clk = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
360 printf("Warning, Fixme Not handle PFD1 mux\n");
366 #ifdef CONFIG_CMD_MMC
367 static u32 __get_esdhc1_clk(void)
369 u32 ret_val = 0, div, pre_pdf, pdf;
370 u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
371 u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
374 esdh1_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC1_CLK_SEL_MASK) \
375 >> MXC_CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET;
376 pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_CLK_PRED_MASK) \
377 >> MXC_CCM_CSCDR1_ESDHC1_CLK_PRED_OFFSET;
378 pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_CLK_PODF_MASK) \
379 >> MXC_CCM_CSCDR1_ESDHC1_CLK_PODF_OFFSET ;
381 div = (pre_pdf + 1) * (pdf + 1);
383 switch (esdh1_clk_sel) {
385 ret_val = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
388 ret_val = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ);
391 ret_val = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ);
394 ret_val = __get_lp_apm();
405 static u32 __get_esdhc3_clk(void)
407 u32 ret_val = 0, div, pre_pdf, pdf;
409 u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
410 u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
411 esdh3_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_MASK) \
412 >> MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_OFFSET;
413 pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_CLK_PRED_MASK) \
414 >> MXC_CCM_CSCDR1_ESDHC3_CLK_PRED_OFFSET;
415 pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_CLK_PODF_MASK) \
416 >> MXC_CCM_CSCDR1_ESDHC3_CLK_PODF_OFFSET ;
418 div = (pre_pdf + 1) * (pdf + 1);
420 switch (esdh3_clk_sel) {
422 ret_val = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
425 ret_val = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ);
428 ret_val = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ);
431 ret_val = __get_lp_apm();
434 puts("Warning, Fixme,not handle PFD mux\n");
446 static u32 __get_esdhc2_clk(void)
448 u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
449 u32 esdh2_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC2_CLK_SEL;
451 return __get_esdhc3_clk();
453 return __get_esdhc1_clk();
456 static u32 __get_esdhc4_clk(void)
458 u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
459 u32 esdh4_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
461 return __get_esdhc3_clk();
463 return __get_esdhc1_clk();
467 unsigned int mxc_get_clock(enum mxc_clock clk)
471 return __get_mcu_main_clk();
473 return __get_periph_clk();
475 return __get_ahb_clk();
477 return __get_ipg_clk();
479 return __get_ipg_per_clk();
481 return __get_uart_clk();
482 #ifdef CONFIG_IMX_CSPI
484 return __get_cspi_clk();
487 return __get_axi_a_clk();
489 return __get_axi_b_clk();
490 case MXC_EMI_SLOW_CLK:
491 return __get_emi_slow_clk();
493 return __get_ddr_clk();
494 #ifdef CONFIG_CMD_MMC
496 return __get_esdhc1_clk();
498 return __get_esdhc2_clk();
500 return __get_esdhc3_clk();
502 return __get_esdhc4_clk();
510 void mxc_dump_clocks(void)
513 freq = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ);
514 printf("mx50 pll1: %dMHz\n", freq / 1000000);
515 freq = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ);
516 printf("mx50 pll2: %dMHz\n", freq / 1000000);
517 freq = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ);
518 printf("mx50 pll3: %dMHz\n", freq / 1000000);
519 printf("ipg clock : %dHz\n", mxc_get_clock(MXC_IPG_CLK));
520 printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK));
521 printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK));
522 #ifdef CONFIG_IMX_ECSPI
523 printf("cspi clock : %dHz\n", mxc_get_clock(MXC_CSPI_CLK));
525 printf("ahb clock : %dHz\n", mxc_get_clock(MXC_AHB_CLK));
526 printf("axi_a clock : %dHz\n", mxc_get_clock(MXC_AXI_A_CLK));
527 printf("axi_b clock : %dHz\n", mxc_get_clock(MXC_AXI_B_CLK));
528 printf("weim_clock : %dHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK));
529 printf("ddr clock : %dHz\n", mxc_get_clock(MXC_DDR_CLK));
530 #ifdef CONFIG_CMD_MMC
531 printf("esdhc1 clock : %dHz\n", mxc_get_clock(MXC_ESDHC_CLK));
532 printf("esdhc2 clock : %dHz\n", mxc_get_clock(MXC_ESDHC2_CLK));
533 printf("esdhc3 clock : %dHz\n", mxc_get_clock(MXC_ESDHC3_CLK));
534 printf("esdhc4 clock : %dHz\n", mxc_get_clock(MXC_ESDHC4_CLK));
538 #ifdef CONFIG_CMD_CLOCK
539 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
540 static int gcd(int m, int n)
555 * This is to calculate various parameters based on reference clock and
556 * targeted clock based on the equation:
557 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
558 * This calculation is based on a fixed MFD value for simplicity.
560 * @param ref reference clock freq in Hz
561 * @param target targeted clock in Hz
562 * @param pll pll_param structure.
564 * @return 0 if successful; non-zero otherwise.
566 static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
568 u64 pd, mfi = 1, mfn, mfd, t1;
569 u32 n_target = target;
573 * Make sure targeted freq is in the valid range.
574 * Otherwise the following calculation might be wrong!!!
576 if (n_target < PLL_FREQ_MIN(ref) ||
577 n_target > PLL_FREQ_MAX(ref)) {
578 printf("Targeted peripheral clock should be"
579 "within [%d - %d]\n",
580 PLL_FREQ_MIN(ref) / SZ_DEC_1M,
581 PLL_FREQ_MAX(ref) / SZ_DEC_1M);
585 for (i = 0; i < ARRAY_SIZE(fixed_mfd); i++) {
586 if (fixed_mfd[i].ref_clk_hz == ref) {
587 mfd = fixed_mfd[i].mfd;
592 if (i == ARRAY_SIZE(fixed_mfd))
595 /* Use n_target and n_ref to avoid overflow */
596 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
598 do_div(t1, (4 * n_ref));
600 if (mfi > PLL_MFI_MAX)
606 /* Now got pd and mfi already */
608 mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
616 #ifdef CMD_CLOCK_DEBUG
617 printf("%d: ref=%d, target=%d, pd=%d,"
618 "mfi=%d,mfn=%d, mfd=%d\n",
619 __LINE__, ref, (u32)n_target,
620 (u32)pd, (u32)mfi, (u32)mfn,
636 int clk_info(u32 clk_type)
640 printf("CPU Clock: %dHz\n",
641 mxc_get_clock(MXC_ARM_CLK));
644 printf("Peripheral Clock: %dHz\n",
645 mxc_get_clock(MXC_PER_CLK));
648 printf("AHB Clock: %dHz\n",
649 mxc_get_clock(MXC_AHB_CLK));
652 printf("IPG Clock: %dHz\n",
653 mxc_get_clock(MXC_IPG_CLK));
656 printf("IPG_PER Clock: %dHz\n",
657 mxc_get_clock(MXC_IPG_PERCLK));
660 printf("UART Clock: %dHz\n",
661 mxc_get_clock(MXC_UART_CLK));
664 printf("CSPI Clock: %dHz\n",
665 mxc_get_clock(MXC_CSPI_CLK));
668 printf("DDR Clock: %dHz\n",
669 mxc_get_clock(MXC_DDR_CLK));
672 printf("cpu clock: %dMHz\n",
673 mxc_get_clock(MXC_ARM_CLK) / SZ_DEC_1M);
677 printf("Unsupported clock type! :(\n");
683 #define calc_div(target_clk, src_clk, limit) ({ \
685 if ((src_clk % target_clk) <= 100) \
686 tmp = src_clk / target_clk; \
688 tmp = (src_clk / target_clk) + 1; \
694 u32 calc_per_cbcdr_val(u32 per_clk, u32 cbcmr)
696 u32 cbcdr = __REG(MXC_CCM_CBCDR);
697 u32 tmp_clk = 0, div = 0, clk_sel = 0;
699 cbcdr &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
701 /* emi_slow_podf divider */
702 tmp_clk = __get_emi_slow_clk();
703 clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL;
705 div = calc_div(tmp_clk, per_clk, 8);
706 cbcdr &= ~MXC_CCM_CBCDR_EMI_PODF_MASK;
707 cbcdr |= (div << MXC_CCM_CBCDR_EMI_PODF_OFFSET);
710 /* axi_b_podf divider */
711 tmp_clk = __get_axi_b_clk();
712 div = calc_div(tmp_clk, per_clk, 8);
713 cbcdr &= ~MXC_CCM_CBCDR_AXI_B_PODF_MASK;
714 cbcdr |= (div << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET);
716 /* axi_b_podf divider */
717 tmp_clk = __get_axi_a_clk();
718 div = calc_div(tmp_clk, per_clk, 8);
719 cbcdr &= ~MXC_CCM_CBCDR_AXI_A_PODF_MASK;
720 cbcdr |= (div << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET);
722 /* ahb podf divider */
723 tmp_clk = AHB_CLK_ROOT;
724 div = calc_div(tmp_clk, per_clk, 8);
725 cbcdr &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
726 cbcdr |= (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
731 #define CHANGE_PLL_SETTINGS(base, pd, mfi, mfn, mfd) \
733 writel(0x1232, base + PLL_DP_CTL); \
734 writel(0x2, base + PLL_DP_CONFIG); \
735 writel(((pd - 1) << 0) | (mfi << 4), \
737 writel(mfn, base + PLL_DP_MFN); \
738 writel(mfd - 1, base + PLL_DP_MFD); \
739 writel(((pd - 1) << 0) | (mfi << 4), \
740 base + PLL_DP_HFS_OP); \
741 writel(mfn, base + PLL_DP_HFS_MFN); \
742 writel(mfd - 1, base + PLL_DP_HFS_MFD); \
743 writel(0x1232, base + PLL_DP_CTL); \
744 while (!readl(base + PLL_DP_CTL) & 0x1) \
748 int config_pll_clk(enum pll_clocks pll, struct pll_param *pll_param)
750 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
755 /* Switch ARM to PLL2 clock */
756 writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
757 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
758 pll_param->mfi, pll_param->mfn,
761 writel(ccsr & ~0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
764 /* Switch to pll2 bypass clock */
765 writel(ccsr | 0x2, CCM_BASE_ADDR + CLKCTL_CCSR);
766 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
767 pll_param->mfi, pll_param->mfn,
770 writel(ccsr & ~0x2, CCM_BASE_ADDR + CLKCTL_CCSR);
773 /* Switch to pll3 bypass clock */
774 writel(ccsr | 0x1, CCM_BASE_ADDR + CLKCTL_CCSR);
775 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
776 pll_param->mfi, pll_param->mfn,
779 writel(ccsr & ~0x1, CCM_BASE_ADDR + CLKCTL_CCSR);
788 int config_core_clk(u32 ref, u32 freq)
792 struct pll_param pll_param;
794 memset(&pll_param, 0, sizeof(struct pll_param));
796 /* The case that periph uses PLL1 is not considered here */
798 ret = calc_pll_params(ref, pll, &pll_param);
800 printf("Can't find pll parameters: %d\n",
805 return config_pll_clk(PLL1_CLK, &pll_param);
808 int config_periph_clk(u32 ref, u32 freq)
812 struct pll_param pll_param;
814 memset(&pll_param, 0, sizeof(struct pll_param));
816 if (__REG(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
817 /* Actually this case is not considered here */
818 ret = calc_pll_params(ref, pll, &pll_param);
820 printf("Can't find pll parameters: %d\n",
824 switch ((__REG(MXC_CCM_CBCMR) & \
825 MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >>
826 MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
828 return config_pll_clk(PLL1_CLK, &pll_param);
831 return config_pll_clk(PLL3_CLK, &pll_param);
837 u32 old_cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
838 u32 new_cbcdr = calc_per_cbcdr_val(pll, old_cbcmr);
840 /* Switch peripheral to PLL3 */
841 writel(0x00015154, CCM_BASE_ADDR + CLKCTL_CBCMR);
842 writel(0x02888945, CCM_BASE_ADDR + CLKCTL_CBCDR);
844 /* Make sure change is effective */
845 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
849 ret = calc_pll_params(ref, pll, &pll_param);
851 printf("Can't find pll parameters: %d\n",
855 config_pll_clk(PLL2_CLK, &pll_param);
857 /* Switch peripheral back */
858 writel(new_cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
859 writel(old_cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR);
861 /* Make sure change is effective */
862 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
870 int config_ddr_clk(u32 emi_clk)
873 s32 shift = 0, clk_sel, div = 1;
874 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
875 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
877 if (emi_clk > MAX_DDR_CLK) {
878 printf("DDR clock should be less than"
879 "%d MHz, assuming max value \n",
880 (MAX_DDR_CLK / SZ_DEC_1M));
881 emi_clk = MAX_DDR_CLK;
884 clk_src = __get_periph_clk();
885 /* Find DDR clock input */
886 clk_sel = (cbcmr >> 10) & 0x3;
904 if ((clk_src % emi_clk) == 0)
905 div = clk_src / emi_clk;
907 div = (clk_src / emi_clk) + 1;
911 cbcdr = cbcdr & ~(0x7 << shift);
912 cbcdr |= ((div - 1) << shift);
913 writel(cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
914 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
916 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
922 * This function assumes the expected core clock has to be changed by
923 * modifying the PLL. This is NOT true always but for most of the times,
924 * it is. So it assumes the PLL output freq is the same as the expected
925 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
926 * In the latter case, it will try to increase the presc value until
927 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
928 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
929 * on the targeted PLL and reference input clock to the PLL. Lastly,
930 * it sets the register based on these values along with the dividers.
931 * Note 1) There is no value checking for the passed-in divider values
932 * so the caller has to make sure those values are sensible.
933 * 2) Also adjust the NFC divider such that the NFC clock doesn't
934 * exceed NFC_CLK_MAX.
935 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
936 * 177MHz for higher voltage, this function fixes the max to 133MHz.
937 * 4) This function should not have allowed diag_printf() calls since
938 * the serial driver has been stoped. But leave then here to allow
939 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
941 * @param ref pll input reference clock (24MHz)
942 * @param freq core clock in Hz
943 * @param clk_type clock type, e.g CPU_CLK, DDR_CLK, etc.
944 * @return 0 if successful; non-zero otherwise
946 int clk_config(u32 ref, u32 freq, u32 clk_type)
952 if (config_core_clk(ref, freq))
956 if (config_periph_clk(ref, freq))
960 if (config_ddr_clk(freq))
964 printf("Unsupported or invalid clock type! :(\n");
971 #if defined(CONFIG_DISPLAY_CPUINFO)
972 int print_cpuinfo(void)
974 printf("CPU: Freescale i.MX50 family %d.%dV at %d MHz\n",
975 (get_board_rev() & 0xFF) >> 4,
976 (get_board_rev() & 0xF),
977 __get_mcu_main_clk() / 1000000);
978 #ifndef CONFIG_CMD_CLOCK
985 #if defined(CONFIG_MXC_FEC)
986 extern int mxc_fec_initialize(bd_t *bis);
987 extern void mxc_fec_set_mac_from_env(char *mac_addr);
990 int cpu_eth_init(bd_t *bis)
993 #if defined(CONFIG_MXC_FEC)
994 rc = mxc_fec_initialize(bis);
999 #if defined(CONFIG_ARCH_CPU_INIT)
1000 int arch_cpu_init(void)
1005 #ifdef CONFIG_L2_OFF