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)
489 return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
490 clk_get_rate(clk->parent));
493 static struct clk mpll_clk = {
496 .get_rate = get_mpll_clk,
499 static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
501 unsigned long parent_rate;
503 parent_rate = clk_get_rate(clk->parent);
506 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
507 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
510 if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
511 return 2UL * parent_rate / 3UL;
516 static struct clk mpll_main_clk[] = {
518 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
519 * It provide the clock source whose rate is same as MPLL
524 .get_rate = _clk_mpll_main_get_rate
526 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
527 * It provide the clock source whose rate is same MPLL * 2/3
532 .get_rate = _clk_mpll_main_get_rate
536 static unsigned long get_spll_clk(struct clk *clk)
539 unsigned long ref_clk;
541 ref_clk = clk_get_rate(clk->parent);
543 reg = __raw_readl(CCM_SPCTL0);
545 /* On TO2 we have to write the value back. Otherwise we
546 * read 0 from this register the next time.
548 if (mx27_revision() >= CHIP_REV_2_0)
549 __raw_writel(reg, CCM_SPCTL0);
551 return mxc_decode_pll(reg, ref_clk);
554 static struct clk spll_clk = {
557 .get_rate = get_spll_clk,
558 .enable = _clk_spll_enable,
559 .disable = _clk_spll_disable,
562 static unsigned long get_cpu_clk(struct clk *clk)
567 if (mx27_revision() >= CHIP_REV_2_0)
568 div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
570 div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
572 rate = clk_get_rate(clk->parent);
573 return rate / (div + 1);
576 static struct clk cpu_clk = {
578 .parent = &mpll_main_clk[1],
579 .set_parent = _clk_cpu_set_parent,
580 .round_rate = _clk_cpu_round_rate,
581 .get_rate = get_cpu_clk,
582 .set_rate = _clk_cpu_set_rate,
585 static unsigned long get_ahb_clk(struct clk *clk)
588 unsigned long bclk_pdf;
590 if (mx27_revision() >= CHIP_REV_2_0)
591 bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
592 >> CCM_CSCR_AHB_OFFSET;
594 bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
595 >> CCM_CSCR_BCLK_OFFSET;
597 rate = clk_get_rate(clk->parent);
598 return rate / (bclk_pdf + 1);
601 static struct clk ahb_clk = {
603 .parent = &mpll_main_clk[1],
604 .get_rate = get_ahb_clk,
607 static unsigned long get_ipg_clk(struct clk *clk)
610 unsigned long ipg_pdf;
612 if (mx27_revision() >= CHIP_REV_2_0)
613 return clk_get_rate(clk->parent);
615 ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
617 rate = clk_get_rate(clk->parent);
618 return rate / (ipg_pdf + 1);
621 static struct clk ipg_clk = {
624 .get_rate = get_ipg_clk,
627 static unsigned long _clk_perclkx_recalc(struct clk *clk)
629 unsigned long perclk_pdf;
630 unsigned long parent_rate;
632 parent_rate = clk_get_rate(clk->parent);
634 if (clk->id < 0 || clk->id > 3)
637 perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
639 return parent_rate / (perclk_pdf + 1);
642 static struct clk per_clk[] = {
646 .parent = &mpll_main_clk[1],
647 .get_rate = _clk_perclkx_recalc,
648 .enable = _clk_enable,
649 .enable_reg = CCM_PCCR1,
650 .enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
651 .disable = _clk_disable,
655 .parent = &mpll_main_clk[1],
656 .get_rate = _clk_perclkx_recalc,
657 .enable = _clk_enable,
658 .enable_reg = CCM_PCCR1,
659 .enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
660 .disable = _clk_disable,
664 .parent = &mpll_main_clk[1],
665 .round_rate = _clk_perclkx_round_rate,
666 .set_rate = _clk_perclkx_set_rate,
667 .get_rate = _clk_perclkx_recalc,
668 .enable = _clk_enable,
669 .enable_reg = CCM_PCCR1,
670 .enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
671 .disable = _clk_disable,
675 .parent = &mpll_main_clk[1],
676 .round_rate = _clk_perclkx_round_rate,
677 .set_rate = _clk_perclkx_set_rate,
678 .get_rate = _clk_perclkx_recalc,
679 .enable = _clk_enable,
680 .enable_reg = CCM_PCCR1,
681 .enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
682 .disable = _clk_disable,
686 struct clk uart1_clk[] = {
690 .parent = &per_clk[0],
691 .secondary = &uart1_clk[1],
693 .name = "uart_ipg_clk",
696 .enable = _clk_enable,
697 .enable_reg = CCM_PCCR1,
698 .enable_shift = CCM_PCCR1_UART1_OFFSET,
699 .disable = _clk_disable,
703 struct clk uart2_clk[] = {
707 .parent = &per_clk[0],
708 .secondary = &uart2_clk[1],
710 .name = "uart_ipg_clk",
713 .enable = _clk_enable,
714 .enable_reg = CCM_PCCR1,
715 .enable_shift = CCM_PCCR1_UART2_OFFSET,
716 .disable = _clk_disable,
720 struct clk uart3_clk[] = {
724 .parent = &per_clk[0],
725 .secondary = &uart3_clk[1],
727 .name = "uart_ipg_clk",
730 .enable = _clk_enable,
731 .enable_reg = CCM_PCCR1,
732 .enable_shift = CCM_PCCR1_UART3_OFFSET,
733 .disable = _clk_disable,
737 struct clk uart4_clk[] = {
741 .parent = &per_clk[0],
742 .secondary = &uart4_clk[1],
744 .name = "uart_ipg_clk",
747 .enable = _clk_enable,
748 .enable_reg = CCM_PCCR1,
749 .enable_shift = CCM_PCCR1_UART4_OFFSET,
750 .disable = _clk_disable,
754 struct clk uart5_clk[] = {
758 .parent = &per_clk[0],
759 .secondary = &uart5_clk[1],
761 .name = "uart_ipg_clk",
764 .enable = _clk_enable,
765 .enable_reg = CCM_PCCR1,
766 .enable_shift = CCM_PCCR1_UART5_OFFSET,
767 .disable = _clk_disable,
771 struct clk uart6_clk[] = {
775 .parent = &per_clk[0],
776 .secondary = &uart6_clk[1],
778 .name = "uart_ipg_clk",
781 .enable = _clk_enable,
782 .enable_reg = CCM_PCCR1,
783 .enable_shift = CCM_PCCR1_UART6_OFFSET,
784 .disable = _clk_disable,
788 static struct clk gpt1_clk[] = {
792 .parent = &per_clk[0],
793 .secondary = &gpt1_clk[1],
795 .name = "gpt_ipg_clk",
798 .enable = _clk_enable,
799 .enable_reg = CCM_PCCR0,
800 .enable_shift = CCM_PCCR0_GPT1_OFFSET,
801 .disable = _clk_disable,
805 static struct clk gpt2_clk[] = {
809 .parent = &per_clk[0],
810 .secondary = &gpt2_clk[1],
812 .name = "gpt_ipg_clk",
815 .enable = _clk_enable,
816 .enable_reg = CCM_PCCR0,
817 .enable_shift = CCM_PCCR0_GPT2_OFFSET,
818 .disable = _clk_disable,
822 static struct clk gpt3_clk[] = {
826 .parent = &per_clk[0],
827 .secondary = &gpt3_clk[1],
829 .name = "gpt_ipg_clk",
832 .enable = _clk_enable,
833 .enable_reg = CCM_PCCR0,
834 .enable_shift = CCM_PCCR0_GPT3_OFFSET,
835 .disable = _clk_disable,
839 static struct clk gpt4_clk[] = {
843 .parent = &per_clk[0],
844 .secondary = &gpt4_clk[1],
846 .name = "gpt_ipg_clk",
849 .enable = _clk_enable,
850 .enable_reg = CCM_PCCR0,
851 .enable_shift = CCM_PCCR0_GPT4_OFFSET,
852 .disable = _clk_disable,
856 static struct clk gpt5_clk[] = {
860 .parent = &per_clk[0],
861 .secondary = &gpt5_clk[1],
863 .name = "gpt_ipg_clk",
866 .enable = _clk_enable,
867 .enable_reg = CCM_PCCR0,
868 .enable_shift = CCM_PCCR0_GPT5_OFFSET,
869 .disable = _clk_disable,
873 static struct clk gpt6_clk[] = {
877 .parent = &per_clk[0],
878 .secondary = &gpt6_clk[1],
880 .name = "gpt_ipg_clk",
883 .enable = _clk_enable,
884 .enable_reg = CCM_PCCR0,
885 .enable_shift = CCM_PCCR0_GPT6_OFFSET,
886 .disable = _clk_disable,
890 static struct clk pwm_clk[] = {
893 .parent = &per_clk[0],
894 .secondary = &pwm_clk[1],
898 .enable = _clk_enable,
899 .enable_reg = CCM_PCCR0,
900 .enable_shift = CCM_PCCR0_PWM_OFFSET,
901 .disable = _clk_disable,
905 static struct clk sdhc1_clk[] = {
909 .parent = &per_clk[1],
910 .secondary = &sdhc1_clk[1],
912 .name = "sdhc_ipg_clk",
915 .enable = _clk_enable,
916 .enable_reg = CCM_PCCR0,
917 .enable_shift = CCM_PCCR0_SDHC1_OFFSET,
918 .disable = _clk_disable,
922 static struct clk sdhc2_clk[] = {
926 .parent = &per_clk[1],
927 .secondary = &sdhc2_clk[1],
929 .name = "sdhc_ipg_clk",
932 .enable = _clk_enable,
933 .enable_reg = CCM_PCCR0,
934 .enable_shift = CCM_PCCR0_SDHC2_OFFSET,
935 .disable = _clk_disable,
939 static struct clk sdhc3_clk[] = {
943 .parent = &per_clk[1],
944 .secondary = &sdhc3_clk[1],
946 .name = "sdhc_ipg_clk",
949 .enable = _clk_enable,
950 .enable_reg = CCM_PCCR0,
951 .enable_shift = CCM_PCCR0_SDHC3_OFFSET,
952 .disable = _clk_disable,
956 static struct clk cspi1_clk[] = {
960 .parent = &per_clk[1],
961 .secondary = &cspi1_clk[1],
963 .name = "cspi_ipg_clk",
966 .enable = _clk_enable,
967 .enable_reg = CCM_PCCR0,
968 .enable_shift = CCM_PCCR0_CSPI1_OFFSET,
969 .disable = _clk_disable,
973 static struct clk cspi2_clk[] = {
977 .parent = &per_clk[1],
978 .secondary = &cspi2_clk[1],
980 .name = "cspi_ipg_clk",
983 .enable = _clk_enable,
984 .enable_reg = CCM_PCCR0,
985 .enable_shift = CCM_PCCR0_CSPI2_OFFSET,
986 .disable = _clk_disable,
990 static struct clk cspi3_clk[] = {
994 .parent = &per_clk[1],
995 .secondary = &cspi3_clk[1],
997 .name = "cspi_ipg_clk",
1000 .enable = _clk_enable,
1001 .enable_reg = CCM_PCCR0,
1002 .enable_shift = CCM_PCCR0_CSPI3_OFFSET,
1003 .disable = _clk_disable,
1007 static struct clk lcdc_clk[] = {
1010 .parent = &per_clk[2],
1011 .secondary = &lcdc_clk[1],
1012 .round_rate = _clk_parent_round_rate,
1013 .set_rate = _clk_parent_set_rate,
1015 .name = "lcdc_ipg_clk",
1017 .secondary = &lcdc_clk[2],
1018 .enable = _clk_enable,
1019 .enable_reg = CCM_PCCR0,
1020 .enable_shift = CCM_PCCR0_LCDC_OFFSET,
1021 .disable = _clk_disable,
1023 .name = "lcdc_ahb_clk",
1025 .enable = _clk_enable,
1026 .enable_reg = CCM_PCCR1,
1027 .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
1028 .disable = _clk_disable,
1032 static struct clk csi_clk[] = {
1034 .name = "csi_perclk",
1035 .parent = &per_clk[3],
1036 .secondary = &csi_clk[1],
1037 .round_rate = _clk_parent_round_rate,
1038 .set_rate = _clk_parent_set_rate,
1040 .name = "csi_ahb_clk",
1042 .enable = _clk_enable,
1043 .enable_reg = CCM_PCCR1,
1044 .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
1045 .disable = _clk_disable,
1049 static struct clk usb_clk[] = {
1052 .parent = &spll_clk,
1053 .get_rate = _clk_usb_recalc,
1054 .enable = _clk_enable,
1055 .enable_reg = CCM_PCCR1,
1056 .enable_shift = CCM_PCCR1_USBOTG_OFFSET,
1057 .disable = _clk_disable,
1059 .name = "usb_ahb_clk",
1061 .enable = _clk_enable,
1062 .enable_reg = CCM_PCCR1,
1063 .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
1064 .disable = _clk_disable,
1068 static struct clk ssi1_clk[] = {
1072 .parent = &mpll_main_clk[1],
1073 .secondary = &ssi1_clk[1],
1074 .get_rate = _clk_ssi1_recalc,
1075 .enable = _clk_enable,
1076 .enable_reg = CCM_PCCR1,
1077 .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
1078 .disable = _clk_disable,
1080 .name = "ssi_ipg_clk",
1083 .enable = _clk_enable,
1084 .enable_reg = CCM_PCCR0,
1085 .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
1086 .disable = _clk_disable,
1090 static struct clk ssi2_clk[] = {
1094 .parent = &mpll_main_clk[1],
1095 .secondary = &ssi2_clk[1],
1096 .get_rate = _clk_ssi2_recalc,
1097 .enable = _clk_enable,
1098 .enable_reg = CCM_PCCR1,
1099 .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
1100 .disable = _clk_disable,
1102 .name = "ssi_ipg_clk",
1105 .enable = _clk_enable,
1106 .enable_reg = CCM_PCCR0,
1107 .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
1108 .disable = _clk_disable,
1112 static struct clk nfc_clk = {
1115 .get_rate = _clk_nfc_recalc,
1116 .enable = _clk_enable,
1117 .enable_reg = CCM_PCCR1,
1118 .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
1119 .disable = _clk_disable,
1122 static struct clk vpu_clk = {
1124 .parent = &mpll_main_clk[1],
1125 .get_rate = _clk_vpu_recalc,
1126 .enable = _clk_vpu_enable,
1127 .disable = _clk_vpu_disable,
1130 static struct clk dma_clk = {
1133 .enable = _clk_dma_enable,
1134 .disable = _clk_dma_disable,
1137 static struct clk rtic_clk = {
1140 .enable = _clk_rtic_enable,
1141 .disable = _clk_rtic_disable,
1144 static struct clk brom_clk = {
1147 .enable = _clk_enable,
1148 .enable_reg = CCM_PCCR1,
1149 .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
1150 .disable = _clk_disable,
1153 static struct clk emma_clk = {
1156 .enable = _clk_emma_enable,
1157 .disable = _clk_emma_disable,
1160 static struct clk slcdc_clk = {
1161 .name = "slcdc_clk",
1163 .enable = _clk_slcdc_enable,
1164 .disable = _clk_slcdc_disable,
1167 static struct clk fec_clk = {
1170 .enable = _clk_fec_enable,
1171 .disable = _clk_fec_disable,
1174 static struct clk emi_clk = {
1177 .enable = _clk_enable,
1178 .enable_reg = CCM_PCCR1,
1179 .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
1180 .disable = _clk_disable,
1183 static struct clk sahara2_clk = {
1184 .name = "sahara_clk",
1186 .enable = _clk_sahara2_enable,
1187 .disable = _clk_sahara2_disable,
1190 static struct clk ata_clk = {
1193 .enable = _clk_enable,
1194 .enable_reg = CCM_PCCR1,
1195 .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
1196 .disable = _clk_disable,
1199 static struct clk mstick1_clk = {
1200 .name = "mstick1_clk",
1202 .enable = _clk_mstick1_enable,
1203 .disable = _clk_mstick1_disable,
1206 static struct clk wdog_clk = {
1209 .enable = _clk_enable,
1210 .enable_reg = CCM_PCCR1,
1211 .enable_shift = CCM_PCCR1_WDT_OFFSET,
1212 .disable = _clk_disable,
1215 static struct clk gpio_clk = {
1218 .enable = _clk_enable,
1219 .enable_reg = CCM_PCCR1,
1220 .enable_shift = CCM_PCCR0_GPIO_OFFSET,
1221 .disable = _clk_disable,
1224 static struct clk i2c_clk[] = {
1229 .enable = _clk_enable,
1230 .enable_reg = CCM_PCCR0,
1231 .enable_shift = CCM_PCCR0_I2C1_OFFSET,
1232 .disable = _clk_disable,
1237 .enable = _clk_enable,
1238 .enable_reg = CCM_PCCR0,
1239 .enable_shift = CCM_PCCR0_I2C2_OFFSET,
1240 .disable = _clk_disable,
1244 static struct clk iim_clk = {
1247 .enable = _clk_enable,
1248 .enable_reg = CCM_PCCR0,
1249 .enable_shift = CCM_PCCR0_IIM_OFFSET,
1250 .disable = _clk_disable,
1253 static struct clk kpp_clk = {
1256 .enable = _clk_enable,
1257 .enable_reg = CCM_PCCR0,
1258 .enable_shift = CCM_PCCR0_KPP_OFFSET,
1259 .disable = _clk_disable,
1262 static struct clk owire_clk = {
1263 .name = "owire_clk",
1265 .enable = _clk_enable,
1266 .enable_reg = CCM_PCCR0,
1267 .enable_shift = CCM_PCCR0_OWIRE_OFFSET,
1268 .disable = _clk_disable,
1271 static struct clk rtc_clk = {
1274 .enable = _clk_enable,
1275 .enable_reg = CCM_PCCR0,
1276 .enable_shift = CCM_PCCR0_RTC_OFFSET,
1277 .disable = _clk_disable,
1280 static struct clk scc_clk = {
1283 .enable = _clk_enable,
1284 .enable_reg = CCM_PCCR0,
1285 .enable_shift = CCM_PCCR0_SCC_OFFSET,
1286 .disable = _clk_disable,
1289 static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
1292 unsigned long parent_rate;
1294 parent_rate = clk_get_rate(clk->parent);
1295 div = parent_rate / rate;
1296 if (parent_rate % rate)
1302 return parent_rate / div;
1305 static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
1309 unsigned long parent_rate;
1311 parent_rate = clk_get_rate(clk->parent);
1313 div = parent_rate / rate;
1315 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
1319 reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
1320 reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
1321 __raw_writel(reg, CCM_PCDR0);
1326 static unsigned long _clk_clko_recalc(struct clk *clk)
1329 unsigned long parent_rate;
1331 parent_rate = clk_get_rate(clk->parent);
1333 div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
1334 CCM_PCDR0_CLKODIV_OFFSET;
1337 return parent_rate / div;
1340 static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
1344 reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
1346 if (parent == &ckil_clk)
1347 reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
1348 else if (parent == &ckih_clk)
1349 reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
1350 else if (parent == mpll_clk.parent)
1351 reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
1352 else if (parent == spll_clk.parent)
1353 reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
1354 else if (parent == &mpll_clk)
1355 reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
1356 else if (parent == &spll_clk)
1357 reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
1358 else if (parent == &cpu_clk)
1359 reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
1360 else if (parent == &ahb_clk)
1361 reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
1362 else if (parent == &ipg_clk)
1363 reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
1364 else if (parent == &per_clk[0])
1365 reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
1366 else if (parent == &per_clk[1])
1367 reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
1368 else if (parent == &per_clk[2])
1369 reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
1370 else if (parent == &per_clk[3])
1371 reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
1372 else if (parent == &ssi1_clk[0])
1373 reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
1374 else if (parent == &ssi2_clk[0])
1375 reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
1376 else if (parent == &nfc_clk)
1377 reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
1378 else if (parent == &mstick1_clk)
1379 reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
1380 else if (parent == &vpu_clk)
1381 reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
1382 else if (parent == &usb_clk[0])
1383 reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
1387 __raw_writel(reg, CCM_CCSR);
1392 static int _clk_clko_enable(struct clk *clk)
1396 reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
1397 __raw_writel(reg, CCM_PCDR0);
1402 static void _clk_clko_disable(struct clk *clk)
1406 reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
1407 __raw_writel(reg, CCM_PCDR0);
1410 static struct clk clko_clk = {
1412 .get_rate = _clk_clko_recalc,
1413 .set_rate = _clk_clko_set_rate,
1414 .round_rate = _clk_clko_round_rate,
1415 .set_parent = _clk_clko_set_parent,
1416 .enable = _clk_clko_enable,
1417 .disable = _clk_clko_disable,
1420 static struct clk *mxc_clks[] = {
1507 void __init change_external_low_reference(unsigned long new_ref)
1509 external_low_reference = new_ref;
1512 unsigned long __init clk_early_get_timer_rate(void)
1514 return clk_get_rate(&per_clk[0]);
1517 static void __init probe_mxc_clocks(void)
1521 if (mx27_revision() >= CHIP_REV_2_0) {
1522 if (CSCR() & 0x8000)
1523 cpu_clk.parent = &mpll_main_clk[0];
1525 if (!(CSCR() & 0x00800000))
1526 ssi2_clk[0].parent = &spll_clk;
1528 if (!(CSCR() & 0x00400000))
1529 ssi1_clk[0].parent = &spll_clk;
1531 if (!(CSCR() & 0x00200000))
1532 vpu_clk.parent = &spll_clk;
1534 cpu_clk.parent = &mpll_clk;
1535 cpu_clk.set_parent = NULL;
1536 cpu_clk.round_rate = NULL;
1537 cpu_clk.set_rate = NULL;
1538 ahb_clk.parent = &mpll_clk;
1540 for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
1541 per_clk[i].parent = &mpll_clk;
1543 ssi1_clk[0].parent = &mpll_clk;
1544 ssi2_clk[0].parent = &mpll_clk;
1546 vpu_clk.parent = &mpll_clk;
1551 * must be called very early to get information about the
1552 * available clock rate when the timer framework starts
1554 int __init mxc_clocks_init(unsigned long fref)
1559 external_high_reference = fref;
1561 /* detect clock reference for both system PLL */
1563 if (cscr & CCM_CSCR_MCU)
1564 mpll_clk.parent = &ckih_clk;
1566 mpll_clk.parent = &ckil_clk;
1568 if (cscr & CCM_CSCR_SP)
1569 spll_clk.parent = &ckih_clk;
1571 spll_clk.parent = &ckil_clk;
1575 per_clk[0].enable(&per_clk[0]);
1576 gpt1_clk[1].enable(&gpt1_clk[1]);
1578 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1579 clk_register(*clkp);
1581 /* Turn off all possible clocks */
1582 __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
1583 __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
1585 spll_clk.disable(&spll_clk);
1587 /* This will propagate to all children and init all the clock rates */
1589 clk_enable(&emi_clk);
1590 clk_enable(&gpio_clk);
1591 clk_enable(&iim_clk);
1592 clk_enable(&gpt1_clk[0]);
1593 #ifdef CONFIG_DEBUG_LL_CONSOLE
1594 clk_enable(&uart1_clk[0]);