]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm_cortexa8/mx53/generic.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / cpu / arm_cortexa8 / mx53 / generic.c
1 /*
2  * Copyright (C) 2010 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
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.
11  *
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.
16  *
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,
20  * MA 02111-1307 USA
21  */
22
23 #include <common.h>
24 #include <asm/arch/mx53.h>
25 #include <asm/errno.h>
26 #include <asm/io.h>
27 #include "crm_regs.h"
28 #ifdef CONFIG_CMD_CLOCK
29 #include <asm/clock.h>
30 #endif
31 #include <div64.h>
32 #ifdef CONFIG_ARCH_CPU_INIT
33 #include <asm/cache-cp15.h>
34 #endif
35
36 enum pll_clocks {
37         PLL1_CLK = MXC_DPLL1_BASE,
38         PLL2_CLK = MXC_DPLL2_BASE,
39         PLL3_CLK = MXC_DPLL3_BASE,
40         PLL4_CLK = MXC_DPLL4_BASE,
41 };
42
43 enum pll_sw_clocks {
44         PLL1_SW_CLK,
45         PLL2_SW_CLK,
46         PLL3_SW_CLK,
47         PLL4_SW_CLK,
48 };
49
50 #define AHB_CLK_ROOT 133333333
51 #define IPG_CLK_ROOT 66666666
52 #define IPG_PER_CLK_ROOT 40000000
53
54 #ifdef CONFIG_CMD_CLOCK
55 #define SZ_DEC_1M       1000000
56 #define PLL_PD_MAX      16      /* Actual pd+1 */
57 #define PLL_MFI_MAX     15
58 #define PLL_MFI_MIN     5
59 #define ARM_DIV_MAX     8
60 #define IPG_DIV_MAX     4
61 #define AHB_DIV_MAX     8
62 #define EMI_DIV_MAX     8
63 #define NFC_DIV_MAX     8
64
65 struct fixed_pll_mfd {
66     u32 ref_clk_hz;
67     u32 mfd;
68 };
69
70 const struct fixed_pll_mfd fixed_mfd[4] = {
71     {0,                   0},      /* reserved */
72     {0,                   0},      /* reserved */
73     {CONFIG_MX53_HCLK_FREQ, 24 * 16},    /* 384 */
74     {0,                   0},      /* reserved */
75 };
76
77 struct pll_param {
78     u32 pd;
79     u32 mfi;
80     u32 mfn;
81     u32 mfd;
82 };
83
84 #define PLL_FREQ_MAX(_ref_clk_) \
85                 (4 * _ref_clk_ * PLL_MFI_MAX)
86 #define PLL_FREQ_MIN(_ref_clk_) \
87                 ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
88 #define MAX_DDR_CLK     420000000
89 #define AHB_CLK_MAX     133333333
90 #define IPG_CLK_MAX     (AHB_CLK_MAX / 2)
91 #define NFC_CLK_MAX     25000000
92 #define HSP_CLK_MAX     133333333
93 #endif
94
95 static u32 __decode_pll(enum pll_clocks pll, u32 infreq)
96 {
97         u32 mfi, mfn, mfd, pd;
98
99         mfn = __REG(pll + MXC_PLL_DP_MFN);
100         mfd = __REG(pll + MXC_PLL_DP_MFD) + 1;
101         mfi = __REG(pll + MXC_PLL_DP_OP);
102         pd = (mfi  & 0xF) + 1;
103         mfi = (mfi >> 4) & 0xF;
104         mfi = (mfi >= 5) ? mfi : 5;
105
106         return ((4 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000;
107 }
108
109 static u32 __get_mcu_main_clk(void)
110 {
111         u32 reg, freq;
112         reg = (__REG(MXC_CCM_CACRR) & MXC_CCM_CACRR_ARM_PODF_MASK) >>
113             MXC_CCM_CACRR_ARM_PODF_OFFSET;
114         freq = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ);
115         return freq / (reg + 1);
116 }
117
118 static u32 __get_periph_clk(void)
119 {
120         u32 reg;
121         reg = __REG(MXC_CCM_CBCDR);
122         if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
123                 reg = __REG(MXC_CCM_CBCMR);
124                 switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >>
125                         MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
126                 case 0:
127                         return __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ);
128                 case 1:
129                         return __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ);
130                 default:
131                         return 0;
132                 }
133         }
134         return __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ);
135 }
136
137 static u32 __get_ipg_clk(void)
138 {
139         u32 ahb_podf, ipg_podf;
140
141         ahb_podf = __REG(MXC_CCM_CBCDR);
142         ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
143                         MXC_CCM_CBCDR_IPG_PODF_OFFSET;
144         ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
145                         MXC_CCM_CBCDR_AHB_PODF_OFFSET;
146         return __get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1));
147 }
148
149 static u32 __get_ipg_per_clk(void)
150 {
151         u32 pred1, pred2, podf;
152         if (__REG(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL)
153                 return __get_ipg_clk();
154         /* Fixme: not handle what about lpm */
155         podf = __REG(MXC_CCM_CBCDR);
156         pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
157                 MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET;
158         pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
159                 MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET;
160         podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
161                 MXC_CCM_CBCDR_PERCLK_PODF_OFFSET;
162
163         return __get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1));
164 }
165
166 /*!
167  * This function returns the low power audio clock.
168  */
169 static u32 __get_lp_apm(void)
170 {
171         u32 ret_val = 0;
172         u32 ccsr = __REG(MXC_CCM_CCSR);
173
174         if (((ccsr >> MXC_CCM_CCSR_LP_APM_SEL_OFFSET) & 1) == 0)
175                 ret_val = CONFIG_MX53_HCLK_FREQ;
176         else
177                 ret_val = ((32768 * 1024));
178
179         return ret_val;
180 }
181
182 /*
183 static u32 __get_perclk_lp_apm(void)
184 {
185         u32 ret_val = 0;
186         u32 cbcmr = __REG(MXC_CCM_CBCMR);
187         u32 clk_sel = (cbcmr & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL) \
188                         >> MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL_OFFSET;
189
190         switch (clk_sel) {
191         case 0:
192                 ret_val =  __get_periph_clk();
193                 break;
194         case 1:
195                 ret_val =  __get_lp_apm();
196                 break;
197         default:
198                 break;
199         }
200
201         return ret_val;
202 }
203 */
204
205 static u32 __get_uart_clk(void)
206 {
207         u32 freq = 0, reg, pred, podf;
208         reg = __REG(MXC_CCM_CSCMR1);
209         switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >>
210                 MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) {
211         case 0x0:
212                 freq = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ);
213                 break;
214         case 0x1:
215                 freq = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ);
216                 break;
217         case 0x2:
218                 freq = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ);
219                 break;
220         case 0x4:
221                 freq = __get_lp_apm();
222                 break;
223         default:
224                 break;
225         }
226
227         reg = __REG(MXC_CCM_CSCDR1);
228
229         pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
230                 MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET;
231
232         podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
233                 MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
234         freq /= (pred + 1) * (podf + 1);
235
236         return freq;
237 }
238
239
240 static u32 __get_cspi_clk(void)
241 {
242         u32 ret_val = 0, pdf, pre_pdf, clk_sel, div;
243         u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
244         u32 cscdr2 = __REG(MXC_CCM_CSCDR2);
245
246         pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \
247                         >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET;
248         pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \
249                         >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET;
250         clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \
251                         >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
252
253         div = (pre_pdf + 1) * (pdf + 1);
254
255         switch (clk_sel) {
256         case 0:
257                 ret_val = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ) / div;
258                 break;
259         case 1:
260                 ret_val = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ) / div;
261                 break;
262         case 2:
263                 ret_val = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ) / div;
264                 break;
265         default:
266                 ret_val = __get_lp_apm() / div;
267                 break;
268         }
269
270         return ret_val;
271 }
272
273 static u32 __get_axi_a_clk(void)
274 {
275         u32 cbcdr =  __REG(MXC_CCM_CBCDR);
276         u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_A_PODF_MASK) \
277                         >> MXC_CCM_CBCDR_AXI_A_PODF_OFFSET;
278
279         return  __get_periph_clk() / (pdf + 1);
280 }
281
282 static u32 __get_axi_b_clk(void)
283 {
284         u32 cbcdr =  __REG(MXC_CCM_CBCDR);
285         u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_B_PODF_MASK) \
286                         >> MXC_CCM_CBCDR_AXI_B_PODF_OFFSET;
287
288         return  __get_periph_clk() / (pdf + 1);
289 }
290
291 static u32 __get_ahb_clk(void)
292 {
293         u32 cbcdr =  __REG(MXC_CCM_CBCDR);
294         u32 pdf = (cbcdr & MXC_CCM_CBCDR_AHB_PODF_MASK) \
295                         >> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
296
297         return  __get_periph_clk() / (pdf + 1);
298 }
299
300
301 static u32 __get_emi_slow_clk(void)
302 {
303         u32 cbcdr =  __REG(MXC_CCM_CBCDR);
304         u32 emi_clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL;
305         u32 pdf = (cbcdr & MXC_CCM_CBCDR_EMI_PODF_MASK) \
306                         >> MXC_CCM_CBCDR_EMI_PODF_OFFSET;
307
308         if (emi_clk_sel)
309                 return  __get_ahb_clk() / (pdf + 1);
310
311         return  __get_periph_clk() / (pdf + 1);
312 }
313
314 /*
315 static u32 __get_nfc_clk(void)
316 {
317         u32 cbcdr =  __REG(MXC_CCM_CBCDR);
318         u32 pdf = (cbcdr & MXC_CCM_CBCDR_NFC_PODF_MASK) \
319                         >> MXC_CCM_CBCDR_NFC_PODF_OFFSET;
320
321         return  __get_emi_slow_clk() / (pdf + 1);
322 }
323 */
324
325 static u32 __get_ddr_clk(void)
326 {
327         u32 ret_val = 0;
328         u32 cbcmr = __REG(MXC_CCM_CBCMR);
329         u32 ddr_clk_sel = (cbcmr & MXC_CCM_CBCMR_DDR_CLK_SEL_MASK) \
330                                 >> MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET;
331
332         switch (ddr_clk_sel) {
333         case 0:
334                 ret_val =  __get_axi_a_clk();
335                 break;
336         case 1:
337                 ret_val =  __get_axi_b_clk();
338                 break;
339         case 2:
340                 ret_val =  __get_emi_slow_clk();
341                 break;
342         case 3:
343                 ret_val =  __get_ahb_clk();
344                 break;
345         default:
346                 break;
347         }
348
349         return ret_val;
350 }
351
352 static u32 __get_esdhc1_clk(void)
353 {
354         u32 ret_val = 0, div, pre_pdf, pdf;
355         u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
356         u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
357         u32 esdh1_clk_sel;
358
359         esdh1_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK) \
360                                 >> MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET;
361         pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK) \
362                         >> MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET;
363         pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK) \
364                         >> MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET ;
365
366         div = (pre_pdf + 1) * (pdf + 1);
367
368         switch (esdh1_clk_sel) {
369         case 0:
370                 ret_val = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ);
371                 break;
372         case 1:
373                 ret_val = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ);
374                 break;
375         case 2:
376                 ret_val = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ);
377                 break;
378         case 3:
379                 ret_val = __get_lp_apm();
380                 break;
381         default:
382                 break;
383         }
384
385         ret_val /= div;
386
387         return ret_val;
388 }
389
390 static u32 __get_esdhc3_clk(void)
391 {
392         u32 ret_val = 0, div, pre_pdf, pdf;
393         u32 esdh3_clk_sel;
394         u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
395         u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
396         esdh3_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_MASK) \
397                                 >> MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_OFFSET;
398         pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK) \
399                         >> MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET;
400         pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK) \
401                         >> MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET ;
402
403         div = (pre_pdf + 1) * (pdf + 1);
404
405         switch (esdh3_clk_sel) {
406         case 0:
407                 ret_val = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ);
408                 break;
409         case 1:
410                 ret_val = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ);
411                 break;
412         case 2:
413                 ret_val = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ);
414                 break;
415         case 3:
416                 ret_val = __get_lp_apm();
417                 break;
418         default:
419                 break;
420         }
421
422         ret_val /= div;
423
424         return ret_val;
425 }
426
427 static u32 __get_esdhc2_clk(void)
428 {
429         u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
430         u32 esdh2_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC2_CLK_SEL;
431         if (esdh2_clk_sel)
432                 return __get_esdhc3_clk();
433
434         return __get_esdhc1_clk();
435 }
436
437 static u32 __get_esdhc4_clk(void)
438 {
439         u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
440         u32 esdh4_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
441         if (esdh4_clk_sel)
442                 return __get_esdhc3_clk();
443
444         return __get_esdhc1_clk();
445 }
446
447 unsigned int mxc_get_clock(enum mxc_clock clk)
448 {
449         switch (clk) {
450         case MXC_ARM_CLK:
451                 return __get_mcu_main_clk();
452         case MXC_PER_CLK:
453                 return __get_periph_clk();
454         case MXC_AHB_CLK:
455                 return __get_ahb_clk();
456         case MXC_IPG_CLK:
457                 return __get_ipg_clk();
458         case MXC_IPG_PERCLK:
459                 return __get_ipg_per_clk();
460         case MXC_UART_CLK:
461                 return __get_uart_clk();
462         case MXC_CSPI_CLK:
463                 return __get_cspi_clk();
464         case MXC_AXI_A_CLK:
465                 return __get_axi_a_clk();
466         case MXC_AXI_B_CLK:
467                 return __get_axi_b_clk();
468         case MXC_EMI_SLOW_CLK:
469                 return __get_emi_slow_clk();
470         case MXC_DDR_CLK:
471                 return __get_ddr_clk();
472         case MXC_ESDHC_CLK:
473                 return __get_esdhc1_clk();
474         case MXC_ESDHC2_CLK:
475                 return __get_esdhc2_clk();
476         case MXC_ESDHC3_CLK:
477                 return __get_esdhc3_clk();
478         case MXC_ESDHC4_CLK:
479                 return __get_esdhc4_clk();
480         case MXC_SATA_CLK:
481                 return __get_ahb_clk();
482         default:
483                 break;
484         }
485         return -1;
486 }
487
488 void mxc_dump_clocks(void)
489 {
490         u32 freq;
491         freq = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ);
492         printf("mx53 pll1: %dMHz\n", freq / 1000000);
493         freq = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ);
494         printf("mx53 pll2: %dMHz\n", freq / 1000000);
495         freq = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ);
496         printf("mx53 pll3: %dMHz\n", freq / 1000000);
497         printf("ipg clock     : %dHz\n", mxc_get_clock(MXC_IPG_CLK));
498         printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK));
499         printf("uart clock    : %dHz\n", mxc_get_clock(MXC_UART_CLK));
500         printf("cspi clock    : %dHz\n", mxc_get_clock(MXC_CSPI_CLK));
501         printf("ahb clock     : %dHz\n", mxc_get_clock(MXC_AHB_CLK));
502         printf("axi_a clock   : %dHz\n", mxc_get_clock(MXC_AXI_A_CLK));
503         printf("axi_b clock   : %dHz\n", mxc_get_clock(MXC_AXI_B_CLK));
504         printf("emi_slow clock: %dHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK));
505         printf("ddr clock     : %dHz\n", mxc_get_clock(MXC_DDR_CLK));
506         printf("esdhc1 clock  : %dHz\n", mxc_get_clock(MXC_ESDHC_CLK));
507         printf("esdhc2 clock  : %dHz\n", mxc_get_clock(MXC_ESDHC2_CLK));
508         printf("esdhc3 clock  : %dHz\n", mxc_get_clock(MXC_ESDHC3_CLK));
509         printf("esdhc4 clock  : %dHz\n", mxc_get_clock(MXC_ESDHC4_CLK));
510 }
511
512 #ifdef CONFIG_CMD_CLOCK
513 /* precondition: m>0 and n>0.  Let g=gcd(m,n). */
514 static int gcd(int m, int n)
515 {
516         int t;
517         while (m > 0) {
518                 if (n > m) {
519                         t = m;
520                         m = n;
521                         n = t;
522                 } /* swap */
523                 m -= n;
524         }
525         return n;
526 }
527
528 /*!
529  * This is to calculate various parameters based on reference clock and
530  * targeted clock based on the equation:
531  *      t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
532  * This calculation is based on a fixed MFD value for simplicity.
533  *
534  * @param ref       reference clock freq in Hz
535  * @param target    targeted clock in Hz
536  * @param pll           pll_param structure.
537  *
538  * @return          0 if successful; non-zero otherwise.
539  */
540 static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
541 {
542         u64 pd, mfi = 1, mfn, mfd, t1;
543         u32 n_target = target;
544         u32 n_ref = ref, i;
545
546         /*
547          * Make sure targeted freq is in the valid range.
548          * Otherwise the following calculation might be wrong!!!
549          */
550         if (n_target < PLL_FREQ_MIN(ref) ||
551                 n_target > PLL_FREQ_MAX(ref)) {
552                 printf("Targeted peripheral clock should be"
553                         "within [%d - %d]\n",
554                         PLL_FREQ_MIN(ref) / SZ_DEC_1M,
555                         PLL_FREQ_MAX(ref) / SZ_DEC_1M);
556                 return -1;
557         }
558
559         for (i = 0; i < ARRAY_SIZE(fixed_mfd); i++) {
560                 if (fixed_mfd[i].ref_clk_hz == ref) {
561                         mfd = fixed_mfd[i].mfd;
562                         break;
563                 }
564         }
565
566         if (i == ARRAY_SIZE(fixed_mfd))
567                 return -1;
568
569         /* Use n_target and n_ref to avoid overflow */
570         for (pd = 1; pd <= PLL_PD_MAX; pd++) {
571                 t1 = n_target * pd;
572                 do_div(t1, (4 * n_ref));
573                 mfi = t1;
574                 if (mfi > PLL_MFI_MAX)
575                         return -1;
576                 else if (mfi < 5)
577                         continue;
578                 break;
579         }
580         /* Now got pd and mfi already */
581         /*
582         mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
583         */
584         t1 = n_target * pd;
585         do_div(t1, 4);
586         t1 -= n_ref * mfi;
587         t1 *= mfd;
588         do_div(t1, n_ref);
589         mfn = t1;
590 #ifdef CMD_CLOCK_DEBUG
591         printf("%d: ref=%d, target=%d, pd=%d,"
592                         "mfi=%d,mfn=%d, mfd=%d\n",
593                         __LINE__, ref, (u32)n_target,
594                         (u32)pd, (u32)mfi, (u32)mfn,
595                         (u32)mfd);
596 #endif
597         i = 1;
598         if (mfn != 0)
599                 i = gcd(mfd, mfn);
600         pll->pd = (u32)pd;
601         pll->mfi = (u32)mfi;
602         do_div(mfn, i);
603         pll->mfn = (u32)mfn;
604         do_div(mfd, i);
605         pll->mfd = (u32)mfd;
606
607         return 0;
608 }
609
610 int clk_info(u32 clk_type)
611 {
612         switch (clk_type) {
613         case CPU_CLK:
614                 printf("CPU Clock: %dHz\n",
615                         mxc_get_clock(MXC_ARM_CLK));
616                 break;
617         case PERIPH_CLK:
618                 printf("Peripheral Clock: %dHz\n",
619                         mxc_get_clock(MXC_PER_CLK));
620                 break;
621         case AHB_CLK:
622                 printf("AHB Clock: %dHz\n",
623                         mxc_get_clock(MXC_AHB_CLK));
624                 break;
625         case IPG_CLK:
626                 printf("IPG Clock: %dHz\n",
627                         mxc_get_clock(MXC_IPG_CLK));
628                 break;
629         case IPG_PERCLK:
630                 printf("IPG_PER Clock: %dHz\n",
631                         mxc_get_clock(MXC_IPG_PERCLK));
632                 break;
633         case UART_CLK:
634                 printf("UART Clock: %dHz\n",
635                         mxc_get_clock(MXC_UART_CLK));
636                 break;
637         case CSPI_CLK:
638                 printf("CSPI Clock: %dHz\n",
639                         mxc_get_clock(MXC_CSPI_CLK));
640                 break;
641         case DDR_CLK:
642                 printf("DDR Clock: %dHz\n",
643                         mxc_get_clock(MXC_DDR_CLK));
644                 break;
645         case ALL_CLK:
646                 printf("cpu clock: %dMHz\n",
647                         mxc_get_clock(MXC_ARM_CLK) / SZ_DEC_1M);
648                 mxc_dump_clocks();
649                 break;
650         default:
651                 printf("Unsupported clock type! :(\n");
652         }
653
654         return 0;
655 }
656
657 #define calc_div(target_clk, src_clk, limit) ({ \
658                 u32 tmp = 0;    \
659                 if ((src_clk % target_clk) <= 100)      \
660                         tmp = src_clk / target_clk;     \
661                 else    \
662                         tmp = (src_clk / target_clk) + 1;       \
663                 if (tmp > limit)        \
664                         tmp = limit;    \
665                 (tmp - 1);      \
666         })
667
668 u32 calc_per_cbcdr_val(u32 per_clk, u32 cbcmr)
669 {
670         u32 cbcdr = __REG(MXC_CCM_CBCDR);
671         u32 tmp_clk = 0, div = 0, clk_sel = 0;
672
673         cbcdr &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
674
675         /* emi_slow_podf divider */
676         tmp_clk = __get_emi_slow_clk();
677         clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL;
678         if (clk_sel) {
679                 div = calc_div(tmp_clk, per_clk, 8);
680                 cbcdr &= ~MXC_CCM_CBCDR_EMI_PODF_MASK;
681                 cbcdr |= (div << MXC_CCM_CBCDR_EMI_PODF_OFFSET);
682         }
683
684         /* axi_b_podf divider */
685         tmp_clk = __get_axi_b_clk();
686         div = calc_div(tmp_clk, per_clk, 8);
687         cbcdr &= ~MXC_CCM_CBCDR_AXI_B_PODF_MASK;
688         cbcdr |= (div << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET);
689
690         /* axi_b_podf divider */
691         tmp_clk = __get_axi_a_clk();
692         div = calc_div(tmp_clk, per_clk, 8);
693         cbcdr &= ~MXC_CCM_CBCDR_AXI_A_PODF_MASK;
694         cbcdr |= (div << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET);
695
696         /* ahb podf divider */
697         tmp_clk = AHB_CLK_ROOT;
698         div = calc_div(tmp_clk, per_clk, 8);
699         cbcdr &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
700         cbcdr |= (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
701
702         return cbcdr;
703 }
704
705 #define CHANGE_PLL_SETTINGS(base, pd, mfi, mfn, mfd) \
706         {       \
707                 writel(0x1232, base + PLL_DP_CTL); \
708                 writel(0x2, base + PLL_DP_CONFIG);    \
709                 writel(((pd - 1) << 0) | (mfi << 4),    \
710                         base + PLL_DP_OP);      \
711                 writel(mfn, base + PLL_DP_MFN); \
712                 writel(mfd - 1, base + PLL_DP_MFD);     \
713                 writel(((pd - 1) << 0) | (mfi << 4),    \
714                         base + PLL_DP_HFS_OP);  \
715                 writel(mfn, base + PLL_DP_HFS_MFN);     \
716                 writel(mfd - 1, base + PLL_DP_HFS_MFD); \
717                 writel(0x1232, base + PLL_DP_CTL); \
718                 while (!readl(base + PLL_DP_CTL) & 0x1)  \
719                         ; \
720         }
721
722 int config_pll_clk(enum pll_clocks pll, struct pll_param *pll_param)
723 {
724         u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
725         u32 pll_base = pll;
726
727         switch (pll) {
728         case PLL1_CLK:
729                 /* Switch ARM to PLL2 clock */
730                 writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
731                 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
732                                         pll_param->mfi, pll_param->mfn,
733                                         pll_param->mfd);
734                 /* Switch back */
735                 writel(ccsr & ~0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
736                 break;
737         case PLL2_CLK:
738                 /* Switch to pll2 bypass clock */
739                 writel(ccsr | 0x2, CCM_BASE_ADDR + CLKCTL_CCSR);
740                 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
741                                         pll_param->mfi, pll_param->mfn,
742                                         pll_param->mfd);
743                 /* Switch back */
744                 writel(ccsr & ~0x2, CCM_BASE_ADDR + CLKCTL_CCSR);
745                 break;
746         case PLL3_CLK:
747                 /* Switch to pll3 bypass clock */
748                 writel(ccsr | 0x1, CCM_BASE_ADDR + CLKCTL_CCSR);
749                 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
750                                         pll_param->mfi, pll_param->mfn,
751                                         pll_param->mfd);
752                 /* Switch back */
753                 writel(ccsr & ~0x1, CCM_BASE_ADDR + CLKCTL_CCSR);
754                 break;
755         case PLL4_CLK:
756                 /* Switch to pll4 bypass clock */
757                 writel(ccsr | 0x20, CCM_BASE_ADDR + CLKCTL_CCSR);
758                 CHANGE_PLL_SETTINGS(pll_base, pll_param->pd,
759                                         pll_param->mfi, pll_param->mfn,
760                                         pll_param->mfd);
761                 /* Switch back */
762                 writel(ccsr & ~0x20, CCM_BASE_ADDR + CLKCTL_CCSR);
763                 break;
764         default:
765                 return -1;
766         }
767
768         return 0;
769 }
770
771 int config_core_clk(u32 ref, u32 freq)
772 {
773         int ret = 0;
774         u32 pll = 0;
775         struct pll_param pll_param;
776
777         memset(&pll_param, 0, sizeof(struct pll_param));
778
779         /* The case that periph uses PLL1 is not considered here */
780         pll = freq;
781         ret = calc_pll_params(ref, pll, &pll_param);
782         if (ret != 0) {
783                 printf("Can't find pll parameters: %d\n",
784                         ret);
785                 return ret;
786         }
787
788         return config_pll_clk(PLL1_CLK, &pll_param);
789 }
790
791 int config_periph_clk(u32 ref, u32 freq)
792 {
793         int ret = 0;
794         u32 pll = freq;
795         struct pll_param pll_param;
796
797         memset(&pll_param, 0, sizeof(struct pll_param));
798
799         if (__REG(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
800                 /* Actually this case is not considered here */
801                 ret = calc_pll_params(ref, pll, &pll_param);
802                 if (ret != 0) {
803                         printf("Can't find pll parameters: %d\n",
804                                 ret);
805                         return ret;
806                 }
807                 switch ((__REG(MXC_CCM_CBCMR) & \
808                         MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >>
809                         MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
810                 case 0:
811                         return config_pll_clk(PLL1_CLK, &pll_param);
812                         break;
813                 case 1:
814                         return config_pll_clk(PLL3_CLK, &pll_param);
815                         break;
816                 default:
817                         return -1;
818                 }
819         } else {
820                 u32 old_cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
821                 u32 new_cbcdr = calc_per_cbcdr_val(pll, old_cbcmr);
822
823                 /* Switch peripheral to PLL3 */
824                 writel(0x00015154, CCM_BASE_ADDR + CLKCTL_CBCMR);
825                 writel(0x02888945, CCM_BASE_ADDR + CLKCTL_CBCDR);
826
827                 /* Make sure change is effective */
828                 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
829                         ;
830
831                 /* Setup PLL2 */
832                 ret = calc_pll_params(ref, pll, &pll_param);
833                 if (ret != 0) {
834                         printf("Can't find pll parameters: %d\n",
835                                 ret);
836                         return ret;
837                 }
838                 config_pll_clk(PLL2_CLK, &pll_param);
839
840                 /* Switch peripheral back */
841                 writel(new_cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
842                 writel(old_cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR);
843
844                 /* Make sure change is effective */
845                 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
846                         ;
847                 puts("\n");
848         }
849
850         return 0;
851 }
852
853 int config_ddr_clk(u32 emi_clk)
854 {
855         u32 clk_src;
856         s32 shift = 0, clk_sel, div = 1;
857         u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
858         u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
859
860         if (emi_clk > MAX_DDR_CLK) {
861                 printf("DDR clock should be less than"
862                         "%d MHz, assuming max value \n",
863                         (MAX_DDR_CLK / SZ_DEC_1M));
864                 emi_clk = MAX_DDR_CLK;
865         }
866
867         clk_src = __get_periph_clk();
868         /* Find DDR clock input */
869         clk_sel = (cbcmr >> 10) & 0x3;
870         switch (clk_sel) {
871         case 0:
872                 shift = 16;
873                 break;
874         case 1:
875                 shift = 19;
876                 break;
877         case 2:
878                 shift = 22;
879                 break;
880         case 3:
881                 shift = 10;
882                 break;
883         default:
884                 return -1;
885         }
886
887         if ((clk_src % emi_clk) == 0)
888                 div = clk_src / emi_clk;
889         else
890                 div = (clk_src / emi_clk) + 1;
891         if (div > 8)
892                 div = 8;
893
894         cbcdr = cbcdr & ~(0x7 << shift);
895         cbcdr |= ((div - 1) << shift);
896         writel(cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
897         while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
898                 ;
899         writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
900
901         return 0;
902 }
903
904 /*!
905  * This function assumes the expected core clock has to be changed by
906  * modifying the PLL. This is NOT true always but for most of the times,
907  * it is. So it assumes the PLL output freq is the same as the expected
908  * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
909  * In the latter case, it will try to increase the presc value until
910  * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
911  * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
912  * on the targeted PLL and reference input clock to the PLL. Lastly,
913  * it sets the register based on these values along with the dividers.
914  * Note 1) There is no value checking for the passed-in divider values
915  *         so the caller has to make sure those values are sensible.
916  *      2) Also adjust the NFC divider such that the NFC clock doesn't
917  *         exceed NFC_CLK_MAX.
918  *      3) IPU HSP clock is independent of AHB clock. Even it can go up to
919  *         177MHz for higher voltage, this function fixes the max to 133MHz.
920  *      4) This function should not have allowed diag_printf() calls since
921  *         the serial driver has been stoped. But leave then here to allow
922  *         easy debugging by NOT calling the cyg_hal_plf_serial_stop().
923  *
924  * @param ref       pll input reference clock (24MHz)
925  * @param freq          core clock in Hz
926  * @param clk_type  clock type, e.g CPU_CLK, DDR_CLK, etc.
927  * @return          0 if successful; non-zero otherwise
928  */
929 int clk_config(u32 ref, u32 freq, u32 clk_type)
930 {
931         freq *= SZ_DEC_1M;
932
933         switch (clk_type) {
934         case CPU_CLK:
935                 if (config_core_clk(ref, freq))
936                         return -1;
937                 break;
938         case PERIPH_CLK:
939                 if (config_periph_clk(ref, freq))
940                         return -1;
941                 break;
942         case DDR_CLK:
943                 if (config_ddr_clk(freq))
944                         return -1;
945                 break;
946         default:
947                 printf("Unsupported or invalid clock type! :(\n");
948         }
949
950         return 0;
951 }
952 #endif
953
954 #if defined(CONFIG_DISPLAY_CPUINFO)
955 int print_cpuinfo(void)
956 {
957         printf("CPU:   Freescale i.MX53 family %d.%dV at %d MHz\n",
958                (get_board_rev() & 0xFF) >> 4,
959                (get_board_rev() & 0xF),
960                 __get_mcu_main_clk() / 1000000);
961         return 0;
962 }
963 #endif
964
965 #if defined(CONFIG_MXC_FEC)
966 extern int mxc_fec_initialize(bd_t *bis);
967 extern void mxc_fec_set_mac_from_env(char *mac_addr);
968 #endif
969
970 int cpu_eth_init(bd_t *bis)
971 {
972         int rc = -ENODEV;
973 #if defined(CONFIG_MXC_FEC)
974         rc = mxc_fec_initialize(bis);
975 #endif
976         return rc;
977 }
978
979 #if defined(CONFIG_ARCH_CPU_INIT)
980 int arch_cpu_init(void)
981 {
982         icache_enable();
983         dcache_enable();
984
985 #ifdef CONFIG_L2_OFF
986         l2_cache_disable();
987 #else
988         l2_cache_enable();
989 #endif
990         return 0;
991 }
992 #endif
993