]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/mx6/clock.c
merged tx6dl-devel into denx master branch
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / mx6 / clock.c
1 /*
2  * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/errno.h>
10 #include <asm/arch/imx-regs.h>
11 #include <asm/arch/crm_regs.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/sys_proto.h>
14
15 enum pll_clocks {
16         PLL_ARM,        /* PLL1: ARM PLL */
17         PLL_BUS,        /* PLL2: System Bus PLL*/
18         PLL_USBOTG,     /* PLL3: OTG USB PLL */
19         PLL_AUDIO,      /* PLL4: Audio PLL */
20         PLL_VIDEO,      /* PLL5: Video PLL */
21         PLL_ENET,       /* PLL6: ENET PLL */
22         PLL_USB2,       /* PLL7: USB2 PLL */
23         PLL_MLB,        /* PLL8: MLB PLL */
24 };
25
26 struct mxc_ccm_reg *const imx_ccm = (void *)CCM_BASE_ADDR;
27 struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
28
29 int clk_enable(struct clk *clk)
30 {
31         int ret = 0;
32
33         if (!clk)
34                 return 0;
35         if (clk->usecount == 0) {
36 debug("%s: Enabling %s clock\n", __func__, clk->name);
37                 ret = clk->enable(clk);
38                 if (ret)
39                         return ret;
40                 clk->usecount++;
41         }
42         assert(clk->usecount > 0);
43         return ret;
44 }
45
46 void clk_disable(struct clk *clk)
47 {
48         if (!clk)
49                 return;
50
51         assert(clk->usecount > 0);
52         if (!(--clk->usecount)) {
53                 if (clk->disable) {
54 debug("%s: Disabling %s clock\n", __func__, clk->name);
55                         clk->disable(clk);
56                 }
57         }
58 }
59
60 int clk_get_usecount(struct clk *clk)
61 {
62         if (clk == NULL)
63                 return 0;
64
65         return clk->usecount;
66 }
67
68 u32 clk_get_rate(struct clk *clk)
69 {
70         if (!clk)
71                 return 0;
72
73         return clk->rate;
74 }
75
76 struct clk *clk_get_parent(struct clk *clk)
77 {
78         if (!clk)
79                 return 0;
80
81         return clk->parent;
82 }
83
84 int clk_set_rate(struct clk *clk, unsigned long rate)
85 {
86         if (clk && clk->set_rate)
87                 clk->set_rate(clk, rate);
88         return clk->rate;
89 }
90
91 long clk_round_rate(struct clk *clk, unsigned long rate)
92 {
93         if (clk == NULL || !clk->round_rate)
94                 return 0;
95
96         return clk->round_rate(clk, rate);
97 }
98
99 int clk_set_parent(struct clk *clk, struct clk *parent)
100 {
101         debug("Setting parent of clk %p to %p (%p)\n", clk, parent,
102                 clk ? clk->parent : NULL);
103
104         if (!clk || clk == parent)
105                 return 0;
106
107         if (clk->set_parent) {
108                 int ret;
109
110                 ret = clk->set_parent(clk, parent);
111                 if (ret)
112                         return ret;
113         }
114         clk->parent = parent;
115         return 0;
116 }
117
118 #ifdef CONFIG_MXC_OCOTP
119 void enable_ocotp_clk(unsigned char enable)
120 {
121         u32 reg;
122
123         reg = __raw_readl(&imx_ccm->CCGR2);
124         if (enable)
125                 reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
126         else
127                 reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
128         __raw_writel(reg, &imx_ccm->CCGR2);
129 }
130 #endif
131
132 void enable_usboh3_clk(unsigned char enable)
133 {
134         u32 reg;
135
136         reg = __raw_readl(&imx_ccm->CCGR6);
137         if (enable)
138                 reg |= MXC_CCM_CCGR6_USBOH3_MASK;
139         else
140                 reg &= ~(MXC_CCM_CCGR6_USBOH3_MASK);
141         __raw_writel(reg, &imx_ccm->CCGR6);
142
143 }
144
145 #ifdef CONFIG_I2C_MXC
146 /* i2c_num can be from 0 - 2 */
147 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
148 {
149         u32 reg;
150         u32 mask;
151
152         if (i2c_num > 2)
153                 return -EINVAL;
154
155         mask = MXC_CCM_CCGR_CG_MASK
156                 << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET + (i2c_num << 1));
157         reg = __raw_readl(&imx_ccm->CCGR2);
158         if (enable)
159                 reg |= mask;
160         else
161                 reg &= ~mask;
162         __raw_writel(reg, &imx_ccm->CCGR2);
163         return 0;
164 }
165 #endif
166
167 static u32 decode_pll(enum pll_clocks pll, u32 infreq)
168 {
169         u32 div;
170
171         switch (pll) {
172         case PLL_ARM:
173                 div = __raw_readl(&anatop->pll_arm);
174                 if (div & BM_ANADIG_PLL_ARM_BYPASS)
175                         /* Assume the bypass clock is always derived from OSC */
176                         return infreq;
177                 div &= BM_ANADIG_PLL_ARM_DIV_SELECT;
178
179                 return infreq * div / 2;
180         case PLL_BUS:
181                 div = __raw_readl(&anatop->pll_528);
182                 if (div & BM_ANADIG_PLL_SYS_BYPASS)
183                         return infreq;
184                 div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
185
186                 return infreq * (20 + div * 2);
187         case PLL_USBOTG:
188                 div = __raw_readl(&anatop->usb1_pll_480_ctrl);
189                 if (div & BM_ANADIG_USB1_PLL_480_CTRL_BYPASS)
190                         return infreq;
191                 div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
192
193                 return infreq * (20 + div * 2);
194         case PLL_AUDIO:
195                 div = __raw_readl(&anatop->pll_audio);
196                 if (div & BM_ANADIG_PLL_AUDIO_BYPASS)
197                         return infreq;
198                 div &= BM_ANADIG_PLL_AUDIO_DIV_SELECT;
199
200                 return infreq * div;
201         case PLL_VIDEO:
202                 div = __raw_readl(&anatop->pll_video);
203                 if (div & BM_ANADIG_PLL_VIDEO_BYPASS)
204                         return infreq;
205                 div &= BM_ANADIG_PLL_VIDEO_DIV_SELECT;
206
207                 return infreq * div;
208         case PLL_ENET:
209                 div = __raw_readl(&anatop->pll_enet);
210                 if (div & BM_ANADIG_PLL_ENET_BYPASS)
211                         return infreq;
212                 div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
213
214                 return (div == 3 ? 125000000 : 25000000 * div * 2);
215         case PLL_USB2:
216                 div = __raw_readl(&anatop->usb2_pll_480_ctrl);
217                 if (div & BM_ANADIG_USB2_PLL_480_CTRL_BYPASS)
218                         return infreq;
219                 div &= BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT;
220
221                 return infreq * (20 + div * 2);
222         case PLL_MLB:
223                 div = __raw_readl(&anatop->pll_mlb);
224                 if (div & BM_ANADIG_PLL_MLB_BYPASS)
225                         return infreq;
226                 /* unknown external clock provided on MLB_CLK pin */
227                 return 0;
228         }
229         return 0;
230 }
231
232 static u32 get_mcu_main_clk(void)
233 {
234         u32 reg, freq;
235
236         reg = __raw_readl(&imx_ccm->cacrr);
237         reg &= MXC_CCM_CACRR_ARM_PODF_MASK;
238         reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET;
239         freq = decode_pll(PLL_ARM, MXC_HCLK);
240
241         return freq / (reg + 1);
242 }
243
244 u32 get_periph_clk(void)
245 {
246         u32 reg, freq = 0;
247
248         reg = __raw_readl(&imx_ccm->cbcdr);
249         if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
250                 reg = __raw_readl(&imx_ccm->cbcmr);
251                 reg &= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
252                 reg >>= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET;
253
254                 switch (reg) {
255                 case 0:
256                         freq = decode_pll(PLL_USBOTG, MXC_HCLK);
257                         break;
258                 case 1:
259                 case 2:
260                         freq = MXC_HCLK;
261                         break;
262                 }
263         } else {
264                 reg = __raw_readl(&imx_ccm->cbcmr);
265                 reg &= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
266                 reg >>= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
267
268                 switch (reg) {
269                 case 0:
270                         freq = decode_pll(PLL_BUS, MXC_HCLK);
271                         break;
272                 case 1:
273                         freq = PLL2_PFD2_FREQ;
274                         break;
275                 case 2:
276                         freq = PLL2_PFD0_FREQ;
277                         break;
278                 case 3:
279                         freq = PLL2_PFD2_DIV_FREQ;
280                         break;
281                 }
282         }
283
284         return freq;
285 }
286
287 static u32 get_ipg_clk(void)
288 {
289         u32 reg, ipg_podf;
290
291         reg = __raw_readl(&imx_ccm->cbcdr);
292         reg &= MXC_CCM_CBCDR_IPG_PODF_MASK;
293         ipg_podf = reg >> MXC_CCM_CBCDR_IPG_PODF_OFFSET;
294
295         return get_ahb_clk() / (ipg_podf + 1);
296 }
297
298 static u32 get_ipg_per_clk(void)
299 {
300         u32 reg, perclk_podf;
301
302         reg = __raw_readl(&imx_ccm->cscmr1);
303         perclk_podf = reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
304
305         return get_ipg_clk() / (perclk_podf + 1);
306 }
307
308 static u32 get_uart_clk(void)
309 {
310         u32 reg, uart_podf;
311         u32 freq = PLL3_80M;
312         reg = __raw_readl(&imx_ccm->cscdr1);
313 #ifdef CONFIG_MX6SL
314         if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL)
315                 freq = MXC_HCLK;
316 #endif
317         reg &= MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
318         uart_podf = reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
319
320         return freq / (uart_podf + 1);
321 }
322
323 static u32 get_cspi_clk(void)
324 {
325         u32 reg, cspi_podf;
326
327         reg = __raw_readl(&imx_ccm->cscdr2);
328         reg &= MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK;
329         cspi_podf = reg >> MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET;
330
331         return  PLL3_60M / (cspi_podf + 1);
332 }
333
334 static u32 get_axi_clk(void)
335 {
336         u32 root_freq, axi_podf;
337         u32 cbcdr =  __raw_readl(&imx_ccm->cbcdr);
338
339         axi_podf = cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK;
340         axi_podf >>= MXC_CCM_CBCDR_AXI_PODF_OFFSET;
341
342         if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
343                 if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
344                         root_freq = PLL2_PFD2_FREQ;
345                 else
346                         root_freq = PLL3_PFD1_FREQ;
347         } else
348                 root_freq = get_periph_clk();
349
350         return  root_freq / (axi_podf + 1);
351 }
352
353 static u32 get_emi_slow_clk(void)
354 {
355         u32 emi_clk_sel, emi_slow_pof, cscmr1, root_freq = 0;
356
357         cscmr1 =  __raw_readl(&imx_ccm->cscmr1);
358         emi_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
359         emi_clk_sel >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET;
360         emi_slow_pof = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
361         emi_slow_pof >>= MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
362
363         switch (emi_clk_sel) {
364         case 0:
365                 root_freq = get_axi_clk();
366                 break;
367         case 1:
368                 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
369                 break;
370         case 2:
371                 root_freq = PLL2_PFD2_FREQ;
372                 break;
373         case 3:
374                 root_freq = PLL2_PFD0_FREQ;
375                 break;
376         }
377
378         return root_freq / (emi_slow_pof + 1);
379 }
380
381 static u32 get_nfc_clk(void)
382 {
383         u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
384         u32 podf = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
385         u32 pred = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
386         int nfc_clk_sel = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK) >>
387                 MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
388         u32 root_freq;
389
390         switch (nfc_clk_sel) {
391         case 0:
392                 root_freq = PLL2_PFD0_FREQ;
393                 break;
394         case 1:
395                 root_freq = decode_pll(PLL_BUS, MXC_HCLK);
396                 break;
397         case 2:
398                 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
399                 break;
400         case 3:
401                 root_freq = PLL2_PFD2_FREQ;
402                 break;
403         }
404
405         return root_freq / (pred + 1) / (podf + 1);
406 }
407
408 #define CS2CDR_ENFC_MASK        (MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |    \
409                                 MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |     \
410                                 MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK)
411
412 static int set_nfc_clk(u32 ref, u32 freq_khz)
413 {
414         u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
415         u32 podf;
416         u32 pred;
417         int nfc_clk_sel;
418         u32 root_freq;
419         u32 min_err = ~0;
420         u32 nfc_val = ~0;
421         u32 freq = freq_khz * 1000;
422
423         for (nfc_clk_sel = 0; nfc_clk_sel < 4; nfc_clk_sel++) {
424                 u32 act_freq;
425                 u32 err;
426
427                 if (ref < 4 && ref != nfc_clk_sel)
428                         continue;
429
430                 switch (nfc_clk_sel) {
431                 case 0:
432                         root_freq = PLL2_PFD0_FREQ;
433                         break;
434                 case 1:
435                         root_freq = decode_pll(PLL_BUS, MXC_HCLK);
436                         break;
437                 case 2:
438                         root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
439                         break;
440                 case 3:
441                         root_freq = PLL2_PFD2_FREQ;
442                         break;
443                 }
444                 if (root_freq < freq)
445                         continue;
446
447                 podf = min(DIV_ROUND_UP(root_freq, freq), 1 << 6);
448                 pred = min(DIV_ROUND_UP(root_freq / podf, freq), 8);
449                 act_freq = root_freq / pred / podf;
450                 err = (freq - act_freq) * 100 / freq;
451                 debug("root=%d[%u] freq=%u pred=%u podf=%u act=%u err=%d\n",
452                         nfc_clk_sel, root_freq, freq, pred, podf, act_freq, err);
453                 if (act_freq > freq)
454                         continue;
455                 if (err < min_err) {
456                         nfc_val = (podf - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
457                         nfc_val |= (pred - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
458                         nfc_val |= nfc_clk_sel << MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
459                         min_err = err;
460                         if (err == 0)
461                                 break;
462                 }
463         }
464
465         if (nfc_val == ~0 || min_err > 10)
466                 return -EINVAL;
467
468         if ((cs2cdr & CS2CDR_ENFC_MASK) != nfc_val) {
469                 debug("changing cs2cdr from %08x to %08x\n", cs2cdr,
470                         (cs2cdr & ~CS2CDR_ENFC_MASK) | nfc_val);
471                 __raw_writel((cs2cdr & ~CS2CDR_ENFC_MASK) | nfc_val,
472                         &imx_ccm->cs2cdr);
473         } else {
474                 debug("Leaving cs2cdr unchanged [%08x]\n", cs2cdr);
475         }
476         return 0;
477 }
478
479 #ifdef CONFIG_MX6SL
480 static u32 get_mmdc_ch0_clk(void)
481 {
482         u32 cbcmr = __raw_readl(&imx_ccm->cbcmr);
483         u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
484         u32 freq, podf;
485
486         podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) \
487                         >> MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
488
489         switch ((cbcmr & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) >>
490                 MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET) {
491         case 0:
492                 freq = decode_pll(PLL_BUS, MXC_HCLK);
493                 break;
494         case 1:
495                 freq = PLL2_PFD2_FREQ;
496                 break;
497         case 2:
498                 freq = PLL2_PFD0_FREQ;
499                 break;
500         case 3:
501                 freq = PLL2_PFD2_DIV_FREQ;
502         }
503
504         return freq / (podf + 1);
505
506 }
507 #else
508 static u32 get_mmdc_ch0_clk(void)
509 {
510         u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
511         u32 mmdc_ch0_podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >>
512                                 MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET;
513
514         return get_periph_clk() / (mmdc_ch0_podf + 1);
515 }
516 #endif
517
518 static u32 get_usdhc_clk(u32 port)
519 {
520         u32 root_freq = 0, usdhc_podf = 0, clk_sel = 0;
521         u32 cscmr1 = __raw_readl(&imx_ccm->cscmr1);
522         u32 cscdr1 = __raw_readl(&imx_ccm->cscdr1);
523
524         switch (port) {
525         case 0:
526                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
527                                         MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
528                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
529
530                 break;
531         case 1:
532                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
533                                         MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
534                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
535
536                 break;
537         case 2:
538                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
539                                         MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
540                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
541
542                 break;
543         case 3:
544                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
545                                         MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
546                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
547
548                 break;
549         default:
550                 break;
551         }
552
553         if (clk_sel)
554                 root_freq = PLL2_PFD0_FREQ;
555         else
556                 root_freq = PLL2_PFD2_FREQ;
557
558         return root_freq / (usdhc_podf + 1);
559 }
560
561 u32 imx_get_uartclk(void)
562 {
563         return get_uart_clk();
564 }
565
566 u32 imx_get_fecclk(void)
567 {
568         return decode_pll(PLL_ENET, MXC_HCLK);
569 }
570
571 int enable_sata_clock(void)
572 {
573         u32 reg;
574         s32 timeout = 100000;
575
576         /* Enable sata clock */
577         reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
578         reg |= MXC_CCM_CCGR5_SATA_MASK;
579         writel(reg, &imx_ccm->CCGR5);
580
581         /* Enable PLLs */
582         reg = readl(&anatop->pll_enet);
583         reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;
584         writel(reg, &anatop->pll_enet);
585         reg |= BM_ANADIG_PLL_ENET_ENABLE;
586         while (timeout--) {
587                 if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK)
588                         break;
589         }
590         if (timeout <= 0)
591                 return -EIO;
592         reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
593         writel(reg, &anatop->pll_enet);
594         reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
595         writel(reg, &anatop->pll_enet);
596
597         return 0 ;
598 }
599
600 void ipu_clk_enable(void)
601 {
602         u32 reg = readl(&imx_ccm->CCGR3);
603         reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK;
604         writel(reg, &imx_ccm->CCGR3);
605 }
606
607 void ipu_clk_disable(void)
608 {
609         u32 reg = readl(&imx_ccm->CCGR3);
610         reg &= ~MXC_CCM_CCGR3_IPU1_IPU_MASK;
611         writel(reg, &imx_ccm->CCGR3);
612 }
613
614 void ocotp_clk_enable(void)
615 {
616         u32 reg = readl(&imx_ccm->CCGR2);
617         reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
618         writel(reg, &imx_ccm->CCGR2);
619 }
620
621 void ocotp_clk_disable(void)
622 {
623         u32 reg = readl(&imx_ccm->CCGR2);
624         reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
625         writel(reg, &imx_ccm->CCGR2);
626 }
627
628 unsigned int mxc_get_clock(enum mxc_clock clk)
629 {
630         switch (clk) {
631         case MXC_ARM_CLK:
632                 return get_mcu_main_clk();
633         case MXC_PER_CLK:
634                 return get_periph_clk();
635         case MXC_AHB_CLK:
636                 return get_ahb_clk();
637         case MXC_IPG_CLK:
638                 return get_ipg_clk();
639         case MXC_IPG_PERCLK:
640         case MXC_I2C_CLK:
641                 return get_ipg_per_clk();
642         case MXC_UART_CLK:
643                 return get_uart_clk();
644         case MXC_CSPI_CLK:
645                 return get_cspi_clk();
646         case MXC_AXI_CLK:
647                 return get_axi_clk();
648         case MXC_EMI_SLOW_CLK:
649                 return get_emi_slow_clk();
650         case MXC_DDR_CLK:
651                 return get_mmdc_ch0_clk();
652         case MXC_ESDHC_CLK:
653                 return get_usdhc_clk(0);
654         case MXC_ESDHC2_CLK:
655                 return get_usdhc_clk(1);
656         case MXC_ESDHC3_CLK:
657                 return get_usdhc_clk(2);
658         case MXC_ESDHC4_CLK:
659                 return get_usdhc_clk(3);
660         case MXC_SATA_CLK:
661                 return get_ahb_clk();
662         case MXC_NFC_CLK:
663                 return get_nfc_clk();
664         }
665
666         return -1;
667 }
668
669 static inline int gcd(int m, int n)
670 {
671         int t;
672         while (m > 0) {
673                 if (n > m) {
674                         t = m;
675                         m = n;
676                         n = t;
677                 } /* swap */
678                 m -= n;
679         }
680         return n;
681 }
682
683 /* Config CPU clock */
684 static int set_arm_clk(u32 ref, u32 freq_khz)
685 {
686         int d;
687         int div = 0;
688         int mul = 0;
689         u32 min_err = ~0;
690         u32 reg;
691
692         if (freq_khz > ref / 1000 * 108 / 2 || freq_khz < ref / 1000 * 54 / 8 / 2) {
693                 printf("Frequency %u.%03uMHz is out of range: %u.%03u..%u.%03u\n",
694                         freq_khz / 1000, freq_khz % 1000,
695                         54 * ref / 1000000 / 8 / 2, 54 * ref / 1000 / 8 / 2 % 1000,
696                         108 * ref / 1000000 / 2, 108 * ref / 1000 / 2 % 1000);
697                 return -EINVAL;
698         }
699
700         for (d = DIV_ROUND_UP(648000, freq_khz); d <= 8; d++) {
701                 int m = freq_khz * 2 * d / (ref / 1000);
702                 u32 f;
703                 u32 err;
704
705                 if (m > 108) {
706                         debug("%s@%d: d=%d m=%d\n", __func__, __LINE__,
707                                 d, m);
708                         break;
709                 }
710
711                 f = ref * m / d / 2;
712                 if (f > freq_khz * 1000) {
713                         debug("%s@%d: d=%d m=%d f=%u freq=%u\n", __func__, __LINE__,
714                                 d, m, f, freq_khz);
715                         if (--m < 54)
716                                 return -EINVAL;
717                         f = ref * m / d / 2;
718                 }
719                 err = freq_khz * 1000 - f;
720                 debug("%s@%d: d=%d m=%d f=%u freq=%u err=%d\n", __func__, __LINE__,
721                         d, m, f, freq_khz, err);
722                 if (err < min_err) {
723                         mul = m;
724                         div = d;
725                         min_err = err;
726                         if (err == 0)
727                                 break;
728                 }
729         }
730         if (min_err == ~0)
731                 return -EINVAL;
732         debug("Setting M=%3u D=%2u for %u.%03uMHz (actual: %u.%03uMHz)\n",
733                 mul, div, freq_khz / 1000, freq_khz % 1000,
734                 ref * mul / 2 / div / 1000000, ref * mul / 2 / div / 1000 % 1000);
735
736         reg = readl(&anatop->pll_arm);
737         debug("anadig_pll_arm=%08x -> %08x\n",
738                 reg, (reg & ~0x7f) | mul);
739
740         reg |= 1 << 16;
741         writel(reg, &anatop->pll_arm); /* bypass PLL */
742
743         reg = (reg & ~0x7f) | mul;
744         writel(reg, &anatop->pll_arm);
745
746         writel(div - 1, &imx_ccm->cacrr);
747
748         reg &= ~(1 << 16);
749         writel(reg, &anatop->pll_arm); /* disable PLL bypass */
750
751         return 0;
752 }
753
754 /*
755  * This function assumes the expected core clock has to be changed by
756  * modifying the PLL. This is NOT true always but for most of the times,
757  * it is. So it assumes the PLL output freq is the same as the expected
758  * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
759  * In the latter case, it will try to increase the presc value until
760  * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
761  * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
762  * on the targeted PLL and reference input clock to the PLL. Lastly,
763  * it sets the register based on these values along with the dividers.
764  * Note 1) There is no value checking for the passed-in divider values
765  *         so the caller has to make sure those values are sensible.
766  *      2) Also adjust the NFC divider such that the NFC clock doesn't
767  *         exceed NFC_CLK_MAX.
768  *      3) IPU HSP clock is independent of AHB clock. Even it can go up to
769  *         177MHz for higher voltage, this function fixes the max to 133MHz.
770  *      4) This function should not have allowed diag_printf() calls since
771  *         the serial driver has been stoped. But leave then here to allow
772  *         easy debugging by NOT calling the cyg_hal_plf_serial_stop().
773  */
774 int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk)
775 {
776         int ret;
777
778         freq *= 1000;
779
780         switch (clk) {
781         case MXC_ARM_CLK:
782                 ret = set_arm_clk(ref, freq);
783                 break;
784
785         case MXC_NFC_CLK:
786                 ret = set_nfc_clk(ref, freq);
787                 break;
788
789         default:
790                 printf("Warning: Unsupported or invalid clock type: %d\n",
791                         clk);
792                 return -EINVAL;
793         }
794
795         return ret;
796 }
797
798 /*
799  * Dump some core clocks.
800  */
801 #define print_pll(pll)  {                               \
802         u32 __pll = decode_pll(pll, MXC_HCLK);          \
803         printf("%-12s %4d.%03d MHz\n", #pll,            \
804                 __pll / 1000000, __pll / 1000 % 1000);  \
805         }
806
807 #define MXC_IPG_PER_CLK MXC_IPG_PERCLK
808
809 #define print_clk(clk)  {                               \
810         u32 __clk = mxc_get_clock(MXC_##clk##_CLK);     \
811         printf("%-12s %4d.%03d MHz\n", #clk,            \
812                 __clk / 1000000, __clk / 1000 % 1000);  \
813         }
814
815 #define print_pfd(pll, pfd)     {                                       \
816         u32 __pfd = readl(&anatop->pfd_##pll);                          \
817         if (__pfd & (0x80 << 8 * pfd)) {                                \
818                 printf("PFD_%s[%d]      OFF\n", #pll, pfd);             \
819         } else {                                                        \
820                 __pfd = (__pfd >> 8 * pfd) & 0x3f;                      \
821                 printf("PFD_%s[%d]   %4d.%03d MHz\n", #pll, pfd,        \
822                         pll * 18 / __pfd,                               \
823                         pll * 18 * 1000 / __pfd % 1000);                \
824         }                                                               \
825 }
826
827 static void do_mx6_showclocks(void)
828 {
829         print_pll(PLL_ARM);
830         print_pll(PLL_BUS);
831         print_pll(PLL_USBOTG);
832         print_pll(PLL_AUDIO);
833         print_pll(PLL_VIDEO);
834         print_pll(PLL_ENET);
835         print_pll(PLL_USB2);
836         printf("\n");
837
838         print_pfd(480, 0);
839         print_pfd(480, 1);
840         print_pfd(480, 2);
841         print_pfd(480, 3);
842         print_pfd(528, 0);
843         print_pfd(528, 1);
844         print_pfd(528, 2);
845         print_pfd(528, 3);
846         printf("\n");
847
848         print_clk(IPG);
849         print_clk(UART);
850         print_clk(CSPI);
851         print_clk(AHB);
852         print_clk(AXI);
853         print_clk(DDR);
854         print_clk(ESDHC);
855         print_clk(ESDHC2);
856         print_clk(ESDHC3);
857         print_clk(ESDHC4);
858         print_clk(EMI_SLOW);
859         print_clk(NFC);
860         print_clk(IPG_PER);
861         print_clk(ARM);
862 }
863
864 static struct clk_lookup {
865         const char *name;
866         unsigned int index;
867 } mx6_clk_lookup[] = {
868         { "arm", MXC_ARM_CLK, },
869         { "nfc", MXC_NFC_CLK, },
870 };
871
872 int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
873 {
874         int i;
875         unsigned long freq;
876         unsigned long ref = ~0UL;
877
878         if (argc < 2) {
879                 do_mx6_showclocks();
880                 return CMD_RET_SUCCESS;
881         } else if (argc == 2 || argc > 4) {
882                 return CMD_RET_USAGE;
883         }
884
885         freq = simple_strtoul(argv[2], NULL, 0);
886         if (freq == 0) {
887                 printf("Invalid clock frequency %lu\n", freq);
888                 return CMD_RET_FAILURE;
889         }
890         if (argc > 3) {
891                 ref = simple_strtoul(argv[3], NULL, 0);
892         }
893         for (i = 0; i < ARRAY_SIZE(mx6_clk_lookup); i++) {
894                 if (strcasecmp(argv[1], mx6_clk_lookup[i].name) == 0) {
895                         switch (mx6_clk_lookup[i].index) {
896                         case MXC_ARM_CLK:
897                                 if (argc > 3)
898                                         return CMD_RET_USAGE;
899                                 ref = CONFIG_SYS_MX6_HCLK;
900                                 break;
901
902                         case MXC_NFC_CLK:
903                                 if (argc > 3 && ref > 3) {
904                                         printf("Invalid clock selector value: %lu\n", ref);
905                                         return CMD_RET_FAILURE;
906                                 }
907                                 break;
908                         }
909                         printf("Setting %s clock to %lu MHz\n",
910                                 mx6_clk_lookup[i].name, freq);
911                         if (mxc_set_clock(ref, freq, mx6_clk_lookup[i].index))
912                                 break;
913                         freq = mxc_get_clock(mx6_clk_lookup[i].index);
914                         printf("%s clock set to %lu.%03lu MHz\n",
915                                 mx6_clk_lookup[i].name,
916                                 freq / 1000000, freq / 1000 % 1000);
917                         return CMD_RET_SUCCESS;
918                 }
919         }
920         if (i == ARRAY_SIZE(mx6_clk_lookup)) {
921                 printf("clock %s not found; supported clocks are:\n", argv[1]);
922                 for (i = 0; i < ARRAY_SIZE(mx6_clk_lookup); i++) {
923                         printf("\t%s\n", mx6_clk_lookup[i].name);
924                 }
925         } else {
926                 printf("Failed to set clock %s to %s MHz\n",
927                         argv[1], argv[2]);
928         }
929         return CMD_RET_FAILURE;
930 }
931
932 /***************************************************/
933
934 U_BOOT_CMD(
935         clocks, 4, 0, do_clocks,
936         "display/set clocks",
937         "                    - display clock settings\n"
938         "clocks <clkname> <freq>    - set clock <clkname> to <freq> MHz"
939 );