2 * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2008 by Sascha Hauer <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/module.h>
21 #include <linux/spinlock.h>
22 #include <linux/delay.h>
23 #include <linux/clk.h>
24 #include <linux/err.h>
26 #include <mach/clock.h>
27 #include <mach/hardware.h>
28 #include <mach/common.h>
29 #include <asm/div64.h>
33 #define PRE_DIV_MIN_FREQ 10000000 /* Minimum Frequency after Predivider */
35 static void __calc_pre_post_dividers(u32 div
, u32
*pre
, u32
*post
)
37 u32 min_pre
, temp_pre
, old_err
, err
;
42 } else if (div
>= 64) {
43 min_pre
= (div
- 1) / 64 + 1;
45 for (temp_pre
= 8; temp_pre
>= min_pre
; temp_pre
--) {
57 *post
= (div
+ *pre
- 1) / *pre
;
58 } else if (div
<= 8) {
67 static struct clk mcu_pll_clk
;
68 static struct clk mcu_main_clk
;
69 static struct clk usb_pll_clk
;
70 static struct clk serial_pll_clk
;
71 static struct clk ipg_clk
;
72 static struct clk ckih_clk
;
73 static struct clk ahb_clk
;
75 static int _clk_enable(struct clk
*clk
)
79 reg
= __raw_readl(clk
->enable_reg
);
80 reg
|= 3 << clk
->enable_shift
;
81 __raw_writel(reg
, clk
->enable_reg
);
86 static void _clk_disable(struct clk
*clk
)
90 reg
= __raw_readl(clk
->enable_reg
);
91 reg
&= ~(3 << clk
->enable_shift
);
92 __raw_writel(reg
, clk
->enable_reg
);
95 static void _clk_emi_disable(struct clk
*clk
)
99 reg
= __raw_readl(clk
->enable_reg
);
100 reg
&= ~(3 << clk
->enable_shift
);
101 reg
|= (1 << clk
->enable_shift
);
102 __raw_writel(reg
, clk
->enable_reg
);
105 static int _clk_pll_set_rate(struct clk
*clk
, unsigned long rate
)
108 signed long pd
= 1; /* Pre-divider */
109 signed long mfi
; /* Multiplication Factor (Integer part) */
110 signed long mfn
; /* Multiplication Factor (Integer part) */
111 signed long mfd
; /* Multiplication Factor (Denominator Part) */
113 u32 ref_freq
= clk_get_rate(clk
->parent
);
115 while (((ref_freq
/ pd
) * 10) > rate
)
118 if ((ref_freq
/ pd
) < PRE_DIV_MIN_FREQ
)
121 /* the ref_freq/2 in the following is to round up */
122 mfi
= (((rate
/ 2) * pd
) + (ref_freq
/ 2)) / ref_freq
;
123 if (mfi
< 5 || mfi
> 15)
126 /* pick a mfd value that will work
127 * then solve for mfn */
128 mfd
= ref_freq
/ 50000;
131 * pll_freq * pd * mfd
132 * mfn = -------------------- - (mfi * mfd)
135 /* the tmp/2 is for rounding */
136 tmp
= ref_freq
/ 10000;
138 ((((((rate
/ 2) + (tmp
/ 2)) / tmp
) * pd
) * mfd
) / 10000) -
145 /* Change the Pll value */
146 reg
= (mfi
<< MXC_CCM_PCTL_MFI_OFFSET
) |
147 (mfn
<< MXC_CCM_PCTL_MFN_OFFSET
) |
148 (mfd
<< MXC_CCM_PCTL_MFD_OFFSET
) | (pd
<< MXC_CCM_PCTL_PD_OFFSET
);
150 if (clk
== &mcu_pll_clk
)
151 __raw_writel(reg
, MXC_CCM_MPCTL
);
152 else if (clk
== &usb_pll_clk
)
153 __raw_writel(reg
, MXC_CCM_UPCTL
);
154 else if (clk
== &serial_pll_clk
)
155 __raw_writel(reg
, MXC_CCM_SRPCTL
);
160 static unsigned long _clk_pll_get_rate(struct clk
*clk
)
162 unsigned long reg
, ccmr
;
163 unsigned int prcs
, ref_clk
;
165 ccmr
= __raw_readl(MXC_CCM_CCMR
);
166 prcs
= (ccmr
& MXC_CCM_CCMR_PRCS_MASK
) >> MXC_CCM_CCMR_PRCS_OFFSET
;
168 ref_clk
= CKIL_CLK_FREQ
* 1024;
170 ref_clk
= clk_get_rate(&ckih_clk
);
172 if (clk
== &mcu_pll_clk
) {
173 if ((ccmr
& MXC_CCM_CCMR_MPE
) == 0)
175 if ((ccmr
& MXC_CCM_CCMR_MDS
) != 0)
177 reg
= __raw_readl(MXC_CCM_MPCTL
);
178 } else if (clk
== &usb_pll_clk
)
179 reg
= __raw_readl(MXC_CCM_UPCTL
);
180 else if (clk
== &serial_pll_clk
)
181 reg
= __raw_readl(MXC_CCM_SRPCTL
);
187 return mxc_decode_pll(reg
, ref_clk
);
190 static int _clk_usb_pll_enable(struct clk
*clk
)
194 reg
= __raw_readl(MXC_CCM_CCMR
);
195 reg
|= MXC_CCM_CCMR_UPE
;
196 __raw_writel(reg
, MXC_CCM_CCMR
);
198 /* No lock bit on MX31, so using max time from spec */
204 static void _clk_usb_pll_disable(struct clk
*clk
)
208 reg
= __raw_readl(MXC_CCM_CCMR
);
209 reg
&= ~MXC_CCM_CCMR_UPE
;
210 __raw_writel(reg
, MXC_CCM_CCMR
);
213 static int _clk_serial_pll_enable(struct clk
*clk
)
217 reg
= __raw_readl(MXC_CCM_CCMR
);
218 reg
|= MXC_CCM_CCMR_SPE
;
219 __raw_writel(reg
, MXC_CCM_CCMR
);
221 /* No lock bit on MX31, so using max time from spec */
227 static void _clk_serial_pll_disable(struct clk
*clk
)
231 reg
= __raw_readl(MXC_CCM_CCMR
);
232 reg
&= ~MXC_CCM_CCMR_SPE
;
233 __raw_writel(reg
, MXC_CCM_CCMR
);
236 #define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
237 #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
238 #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
240 static unsigned long _clk_mcu_main_get_rate(struct clk
*clk
)
242 u32 pmcr0
= __raw_readl(MXC_CCM_PMCR0
);
244 if ((pmcr0
& MXC_CCM_PMCR0_DFSUP1
) == MXC_CCM_PMCR0_DFSUP1_SPLL
)
245 return clk_get_rate(&serial_pll_clk
);
247 return clk_get_rate(&mcu_pll_clk
);
250 static unsigned long _clk_hclk_get_rate(struct clk
*clk
)
252 unsigned long max_pdf
;
254 max_pdf
= PDR0(MXC_CCM_PDR0_MAX_PODF_MASK
,
255 MXC_CCM_PDR0_MAX_PODF_OFFSET
);
256 return clk_get_rate(clk
->parent
) / (max_pdf
+ 1);
259 static unsigned long _clk_ipg_get_rate(struct clk
*clk
)
261 unsigned long ipg_pdf
;
263 ipg_pdf
= PDR0(MXC_CCM_PDR0_IPG_PODF_MASK
,
264 MXC_CCM_PDR0_IPG_PODF_OFFSET
);
265 return clk_get_rate(clk
->parent
) / (ipg_pdf
+ 1);
268 static unsigned long _clk_nfc_get_rate(struct clk
*clk
)
270 unsigned long nfc_pdf
;
272 nfc_pdf
= PDR0(MXC_CCM_PDR0_NFC_PODF_MASK
,
273 MXC_CCM_PDR0_NFC_PODF_OFFSET
);
274 return clk_get_rate(clk
->parent
) / (nfc_pdf
+ 1);
277 static unsigned long _clk_hsp_get_rate(struct clk
*clk
)
279 unsigned long hsp_pdf
;
281 hsp_pdf
= PDR0(MXC_CCM_PDR0_HSP_PODF_MASK
,
282 MXC_CCM_PDR0_HSP_PODF_OFFSET
);
283 return clk_get_rate(clk
->parent
) / (hsp_pdf
+ 1);
286 static unsigned long _clk_usb_get_rate(struct clk
*clk
)
288 unsigned long usb_pdf
, usb_prepdf
;
290 usb_pdf
= PDR1(MXC_CCM_PDR1_USB_PODF_MASK
,
291 MXC_CCM_PDR1_USB_PODF_OFFSET
);
292 usb_prepdf
= PDR1(MXC_CCM_PDR1_USB_PRDF_MASK
,
293 MXC_CCM_PDR1_USB_PRDF_OFFSET
);
294 return clk_get_rate(clk
->parent
) / (usb_prepdf
+ 1) / (usb_pdf
+ 1);
297 static unsigned long _clk_csi_get_rate(struct clk
*clk
)
301 reg
= __raw_readl(MXC_CCM_PDR0
);
302 pre
= (reg
& MXC_CCM_PDR0_CSI_PRDF_MASK
) >>
303 MXC_CCM_PDR0_CSI_PRDF_OFFSET
;
305 post
= (reg
& MXC_CCM_PDR0_CSI_PODF_MASK
) >>
306 MXC_CCM_PDR0_CSI_PODF_OFFSET
;
308 return clk_get_rate(clk
->parent
) / (pre
* post
);
311 static unsigned long _clk_csi_round_rate(struct clk
*clk
, unsigned long rate
)
313 u32 pre
, post
, parent
= clk_get_rate(clk
->parent
);
314 u32 div
= parent
/ rate
;
319 __calc_pre_post_dividers(div
, &pre
, &post
);
321 return parent
/ (pre
* post
);
324 static int _clk_csi_set_rate(struct clk
*clk
, unsigned long rate
)
326 u32 reg
, div
, pre
, post
, parent
= clk_get_rate(clk
->parent
);
330 if ((parent
/ div
) != rate
)
333 __calc_pre_post_dividers(div
, &pre
, &post
);
335 /* Set CSI clock divider */
336 reg
= __raw_readl(MXC_CCM_PDR0
) &
337 ~(MXC_CCM_PDR0_CSI_PODF_MASK
| MXC_CCM_PDR0_CSI_PRDF_MASK
);
338 reg
|= (post
- 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET
;
339 reg
|= (pre
- 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET
;
340 __raw_writel(reg
, MXC_CCM_PDR0
);
345 static unsigned long _clk_per_get_rate(struct clk
*clk
)
347 unsigned long per_pdf
;
349 per_pdf
= PDR0(MXC_CCM_PDR0_PER_PODF_MASK
,
350 MXC_CCM_PDR0_PER_PODF_OFFSET
);
351 return clk_get_rate(clk
->parent
) / (per_pdf
+ 1);
354 static unsigned long _clk_ssi1_get_rate(struct clk
*clk
)
356 unsigned long ssi1_pdf
, ssi1_prepdf
;
358 ssi1_pdf
= PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK
,
359 MXC_CCM_PDR1_SSI1_PODF_OFFSET
);
360 ssi1_prepdf
= PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK
,
361 MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET
);
362 return clk_get_rate(clk
->parent
) / (ssi1_prepdf
+ 1) / (ssi1_pdf
+ 1);
365 static unsigned long _clk_ssi2_get_rate(struct clk
*clk
)
367 unsigned long ssi2_pdf
, ssi2_prepdf
;
369 ssi2_pdf
= PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK
,
370 MXC_CCM_PDR1_SSI2_PODF_OFFSET
);
371 ssi2_prepdf
= PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK
,
372 MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET
);
373 return clk_get_rate(clk
->parent
) / (ssi2_prepdf
+ 1) / (ssi2_pdf
+ 1);
376 static unsigned long _clk_firi_get_rate(struct clk
*clk
)
378 unsigned long firi_pdf
, firi_prepdf
;
380 firi_pdf
= PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK
,
381 MXC_CCM_PDR1_FIRI_PODF_OFFSET
);
382 firi_prepdf
= PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK
,
383 MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET
);
384 return clk_get_rate(clk
->parent
) / (firi_prepdf
+ 1) / (firi_pdf
+ 1);
387 static unsigned long _clk_firi_round_rate(struct clk
*clk
, unsigned long rate
)
390 u32 parent
= clk_get_rate(clk
->parent
);
391 u32 div
= parent
/ rate
;
396 __calc_pre_post_dividers(div
, &pre
, &post
);
398 return parent
/ (pre
* post
);
402 static int _clk_firi_set_rate(struct clk
*clk
, unsigned long rate
)
404 u32 reg
, div
, pre
, post
, parent
= clk_get_rate(clk
->parent
);
408 if ((parent
/ div
) != rate
)
411 __calc_pre_post_dividers(div
, &pre
, &post
);
413 /* Set FIRI clock divider */
414 reg
= __raw_readl(MXC_CCM_PDR1
) &
415 ~(MXC_CCM_PDR1_FIRI_PODF_MASK
| MXC_CCM_PDR1_FIRI_PRE_PODF_MASK
);
416 reg
|= (pre
- 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET
;
417 reg
|= (post
- 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET
;
418 __raw_writel(reg
, MXC_CCM_PDR1
);
423 static unsigned long _clk_mbx_get_rate(struct clk
*clk
)
425 return clk_get_rate(clk
->parent
) / 2;
428 static unsigned long _clk_mstick1_get_rate(struct clk
*clk
)
430 unsigned long msti_pdf
;
432 msti_pdf
= PDR2(MXC_CCM_PDR2_MST1_PDF_MASK
,
433 MXC_CCM_PDR2_MST1_PDF_OFFSET
);
434 return clk_get_rate(clk
->parent
) / (msti_pdf
+ 1);
437 static unsigned long _clk_mstick2_get_rate(struct clk
*clk
)
439 unsigned long msti_pdf
;
441 msti_pdf
= PDR2(MXC_CCM_PDR2_MST2_PDF_MASK
,
442 MXC_CCM_PDR2_MST2_PDF_OFFSET
);
443 return clk_get_rate(clk
->parent
) / (msti_pdf
+ 1);
446 static unsigned long ckih_rate
;
448 static unsigned long clk_ckih_get_rate(struct clk
*clk
)
453 static struct clk ckih_clk
= {
455 .get_rate
= clk_ckih_get_rate
,
458 static unsigned long clk_ckil_get_rate(struct clk
*clk
)
460 return CKIL_CLK_FREQ
;
463 static struct clk ckil_clk
= {
465 .get_rate
= clk_ckil_get_rate
,
468 static struct clk mcu_pll_clk
= {
471 .set_rate
= _clk_pll_set_rate
,
472 .get_rate
= _clk_pll_get_rate
,
475 static struct clk mcu_main_clk
= {
476 .name
= "mcu_main_clk",
477 .parent
= &mcu_pll_clk
,
478 .get_rate
= _clk_mcu_main_get_rate
,
481 static struct clk serial_pll_clk
= {
482 .name
= "serial_pll",
484 .set_rate
= _clk_pll_set_rate
,
485 .get_rate
= _clk_pll_get_rate
,
486 .enable
= _clk_serial_pll_enable
,
487 .disable
= _clk_serial_pll_disable
,
490 static struct clk usb_pll_clk
= {
493 .set_rate
= _clk_pll_set_rate
,
494 .get_rate
= _clk_pll_get_rate
,
495 .enable
= _clk_usb_pll_enable
,
496 .disable
= _clk_usb_pll_disable
,
499 static struct clk ahb_clk
= {
501 .parent
= &mcu_main_clk
,
502 .get_rate
= _clk_hclk_get_rate
,
505 static struct clk per_clk
= {
507 .parent
= &usb_pll_clk
,
508 .get_rate
= _clk_per_get_rate
,
511 static struct clk perclk_clk
= {
512 .name
= "perclk_clk",
516 static struct clk cspi_clk
[] = {
521 .enable
= _clk_enable
,
522 .enable_reg
= MXC_CCM_CGR2
,
523 .enable_shift
= MXC_CCM_CGR2_CSPI1_OFFSET
,
524 .disable
= _clk_disable
,},
529 .enable
= _clk_enable
,
530 .enable_reg
= MXC_CCM_CGR2
,
531 .enable_shift
= MXC_CCM_CGR2_CSPI2_OFFSET
,
532 .disable
= _clk_disable
,},
537 .enable
= _clk_enable
,
538 .enable_reg
= MXC_CCM_CGR0
,
539 .enable_shift
= MXC_CCM_CGR0_CSPI3_OFFSET
,
540 .disable
= _clk_disable
,},
543 static struct clk ipg_clk
= {
546 .get_rate
= _clk_ipg_get_rate
,
549 static struct clk emi_clk
= {
552 .enable
= _clk_enable
,
553 .enable_reg
= MXC_CCM_CGR2
,
554 .enable_shift
= MXC_CCM_CGR2_EMI_OFFSET
,
555 .disable
= _clk_emi_disable
,
558 static struct clk gpt_clk
= {
560 .parent
= &perclk_clk
,
561 .enable
= _clk_enable
,
562 .enable_reg
= MXC_CCM_CGR0
,
563 .enable_shift
= MXC_CCM_CGR0_GPT_OFFSET
,
564 .disable
= _clk_disable
,
567 static struct clk pwm_clk
= {
569 .parent
= &perclk_clk
,
570 .enable
= _clk_enable
,
571 .enable_reg
= MXC_CCM_CGR0
,
572 .enable_shift
= MXC_CCM_CGR1_PWM_OFFSET
,
573 .disable
= _clk_disable
,
576 static struct clk epit_clk
[] = {
580 .parent
= &perclk_clk
,
581 .enable
= _clk_enable
,
582 .enable_reg
= MXC_CCM_CGR0
,
583 .enable_shift
= MXC_CCM_CGR0_EPIT1_OFFSET
,
584 .disable
= _clk_disable
,},
588 .parent
= &perclk_clk
,
589 .enable
= _clk_enable
,
590 .enable_reg
= MXC_CCM_CGR0
,
591 .enable_shift
= MXC_CCM_CGR0_EPIT2_OFFSET
,
592 .disable
= _clk_disable
,},
595 static struct clk nfc_clk
= {
598 .get_rate
= _clk_nfc_get_rate
,
601 static struct clk scc_clk
= {
606 static struct clk ipu_clk
= {
608 .parent
= &mcu_main_clk
,
609 .get_rate
= _clk_hsp_get_rate
,
610 .enable
= _clk_enable
,
611 .enable_reg
= MXC_CCM_CGR1
,
612 .enable_shift
= MXC_CCM_CGR1_IPU_OFFSET
,
613 .disable
= _clk_disable
,
616 static struct clk kpp_clk
= {
619 .enable
= _clk_enable
,
620 .enable_reg
= MXC_CCM_CGR1
,
621 .enable_shift
= MXC_CCM_CGR1_KPP_OFFSET
,
622 .disable
= _clk_disable
,
625 static struct clk wdog_clk
= {
628 .enable
= _clk_enable
,
629 .enable_reg
= MXC_CCM_CGR1
,
630 .enable_shift
= MXC_CCM_CGR1_WDOG_OFFSET
,
631 .disable
= _clk_disable
,
633 static struct clk rtc_clk
= {
636 .enable
= _clk_enable
,
637 .enable_reg
= MXC_CCM_CGR1
,
638 .enable_shift
= MXC_CCM_CGR1_RTC_OFFSET
,
639 .disable
= _clk_disable
,
642 static struct clk usb_clk
[] = {
645 .parent
= &usb_pll_clk
,
646 .get_rate
= _clk_usb_get_rate
,},
648 .name
= "usb_ahb_clk",
650 .enable
= _clk_enable
,
651 .enable_reg
= MXC_CCM_CGR1
,
652 .enable_shift
= MXC_CCM_CGR1_USBOTG_OFFSET
,
653 .disable
= _clk_disable
,},
656 static struct clk csi_clk
= {
658 .parent
= &serial_pll_clk
,
659 .get_rate
= _clk_csi_get_rate
,
660 .round_rate
= _clk_csi_round_rate
,
661 .set_rate
= _clk_csi_set_rate
,
662 .enable
= _clk_enable
,
663 .enable_reg
= MXC_CCM_CGR1
,
664 .enable_shift
= MXC_CCM_CGR1_CSI_OFFSET
,
665 .disable
= _clk_disable
,
668 static struct clk uart_clk
[] = {
672 .parent
= &perclk_clk
,
673 .enable
= _clk_enable
,
674 .enable_reg
= MXC_CCM_CGR0
,
675 .enable_shift
= MXC_CCM_CGR0_UART1_OFFSET
,
676 .disable
= _clk_disable
,},
680 .parent
= &perclk_clk
,
681 .enable
= _clk_enable
,
682 .enable_reg
= MXC_CCM_CGR0
,
683 .enable_shift
= MXC_CCM_CGR0_UART2_OFFSET
,
684 .disable
= _clk_disable
,},
688 .parent
= &perclk_clk
,
689 .enable
= _clk_enable
,
690 .enable_reg
= MXC_CCM_CGR1
,
691 .enable_shift
= MXC_CCM_CGR1_UART3_OFFSET
,
692 .disable
= _clk_disable
,},
696 .parent
= &perclk_clk
,
697 .enable
= _clk_enable
,
698 .enable_reg
= MXC_CCM_CGR1
,
699 .enable_shift
= MXC_CCM_CGR1_UART4_OFFSET
,
700 .disable
= _clk_disable
,},
704 .parent
= &perclk_clk
,
705 .enable
= _clk_enable
,
706 .enable_reg
= MXC_CCM_CGR1
,
707 .enable_shift
= MXC_CCM_CGR1_UART5_OFFSET
,
708 .disable
= _clk_disable
,},
711 static struct clk i2c_clk
[] = {
715 .parent
= &perclk_clk
,
716 .enable
= _clk_enable
,
717 .enable_reg
= MXC_CCM_CGR0
,
718 .enable_shift
= MXC_CCM_CGR0_I2C1_OFFSET
,
719 .disable
= _clk_disable
,},
723 .parent
= &perclk_clk
,
724 .enable
= _clk_enable
,
725 .enable_reg
= MXC_CCM_CGR0
,
726 .enable_shift
= MXC_CCM_CGR0_I2C2_OFFSET
,
727 .disable
= _clk_disable
,},
731 .parent
= &perclk_clk
,
732 .enable
= _clk_enable
,
733 .enable_reg
= MXC_CCM_CGR0
,
734 .enable_shift
= MXC_CCM_CGR0_I2C3_OFFSET
,
735 .disable
= _clk_disable
,},
738 static struct clk owire_clk
= {
740 .parent
= &perclk_clk
,
741 .enable_reg
= MXC_CCM_CGR1
,
742 .enable_shift
= MXC_CCM_CGR1_OWIRE_OFFSET
,
743 .enable
= _clk_enable
,
744 .disable
= _clk_disable
,
747 static struct clk sdhc_clk
[] = {
751 .parent
= &perclk_clk
,
752 .enable
= _clk_enable
,
753 .enable_reg
= MXC_CCM_CGR0
,
754 .enable_shift
= MXC_CCM_CGR0_SD_MMC1_OFFSET
,
755 .disable
= _clk_disable
,},
759 .parent
= &perclk_clk
,
760 .enable
= _clk_enable
,
761 .enable_reg
= MXC_CCM_CGR0
,
762 .enable_shift
= MXC_CCM_CGR0_SD_MMC2_OFFSET
,
763 .disable
= _clk_disable
,},
766 static struct clk ssi_clk
[] = {
769 .parent
= &serial_pll_clk
,
770 .get_rate
= _clk_ssi1_get_rate
,
771 .enable
= _clk_enable
,
772 .enable_reg
= MXC_CCM_CGR0
,
773 .enable_shift
= MXC_CCM_CGR0_SSI1_OFFSET
,
774 .disable
= _clk_disable
,},
778 .parent
= &serial_pll_clk
,
779 .get_rate
= _clk_ssi2_get_rate
,
780 .enable
= _clk_enable
,
781 .enable_reg
= MXC_CCM_CGR2
,
782 .enable_shift
= MXC_CCM_CGR2_SSI2_OFFSET
,
783 .disable
= _clk_disable
,},
786 static struct clk firi_clk
= {
788 .parent
= &usb_pll_clk
,
789 .round_rate
= _clk_firi_round_rate
,
790 .set_rate
= _clk_firi_set_rate
,
791 .get_rate
= _clk_firi_get_rate
,
792 .enable
= _clk_enable
,
793 .enable_reg
= MXC_CCM_CGR2
,
794 .enable_shift
= MXC_CCM_CGR2_FIRI_OFFSET
,
795 .disable
= _clk_disable
,
798 static struct clk ata_clk
= {
801 .enable
= _clk_enable
,
802 .enable_reg
= MXC_CCM_CGR0
,
803 .enable_shift
= MXC_CCM_CGR0_ATA_OFFSET
,
804 .disable
= _clk_disable
,
807 static struct clk mbx_clk
= {
810 .enable
= _clk_enable
,
811 .enable_reg
= MXC_CCM_CGR2
,
812 .enable_shift
= MXC_CCM_CGR2_GACC_OFFSET
,
813 .get_rate
= _clk_mbx_get_rate
,
816 static struct clk vpu_clk
= {
819 .enable
= _clk_enable
,
820 .enable_reg
= MXC_CCM_CGR2
,
821 .enable_shift
= MXC_CCM_CGR2_GACC_OFFSET
,
822 .get_rate
= _clk_mbx_get_rate
,
825 static struct clk rtic_clk
= {
828 .enable
= _clk_enable
,
829 .enable_reg
= MXC_CCM_CGR2
,
830 .enable_shift
= MXC_CCM_CGR2_RTIC_OFFSET
,
831 .disable
= _clk_disable
,
834 static struct clk rng_clk
= {
837 .enable
= _clk_enable
,
838 .enable_reg
= MXC_CCM_CGR0
,
839 .enable_shift
= MXC_CCM_CGR0_RNG_OFFSET
,
840 .disable
= _clk_disable
,
843 static struct clk sdma_clk
[] = {
845 .name
= "sdma_ahb_clk",
847 .enable
= _clk_enable
,
848 .enable_reg
= MXC_CCM_CGR0
,
849 .enable_shift
= MXC_CCM_CGR0_SDMA_OFFSET
,
850 .disable
= _clk_disable
,},
852 .name
= "sdma_ipg_clk",
856 static struct clk mpeg4_clk
= {
859 .enable
= _clk_enable
,
860 .enable_reg
= MXC_CCM_CGR1
,
861 .enable_shift
= MXC_CCM_CGR1_HANTRO_OFFSET
,
862 .disable
= _clk_disable
,
865 static struct clk vl2cc_clk
= {
868 .enable
= _clk_enable
,
869 .enable_reg
= MXC_CCM_CGR1
,
870 .enable_shift
= MXC_CCM_CGR1_HANTRO_OFFSET
,
871 .disable
= _clk_disable
,
874 static struct clk mstick_clk
[] = {
876 .name
= "mstick_clk",
878 .parent
= &usb_pll_clk
,
879 .get_rate
= _clk_mstick1_get_rate
,
880 .enable
= _clk_enable
,
881 .enable_reg
= MXC_CCM_CGR1
,
882 .enable_shift
= MXC_CCM_CGR1_MEMSTICK1_OFFSET
,
883 .disable
= _clk_disable
,},
885 .name
= "mstick_clk",
887 .parent
= &usb_pll_clk
,
888 .get_rate
= _clk_mstick2_get_rate
,
889 .enable
= _clk_enable
,
890 .enable_reg
= MXC_CCM_CGR1
,
891 .enable_shift
= MXC_CCM_CGR1_MEMSTICK2_OFFSET
,
892 .disable
= _clk_disable
,},
895 static struct clk iim_clk
= {
898 .enable
= _clk_enable
,
899 .enable_reg
= MXC_CCM_CGR0
,
900 .enable_shift
= MXC_CCM_CGR0_IIM_OFFSET
,
901 .disable
= _clk_disable
,
904 static unsigned long _clk_cko1_round_rate(struct clk
*clk
, unsigned long rate
)
906 u32 div
, parent
= clk_get_rate(clk
->parent
);
922 static int _clk_cko1_set_rate(struct clk
*clk
, unsigned long rate
)
924 u32 reg
, div
, parent
= clk_get_rate(clk
->parent
);
941 reg
= __raw_readl(MXC_CCM_COSR
) & ~MXC_CCM_COSR_CLKOUTDIV_MASK
;
942 reg
|= div
<< MXC_CCM_COSR_CLKOUTDIV_OFFSET
;
943 __raw_writel(reg
, MXC_CCM_COSR
);
948 static unsigned long _clk_cko1_get_rate(struct clk
*clk
)
952 div
= __raw_readl(MXC_CCM_COSR
) & MXC_CCM_COSR_CLKOUTDIV_MASK
>>
953 MXC_CCM_COSR_CLKOUTDIV_OFFSET
;
955 return clk_get_rate(clk
->parent
) / (1 << div
);
958 static int _clk_cko1_set_parent(struct clk
*clk
, struct clk
*parent
)
962 reg
= __raw_readl(MXC_CCM_COSR
) & ~MXC_CCM_COSR_CLKOSEL_MASK
;
964 if (parent
== &mcu_main_clk
)
965 reg
|= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
966 else if (parent
== &ipg_clk
)
967 reg
|= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
968 else if (parent
== &usb_pll_clk
)
969 reg
|= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
970 else if (parent
== mcu_main_clk
.parent
)
971 reg
|= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
972 else if (parent
== &ahb_clk
)
973 reg
|= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
974 else if (parent
== &serial_pll_clk
)
975 reg
|= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
976 else if (parent
== &ckih_clk
)
977 reg
|= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
978 else if (parent
== &emi_clk
)
979 reg
|= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET
;
980 else if (parent
== &ipu_clk
)
981 reg
|= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET
;
982 else if (parent
== &nfc_clk
)
983 reg
|= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET
;
984 else if (parent
== &uart_clk
[0])
985 reg
|= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET
;
989 __raw_writel(reg
, MXC_CCM_COSR
);
994 static int _clk_cko1_enable(struct clk
*clk
)
998 reg
= __raw_readl(MXC_CCM_COSR
) | MXC_CCM_COSR_CLKOEN
;
999 __raw_writel(reg
, MXC_CCM_COSR
);
1004 static void _clk_cko1_disable(struct clk
*clk
)
1008 reg
= __raw_readl(MXC_CCM_COSR
) & ~MXC_CCM_COSR_CLKOEN
;
1009 __raw_writel(reg
, MXC_CCM_COSR
);
1012 static struct clk cko1_clk
= {
1014 .get_rate
= _clk_cko1_get_rate
,
1015 .set_rate
= _clk_cko1_set_rate
,
1016 .round_rate
= _clk_cko1_round_rate
,
1017 .set_parent
= _clk_cko1_set_parent
,
1018 .enable
= _clk_cko1_enable
,
1019 .disable
= _clk_cko1_disable
,
1022 static struct clk
*mxc_clks
[] = {
1075 int __init
mx31_clocks_init(unsigned long fref
)
1082 for (clkp
= mxc_clks
; clkp
< mxc_clks
+ ARRAY_SIZE(mxc_clks
); clkp
++)
1083 clk_register(*clkp
);
1085 if (cpu_is_mx31()) {
1086 clk_register(&mpeg4_clk
);
1087 clk_register(&mbx_clk
);
1089 clk_register(&vpu_clk
);
1090 clk_register(&vl2cc_clk
);
1093 /* Turn off all possible clocks */
1094 __raw_writel(MXC_CCM_CGR0_GPT_MASK
, MXC_CCM_CGR0
);
1095 __raw_writel(0, MXC_CCM_CGR1
);
1097 __raw_writel(MXC_CCM_CGR2_EMI_MASK
|
1098 MXC_CCM_CGR2_IPMUX1_MASK
|
1099 MXC_CCM_CGR2_IPMUX2_MASK
|
1100 MXC_CCM_CGR2_MXCCLKENSEL_MASK
| /* for MX32 */
1101 MXC_CCM_CGR2_CHIKCAMPEN_MASK
| /* for MX32 */
1102 MXC_CCM_CGR2_OVRVPUBUSY_MASK
| /* for MX32 */
1103 1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
1104 MX32, but still required to be set */
1107 clk_disable(&cko1_clk
);
1108 clk_disable(&usb_pll_clk
);
1110 pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk
));
1112 clk_enable(&gpt_clk
);
1113 clk_enable(&emi_clk
);
1114 clk_enable(&iim_clk
);
1116 clk_enable(&serial_pll_clk
);
1118 if (mx31_revision() >= CHIP_REV_2_0
) {
1119 reg
= __raw_readl(MXC_CCM_PMCR1
);
1120 /* No PLL restart on DVFS switch; enable auto EMI handshake */
1121 reg
|= MXC_CCM_PMCR1_PLLRDIS
| MXC_CCM_PMCR1_EMIRQ_EN
;
1122 __raw_writel(reg
, MXC_CCM_PMCR1
);
1125 mxc_timer_init(&ipg_clk
);