2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 #include <linux/clk.h>
22 #include <linux/module.h>
23 #include <linux/spinlock.h>
25 #include <mach/clock.h>
26 #include <mach/common.h>
27 #include <asm/div64.h>
31 static struct clk ckil_clk
;
32 static struct clk mpll_clk
;
33 static struct clk mpll_main_clk
[];
34 static struct clk spll_clk
;
36 static int _clk_enable(struct clk
*clk
)
40 reg
= __raw_readl(clk
->enable_reg
);
41 reg
|= 1 << clk
->enable_shift
;
42 __raw_writel(reg
, clk
->enable_reg
);
47 static void _clk_disable(struct clk
*clk
)
51 reg
= __raw_readl(clk
->enable_reg
);
52 reg
&= ~(1 << clk
->enable_shift
);
53 __raw_writel(reg
, clk
->enable_reg
);
56 static int _clk_spll_enable(struct clk
*clk
)
60 reg
= __raw_readl(CCM_CSCR
);
62 __raw_writel(reg
, CCM_CSCR
);
64 while ((__raw_readl(CCM_SPCTL1
) & CCM_SPCTL1_LF
) == 0)
70 static void _clk_spll_disable(struct clk
*clk
)
74 reg
= __raw_readl(CCM_CSCR
);
75 reg
&= ~CCM_CSCR_SPEN
;
76 __raw_writel(reg
, CCM_CSCR
);
79 static void _clk_pccr01_enable(unsigned long mask0
, unsigned long mask1
)
83 reg
= __raw_readl(CCM_PCCR0
);
85 __raw_writel(reg
, CCM_PCCR0
);
87 reg
= __raw_readl(CCM_PCCR1
);
89 __raw_writel(reg
, CCM_PCCR1
);
93 static void _clk_pccr01_disable(unsigned long mask0
, unsigned long mask1
)
97 reg
= __raw_readl(CCM_PCCR0
);
99 __raw_writel(reg
, CCM_PCCR0
);
101 reg
= __raw_readl(CCM_PCCR1
);
103 __raw_writel(reg
, CCM_PCCR1
);
106 static void _clk_pccr10_enable(unsigned long mask1
, unsigned long mask0
)
110 reg
= __raw_readl(CCM_PCCR1
);
112 __raw_writel(reg
, CCM_PCCR1
);
114 reg
= __raw_readl(CCM_PCCR0
);
116 __raw_writel(reg
, CCM_PCCR0
);
119 static void _clk_pccr10_disable(unsigned long mask1
, unsigned long mask0
)
123 reg
= __raw_readl(CCM_PCCR1
);
125 __raw_writel(reg
, CCM_PCCR1
);
127 reg
= __raw_readl(CCM_PCCR0
);
129 __raw_writel(reg
, CCM_PCCR0
);
132 static int _clk_dma_enable(struct clk
*clk
)
134 _clk_pccr01_enable(CCM_PCCR0_DMA_MASK
, CCM_PCCR1_HCLK_DMA_MASK
);
139 static void _clk_dma_disable(struct clk
*clk
)
141 _clk_pccr01_disable(CCM_PCCR0_DMA_MASK
, CCM_PCCR1_HCLK_DMA_MASK
);
144 static int _clk_rtic_enable(struct clk
*clk
)
146 _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK
, CCM_PCCR1_HCLK_RTIC_MASK
);
151 static void _clk_rtic_disable(struct clk
*clk
)
153 _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK
, CCM_PCCR1_HCLK_RTIC_MASK
);
156 static int _clk_emma_enable(struct clk
*clk
)
158 _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK
, CCM_PCCR1_HCLK_EMMA_MASK
);
163 static void _clk_emma_disable(struct clk
*clk
)
165 _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK
, CCM_PCCR1_HCLK_EMMA_MASK
);
168 static int _clk_slcdc_enable(struct clk
*clk
)
170 _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK
, CCM_PCCR1_HCLK_SLCDC_MASK
);
175 static void _clk_slcdc_disable(struct clk
*clk
)
177 _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK
, CCM_PCCR1_HCLK_SLCDC_MASK
);
180 static int _clk_fec_enable(struct clk
*clk
)
182 _clk_pccr01_enable(CCM_PCCR0_FEC_MASK
, CCM_PCCR1_HCLK_FEC_MASK
);
187 static void _clk_fec_disable(struct clk
*clk
)
189 _clk_pccr01_disable(CCM_PCCR0_FEC_MASK
, CCM_PCCR1_HCLK_FEC_MASK
);
192 static int _clk_vpu_enable(struct clk
*clk
)
196 reg
= __raw_readl(CCM_PCCR1
);
197 reg
|= CCM_PCCR1_VPU_BAUD_MASK
| CCM_PCCR1_HCLK_VPU_MASK
;
198 __raw_writel(reg
, CCM_PCCR1
);
203 static void _clk_vpu_disable(struct clk
*clk
)
207 reg
= __raw_readl(CCM_PCCR1
);
208 reg
&= ~(CCM_PCCR1_VPU_BAUD_MASK
| CCM_PCCR1_HCLK_VPU_MASK
);
209 __raw_writel(reg
, CCM_PCCR1
);
212 static int _clk_sahara2_enable(struct clk
*clk
)
214 _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK
, CCM_PCCR1_HCLK_SAHARA_MASK
);
219 static void _clk_sahara2_disable(struct clk
*clk
)
221 _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK
, CCM_PCCR1_HCLK_SAHARA_MASK
);
224 static int _clk_mstick1_enable(struct clk
*clk
)
226 _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK
, CCM_PCCR0_MSHC_MASK
);
231 static void _clk_mstick1_disable(struct clk
*clk
)
233 _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK
, CCM_PCCR0_MSHC_MASK
);
236 #define CSCR() (__raw_readl(CCM_CSCR))
237 #define PCDR0() (__raw_readl(CCM_PCDR0))
238 #define PCDR1() (__raw_readl(CCM_PCDR1))
240 static int _clk_cpu_set_parent(struct clk
*clk
, struct clk
*parent
)
244 if (clk
->parent
== parent
)
247 if (mx27_revision() >= CHIP_REV_2_0
) {
248 if (parent
== &mpll_main_clk
[0]) {
249 cscr
|= CCM_CSCR_ARM_SRC
;
251 if (parent
== &mpll_main_clk
[1])
252 cscr
&= ~CCM_CSCR_ARM_SRC
;
256 __raw_writel(cscr
, CCM_CSCR
);
260 clk
->parent
= parent
;
264 static unsigned long _clk_cpu_round_rate(struct clk
*clk
, unsigned long rate
)
267 unsigned long parent_rate
;
269 parent_rate
= clk_get_rate(clk
->parent
);
271 div
= parent_rate
/ rate
;
272 if (parent_rate
% rate
)
278 return parent_rate
/ div
;
281 static int _clk_cpu_set_rate(struct clk
*clk
, unsigned long rate
)
285 unsigned long parent_rate
;
287 parent_rate
= clk_get_rate(clk
->parent
);
289 div
= parent_rate
/ rate
;
291 if (div
> 4 || div
< 1 || ((parent_rate
/ div
) != rate
))
296 reg
= __raw_readl(CCM_CSCR
);
297 if (mx27_revision() >= CHIP_REV_2_0
) {
298 reg
&= ~CCM_CSCR_ARM_MASK
;
299 reg
|= div
<< CCM_CSCR_ARM_OFFSET
;
301 __raw_writel(reg
| 0x80000000, CCM_CSCR
);
303 printk(KERN_ERR
"Cant set CPU frequency!\n");
309 static unsigned long _clk_perclkx_round_rate(struct clk
*clk
,
313 unsigned long parent_rate
;
315 parent_rate
= clk_get_rate(clk
->parent
);
317 div
= parent_rate
/ rate
;
318 if (parent_rate
% rate
)
324 return parent_rate
/ div
;
327 static int _clk_perclkx_set_rate(struct clk
*clk
, unsigned long rate
)
331 unsigned long parent_rate
;
333 parent_rate
= clk_get_rate(clk
->parent
);
335 if (clk
->id
< 0 || clk
->id
> 3)
338 div
= parent_rate
/ rate
;
339 if (div
> 64 || div
< 1 || ((parent_rate
/ div
) != rate
))
344 __raw_readl(CCM_PCDR1
) & ~(CCM_PCDR1_PERDIV1_MASK
<<
346 reg
|= div
<< (clk
->id
<< 3);
347 __raw_writel(reg
, CCM_PCDR1
);
352 static unsigned long _clk_usb_recalc(struct clk
*clk
)
354 unsigned long usb_pdf
;
355 unsigned long parent_rate
;
357 parent_rate
= clk_get_rate(clk
->parent
);
359 usb_pdf
= (CSCR() & CCM_CSCR_USB_MASK
) >> CCM_CSCR_USB_OFFSET
;
361 return parent_rate
/ (usb_pdf
+ 1U);
364 static unsigned long _clk_ssi1_recalc(struct clk
*clk
)
366 unsigned long ssi1_pdf
;
367 unsigned long parent_rate
;
369 parent_rate
= clk_get_rate(clk
->parent
);
371 ssi1_pdf
= (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK
) >>
372 CCM_PCDR0_SSI1BAUDDIV_OFFSET
;
374 if (mx27_revision() >= CHIP_REV_2_0
)
377 ssi1_pdf
= (ssi1_pdf
< 2) ? 124UL : ssi1_pdf
;
379 return 2UL * parent_rate
/ ssi1_pdf
;
382 static unsigned long _clk_ssi2_recalc(struct clk
*clk
)
384 unsigned long ssi2_pdf
;
385 unsigned long parent_rate
;
387 parent_rate
= clk_get_rate(clk
->parent
);
389 ssi2_pdf
= (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK
) >>
390 CCM_PCDR0_SSI2BAUDDIV_OFFSET
;
392 if (mx27_revision() >= CHIP_REV_2_0
)
395 ssi2_pdf
= (ssi2_pdf
< 2) ? 124UL : ssi2_pdf
;
397 return 2UL * parent_rate
/ ssi2_pdf
;
400 static unsigned long _clk_nfc_recalc(struct clk
*clk
)
402 unsigned long nfc_pdf
;
403 unsigned long parent_rate
;
405 parent_rate
= clk_get_rate(clk
->parent
);
407 if (mx27_revision() >= CHIP_REV_2_0
) {
409 (PCDR0() & CCM_PCDR0_NFCDIV2_MASK
) >>
410 CCM_PCDR0_NFCDIV2_OFFSET
;
413 (PCDR0() & CCM_PCDR0_NFCDIV_MASK
) >>
414 CCM_PCDR0_NFCDIV_OFFSET
;
417 return parent_rate
/ (nfc_pdf
+ 1);
420 static unsigned long _clk_vpu_recalc(struct clk
*clk
)
422 unsigned long vpu_pdf
;
423 unsigned long parent_rate
;
425 parent_rate
= clk_get_rate(clk
->parent
);
427 if (mx27_revision() >= CHIP_REV_2_0
) {
429 (PCDR0() & CCM_PCDR0_VPUDIV2_MASK
) >>
430 CCM_PCDR0_VPUDIV2_OFFSET
;
434 (PCDR0() & CCM_PCDR0_VPUDIV_MASK
) >>
435 CCM_PCDR0_VPUDIV_OFFSET
;
436 vpu_pdf
= (vpu_pdf
< 2) ? 124 : vpu_pdf
;
438 return 2UL * parent_rate
/ vpu_pdf
;
441 static unsigned long _clk_parent_round_rate(struct clk
*clk
, unsigned long rate
)
443 return clk
->parent
->round_rate(clk
->parent
, rate
);
446 static int _clk_parent_set_rate(struct clk
*clk
, unsigned long rate
)
448 return clk
->parent
->set_rate(clk
->parent
, rate
);
452 static unsigned long external_high_reference
= 26000000;
454 static unsigned long get_high_reference_clock_rate(struct clk
*clk
)
456 return external_high_reference
;
460 * the high frequency external clock reference
461 * Default case is 26MHz. Could be changed at runtime
462 * with a call to change_external_high_reference()
464 static struct clk ckih_clk
= {
466 .get_rate
= get_high_reference_clock_rate
,
470 static unsigned long external_low_reference
= 32768;
472 static unsigned long get_low_reference_clock_rate(struct clk
*clk
)
474 return external_low_reference
;
478 * the low frequency external clock reference
479 * Default case is 32.768kHz Could be changed at runtime
480 * with a call to change_external_low_reference()
482 static struct clk ckil_clk
= {
484 .get_rate
= get_low_reference_clock_rate
,
487 static unsigned long get_mpll_clk(struct clk
*clk
)
490 unsigned long ref_clk
;
491 unsigned long mfi
= 0, mfn
= 0, mfd
= 0, pdf
= 0;
492 unsigned long long temp
;
494 ref_clk
= clk_get_rate(clk
->parent
);
496 reg
= __raw_readl(CCM_MPCTL0
);
497 pdf
= (reg
& CCM_MPCTL0_PD_MASK
) >> CCM_MPCTL0_PD_OFFSET
;
498 mfd
= (reg
& CCM_MPCTL0_MFD_MASK
) >> CCM_MPCTL0_MFD_OFFSET
;
499 mfi
= (reg
& CCM_MPCTL0_MFI_MASK
) >> CCM_MPCTL0_MFI_OFFSET
;
500 mfn
= (reg
& CCM_MPCTL0_MFN_MASK
) >> CCM_MPCTL0_MFN_OFFSET
;
502 mfi
= (mfi
<= 5) ? 5 : mfi
;
503 temp
= 2LL * ref_clk
* mfn
;
504 do_div(temp
, mfd
+ 1);
505 temp
= 2LL * ref_clk
* mfi
+ temp
;
506 do_div(temp
, pdf
+ 1);
508 return (unsigned long)temp
;
511 static struct clk mpll_clk
= {
514 .get_rate
= get_mpll_clk
,
517 static unsigned long _clk_mpll_main_get_rate(struct clk
*clk
)
519 unsigned long parent_rate
;
521 parent_rate
= clk_get_rate(clk
->parent
);
524 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
525 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
528 if (mx27_revision() >= CHIP_REV_2_0
&& clk
->id
== 1)
529 return 2UL * parent_rate
/ 3UL;
534 static struct clk mpll_main_clk
[] = {
536 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
537 * It provide the clock source whose rate is same as MPLL
542 .get_rate
= _clk_mpll_main_get_rate
544 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
545 * It provide the clock source whose rate is same MPLL * 2/3
550 .get_rate
= _clk_mpll_main_get_rate
554 static unsigned long get_spll_clk(struct clk
*clk
)
557 unsigned long ref_clk
;
558 unsigned long mfi
= 0, mfn
= 0, mfd
= 0, pdf
= 0;
559 unsigned long long temp
;
561 ref_clk
= clk_get_rate(clk
->parent
);
563 reg
= __raw_readl(CCM_SPCTL0
);
564 /*TODO: This is TO2 Bug */
565 if (mx27_revision() >= CHIP_REV_2_0
)
566 __raw_writel(reg
, CCM_SPCTL0
);
568 pdf
= (reg
& CCM_SPCTL0_PD_MASK
) >> CCM_SPCTL0_PD_OFFSET
;
569 mfd
= (reg
& CCM_SPCTL0_MFD_MASK
) >> CCM_SPCTL0_MFD_OFFSET
;
570 mfi
= (reg
& CCM_SPCTL0_MFI_MASK
) >> CCM_SPCTL0_MFI_OFFSET
;
571 mfn
= (reg
& CCM_SPCTL0_MFN_MASK
) >> CCM_SPCTL0_MFN_OFFSET
;
573 mfi
= (mfi
<= 5) ? 5 : mfi
;
574 temp
= 2LL * ref_clk
* mfn
;
575 do_div(temp
, mfd
+ 1);
576 temp
= 2LL * ref_clk
* mfi
+ temp
;
577 do_div(temp
, pdf
+ 1);
579 return (unsigned long)temp
;
582 static struct clk spll_clk
= {
585 .get_rate
= get_spll_clk
,
586 .enable
= _clk_spll_enable
,
587 .disable
= _clk_spll_disable
,
590 static unsigned long get_cpu_clk(struct clk
*clk
)
595 if (mx27_revision() >= CHIP_REV_2_0
)
596 div
= (CSCR() & CCM_CSCR_ARM_MASK
) >> CCM_CSCR_ARM_OFFSET
;
598 div
= (CSCR() & CCM_CSCR_PRESC_MASK
) >> CCM_CSCR_PRESC_OFFSET
;
600 rate
= clk_get_rate(clk
->parent
);
601 return rate
/ (div
+ 1);
604 static struct clk cpu_clk
= {
606 .parent
= &mpll_main_clk
[1],
607 .set_parent
= _clk_cpu_set_parent
,
608 .round_rate
= _clk_cpu_round_rate
,
609 .get_rate
= get_cpu_clk
,
610 .set_rate
= _clk_cpu_set_rate
,
613 static unsigned long get_ahb_clk(struct clk
*clk
)
616 unsigned long bclk_pdf
;
618 if (mx27_revision() >= CHIP_REV_2_0
)
619 bclk_pdf
= (CSCR() & CCM_CSCR_AHB_MASK
)
620 >> CCM_CSCR_AHB_OFFSET
;
622 bclk_pdf
= (CSCR() & CCM_CSCR_BCLK_MASK
)
623 >> CCM_CSCR_BCLK_OFFSET
;
625 rate
= clk_get_rate(clk
->parent
);
626 return rate
/ (bclk_pdf
+ 1);
629 static struct clk ahb_clk
= {
631 .parent
= &mpll_main_clk
[1],
632 .get_rate
= get_ahb_clk
,
635 static unsigned long get_ipg_clk(struct clk
*clk
)
638 unsigned long ipg_pdf
;
640 if (mx27_revision() >= CHIP_REV_2_0
)
641 return clk_get_rate(clk
->parent
);
643 ipg_pdf
= (CSCR() & CCM_CSCR_IPDIV
) >> CCM_CSCR_IPDIV_OFFSET
;
645 rate
= clk_get_rate(clk
->parent
);
646 return rate
/ (ipg_pdf
+ 1);
649 static struct clk ipg_clk
= {
652 .get_rate
= get_ipg_clk
,
655 static unsigned long _clk_perclkx_recalc(struct clk
*clk
)
657 unsigned long perclk_pdf
;
658 unsigned long parent_rate
;
660 parent_rate
= clk_get_rate(clk
->parent
);
662 if (clk
->id
< 0 || clk
->id
> 3)
665 perclk_pdf
= (PCDR1() >> (clk
->id
<< 3)) & CCM_PCDR1_PERDIV1_MASK
;
667 return parent_rate
/ (perclk_pdf
+ 1);
670 static struct clk per_clk
[] = {
674 .parent
= &mpll_main_clk
[1],
675 .get_rate
= _clk_perclkx_recalc
,
676 .enable
= _clk_enable
,
677 .enable_reg
= CCM_PCCR1
,
678 .enable_shift
= CCM_PCCR1_PERCLK1_OFFSET
,
679 .disable
= _clk_disable
,
683 .parent
= &mpll_main_clk
[1],
684 .get_rate
= _clk_perclkx_recalc
,
685 .enable
= _clk_enable
,
686 .enable_reg
= CCM_PCCR1
,
687 .enable_shift
= CCM_PCCR1_PERCLK2_OFFSET
,
688 .disable
= _clk_disable
,
692 .parent
= &mpll_main_clk
[1],
693 .round_rate
= _clk_perclkx_round_rate
,
694 .set_rate
= _clk_perclkx_set_rate
,
695 .get_rate
= _clk_perclkx_recalc
,
696 .enable
= _clk_enable
,
697 .enable_reg
= CCM_PCCR1
,
698 .enable_shift
= CCM_PCCR1_PERCLK3_OFFSET
,
699 .disable
= _clk_disable
,
703 .parent
= &mpll_main_clk
[1],
704 .round_rate
= _clk_perclkx_round_rate
,
705 .set_rate
= _clk_perclkx_set_rate
,
706 .get_rate
= _clk_perclkx_recalc
,
707 .enable
= _clk_enable
,
708 .enable_reg
= CCM_PCCR1
,
709 .enable_shift
= CCM_PCCR1_PERCLK4_OFFSET
,
710 .disable
= _clk_disable
,
714 struct clk uart1_clk
[] = {
718 .parent
= &per_clk
[0],
719 .secondary
= &uart1_clk
[1],
721 .name
= "uart_ipg_clk",
724 .enable
= _clk_enable
,
725 .enable_reg
= CCM_PCCR1
,
726 .enable_shift
= CCM_PCCR1_UART1_OFFSET
,
727 .disable
= _clk_disable
,
731 struct clk uart2_clk
[] = {
735 .parent
= &per_clk
[0],
736 .secondary
= &uart2_clk
[1],
738 .name
= "uart_ipg_clk",
741 .enable
= _clk_enable
,
742 .enable_reg
= CCM_PCCR1
,
743 .enable_shift
= CCM_PCCR1_UART2_OFFSET
,
744 .disable
= _clk_disable
,
748 struct clk uart3_clk
[] = {
752 .parent
= &per_clk
[0],
753 .secondary
= &uart3_clk
[1],
755 .name
= "uart_ipg_clk",
758 .enable
= _clk_enable
,
759 .enable_reg
= CCM_PCCR1
,
760 .enable_shift
= CCM_PCCR1_UART3_OFFSET
,
761 .disable
= _clk_disable
,
765 struct clk uart4_clk
[] = {
769 .parent
= &per_clk
[0],
770 .secondary
= &uart4_clk
[1],
772 .name
= "uart_ipg_clk",
775 .enable
= _clk_enable
,
776 .enable_reg
= CCM_PCCR1
,
777 .enable_shift
= CCM_PCCR1_UART4_OFFSET
,
778 .disable
= _clk_disable
,
782 struct clk uart5_clk
[] = {
786 .parent
= &per_clk
[0],
787 .secondary
= &uart5_clk
[1],
789 .name
= "uart_ipg_clk",
792 .enable
= _clk_enable
,
793 .enable_reg
= CCM_PCCR1
,
794 .enable_shift
= CCM_PCCR1_UART5_OFFSET
,
795 .disable
= _clk_disable
,
799 struct clk uart6_clk
[] = {
803 .parent
= &per_clk
[0],
804 .secondary
= &uart6_clk
[1],
806 .name
= "uart_ipg_clk",
809 .enable
= _clk_enable
,
810 .enable_reg
= CCM_PCCR1
,
811 .enable_shift
= CCM_PCCR1_UART6_OFFSET
,
812 .disable
= _clk_disable
,
816 static struct clk gpt1_clk
[] = {
820 .parent
= &per_clk
[0],
821 .secondary
= &gpt1_clk
[1],
823 .name
= "gpt_ipg_clk",
826 .enable
= _clk_enable
,
827 .enable_reg
= CCM_PCCR0
,
828 .enable_shift
= CCM_PCCR0_GPT1_OFFSET
,
829 .disable
= _clk_disable
,
833 static struct clk gpt2_clk
[] = {
837 .parent
= &per_clk
[0],
838 .secondary
= &gpt2_clk
[1],
840 .name
= "gpt_ipg_clk",
843 .enable
= _clk_enable
,
844 .enable_reg
= CCM_PCCR0
,
845 .enable_shift
= CCM_PCCR0_GPT2_OFFSET
,
846 .disable
= _clk_disable
,
850 static struct clk gpt3_clk
[] = {
854 .parent
= &per_clk
[0],
855 .secondary
= &gpt3_clk
[1],
857 .name
= "gpt_ipg_clk",
860 .enable
= _clk_enable
,
861 .enable_reg
= CCM_PCCR0
,
862 .enable_shift
= CCM_PCCR0_GPT3_OFFSET
,
863 .disable
= _clk_disable
,
867 static struct clk gpt4_clk
[] = {
871 .parent
= &per_clk
[0],
872 .secondary
= &gpt4_clk
[1],
874 .name
= "gpt_ipg_clk",
877 .enable
= _clk_enable
,
878 .enable_reg
= CCM_PCCR0
,
879 .enable_shift
= CCM_PCCR0_GPT4_OFFSET
,
880 .disable
= _clk_disable
,
884 static struct clk gpt5_clk
[] = {
888 .parent
= &per_clk
[0],
889 .secondary
= &gpt5_clk
[1],
891 .name
= "gpt_ipg_clk",
894 .enable
= _clk_enable
,
895 .enable_reg
= CCM_PCCR0
,
896 .enable_shift
= CCM_PCCR0_GPT5_OFFSET
,
897 .disable
= _clk_disable
,
901 static struct clk gpt6_clk
[] = {
905 .parent
= &per_clk
[0],
906 .secondary
= &gpt6_clk
[1],
908 .name
= "gpt_ipg_clk",
911 .enable
= _clk_enable
,
912 .enable_reg
= CCM_PCCR0
,
913 .enable_shift
= CCM_PCCR0_GPT6_OFFSET
,
914 .disable
= _clk_disable
,
918 static struct clk pwm_clk
[] = {
921 .parent
= &per_clk
[0],
922 .secondary
= &pwm_clk
[1],
926 .enable
= _clk_enable
,
927 .enable_reg
= CCM_PCCR0
,
928 .enable_shift
= CCM_PCCR0_PWM_OFFSET
,
929 .disable
= _clk_disable
,
933 static struct clk sdhc1_clk
[] = {
937 .parent
= &per_clk
[1],
938 .secondary
= &sdhc1_clk
[1],
940 .name
= "sdhc_ipg_clk",
943 .enable
= _clk_enable
,
944 .enable_reg
= CCM_PCCR0
,
945 .enable_shift
= CCM_PCCR0_SDHC1_OFFSET
,
946 .disable
= _clk_disable
,
950 static struct clk sdhc2_clk
[] = {
954 .parent
= &per_clk
[1],
955 .secondary
= &sdhc2_clk
[1],
957 .name
= "sdhc_ipg_clk",
960 .enable
= _clk_enable
,
961 .enable_reg
= CCM_PCCR0
,
962 .enable_shift
= CCM_PCCR0_SDHC2_OFFSET
,
963 .disable
= _clk_disable
,
967 static struct clk sdhc3_clk
[] = {
971 .parent
= &per_clk
[1],
972 .secondary
= &sdhc3_clk
[1],
974 .name
= "sdhc_ipg_clk",
977 .enable
= _clk_enable
,
978 .enable_reg
= CCM_PCCR0
,
979 .enable_shift
= CCM_PCCR0_SDHC3_OFFSET
,
980 .disable
= _clk_disable
,
984 static struct clk cspi1_clk
[] = {
988 .parent
= &per_clk
[1],
989 .secondary
= &cspi1_clk
[1],
991 .name
= "cspi_ipg_clk",
994 .enable
= _clk_enable
,
995 .enable_reg
= CCM_PCCR0
,
996 .enable_shift
= CCM_PCCR0_CSPI1_OFFSET
,
997 .disable
= _clk_disable
,
1001 static struct clk cspi2_clk
[] = {
1005 .parent
= &per_clk
[1],
1006 .secondary
= &cspi2_clk
[1],
1008 .name
= "cspi_ipg_clk",
1011 .enable
= _clk_enable
,
1012 .enable_reg
= CCM_PCCR0
,
1013 .enable_shift
= CCM_PCCR0_CSPI2_OFFSET
,
1014 .disable
= _clk_disable
,
1018 static struct clk cspi3_clk
[] = {
1022 .parent
= &per_clk
[1],
1023 .secondary
= &cspi3_clk
[1],
1025 .name
= "cspi_ipg_clk",
1028 .enable
= _clk_enable
,
1029 .enable_reg
= CCM_PCCR0
,
1030 .enable_shift
= CCM_PCCR0_CSPI3_OFFSET
,
1031 .disable
= _clk_disable
,
1035 static struct clk lcdc_clk
[] = {
1038 .parent
= &per_clk
[2],
1039 .secondary
= &lcdc_clk
[1],
1040 .round_rate
= _clk_parent_round_rate
,
1041 .set_rate
= _clk_parent_set_rate
,
1043 .name
= "lcdc_ipg_clk",
1045 .secondary
= &lcdc_clk
[2],
1046 .enable
= _clk_enable
,
1047 .enable_reg
= CCM_PCCR0
,
1048 .enable_shift
= CCM_PCCR0_LCDC_OFFSET
,
1049 .disable
= _clk_disable
,
1051 .name
= "lcdc_ahb_clk",
1053 .enable
= _clk_enable
,
1054 .enable_reg
= CCM_PCCR1
,
1055 .enable_shift
= CCM_PCCR1_HCLK_LCDC_OFFSET
,
1056 .disable
= _clk_disable
,
1060 static struct clk csi_clk
[] = {
1062 .name
= "csi_perclk",
1063 .parent
= &per_clk
[3],
1064 .secondary
= &csi_clk
[1],
1065 .round_rate
= _clk_parent_round_rate
,
1066 .set_rate
= _clk_parent_set_rate
,
1068 .name
= "csi_ahb_clk",
1070 .enable
= _clk_enable
,
1071 .enable_reg
= CCM_PCCR1
,
1072 .enable_shift
= CCM_PCCR1_HCLK_CSI_OFFSET
,
1073 .disable
= _clk_disable
,
1077 static struct clk usb_clk
[] = {
1080 .parent
= &spll_clk
,
1081 .get_rate
= _clk_usb_recalc
,
1082 .enable
= _clk_enable
,
1083 .enable_reg
= CCM_PCCR1
,
1084 .enable_shift
= CCM_PCCR1_USBOTG_OFFSET
,
1085 .disable
= _clk_disable
,
1087 .name
= "usb_ahb_clk",
1089 .enable
= _clk_enable
,
1090 .enable_reg
= CCM_PCCR1
,
1091 .enable_shift
= CCM_PCCR1_HCLK_USBOTG_OFFSET
,
1092 .disable
= _clk_disable
,
1096 static struct clk ssi1_clk
[] = {
1100 .parent
= &mpll_main_clk
[1],
1101 .secondary
= &ssi1_clk
[1],
1102 .get_rate
= _clk_ssi1_recalc
,
1103 .enable
= _clk_enable
,
1104 .enable_reg
= CCM_PCCR1
,
1105 .enable_shift
= CCM_PCCR1_SSI1_BAUD_OFFSET
,
1106 .disable
= _clk_disable
,
1108 .name
= "ssi_ipg_clk",
1111 .enable
= _clk_enable
,
1112 .enable_reg
= CCM_PCCR0
,
1113 .enable_shift
= CCM_PCCR0_SSI1_IPG_OFFSET
,
1114 .disable
= _clk_disable
,
1118 static struct clk ssi2_clk
[] = {
1122 .parent
= &mpll_main_clk
[1],
1123 .secondary
= &ssi2_clk
[1],
1124 .get_rate
= _clk_ssi2_recalc
,
1125 .enable
= _clk_enable
,
1126 .enable_reg
= CCM_PCCR1
,
1127 .enable_shift
= CCM_PCCR1_SSI2_BAUD_OFFSET
,
1128 .disable
= _clk_disable
,
1130 .name
= "ssi_ipg_clk",
1133 .enable
= _clk_enable
,
1134 .enable_reg
= CCM_PCCR0
,
1135 .enable_shift
= CCM_PCCR0_SSI2_IPG_OFFSET
,
1136 .disable
= _clk_disable
,
1140 static struct clk nfc_clk
= {
1143 .get_rate
= _clk_nfc_recalc
,
1144 .enable
= _clk_enable
,
1145 .enable_reg
= CCM_PCCR1
,
1146 .enable_shift
= CCM_PCCR1_NFC_BAUD_OFFSET
,
1147 .disable
= _clk_disable
,
1150 static struct clk vpu_clk
= {
1152 .parent
= &mpll_main_clk
[1],
1153 .get_rate
= _clk_vpu_recalc
,
1154 .enable
= _clk_vpu_enable
,
1155 .disable
= _clk_vpu_disable
,
1158 static struct clk dma_clk
= {
1161 .enable
= _clk_dma_enable
,
1162 .disable
= _clk_dma_disable
,
1165 static struct clk rtic_clk
= {
1168 .enable
= _clk_rtic_enable
,
1169 .disable
= _clk_rtic_disable
,
1172 static struct clk brom_clk
= {
1175 .enable
= _clk_enable
,
1176 .enable_reg
= CCM_PCCR1
,
1177 .enable_shift
= CCM_PCCR1_HCLK_BROM_OFFSET
,
1178 .disable
= _clk_disable
,
1181 static struct clk emma_clk
= {
1184 .enable
= _clk_emma_enable
,
1185 .disable
= _clk_emma_disable
,
1188 static struct clk slcdc_clk
= {
1189 .name
= "slcdc_clk",
1191 .enable
= _clk_slcdc_enable
,
1192 .disable
= _clk_slcdc_disable
,
1195 static struct clk fec_clk
= {
1198 .enable
= _clk_fec_enable
,
1199 .disable
= _clk_fec_disable
,
1202 static struct clk emi_clk
= {
1205 .enable
= _clk_enable
,
1206 .enable_reg
= CCM_PCCR1
,
1207 .enable_shift
= CCM_PCCR1_HCLK_EMI_OFFSET
,
1208 .disable
= _clk_disable
,
1211 static struct clk sahara2_clk
= {
1212 .name
= "sahara_clk",
1214 .enable
= _clk_sahara2_enable
,
1215 .disable
= _clk_sahara2_disable
,
1218 static struct clk ata_clk
= {
1221 .enable
= _clk_enable
,
1222 .enable_reg
= CCM_PCCR1
,
1223 .enable_shift
= CCM_PCCR1_HCLK_ATA_OFFSET
,
1224 .disable
= _clk_disable
,
1227 static struct clk mstick1_clk
= {
1228 .name
= "mstick1_clk",
1230 .enable
= _clk_mstick1_enable
,
1231 .disable
= _clk_mstick1_disable
,
1234 static struct clk wdog_clk
= {
1237 .enable
= _clk_enable
,
1238 .enable_reg
= CCM_PCCR1
,
1239 .enable_shift
= CCM_PCCR1_WDT_OFFSET
,
1240 .disable
= _clk_disable
,
1243 static struct clk gpio_clk
= {
1246 .enable
= _clk_enable
,
1247 .enable_reg
= CCM_PCCR1
,
1248 .enable_shift
= CCM_PCCR0_GPIO_OFFSET
,
1249 .disable
= _clk_disable
,
1252 static struct clk i2c_clk
[] = {
1257 .enable
= _clk_enable
,
1258 .enable_reg
= CCM_PCCR0
,
1259 .enable_shift
= CCM_PCCR0_I2C1_OFFSET
,
1260 .disable
= _clk_disable
,
1265 .enable
= _clk_enable
,
1266 .enable_reg
= CCM_PCCR0
,
1267 .enable_shift
= CCM_PCCR0_I2C2_OFFSET
,
1268 .disable
= _clk_disable
,
1272 static struct clk iim_clk
= {
1275 .enable
= _clk_enable
,
1276 .enable_reg
= CCM_PCCR0
,
1277 .enable_shift
= CCM_PCCR0_IIM_OFFSET
,
1278 .disable
= _clk_disable
,
1281 static struct clk kpp_clk
= {
1284 .enable
= _clk_enable
,
1285 .enable_reg
= CCM_PCCR0
,
1286 .enable_shift
= CCM_PCCR0_KPP_OFFSET
,
1287 .disable
= _clk_disable
,
1290 static struct clk owire_clk
= {
1291 .name
= "owire_clk",
1293 .enable
= _clk_enable
,
1294 .enable_reg
= CCM_PCCR0
,
1295 .enable_shift
= CCM_PCCR0_OWIRE_OFFSET
,
1296 .disable
= _clk_disable
,
1299 static struct clk rtc_clk
= {
1302 .enable
= _clk_enable
,
1303 .enable_reg
= CCM_PCCR0
,
1304 .enable_shift
= CCM_PCCR0_RTC_OFFSET
,
1305 .disable
= _clk_disable
,
1308 static struct clk scc_clk
= {
1311 .enable
= _clk_enable
,
1312 .enable_reg
= CCM_PCCR0
,
1313 .enable_shift
= CCM_PCCR0_SCC_OFFSET
,
1314 .disable
= _clk_disable
,
1317 static unsigned long _clk_clko_round_rate(struct clk
*clk
, unsigned long rate
)
1320 unsigned long parent_rate
;
1322 parent_rate
= clk_get_rate(clk
->parent
);
1323 div
= parent_rate
/ rate
;
1324 if (parent_rate
% rate
)
1330 return parent_rate
/ div
;
1333 static int _clk_clko_set_rate(struct clk
*clk
, unsigned long rate
)
1337 unsigned long parent_rate
;
1339 parent_rate
= clk_get_rate(clk
->parent
);
1341 div
= parent_rate
/ rate
;
1343 if (div
> 8 || div
< 1 || ((parent_rate
/ div
) != rate
))
1347 reg
= __raw_readl(CCM_PCDR0
) & ~CCM_PCDR0_CLKODIV_MASK
;
1348 reg
|= div
<< CCM_PCDR0_CLKODIV_OFFSET
;
1349 __raw_writel(reg
, CCM_PCDR0
);
1354 static unsigned long _clk_clko_recalc(struct clk
*clk
)
1357 unsigned long parent_rate
;
1359 parent_rate
= clk_get_rate(clk
->parent
);
1361 div
= __raw_readl(CCM_PCDR0
) & CCM_PCDR0_CLKODIV_MASK
>>
1362 CCM_PCDR0_CLKODIV_OFFSET
;
1365 return parent_rate
/ div
;
1368 static int _clk_clko_set_parent(struct clk
*clk
, struct clk
*parent
)
1372 reg
= __raw_readl(CCM_CCSR
) & ~CCM_CCSR_CLKOSEL_MASK
;
1374 if (parent
== &ckil_clk
)
1375 reg
|= 0 << CCM_CCSR_CLKOSEL_OFFSET
;
1376 else if (parent
== &ckih_clk
)
1377 reg
|= 2 << CCM_CCSR_CLKOSEL_OFFSET
;
1378 else if (parent
== mpll_clk
.parent
)
1379 reg
|= 3 << CCM_CCSR_CLKOSEL_OFFSET
;
1380 else if (parent
== spll_clk
.parent
)
1381 reg
|= 4 << CCM_CCSR_CLKOSEL_OFFSET
;
1382 else if (parent
== &mpll_clk
)
1383 reg
|= 5 << CCM_CCSR_CLKOSEL_OFFSET
;
1384 else if (parent
== &spll_clk
)
1385 reg
|= 6 << CCM_CCSR_CLKOSEL_OFFSET
;
1386 else if (parent
== &cpu_clk
)
1387 reg
|= 7 << CCM_CCSR_CLKOSEL_OFFSET
;
1388 else if (parent
== &ahb_clk
)
1389 reg
|= 8 << CCM_CCSR_CLKOSEL_OFFSET
;
1390 else if (parent
== &ipg_clk
)
1391 reg
|= 9 << CCM_CCSR_CLKOSEL_OFFSET
;
1392 else if (parent
== &per_clk
[0])
1393 reg
|= 0xA << CCM_CCSR_CLKOSEL_OFFSET
;
1394 else if (parent
== &per_clk
[1])
1395 reg
|= 0xB << CCM_CCSR_CLKOSEL_OFFSET
;
1396 else if (parent
== &per_clk
[2])
1397 reg
|= 0xC << CCM_CCSR_CLKOSEL_OFFSET
;
1398 else if (parent
== &per_clk
[3])
1399 reg
|= 0xD << CCM_CCSR_CLKOSEL_OFFSET
;
1400 else if (parent
== &ssi1_clk
[0])
1401 reg
|= 0xE << CCM_CCSR_CLKOSEL_OFFSET
;
1402 else if (parent
== &ssi2_clk
[0])
1403 reg
|= 0xF << CCM_CCSR_CLKOSEL_OFFSET
;
1404 else if (parent
== &nfc_clk
)
1405 reg
|= 0x10 << CCM_CCSR_CLKOSEL_OFFSET
;
1406 else if (parent
== &mstick1_clk
)
1407 reg
|= 0x11 << CCM_CCSR_CLKOSEL_OFFSET
;
1408 else if (parent
== &vpu_clk
)
1409 reg
|= 0x12 << CCM_CCSR_CLKOSEL_OFFSET
;
1410 else if (parent
== &usb_clk
[0])
1411 reg
|= 0x15 << CCM_CCSR_CLKOSEL_OFFSET
;
1415 __raw_writel(reg
, CCM_CCSR
);
1420 static int _clk_clko_enable(struct clk
*clk
)
1424 reg
= __raw_readl(CCM_PCDR0
) | CCM_PCDR0_CLKO_EN
;
1425 __raw_writel(reg
, CCM_PCDR0
);
1430 static void _clk_clko_disable(struct clk
*clk
)
1434 reg
= __raw_readl(CCM_PCDR0
) & ~CCM_PCDR0_CLKO_EN
;
1435 __raw_writel(reg
, CCM_PCDR0
);
1438 static struct clk clko_clk
= {
1440 .get_rate
= _clk_clko_recalc
,
1441 .set_rate
= _clk_clko_set_rate
,
1442 .round_rate
= _clk_clko_round_rate
,
1443 .set_parent
= _clk_clko_set_parent
,
1444 .enable
= _clk_clko_enable
,
1445 .disable
= _clk_clko_disable
,
1448 static struct clk
*mxc_clks
[] = {
1535 void __init
change_external_low_reference(unsigned long new_ref
)
1537 external_low_reference
= new_ref
;
1540 unsigned long __init
clk_early_get_timer_rate(void)
1542 return clk_get_rate(&per_clk
[0]);
1545 static void __init
probe_mxc_clocks(void)
1549 if (mx27_revision() >= CHIP_REV_2_0
) {
1550 if (CSCR() & 0x8000)
1551 cpu_clk
.parent
= &mpll_main_clk
[0];
1553 if (!(CSCR() & 0x00800000))
1554 ssi2_clk
[0].parent
= &spll_clk
;
1556 if (!(CSCR() & 0x00400000))
1557 ssi1_clk
[0].parent
= &spll_clk
;
1559 if (!(CSCR() & 0x00200000))
1560 vpu_clk
.parent
= &spll_clk
;
1562 cpu_clk
.parent
= &mpll_clk
;
1563 cpu_clk
.set_parent
= NULL
;
1564 cpu_clk
.round_rate
= NULL
;
1565 cpu_clk
.set_rate
= NULL
;
1566 ahb_clk
.parent
= &mpll_clk
;
1568 for (i
= 0; i
< sizeof(per_clk
) / sizeof(per_clk
[0]); i
++)
1569 per_clk
[i
].parent
= &mpll_clk
;
1571 ssi1_clk
[0].parent
= &mpll_clk
;
1572 ssi2_clk
[0].parent
= &mpll_clk
;
1574 vpu_clk
.parent
= &mpll_clk
;
1579 * must be called very early to get information about the
1580 * available clock rate when the timer framework starts
1582 int __init
mxc_clocks_init(unsigned long fref
)
1587 external_high_reference
= fref
;
1589 /* detect clock reference for both system PLL */
1591 if (cscr
& CCM_CSCR_MCU
)
1592 mpll_clk
.parent
= &ckih_clk
;
1594 mpll_clk
.parent
= &ckil_clk
;
1596 if (cscr
& CCM_CSCR_SP
)
1597 spll_clk
.parent
= &ckih_clk
;
1599 spll_clk
.parent
= &ckil_clk
;
1603 per_clk
[0].enable(&per_clk
[0]);
1604 gpt1_clk
[1].enable(&gpt1_clk
[1]);
1606 for (clkp
= mxc_clks
; clkp
< mxc_clks
+ ARRAY_SIZE(mxc_clks
); clkp
++)
1607 clk_register(*clkp
);
1609 /* Turn off all possible clocks */
1610 __raw_writel(CCM_PCCR0_GPT1_MASK
, CCM_PCCR0
);
1611 __raw_writel(CCM_PCCR1_PERCLK1_MASK
| CCM_PCCR1_HCLK_EMI_MASK
,
1613 spll_clk
.disable(&spll_clk
);
1615 /* This will propagate to all children and init all the clock rates */
1617 clk_enable(&emi_clk
);
1618 clk_enable(&gpio_clk
);
1619 clk_enable(&iim_clk
);
1620 clk_enable(&gpt1_clk
[0]);
1621 #ifdef CONFIG_DEBUG_LL_CONSOLE
1622 clk_enable(&uart1_clk
[0]);