2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 #include <linux/clk.h>
23 #include <linux/module.h>
25 #include <mach/clock.h>
26 #include <mach/common.h>
27 #include <asm/clkdev.h>
28 #include <asm/div64.h>
32 static int _clk_enable(struct clk
*clk
)
36 reg
= __raw_readl(clk
->enable_reg
);
37 reg
|= 1 << clk
->enable_shift
;
38 __raw_writel(reg
, clk
->enable_reg
);
42 static void _clk_disable(struct clk
*clk
)
46 reg
= __raw_readl(clk
->enable_reg
);
47 reg
&= ~(1 << clk
->enable_shift
);
48 __raw_writel(reg
, clk
->enable_reg
);
51 static int _clk_spll_enable(struct clk
*clk
)
55 reg
= __raw_readl(CCM_CSCR
);
57 __raw_writel(reg
, CCM_CSCR
);
59 while ((__raw_readl(CCM_SPCTL1
) & CCM_SPCTL1_LF
) == 0)
64 static void _clk_spll_disable(struct clk
*clk
)
68 reg
= __raw_readl(CCM_CSCR
);
69 reg
&= ~CCM_CSCR_SPEN
;
70 __raw_writel(reg
, CCM_CSCR
);
74 #define CSCR() (__raw_readl(CCM_CSCR))
75 #define PCDR0() (__raw_readl(CCM_PCDR0))
76 #define PCDR1() (__raw_readl(CCM_PCDR1))
78 static unsigned long _clk_perclkx_round_rate(struct clk
*clk
,
82 unsigned long parent_rate
;
84 parent_rate
= clk_get_rate(clk
->parent
);
86 div
= parent_rate
/ rate
;
87 if (parent_rate
% rate
)
93 return parent_rate
/ div
;
96 static int _clk_perclkx_set_rate(struct clk
*clk
, unsigned long rate
)
100 unsigned long parent_rate
;
102 parent_rate
= clk_get_rate(clk
->parent
);
104 if (clk
->id
< 0 || clk
->id
> 3)
107 div
= parent_rate
/ rate
;
108 if (div
> 64 || div
< 1 || ((parent_rate
/ div
) != rate
))
113 __raw_readl(CCM_PCDR1
) & ~(CCM_PCDR1_PERDIV1_MASK
<<
115 reg
|= div
<< (clk
->id
<< 3);
116 __raw_writel(reg
, CCM_PCDR1
);
121 static unsigned long _clk_usb_recalc(struct clk
*clk
)
123 unsigned long usb_pdf
;
124 unsigned long parent_rate
;
126 parent_rate
= clk_get_rate(clk
->parent
);
128 usb_pdf
= (CSCR() & CCM_CSCR_USB_MASK
) >> CCM_CSCR_USB_OFFSET
;
130 return parent_rate
/ (usb_pdf
+ 1U);
133 static unsigned long _clk_ssix_recalc(struct clk
*clk
, unsigned long pdf
)
135 unsigned long parent_rate
;
137 parent_rate
= clk_get_rate(clk
->parent
);
139 pdf
= (pdf
< 2) ? 124UL : pdf
; /* MX21 & MX27 TO1 */
141 return 2UL * parent_rate
/ pdf
;
144 static unsigned long _clk_ssi1_recalc(struct clk
*clk
)
146 return _clk_ssix_recalc(clk
,
147 (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK
)
148 >> CCM_PCDR0_SSI1BAUDDIV_OFFSET
);
151 static unsigned long _clk_ssi2_recalc(struct clk
*clk
)
153 return _clk_ssix_recalc(clk
,
154 (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK
) >>
155 CCM_PCDR0_SSI2BAUDDIV_OFFSET
);
158 static unsigned long _clk_nfc_recalc(struct clk
*clk
)
160 unsigned long nfc_pdf
;
161 unsigned long parent_rate
;
163 parent_rate
= clk_get_rate(clk
->parent
);
165 nfc_pdf
= (PCDR0() & CCM_PCDR0_NFCDIV_MASK
)
166 >> CCM_PCDR0_NFCDIV_OFFSET
;
168 return parent_rate
/ (nfc_pdf
+ 1);
171 static unsigned long _clk_parent_round_rate(struct clk
*clk
, unsigned long rate
)
173 return clk
->parent
->round_rate(clk
->parent
, rate
);
176 static int _clk_parent_set_rate(struct clk
*clk
, unsigned long rate
)
178 return clk
->parent
->set_rate(clk
->parent
, rate
);
181 static unsigned long external_high_reference
; /* in Hz */
183 static unsigned long get_high_reference_clock_rate(struct clk
*clk
)
185 return external_high_reference
;
189 * the high frequency external clock reference
190 * Default case is 26MHz.
192 static struct clk ckih_clk
= {
193 .get_rate
= get_high_reference_clock_rate
,
196 static unsigned long external_low_reference
; /* in Hz */
198 static unsigned long get_low_reference_clock_rate(struct clk
*clk
)
200 return external_low_reference
;
204 * the low frequency external clock reference
205 * Default case is 32.768kHz.
207 static struct clk ckil_clk
= {
208 .get_rate
= get_low_reference_clock_rate
,
212 static unsigned long _clk_fpm_recalc(struct clk
*clk
)
214 return clk_get_rate(clk
->parent
) * 512;
217 /* Output of frequency pre multiplier */
218 static struct clk fpm_clk
= {
220 .get_rate
= _clk_fpm_recalc
,
223 static unsigned long get_mpll_clk(struct clk
*clk
)
226 unsigned long ref_clk
;
227 unsigned long mfi
= 0, mfn
= 0, mfd
= 0, pdf
= 0;
228 unsigned long long temp
;
230 ref_clk
= clk_get_rate(clk
->parent
);
232 reg
= __raw_readl(CCM_MPCTL0
);
233 pdf
= (reg
& CCM_MPCTL0_PD_MASK
) >> CCM_MPCTL0_PD_OFFSET
;
234 mfd
= (reg
& CCM_MPCTL0_MFD_MASK
) >> CCM_MPCTL0_MFD_OFFSET
;
235 mfi
= (reg
& CCM_MPCTL0_MFI_MASK
) >> CCM_MPCTL0_MFI_OFFSET
;
236 mfn
= (reg
& CCM_MPCTL0_MFN_MASK
) >> CCM_MPCTL0_MFN_OFFSET
;
238 mfi
= (mfi
<= 5) ? 5 : mfi
;
239 temp
= 2LL * ref_clk
* mfn
;
240 do_div(temp
, mfd
+ 1);
241 temp
= 2LL * ref_clk
* mfi
+ temp
;
242 do_div(temp
, pdf
+ 1);
244 return (unsigned long)temp
;
247 static struct clk mpll_clk
= {
249 .get_rate
= get_mpll_clk
,
252 static unsigned long _clk_fclk_get_rate(struct clk
*clk
)
254 unsigned long parent_rate
;
257 div
= (CSCR() & CCM_CSCR_PRESC_MASK
) >> CCM_CSCR_PRESC_OFFSET
;
258 parent_rate
= clk_get_rate(clk
->parent
);
260 return parent_rate
/ (div
+1);
263 static struct clk fclk_clk
= {
265 .get_rate
= _clk_fclk_get_rate
268 static unsigned long get_spll_clk(struct clk
*clk
)
271 unsigned long ref_clk
;
272 unsigned long mfi
= 0, mfn
= 0, mfd
= 0, pdf
= 0;
273 unsigned long long temp
;
275 ref_clk
= clk_get_rate(clk
->parent
);
277 reg
= __raw_readl(CCM_SPCTL0
);
278 pdf
= (reg
& CCM_SPCTL0_PD_MASK
) >> CCM_SPCTL0_PD_OFFSET
;
279 mfd
= (reg
& CCM_SPCTL0_MFD_MASK
) >> CCM_SPCTL0_MFD_OFFSET
;
280 mfi
= (reg
& CCM_SPCTL0_MFI_MASK
) >> CCM_SPCTL0_MFI_OFFSET
;
281 mfn
= (reg
& CCM_SPCTL0_MFN_MASK
) >> CCM_SPCTL0_MFN_OFFSET
;
283 mfi
= (mfi
<= 5) ? 5 : mfi
;
284 temp
= 2LL * ref_clk
* mfn
;
285 do_div(temp
, mfd
+ 1);
286 temp
= 2LL * ref_clk
* mfi
+ temp
;
287 do_div(temp
, pdf
+ 1);
289 return (unsigned long)temp
;
292 static struct clk spll_clk
= {
294 .get_rate
= get_spll_clk
,
295 .enable
= _clk_spll_enable
,
296 .disable
= _clk_spll_disable
,
299 static unsigned long get_hclk_clk(struct clk
*clk
)
302 unsigned long bclk_pdf
;
304 bclk_pdf
= (CSCR() & CCM_CSCR_BCLK_MASK
)
305 >> CCM_CSCR_BCLK_OFFSET
;
307 rate
= clk_get_rate(clk
->parent
);
308 return rate
/ (bclk_pdf
+ 1);
311 static struct clk hclk_clk
= {
313 .get_rate
= get_hclk_clk
,
316 static unsigned long get_ipg_clk(struct clk
*clk
)
319 unsigned long ipg_pdf
;
321 ipg_pdf
= (CSCR() & CCM_CSCR_IPDIV
) >> CCM_CSCR_IPDIV_OFFSET
;
323 rate
= clk_get_rate(clk
->parent
);
324 return rate
/ (ipg_pdf
+ 1);
327 static struct clk ipg_clk
= {
329 .get_rate
= get_ipg_clk
,
332 static unsigned long _clk_perclkx_recalc(struct clk
*clk
)
334 unsigned long perclk_pdf
;
335 unsigned long parent_rate
;
337 parent_rate
= clk_get_rate(clk
->parent
);
339 if (clk
->id
< 0 || clk
->id
> 3)
342 perclk_pdf
= (PCDR1() >> (clk
->id
<< 3)) & CCM_PCDR1_PERDIV1_MASK
;
344 return parent_rate
/ (perclk_pdf
+ 1);
347 static struct clk per_clk
[] = {
351 .get_rate
= _clk_perclkx_recalc
,
355 .get_rate
= _clk_perclkx_recalc
,
359 .round_rate
= _clk_perclkx_round_rate
,
360 .set_rate
= _clk_perclkx_set_rate
,
361 .get_rate
= _clk_perclkx_recalc
,
362 /* Enable/Disable done via lcd_clkc[1] */
366 .round_rate
= _clk_perclkx_round_rate
,
367 .set_rate
= _clk_perclkx_set_rate
,
368 .get_rate
= _clk_perclkx_recalc
,
369 /* Enable/Disable done via csi_clk[1] */
373 static struct clk uart_ipg_clk
[];
375 static struct clk uart_clk
[] = {
378 .parent
= &per_clk
[0],
379 .secondary
= &uart_ipg_clk
[0],
382 .parent
= &per_clk
[0],
383 .secondary
= &uart_ipg_clk
[1],
386 .parent
= &per_clk
[0],
387 .secondary
= &uart_ipg_clk
[2],
390 .parent
= &per_clk
[0],
391 .secondary
= &uart_ipg_clk
[3],
395 static struct clk uart_ipg_clk
[] = {
399 .enable
= _clk_enable
,
400 .enable_reg
= CCM_PCCR_UART1_REG
,
401 .enable_shift
= CCM_PCCR_UART1_OFFSET
,
402 .disable
= _clk_disable
,
406 .enable
= _clk_enable
,
407 .enable_reg
= CCM_PCCR_UART2_REG
,
408 .enable_shift
= CCM_PCCR_UART2_OFFSET
,
409 .disable
= _clk_disable
,
413 .enable
= _clk_enable
,
414 .enable_reg
= CCM_PCCR_UART3_REG
,
415 .enable_shift
= CCM_PCCR_UART3_OFFSET
,
416 .disable
= _clk_disable
,
420 .enable
= _clk_enable
,
421 .enable_reg
= CCM_PCCR_UART4_REG
,
422 .enable_shift
= CCM_PCCR_UART4_OFFSET
,
423 .disable
= _clk_disable
,
427 static struct clk gpt_ipg_clk
[];
429 static struct clk gpt_clk
[] = {
432 .parent
= &per_clk
[0],
433 .secondary
= &gpt_ipg_clk
[0],
436 .parent
= &per_clk
[0],
437 .secondary
= &gpt_ipg_clk
[1],
440 .parent
= &per_clk
[0],
441 .secondary
= &gpt_ipg_clk
[2],
445 static struct clk gpt_ipg_clk
[] = {
449 .enable
= _clk_enable
,
450 .enable_reg
= CCM_PCCR_GPT1_REG
,
451 .enable_shift
= CCM_PCCR_GPT1_OFFSET
,
452 .disable
= _clk_disable
,
456 .enable
= _clk_enable
,
457 .enable_reg
= CCM_PCCR_GPT2_REG
,
458 .enable_shift
= CCM_PCCR_GPT2_OFFSET
,
459 .disable
= _clk_disable
,
463 .enable
= _clk_enable
,
464 .enable_reg
= CCM_PCCR_GPT3_REG
,
465 .enable_shift
= CCM_PCCR_GPT3_OFFSET
,
466 .disable
= _clk_disable
,
470 static struct clk pwm_clk
[] = {
472 .parent
= &per_clk
[0],
473 .secondary
= &pwm_clk
[1],
476 .enable
= _clk_enable
,
477 .enable_reg
= CCM_PCCR_PWM_REG
,
478 .enable_shift
= CCM_PCCR_PWM_OFFSET
,
479 .disable
= _clk_disable
,
483 static struct clk sdhc_ipg_clk
[];
485 static struct clk sdhc_clk
[] = {
488 .parent
= &per_clk
[1],
489 .secondary
= &sdhc_ipg_clk
[0],
492 .parent
= &per_clk
[1],
493 .secondary
= &sdhc_ipg_clk
[1],
497 static struct clk sdhc_ipg_clk
[] = {
501 .enable
= _clk_enable
,
502 .enable_reg
= CCM_PCCR_SDHC1_REG
,
503 .enable_shift
= CCM_PCCR_SDHC1_OFFSET
,
504 .disable
= _clk_disable
,
508 .enable
= _clk_enable
,
509 .enable_reg
= CCM_PCCR_SDHC2_REG
,
510 .enable_shift
= CCM_PCCR_SDHC2_OFFSET
,
511 .disable
= _clk_disable
,
515 static struct clk cspi_ipg_clk
[];
517 static struct clk cspi_clk
[] = {
520 .parent
= &per_clk
[1],
521 .secondary
= &cspi_ipg_clk
[0],
524 .parent
= &per_clk
[1],
525 .secondary
= &cspi_ipg_clk
[1],
528 .parent
= &per_clk
[1],
529 .secondary
= &cspi_ipg_clk
[2],
533 static struct clk cspi_ipg_clk
[] = {
537 .enable
= _clk_enable
,
538 .enable_reg
= CCM_PCCR_CSPI1_REG
,
539 .enable_shift
= CCM_PCCR_CSPI1_OFFSET
,
540 .disable
= _clk_disable
,
544 .enable
= _clk_enable
,
545 .enable_reg
= CCM_PCCR_CSPI2_REG
,
546 .enable_shift
= CCM_PCCR_CSPI2_OFFSET
,
547 .disable
= _clk_disable
,
551 .enable
= _clk_enable
,
552 .enable_reg
= CCM_PCCR_CSPI3_REG
,
553 .enable_shift
= CCM_PCCR_CSPI3_OFFSET
,
554 .disable
= _clk_disable
,
558 static struct clk lcdc_clk
[] = {
560 .parent
= &per_clk
[2],
561 .secondary
= &lcdc_clk
[1],
562 .round_rate
= _clk_parent_round_rate
,
563 .set_rate
= _clk_parent_set_rate
,
566 .secondary
= &lcdc_clk
[2],
567 .enable
= _clk_enable
,
568 .enable_reg
= CCM_PCCR_LCDC_REG
,
569 .enable_shift
= CCM_PCCR_LCDC_OFFSET
,
570 .disable
= _clk_disable
,
573 .enable
= _clk_enable
,
574 .enable_reg
= CCM_PCCR_HCLK_LCDC_REG
,
575 .enable_shift
= CCM_PCCR_HCLK_LCDC_OFFSET
,
576 .disable
= _clk_disable
,
580 static struct clk csi_clk
[] = {
582 .parent
= &per_clk
[3],
583 .secondary
= &csi_clk
[1],
584 .round_rate
= _clk_parent_round_rate
,
585 .set_rate
= _clk_parent_set_rate
,
588 .enable
= _clk_enable
,
589 .enable_reg
= CCM_PCCR_HCLK_CSI_REG
,
590 .enable_shift
= CCM_PCCR_HCLK_CSI_OFFSET
,
591 .disable
= _clk_disable
,
595 static struct clk usb_clk
[] = {
598 .get_rate
= _clk_usb_recalc
,
599 .enable
= _clk_enable
,
600 .enable_reg
= CCM_PCCR_USBOTG_REG
,
601 .enable_shift
= CCM_PCCR_USBOTG_OFFSET
,
602 .disable
= _clk_disable
,
605 .enable
= _clk_enable
,
606 .enable_reg
= CCM_PCCR_HCLK_USBOTG_REG
,
607 .enable_shift
= CCM_PCCR_HCLK_USBOTG_OFFSET
,
608 .disable
= _clk_disable
,
612 static struct clk ssi_ipg_clk
[];
614 static struct clk ssi_clk
[] = {
618 .secondary
= &ssi_ipg_clk
[0],
619 .get_rate
= _clk_ssi1_recalc
,
620 .enable
= _clk_enable
,
621 .enable_reg
= CCM_PCCR_SSI1_BAUD_REG
,
622 .enable_shift
= CCM_PCCR_SSI1_BAUD_OFFSET
,
623 .disable
= _clk_disable
,
627 .secondary
= &ssi_ipg_clk
[1],
628 .get_rate
= _clk_ssi2_recalc
,
629 .enable
= _clk_enable
,
630 .enable_reg
= CCM_PCCR_SSI2_BAUD_REG
,
631 .enable_shift
= CCM_PCCR_SSI2_BAUD_OFFSET
,
632 .disable
= _clk_disable
,
636 static struct clk ssi_ipg_clk
[] = {
640 .enable
= _clk_enable
,
641 .enable_reg
= CCM_PCCR_SSI1_REG
,
642 .enable_shift
= CCM_PCCR_SSI1_IPG_OFFSET
,
643 .disable
= _clk_disable
,
647 .enable
= _clk_enable
,
648 .enable_reg
= CCM_PCCR_SSI2_REG
,
649 .enable_shift
= CCM_PCCR_SSI2_IPG_OFFSET
,
650 .disable
= _clk_disable
,
655 static struct clk nfc_clk
= {
657 .get_rate
= _clk_nfc_recalc
,
658 .enable
= _clk_enable
,
659 .enable_reg
= CCM_PCCR_NFC_REG
,
660 .enable_shift
= CCM_PCCR_NFC_OFFSET
,
661 .disable
= _clk_disable
,
664 static struct clk dma_clk
[] = {
667 .enable
= _clk_enable
,
668 .enable_reg
= CCM_PCCR_DMA_REG
,
669 .enable_shift
= CCM_PCCR_DMA_OFFSET
,
670 .disable
= _clk_disable
,
671 .secondary
= &dma_clk
[1],
673 .enable
= _clk_enable
,
674 .enable_reg
= CCM_PCCR_HCLK_DMA_REG
,
675 .enable_shift
= CCM_PCCR_HCLK_DMA_OFFSET
,
676 .disable
= _clk_disable
,
680 static struct clk brom_clk
= {
682 .enable
= _clk_enable
,
683 .enable_reg
= CCM_PCCR_HCLK_BROM_REG
,
684 .enable_shift
= CCM_PCCR_HCLK_BROM_OFFSET
,
685 .disable
= _clk_disable
,
688 static struct clk emma_clk
[] = {
691 .enable
= _clk_enable
,
692 .enable_reg
= CCM_PCCR_EMMA_REG
,
693 .enable_shift
= CCM_PCCR_EMMA_OFFSET
,
694 .disable
= _clk_disable
,
695 .secondary
= &emma_clk
[1],
697 .enable
= _clk_enable
,
698 .enable_reg
= CCM_PCCR_HCLK_EMMA_REG
,
699 .enable_shift
= CCM_PCCR_HCLK_EMMA_OFFSET
,
700 .disable
= _clk_disable
,
704 static struct clk slcdc_clk
[] = {
707 .enable
= _clk_enable
,
708 .enable_reg
= CCM_PCCR_SLCDC_REG
,
709 .enable_shift
= CCM_PCCR_SLCDC_OFFSET
,
710 .disable
= _clk_disable
,
711 .secondary
= &slcdc_clk
[1],
713 .enable
= _clk_enable
,
714 .enable_reg
= CCM_PCCR_HCLK_SLCDC_REG
,
715 .enable_shift
= CCM_PCCR_HCLK_SLCDC_OFFSET
,
716 .disable
= _clk_disable
,
720 static struct clk wdog_clk
= {
722 .enable
= _clk_enable
,
723 .enable_reg
= CCM_PCCR_WDT_REG
,
724 .enable_shift
= CCM_PCCR_WDT_OFFSET
,
725 .disable
= _clk_disable
,
728 static struct clk gpio_clk
= {
730 .enable
= _clk_enable
,
731 .enable_reg
= CCM_PCCR_GPIO_REG
,
732 .enable_shift
= CCM_PCCR_GPIO_OFFSET
,
733 .disable
= _clk_disable
,
736 static struct clk i2c_clk
= {
739 .enable
= _clk_enable
,
740 .enable_reg
= CCM_PCCR_I2C1_REG
,
741 .enable_shift
= CCM_PCCR_I2C1_OFFSET
,
742 .disable
= _clk_disable
,
745 static struct clk kpp_clk
= {
747 .enable
= _clk_enable
,
748 .enable_reg
= CCM_PCCR_KPP_REG
,
749 .enable_shift
= CCM_PCCR_KPP_OFFSET
,
750 .disable
= _clk_disable
,
753 static struct clk owire_clk
= {
755 .enable
= _clk_enable
,
756 .enable_reg
= CCM_PCCR_OWIRE_REG
,
757 .enable_shift
= CCM_PCCR_OWIRE_OFFSET
,
758 .disable
= _clk_disable
,
761 static struct clk rtc_clk
= {
763 .enable
= _clk_enable
,
764 .enable_reg
= CCM_PCCR_RTC_REG
,
765 .enable_shift
= CCM_PCCR_RTC_OFFSET
,
766 .disable
= _clk_disable
,
769 static unsigned long _clk_clko_round_rate(struct clk
*clk
, unsigned long rate
)
772 unsigned long parent_rate
;
774 parent_rate
= clk_get_rate(clk
->parent
);
775 div
= parent_rate
/ rate
;
776 if (parent_rate
% rate
)
782 return parent_rate
/ div
;
785 static int _clk_clko_set_rate(struct clk
*clk
, unsigned long rate
)
789 unsigned long parent_rate
;
791 parent_rate
= clk_get_rate(clk
->parent
);
793 div
= parent_rate
/ rate
;
795 if (div
> 8 || div
< 1 || ((parent_rate
/ div
) != rate
))
799 reg
= __raw_readl(CCM_PCDR0
);
801 if (clk
->parent
== &usb_clk
[0]) {
802 reg
&= ~CCM_PCDR0_48MDIV_MASK
;
803 reg
|= div
<< CCM_PCDR0_48MDIV_OFFSET
;
805 __raw_writel(reg
, CCM_PCDR0
);
810 static unsigned long _clk_clko_recalc(struct clk
*clk
)
813 unsigned long parent_rate
;
815 parent_rate
= clk_get_rate(clk
->parent
);
817 if (clk
->parent
== &usb_clk
[0]) /* 48M */
818 div
= __raw_readl(CCM_PCDR0
) & CCM_PCDR0_48MDIV_MASK
819 >> CCM_PCDR0_48MDIV_OFFSET
;
822 return parent_rate
/ div
;
825 static struct clk clko_clk
;
827 static int _clk_clko_set_parent(struct clk
*clk
, struct clk
*parent
)
831 reg
= __raw_readl(CCM_CCSR
) & ~CCM_CCSR_CLKOSEL_MASK
;
833 if (parent
== &ckil_clk
)
834 reg
|= 0 << CCM_CCSR_CLKOSEL_OFFSET
;
835 else if (parent
== &fpm_clk
)
836 reg
|= 1 << CCM_CCSR_CLKOSEL_OFFSET
;
837 else if (parent
== &ckih_clk
)
838 reg
|= 2 << CCM_CCSR_CLKOSEL_OFFSET
;
839 else if (parent
== mpll_clk
.parent
)
840 reg
|= 3 << CCM_CCSR_CLKOSEL_OFFSET
;
841 else if (parent
== spll_clk
.parent
)
842 reg
|= 4 << CCM_CCSR_CLKOSEL_OFFSET
;
843 else if (parent
== &mpll_clk
)
844 reg
|= 5 << CCM_CCSR_CLKOSEL_OFFSET
;
845 else if (parent
== &spll_clk
)
846 reg
|= 6 << CCM_CCSR_CLKOSEL_OFFSET
;
847 else if (parent
== &fclk_clk
)
848 reg
|= 7 << CCM_CCSR_CLKOSEL_OFFSET
;
849 else if (parent
== &hclk_clk
)
850 reg
|= 8 << CCM_CCSR_CLKOSEL_OFFSET
;
851 else if (parent
== &ipg_clk
)
852 reg
|= 9 << CCM_CCSR_CLKOSEL_OFFSET
;
853 else if (parent
== &per_clk
[0])
854 reg
|= 0xA << CCM_CCSR_CLKOSEL_OFFSET
;
855 else if (parent
== &per_clk
[1])
856 reg
|= 0xB << CCM_CCSR_CLKOSEL_OFFSET
;
857 else if (parent
== &per_clk
[2])
858 reg
|= 0xC << CCM_CCSR_CLKOSEL_OFFSET
;
859 else if (parent
== &per_clk
[3])
860 reg
|= 0xD << CCM_CCSR_CLKOSEL_OFFSET
;
861 else if (parent
== &ssi_clk
[0])
862 reg
|= 0xE << CCM_CCSR_CLKOSEL_OFFSET
;
863 else if (parent
== &ssi_clk
[1])
864 reg
|= 0xF << CCM_CCSR_CLKOSEL_OFFSET
;
865 else if (parent
== &nfc_clk
)
866 reg
|= 0x10 << CCM_CCSR_CLKOSEL_OFFSET
;
867 else if (parent
== &usb_clk
[0])
868 reg
|= 0x14 << CCM_CCSR_CLKOSEL_OFFSET
;
869 else if (parent
== &clko_clk
)
870 reg
|= 0x15 << CCM_CCSR_CLKOSEL_OFFSET
;
874 __raw_writel(reg
, CCM_CCSR
);
879 static struct clk clko_clk
= {
880 .get_rate
= _clk_clko_recalc
,
881 .set_rate
= _clk_clko_set_rate
,
882 .round_rate
= _clk_clko_round_rate
,
883 .set_parent
= _clk_clko_set_parent
,
887 #define _REGISTER_CLOCK(d, n, c) \
893 static struct clk_lookup lookups
[] __initdata
= {
894 /* It's unlikely that any driver wants one of them directly:
895 _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
896 _REGISTER_CLOCK(NULL, "ckil", ckil_clk)
897 _REGISTER_CLOCK(NULL, "fpm", fpm_clk)
898 _REGISTER_CLOCK(NULL, "mpll", mpll_clk)
899 _REGISTER_CLOCK(NULL, "spll", spll_clk)
900 _REGISTER_CLOCK(NULL, "fclk", fclk_clk)
901 _REGISTER_CLOCK(NULL, "hclk", hclk_clk)
902 _REGISTER_CLOCK(NULL, "ipg", ipg_clk)
904 _REGISTER_CLOCK(NULL
, "perclk1", per_clk
[0])
905 _REGISTER_CLOCK(NULL
, "perclk2", per_clk
[1])
906 _REGISTER_CLOCK(NULL
, "perclk3", per_clk
[2])
907 _REGISTER_CLOCK(NULL
, "perclk4", per_clk
[3])
908 _REGISTER_CLOCK(NULL
, "clko", clko_clk
)
909 _REGISTER_CLOCK("imx-uart.0", NULL
, uart_clk
[0])
910 _REGISTER_CLOCK("imx-uart.1", NULL
, uart_clk
[1])
911 _REGISTER_CLOCK("imx-uart.2", NULL
, uart_clk
[2])
912 _REGISTER_CLOCK("imx-uart.3", NULL
, uart_clk
[3])
913 _REGISTER_CLOCK(NULL
, "gpt1", gpt_clk
[0])
914 _REGISTER_CLOCK(NULL
, "gpt1", gpt_clk
[1])
915 _REGISTER_CLOCK(NULL
, "gpt1", gpt_clk
[2])
916 _REGISTER_CLOCK(NULL
, "pwm", pwm_clk
[0])
917 _REGISTER_CLOCK(NULL
, "sdhc1", sdhc_clk
[0])
918 _REGISTER_CLOCK(NULL
, "sdhc2", sdhc_clk
[1])
919 _REGISTER_CLOCK(NULL
, "cspi1", cspi_clk
[0])
920 _REGISTER_CLOCK(NULL
, "cspi2", cspi_clk
[1])
921 _REGISTER_CLOCK(NULL
, "cspi3", cspi_clk
[2])
922 _REGISTER_CLOCK("imx-fb.0", NULL
, lcdc_clk
[0])
923 _REGISTER_CLOCK(NULL
, "csi", csi_clk
[0])
924 _REGISTER_CLOCK(NULL
, "usb", usb_clk
[0])
925 _REGISTER_CLOCK(NULL
, "ssi1", ssi_clk
[0])
926 _REGISTER_CLOCK(NULL
, "ssi2", ssi_clk
[1])
927 _REGISTER_CLOCK("mxc_nand.0", NULL
, nfc_clk
)
928 _REGISTER_CLOCK(NULL
, "dma", dma_clk
[0])
929 _REGISTER_CLOCK(NULL
, "brom", brom_clk
)
930 _REGISTER_CLOCK(NULL
, "emma", emma_clk
[0])
931 _REGISTER_CLOCK(NULL
, "slcdc", slcdc_clk
[0])
932 _REGISTER_CLOCK("imx-wdt.0", NULL
, wdog_clk
)
933 _REGISTER_CLOCK(NULL
, "gpio", gpio_clk
)
934 _REGISTER_CLOCK("imx-i2c.0", NULL
, i2c_clk
)
935 _REGISTER_CLOCK("mxc-keypad", NULL
, kpp_clk
)
936 _REGISTER_CLOCK(NULL
, "owire", owire_clk
)
937 _REGISTER_CLOCK(NULL
, "rtc", rtc_clk
)
941 * must be called very early to get information about the
942 * available clock rate when the timer framework starts
944 int __init
mx21_clocks_init(unsigned long lref
, unsigned long href
)
949 external_low_reference
= lref
;
950 external_high_reference
= href
;
952 /* detect clock reference for both system PLL */
954 if (cscr
& CCM_CSCR_MCU
)
955 mpll_clk
.parent
= &ckih_clk
;
957 mpll_clk
.parent
= &fpm_clk
;
959 if (cscr
& CCM_CSCR_SP
)
960 spll_clk
.parent
= &ckih_clk
;
962 spll_clk
.parent
= &fpm_clk
;
964 for (i
= 0; i
< ARRAY_SIZE(lookups
); i
++)
965 clkdev_add(&lookups
[i
]);
967 /* Turn off all clock gates */
968 __raw_writel(0, CCM_PCCR0
);
969 __raw_writel(CCM_PCCR_GPT1_MASK
, CCM_PCCR1
);
971 /* This turns of the serial PLL as well */
972 spll_clk
.disable(&spll_clk
);
974 /* This will propagate to all children and init all the clock rates. */
975 clk_enable(&per_clk
[0]);
976 clk_enable(&gpio_clk
);
978 #ifdef CONFIG_DEBUG_LL_CONSOLE
979 clk_enable(&uart_clk
[0]);
982 mxc_timer_init(&gpt_clk
[0]);