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 <asm/arch/clock.h>
26 #include <asm/arch/common.h>
27 #include <asm/div64.h>
28 #include <asm/mach-types.h>
32 static struct clk ckil_clk;
33 static struct clk mpll_clk;
34 static struct clk mpll_main_clk[];
35 static struct clk spll_clk;
37 static int _clk_enable(struct clk *clk)
41 reg = __raw_readl(clk->enable_reg);
42 reg |= 1 << clk->enable_shift;
43 __raw_writel(reg, clk->enable_reg);
48 static void _clk_disable(struct clk *clk)
52 reg = __raw_readl(clk->enable_reg);
53 reg &= ~(1 << clk->enable_shift);
54 __raw_writel(reg, clk->enable_reg);
57 static int _clk_spll_enable(struct clk *clk)
61 reg = __raw_readl(CCM_CSCR);
63 __raw_writel(reg, CCM_CSCR);
65 while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
71 static void _clk_spll_disable(struct clk *clk)
75 reg = __raw_readl(CCM_CSCR);
76 reg &= ~CCM_CSCR_SPEN;
77 __raw_writel(reg, CCM_CSCR);
80 static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
84 reg = __raw_readl(CCM_PCCR0);
86 __raw_writel(reg, CCM_PCCR0);
88 reg = __raw_readl(CCM_PCCR1);
90 __raw_writel(reg, CCM_PCCR1);
94 static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
98 reg = __raw_readl(CCM_PCCR0);
100 __raw_writel(reg, CCM_PCCR0);
102 reg = __raw_readl(CCM_PCCR1);
104 __raw_writel(reg, CCM_PCCR1);
107 static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
111 reg = __raw_readl(CCM_PCCR1);
113 __raw_writel(reg, CCM_PCCR1);
115 reg = __raw_readl(CCM_PCCR0);
117 __raw_writel(reg, CCM_PCCR0);
120 static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
124 reg = __raw_readl(CCM_PCCR1);
126 __raw_writel(reg, CCM_PCCR1);
128 reg = __raw_readl(CCM_PCCR0);
130 __raw_writel(reg, CCM_PCCR0);
133 static int _clk_dma_enable(struct clk *clk)
135 _clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
140 static void _clk_dma_disable(struct clk *clk)
142 _clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
145 static int _clk_rtic_enable(struct clk *clk)
147 _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
152 static void _clk_rtic_disable(struct clk *clk)
154 _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
157 static int _clk_emma_enable(struct clk *clk)
159 _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
164 static void _clk_emma_disable(struct clk *clk)
166 _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
169 static int _clk_slcdc_enable(struct clk *clk)
171 _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
176 static void _clk_slcdc_disable(struct clk *clk)
178 _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
181 static int _clk_fec_enable(struct clk *clk)
183 _clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
188 static void _clk_fec_disable(struct clk *clk)
190 _clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
193 static int _clk_vpu_enable(struct clk *clk)
197 reg = __raw_readl(CCM_PCCR1);
198 reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
199 __raw_writel(reg, CCM_PCCR1);
204 static void _clk_vpu_disable(struct clk *clk)
208 reg = __raw_readl(CCM_PCCR1);
209 reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
210 __raw_writel(reg, CCM_PCCR1);
213 static int _clk_sahara2_enable(struct clk *clk)
215 _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
220 static void _clk_sahara2_disable(struct clk *clk)
222 _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
225 static int _clk_mstick1_enable(struct clk *clk)
227 _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
232 static void _clk_mstick1_disable(struct clk *clk)
234 _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
237 #define CSCR() (__raw_readl(CCM_CSCR))
238 #define PCDR0() (__raw_readl(CCM_PCDR0))
239 #define PCDR1() (__raw_readl(CCM_PCDR1))
241 static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
245 if (clk->parent == parent)
248 if (mx27_revision() >= CHIP_REV_2_0) {
249 if (parent == &mpll_main_clk[0]) {
250 cscr |= CCM_CSCR_ARM_SRC;
252 if (parent == &mpll_main_clk[1])
253 cscr &= ~CCM_CSCR_ARM_SRC;
257 __raw_writel(cscr, CCM_CSCR);
261 clk->parent = parent;
265 static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
268 unsigned long parent_rate;
270 parent_rate = clk_get_rate(clk->parent);
272 div = parent_rate / rate;
273 if (parent_rate % rate)
279 return parent_rate / div;
282 static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
286 unsigned long parent_rate;
288 parent_rate = clk_get_rate(clk->parent);
290 div = parent_rate / rate;
292 if (div > 4 || div < 1 || ((parent_rate / div) != rate))
297 reg = __raw_readl(CCM_CSCR);
298 if (mx27_revision() >= CHIP_REV_2_0) {
299 reg &= ~CCM_CSCR_ARM_MASK;
300 reg |= div << CCM_CSCR_ARM_OFFSET;
302 __raw_writel(reg | 0x80000000, CCM_CSCR);
304 printk(KERN_ERR "Cant set CPU frequency!\n");
310 static unsigned long _clk_perclkx_round_rate(struct clk *clk,
314 unsigned long parent_rate;
316 parent_rate = clk_get_rate(clk->parent);
318 div = parent_rate / rate;
319 if (parent_rate % rate)
325 return parent_rate / div;
328 static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
332 unsigned long parent_rate;
334 parent_rate = clk_get_rate(clk->parent);
336 if (clk->id < 0 || clk->id > 3)
339 div = parent_rate / rate;
340 if (div > 64 || div < 1 || ((parent_rate / div) != rate))
345 __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
347 reg |= div << (clk->id << 3);
348 __raw_writel(reg, CCM_PCDR1);
353 static unsigned long _clk_usb_recalc(struct clk *clk)
355 unsigned long usb_pdf;
356 unsigned long parent_rate;
358 parent_rate = clk_get_rate(clk->parent);
360 usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
362 return parent_rate / (usb_pdf + 1U);
365 static unsigned long _clk_ssi1_recalc(struct clk *clk)
367 unsigned long ssi1_pdf;
368 unsigned long parent_rate;
370 parent_rate = clk_get_rate(clk->parent);
372 ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
373 CCM_PCDR0_SSI1BAUDDIV_OFFSET;
375 if (mx27_revision() >= CHIP_REV_2_0)
378 ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf;
380 return 2UL * parent_rate / ssi1_pdf;
383 static unsigned long _clk_ssi2_recalc(struct clk *clk)
385 unsigned long ssi2_pdf;
386 unsigned long parent_rate;
388 parent_rate = clk_get_rate(clk->parent);
390 ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
391 CCM_PCDR0_SSI2BAUDDIV_OFFSET;
393 if (mx27_revision() >= CHIP_REV_2_0)
396 ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf;
398 return 2UL * parent_rate / ssi2_pdf;
401 static unsigned long _clk_nfc_recalc(struct clk *clk)
403 unsigned long nfc_pdf;
404 unsigned long parent_rate;
406 parent_rate = clk_get_rate(clk->parent);
408 if (mx27_revision() >= CHIP_REV_2_0) {
410 (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
411 CCM_PCDR0_NFCDIV2_OFFSET;
414 (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
415 CCM_PCDR0_NFCDIV_OFFSET;
418 return parent_rate / (nfc_pdf + 1);
421 static unsigned long _clk_vpu_recalc(struct clk *clk)
423 unsigned long vpu_pdf;
424 unsigned long parent_rate;
426 parent_rate = clk_get_rate(clk->parent);
428 if (mx27_revision() >= CHIP_REV_2_0) {
430 (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
431 CCM_PCDR0_VPUDIV2_OFFSET;
435 (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
436 CCM_PCDR0_VPUDIV_OFFSET;
437 vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
439 return 2UL * parent_rate / vpu_pdf;
442 static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
444 return clk->parent->round_rate(clk->parent, rate);
447 static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
449 return clk->parent->set_rate(clk->parent, rate);
453 static unsigned long external_high_reference = 26000000;
455 static unsigned long get_high_reference_clock_rate(struct clk *clk)
457 return external_high_reference;
461 * the high frequency external clock reference
462 * Default case is 26MHz. Could be changed at runtime
463 * with a call to change_external_high_reference()
465 static struct clk ckih_clk = {
467 .get_rate = get_high_reference_clock_rate,
471 static unsigned long external_low_reference = 32768;
473 static unsigned long get_low_reference_clock_rate(struct clk *clk)
475 return external_low_reference;
479 * the low frequency external clock reference
480 * Default case is 32.768kHz Could be changed at runtime
481 * with a call to change_external_low_reference()
483 static struct clk ckil_clk = {
485 .get_rate = get_low_reference_clock_rate,
488 static unsigned long get_mpll_clk(struct clk *clk)
491 unsigned long ref_clk;
492 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
493 unsigned long long temp;
495 ref_clk = clk_get_rate(clk->parent);
497 reg = __raw_readl(CCM_MPCTL0);
498 pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
499 mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
500 mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
501 mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
503 mfi = (mfi <= 5) ? 5 : mfi;
504 temp = 2LL * ref_clk * mfn;
505 do_div(temp, mfd + 1);
506 temp = 2LL * ref_clk * mfi + temp;
507 do_div(temp, pdf + 1);
509 return (unsigned long)temp;
512 static struct clk mpll_clk = {
515 .get_rate = get_mpll_clk,
518 static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
520 unsigned long parent_rate;
522 parent_rate = clk_get_rate(clk->parent);
525 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
526 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
529 if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
530 return 2UL * parent_rate / 3UL;
535 static struct clk mpll_main_clk[] = {
537 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
538 * It provide the clock source whose rate is same as MPLL
543 .get_rate = _clk_mpll_main_get_rate
545 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
546 * It provide the clock source whose rate is same MPLL * 2/3
551 .get_rate = _clk_mpll_main_get_rate
555 static unsigned long get_spll_clk(struct clk *clk)
558 unsigned long ref_clk;
559 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
560 unsigned long long temp;
562 ref_clk = clk_get_rate(clk->parent);
564 reg = __raw_readl(CCM_SPCTL0);
565 /*TODO: This is TO2 Bug */
566 if (mx27_revision() >= CHIP_REV_2_0)
567 __raw_writel(reg, CCM_SPCTL0);
569 pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
570 mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
571 mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
572 mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
574 mfi = (mfi <= 5) ? 5 : mfi;
575 temp = 2LL * ref_clk * mfn;
576 do_div(temp, mfd + 1);
577 temp = 2LL * ref_clk * mfi + temp;
578 do_div(temp, pdf + 1);
580 return (unsigned long)temp;
583 static struct clk spll_clk = {
586 .get_rate = get_spll_clk,
587 .enable = _clk_spll_enable,
588 .disable = _clk_spll_disable,
591 static unsigned long get_cpu_clk(struct clk *clk)
596 if (mx27_revision() >= CHIP_REV_2_0)
597 div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
599 div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
601 rate = clk_get_rate(clk->parent);
602 return rate / (div + 1);
605 static struct clk cpu_clk = {
607 .parent = &mpll_main_clk[1],
608 .set_parent = _clk_cpu_set_parent,
609 .round_rate = _clk_cpu_round_rate,
610 .get_rate = get_cpu_clk,
611 .set_rate = _clk_cpu_set_rate,
614 static unsigned long get_ahb_clk(struct clk *clk)
617 unsigned long bclk_pdf;
619 if (mx27_revision() >= CHIP_REV_2_0)
620 bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
621 >> CCM_CSCR_AHB_OFFSET;
623 bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
624 >> CCM_CSCR_BCLK_OFFSET;
626 rate = clk_get_rate(clk->parent);
627 return rate / (bclk_pdf + 1);
630 static struct clk ahb_clk = {
632 .parent = &mpll_main_clk[1],
633 .get_rate = get_ahb_clk,
636 static unsigned long get_ipg_clk(struct clk *clk)
639 unsigned long ipg_pdf;
641 if (mx27_revision() >= CHIP_REV_2_0)
642 return clk_get_rate(clk->parent);
644 ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
646 rate = clk_get_rate(clk->parent);
647 return rate / (ipg_pdf + 1);
650 static struct clk ipg_clk = {
653 .get_rate = get_ipg_clk,
656 static unsigned long _clk_perclkx_recalc(struct clk *clk)
658 unsigned long perclk_pdf;
659 unsigned long parent_rate;
661 parent_rate = clk_get_rate(clk->parent);
663 if (clk->id < 0 || clk->id > 3)
666 perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
668 return parent_rate / (perclk_pdf + 1);
671 static struct clk per_clk[] = {
675 .parent = &mpll_main_clk[1],
676 .get_rate = _clk_perclkx_recalc,
677 .enable = _clk_enable,
678 .enable_reg = CCM_PCCR1,
679 .enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
680 .disable = _clk_disable,
684 .parent = &mpll_main_clk[1],
685 .get_rate = _clk_perclkx_recalc,
686 .enable = _clk_enable,
687 .enable_reg = CCM_PCCR1,
688 .enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
689 .disable = _clk_disable,
693 .parent = &mpll_main_clk[1],
694 .round_rate = _clk_perclkx_round_rate,
695 .set_rate = _clk_perclkx_set_rate,
696 .get_rate = _clk_perclkx_recalc,
697 .enable = _clk_enable,
698 .enable_reg = CCM_PCCR1,
699 .enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
700 .disable = _clk_disable,
704 .parent = &mpll_main_clk[1],
705 .round_rate = _clk_perclkx_round_rate,
706 .set_rate = _clk_perclkx_set_rate,
707 .get_rate = _clk_perclkx_recalc,
708 .enable = _clk_enable,
709 .enable_reg = CCM_PCCR1,
710 .enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
711 .disable = _clk_disable,
715 struct clk uart1_clk[] = {
719 .parent = &per_clk[0],
720 .secondary = &uart1_clk[1],
722 .name = "uart_ipg_clk",
725 .enable = _clk_enable,
726 .enable_reg = CCM_PCCR1,
727 .enable_shift = CCM_PCCR1_UART1_OFFSET,
728 .disable = _clk_disable,
732 struct clk uart2_clk[] = {
736 .parent = &per_clk[0],
737 .secondary = &uart2_clk[1],
739 .name = "uart_ipg_clk",
742 .enable = _clk_enable,
743 .enable_reg = CCM_PCCR1,
744 .enable_shift = CCM_PCCR1_UART2_OFFSET,
745 .disable = _clk_disable,
749 struct clk uart3_clk[] = {
753 .parent = &per_clk[0],
754 .secondary = &uart3_clk[1],
756 .name = "uart_ipg_clk",
759 .enable = _clk_enable,
760 .enable_reg = CCM_PCCR1,
761 .enable_shift = CCM_PCCR1_UART3_OFFSET,
762 .disable = _clk_disable,
766 struct clk uart4_clk[] = {
770 .parent = &per_clk[0],
771 .secondary = &uart4_clk[1],
773 .name = "uart_ipg_clk",
776 .enable = _clk_enable,
777 .enable_reg = CCM_PCCR1,
778 .enable_shift = CCM_PCCR1_UART4_OFFSET,
779 .disable = _clk_disable,
783 struct clk uart5_clk[] = {
787 .parent = &per_clk[0],
788 .secondary = &uart5_clk[1],
790 .name = "uart_ipg_clk",
793 .enable = _clk_enable,
794 .enable_reg = CCM_PCCR1,
795 .enable_shift = CCM_PCCR1_UART5_OFFSET,
796 .disable = _clk_disable,
800 struct clk uart6_clk[] = {
804 .parent = &per_clk[0],
805 .secondary = &uart6_clk[1],
807 .name = "uart_ipg_clk",
810 .enable = _clk_enable,
811 .enable_reg = CCM_PCCR1,
812 .enable_shift = CCM_PCCR1_UART6_OFFSET,
813 .disable = _clk_disable,
817 static struct clk gpt1_clk[] = {
821 .parent = &per_clk[0],
822 .secondary = &gpt1_clk[1],
824 .name = "gpt_ipg_clk",
827 .enable = _clk_enable,
828 .enable_reg = CCM_PCCR0,
829 .enable_shift = CCM_PCCR0_GPT1_OFFSET,
830 .disable = _clk_disable,
834 static struct clk gpt2_clk[] = {
838 .parent = &per_clk[0],
839 .secondary = &gpt2_clk[1],
841 .name = "gpt_ipg_clk",
844 .enable = _clk_enable,
845 .enable_reg = CCM_PCCR0,
846 .enable_shift = CCM_PCCR0_GPT2_OFFSET,
847 .disable = _clk_disable,
851 static struct clk gpt3_clk[] = {
855 .parent = &per_clk[0],
856 .secondary = &gpt3_clk[1],
858 .name = "gpt_ipg_clk",
861 .enable = _clk_enable,
862 .enable_reg = CCM_PCCR0,
863 .enable_shift = CCM_PCCR0_GPT3_OFFSET,
864 .disable = _clk_disable,
868 static struct clk gpt4_clk[] = {
872 .parent = &per_clk[0],
873 .secondary = &gpt4_clk[1],
875 .name = "gpt_ipg_clk",
878 .enable = _clk_enable,
879 .enable_reg = CCM_PCCR0,
880 .enable_shift = CCM_PCCR0_GPT4_OFFSET,
881 .disable = _clk_disable,
885 static struct clk gpt5_clk[] = {
889 .parent = &per_clk[0],
890 .secondary = &gpt5_clk[1],
892 .name = "gpt_ipg_clk",
895 .enable = _clk_enable,
896 .enable_reg = CCM_PCCR0,
897 .enable_shift = CCM_PCCR0_GPT5_OFFSET,
898 .disable = _clk_disable,
902 static struct clk gpt6_clk[] = {
906 .parent = &per_clk[0],
907 .secondary = &gpt6_clk[1],
909 .name = "gpt_ipg_clk",
912 .enable = _clk_enable,
913 .enable_reg = CCM_PCCR0,
914 .enable_shift = CCM_PCCR0_GPT6_OFFSET,
915 .disable = _clk_disable,
919 static struct clk pwm_clk[] = {
922 .parent = &per_clk[0],
923 .secondary = &pwm_clk[1],
927 .enable = _clk_enable,
928 .enable_reg = CCM_PCCR0,
929 .enable_shift = CCM_PCCR0_PWM_OFFSET,
930 .disable = _clk_disable,
934 static struct clk sdhc1_clk[] = {
938 .parent = &per_clk[1],
939 .secondary = &sdhc1_clk[1],
941 .name = "sdhc_ipg_clk",
944 .enable = _clk_enable,
945 .enable_reg = CCM_PCCR0,
946 .enable_shift = CCM_PCCR0_SDHC1_OFFSET,
947 .disable = _clk_disable,
951 static struct clk sdhc2_clk[] = {
955 .parent = &per_clk[1],
956 .secondary = &sdhc2_clk[1],
958 .name = "sdhc_ipg_clk",
961 .enable = _clk_enable,
962 .enable_reg = CCM_PCCR0,
963 .enable_shift = CCM_PCCR0_SDHC2_OFFSET,
964 .disable = _clk_disable,
968 static struct clk sdhc3_clk[] = {
972 .parent = &per_clk[1],
973 .secondary = &sdhc3_clk[1],
975 .name = "sdhc_ipg_clk",
978 .enable = _clk_enable,
979 .enable_reg = CCM_PCCR0,
980 .enable_shift = CCM_PCCR0_SDHC3_OFFSET,
981 .disable = _clk_disable,
985 static struct clk cspi1_clk[] = {
989 .parent = &per_clk[1],
990 .secondary = &cspi1_clk[1],
992 .name = "cspi_ipg_clk",
995 .enable = _clk_enable,
996 .enable_reg = CCM_PCCR0,
997 .enable_shift = CCM_PCCR0_CSPI1_OFFSET,
998 .disable = _clk_disable,
1002 static struct clk cspi2_clk[] = {
1006 .parent = &per_clk[1],
1007 .secondary = &cspi2_clk[1],
1009 .name = "cspi_ipg_clk",
1012 .enable = _clk_enable,
1013 .enable_reg = CCM_PCCR0,
1014 .enable_shift = CCM_PCCR0_CSPI2_OFFSET,
1015 .disable = _clk_disable,
1019 static struct clk cspi3_clk[] = {
1023 .parent = &per_clk[1],
1024 .secondary = &cspi3_clk[1],
1026 .name = "cspi_ipg_clk",
1029 .enable = _clk_enable,
1030 .enable_reg = CCM_PCCR0,
1031 .enable_shift = CCM_PCCR0_CSPI3_OFFSET,
1032 .disable = _clk_disable,
1036 static struct clk lcdc_clk[] = {
1039 .parent = &per_clk[2],
1040 .secondary = &lcdc_clk[1],
1041 .round_rate = _clk_parent_round_rate,
1042 .set_rate = _clk_parent_set_rate,
1044 .name = "lcdc_ipg_clk",
1046 .secondary = &lcdc_clk[2],
1047 .enable = _clk_enable,
1048 .enable_reg = CCM_PCCR0,
1049 .enable_shift = CCM_PCCR0_LCDC_OFFSET,
1050 .disable = _clk_disable,
1052 .name = "lcdc_ahb_clk",
1054 .enable = _clk_enable,
1055 .enable_reg = CCM_PCCR1,
1056 .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
1057 .disable = _clk_disable,
1061 static struct clk csi_clk[] = {
1063 .name = "csi_perclk",
1064 .parent = &per_clk[3],
1065 .secondary = &csi_clk[1],
1066 .round_rate = _clk_parent_round_rate,
1067 .set_rate = _clk_parent_set_rate,
1069 .name = "csi_ahb_clk",
1071 .enable = _clk_enable,
1072 .enable_reg = CCM_PCCR1,
1073 .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
1074 .disable = _clk_disable,
1078 static struct clk usb_clk[] = {
1081 .parent = &spll_clk,
1082 .get_rate = _clk_usb_recalc,
1083 .enable = _clk_enable,
1084 .enable_reg = CCM_PCCR1,
1085 .enable_shift = CCM_PCCR1_USBOTG_OFFSET,
1086 .disable = _clk_disable,
1088 .name = "usb_ahb_clk",
1090 .enable = _clk_enable,
1091 .enable_reg = CCM_PCCR1,
1092 .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
1093 .disable = _clk_disable,
1097 static struct clk ssi1_clk[] = {
1101 .parent = &mpll_main_clk[1],
1102 .secondary = &ssi1_clk[1],
1103 .get_rate = _clk_ssi1_recalc,
1104 .enable = _clk_enable,
1105 .enable_reg = CCM_PCCR1,
1106 .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
1107 .disable = _clk_disable,
1109 .name = "ssi_ipg_clk",
1112 .enable = _clk_enable,
1113 .enable_reg = CCM_PCCR0,
1114 .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
1115 .disable = _clk_disable,
1119 static struct clk ssi2_clk[] = {
1123 .parent = &mpll_main_clk[1],
1124 .secondary = &ssi2_clk[1],
1125 .get_rate = _clk_ssi2_recalc,
1126 .enable = _clk_enable,
1127 .enable_reg = CCM_PCCR1,
1128 .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
1129 .disable = _clk_disable,
1131 .name = "ssi_ipg_clk",
1134 .enable = _clk_enable,
1135 .enable_reg = CCM_PCCR0,
1136 .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
1137 .disable = _clk_disable,
1141 static struct clk nfc_clk = {
1144 .get_rate = _clk_nfc_recalc,
1145 .enable = _clk_enable,
1146 .enable_reg = CCM_PCCR1,
1147 .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
1148 .disable = _clk_disable,
1151 static struct clk vpu_clk = {
1153 .parent = &mpll_main_clk[1],
1154 .get_rate = _clk_vpu_recalc,
1155 .enable = _clk_vpu_enable,
1156 .disable = _clk_vpu_disable,
1159 static struct clk dma_clk = {
1162 .enable = _clk_dma_enable,
1163 .disable = _clk_dma_disable,
1166 static struct clk rtic_clk = {
1169 .enable = _clk_rtic_enable,
1170 .disable = _clk_rtic_disable,
1173 static struct clk brom_clk = {
1176 .enable = _clk_enable,
1177 .enable_reg = CCM_PCCR1,
1178 .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
1179 .disable = _clk_disable,
1182 static struct clk emma_clk = {
1185 .enable = _clk_emma_enable,
1186 .disable = _clk_emma_disable,
1189 static struct clk slcdc_clk = {
1190 .name = "slcdc_clk",
1192 .enable = _clk_slcdc_enable,
1193 .disable = _clk_slcdc_disable,
1196 static struct clk fec_clk = {
1199 .enable = _clk_fec_enable,
1200 .disable = _clk_fec_disable,
1203 static struct clk emi_clk = {
1206 .enable = _clk_enable,
1207 .enable_reg = CCM_PCCR1,
1208 .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
1209 .disable = _clk_disable,
1212 static struct clk sahara2_clk = {
1213 .name = "sahara_clk",
1215 .enable = _clk_sahara2_enable,
1216 .disable = _clk_sahara2_disable,
1219 static struct clk ata_clk = {
1222 .enable = _clk_enable,
1223 .enable_reg = CCM_PCCR1,
1224 .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
1225 .disable = _clk_disable,
1228 static struct clk mstick1_clk = {
1229 .name = "mstick1_clk",
1231 .enable = _clk_mstick1_enable,
1232 .disable = _clk_mstick1_disable,
1235 static struct clk wdog_clk = {
1238 .enable = _clk_enable,
1239 .enable_reg = CCM_PCCR1,
1240 .enable_shift = CCM_PCCR1_WDT_OFFSET,
1241 .disable = _clk_disable,
1244 static struct clk gpio_clk = {
1247 .enable = _clk_enable,
1248 .enable_reg = CCM_PCCR1,
1249 .enable_shift = CCM_PCCR0_GPIO_OFFSET,
1250 .disable = _clk_disable,
1253 static struct clk i2c_clk[] = {
1258 .enable = _clk_enable,
1259 .enable_reg = CCM_PCCR0,
1260 .enable_shift = CCM_PCCR0_I2C1_OFFSET,
1261 .disable = _clk_disable,
1266 .enable = _clk_enable,
1267 .enable_reg = CCM_PCCR0,
1268 .enable_shift = CCM_PCCR0_I2C2_OFFSET,
1269 .disable = _clk_disable,
1273 static struct clk iim_clk = {
1276 .enable = _clk_enable,
1277 .enable_reg = CCM_PCCR0,
1278 .enable_shift = CCM_PCCR0_IIM_OFFSET,
1279 .disable = _clk_disable,
1282 static struct clk kpp_clk = {
1285 .enable = _clk_enable,
1286 .enable_reg = CCM_PCCR0,
1287 .enable_shift = CCM_PCCR0_KPP_OFFSET,
1288 .disable = _clk_disable,
1291 static struct clk owire_clk = {
1292 .name = "owire_clk",
1294 .enable = _clk_enable,
1295 .enable_reg = CCM_PCCR0,
1296 .enable_shift = CCM_PCCR0_OWIRE_OFFSET,
1297 .disable = _clk_disable,
1300 static struct clk rtc_clk = {
1303 .enable = _clk_enable,
1304 .enable_reg = CCM_PCCR0,
1305 .enable_shift = CCM_PCCR0_RTC_OFFSET,
1306 .disable = _clk_disable,
1309 static struct clk scc_clk = {
1312 .enable = _clk_enable,
1313 .enable_reg = CCM_PCCR0,
1314 .enable_shift = CCM_PCCR0_SCC_OFFSET,
1315 .disable = _clk_disable,
1318 static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
1321 unsigned long parent_rate;
1323 parent_rate = clk_get_rate(clk->parent);
1324 div = parent_rate / rate;
1325 if (parent_rate % rate)
1331 return parent_rate / div;
1334 static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
1338 unsigned long parent_rate;
1340 parent_rate = clk_get_rate(clk->parent);
1342 div = parent_rate / rate;
1344 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
1348 reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
1349 reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
1350 __raw_writel(reg, CCM_PCDR0);
1355 static unsigned long _clk_clko_recalc(struct clk *clk)
1358 unsigned long parent_rate;
1360 parent_rate = clk_get_rate(clk->parent);
1362 div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
1363 CCM_PCDR0_CLKODIV_OFFSET;
1366 return parent_rate / div;
1369 static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
1373 reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
1375 if (parent == &ckil_clk)
1376 reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
1377 else if (parent == &ckih_clk)
1378 reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
1379 else if (parent == mpll_clk.parent)
1380 reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
1381 else if (parent == spll_clk.parent)
1382 reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
1383 else if (parent == &mpll_clk)
1384 reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
1385 else if (parent == &spll_clk)
1386 reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
1387 else if (parent == &cpu_clk)
1388 reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
1389 else if (parent == &ahb_clk)
1390 reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
1391 else if (parent == &ipg_clk)
1392 reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
1393 else if (parent == &per_clk[0])
1394 reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
1395 else if (parent == &per_clk[1])
1396 reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
1397 else if (parent == &per_clk[2])
1398 reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
1399 else if (parent == &per_clk[3])
1400 reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
1401 else if (parent == &ssi1_clk[0])
1402 reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
1403 else if (parent == &ssi2_clk[0])
1404 reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
1405 else if (parent == &nfc_clk)
1406 reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
1407 else if (parent == &mstick1_clk)
1408 reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
1409 else if (parent == &vpu_clk)
1410 reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
1411 else if (parent == &usb_clk[0])
1412 reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
1416 __raw_writel(reg, CCM_CCSR);
1421 static int _clk_clko_enable(struct clk *clk)
1425 reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
1426 __raw_writel(reg, CCM_PCDR0);
1431 static void _clk_clko_disable(struct clk *clk)
1435 reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
1436 __raw_writel(reg, CCM_PCDR0);
1439 static struct clk clko_clk = {
1441 .get_rate = _clk_clko_recalc,
1442 .set_rate = _clk_clko_set_rate,
1443 .round_rate = _clk_clko_round_rate,
1444 .set_parent = _clk_clko_set_parent,
1445 .enable = _clk_clko_enable,
1446 .disable = _clk_clko_disable,
1449 static struct clk *mxc_clks[] = {
1536 void __init change_external_low_reference(unsigned long new_ref)
1538 external_low_reference = new_ref;
1541 unsigned long __init clk_early_get_timer_rate(void)
1543 return clk_get_rate(&per_clk[0]);
1546 static void __init probe_mxc_clocks(void)
1550 if (mx27_revision() >= CHIP_REV_2_0) {
1551 if (CSCR() & 0x8000)
1552 cpu_clk.parent = &mpll_main_clk[0];
1554 if (!(CSCR() & 0x00800000))
1555 ssi2_clk[0].parent = &spll_clk;
1557 if (!(CSCR() & 0x00400000))
1558 ssi1_clk[0].parent = &spll_clk;
1560 if (!(CSCR() & 0x00200000))
1561 vpu_clk.parent = &spll_clk;
1563 cpu_clk.parent = &mpll_clk;
1564 cpu_clk.set_parent = NULL;
1565 cpu_clk.round_rate = NULL;
1566 cpu_clk.set_rate = NULL;
1567 ahb_clk.parent = &mpll_clk;
1569 for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
1570 per_clk[i].parent = &mpll_clk;
1572 ssi1_clk[0].parent = &mpll_clk;
1573 ssi2_clk[0].parent = &mpll_clk;
1575 vpu_clk.parent = &mpll_clk;
1580 * must be called very early to get information about the
1581 * available clock rate when the timer framework starts
1583 int __init mxc_clocks_init(unsigned long fref)
1588 external_high_reference = fref;
1590 /* detect clock reference for both system PLL */
1592 if (cscr & CCM_CSCR_MCU)
1593 mpll_clk.parent = &ckih_clk;
1595 mpll_clk.parent = &ckil_clk;
1597 if (cscr & CCM_CSCR_SP)
1598 spll_clk.parent = &ckih_clk;
1600 spll_clk.parent = &ckil_clk;
1604 per_clk[0].enable(&per_clk[0]);
1605 gpt1_clk[1].enable(&gpt1_clk[1]);
1607 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1608 clk_register(*clkp);
1610 /* Turn off all possible clocks */
1611 __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
1612 __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
1614 spll_clk.disable(&spll_clk);
1616 /* This will propagate to all children and init all the clock rates */
1618 clk_enable(&emi_clk);
1619 clk_enable(&gpio_clk);
1620 clk_enable(&iim_clk);
1621 clk_enable(&gpt1_clk[0]);
1622 #ifdef CONFIG_DEBUG_LL_CONSOLE
1623 clk_enable(&uart1_clk[0]);