x86, fixmap: define reserve_top_address for x86_64
[linux-2.6/mini2440.git] / arch / arm / mach-mx3 / clock.c
blobb1746aae1f89eaeaf1eb2fb7a79037b02da4c1bd
1 /*
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,
17 * MA 02110-1301, USA.
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>
25 #include <linux/io.h>
26 #include <mach/clock.h>
27 #include <mach/hardware.h>
28 #include <asm/div64.h>
30 #include "crm_regs.h"
32 #define PRE_DIV_MIN_FREQ 10000000 /* Minimum Frequency after Predivider */
34 static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
36 u32 min_pre, temp_pre, old_err, err;
38 if (div >= 512) {
39 *pre = 8;
40 *post = 64;
41 } else if (div >= 64) {
42 min_pre = (div - 1) / 64 + 1;
43 old_err = 8;
44 for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
45 err = div % temp_pre;
46 if (err == 0) {
47 *pre = temp_pre;
48 break;
50 err = temp_pre - err;
51 if (err < old_err) {
52 old_err = err;
53 *pre = temp_pre;
56 *post = (div + *pre - 1) / *pre;
57 } else if (div <= 8) {
58 *pre = div;
59 *post = 1;
60 } else {
61 *pre = 1;
62 *post = div;
66 static struct clk mcu_pll_clk;
67 static struct clk mcu_main_clk;
68 static struct clk usb_pll_clk;
69 static struct clk serial_pll_clk;
70 static struct clk ipg_clk;
71 static struct clk ckih_clk;
72 static struct clk ahb_clk;
74 static int _clk_enable(struct clk *clk)
76 u32 reg;
78 reg = __raw_readl(clk->enable_reg);
79 reg |= 3 << clk->enable_shift;
80 __raw_writel(reg, clk->enable_reg);
82 return 0;
85 static void _clk_disable(struct clk *clk)
87 u32 reg;
89 reg = __raw_readl(clk->enable_reg);
90 reg &= ~(3 << clk->enable_shift);
91 __raw_writel(reg, clk->enable_reg);
94 static void _clk_emi_disable(struct clk *clk)
96 u32 reg;
98 reg = __raw_readl(clk->enable_reg);
99 reg &= ~(3 << clk->enable_shift);
100 reg |= (1 << clk->enable_shift);
101 __raw_writel(reg, clk->enable_reg);
104 static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
106 u32 reg;
107 signed long pd = 1; /* Pre-divider */
108 signed long mfi; /* Multiplication Factor (Integer part) */
109 signed long mfn; /* Multiplication Factor (Integer part) */
110 signed long mfd; /* Multiplication Factor (Denominator Part) */
111 signed long tmp;
112 u32 ref_freq = clk_get_rate(clk->parent);
114 while (((ref_freq / pd) * 10) > rate)
115 pd++;
117 if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
118 return -EINVAL;
120 /* the ref_freq/2 in the following is to round up */
121 mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
122 if (mfi < 5 || mfi > 15)
123 return -EINVAL;
125 /* pick a mfd value that will work
126 * then solve for mfn */
127 mfd = ref_freq / 50000;
130 * pll_freq * pd * mfd
131 * mfn = -------------------- - (mfi * mfd)
132 * 2 * ref_freq
134 /* the tmp/2 is for rounding */
135 tmp = ref_freq / 10000;
136 mfn =
137 ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
138 (mfi * mfd);
140 mfn = mfn & 0x3ff;
141 pd--;
142 mfd--;
144 /* Change the Pll value */
145 reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
146 (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
147 (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
149 if (clk == &mcu_pll_clk)
150 __raw_writel(reg, MXC_CCM_MPCTL);
151 else if (clk == &usb_pll_clk)
152 __raw_writel(reg, MXC_CCM_UPCTL);
153 else if (clk == &serial_pll_clk)
154 __raw_writel(reg, MXC_CCM_SRPCTL);
156 return 0;
159 static unsigned long _clk_pll_get_rate(struct clk *clk)
161 long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
162 unsigned long reg, ccmr;
163 s64 temp;
164 unsigned int prcs;
166 ccmr = __raw_readl(MXC_CCM_CCMR);
167 prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
168 if (prcs == 0x1)
169 ref_clk = CKIL_CLK_FREQ * 1024;
170 else
171 ref_clk = clk_get_rate(&ckih_clk);
173 if (clk == &mcu_pll_clk) {
174 if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
175 return ref_clk;
176 if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
177 return ref_clk;
178 reg = __raw_readl(MXC_CCM_MPCTL);
179 } else if (clk == &usb_pll_clk)
180 reg = __raw_readl(MXC_CCM_UPCTL);
181 else if (clk == &serial_pll_clk)
182 reg = __raw_readl(MXC_CCM_SRPCTL);
183 else {
184 BUG();
185 return 0;
188 pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
189 mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
190 mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
191 mfi = (mfi <= 5) ? 5 : mfi;
192 mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
194 if (mfn >= 0x200) {
195 mfn |= 0xFFFFFE00;
196 mfn_abs = -mfn;
199 ref_clk *= 2;
200 ref_clk /= pdf + 1;
202 temp = (u64) ref_clk * mfn_abs;
203 do_div(temp, mfd + 1);
204 if (mfn < 0)
205 temp = -temp;
206 temp = (ref_clk * mfi) + temp;
208 return temp;
211 static int _clk_usb_pll_enable(struct clk *clk)
213 u32 reg;
215 reg = __raw_readl(MXC_CCM_CCMR);
216 reg |= MXC_CCM_CCMR_UPE;
217 __raw_writel(reg, MXC_CCM_CCMR);
219 /* No lock bit on MX31, so using max time from spec */
220 udelay(80);
222 return 0;
225 static void _clk_usb_pll_disable(struct clk *clk)
227 u32 reg;
229 reg = __raw_readl(MXC_CCM_CCMR);
230 reg &= ~MXC_CCM_CCMR_UPE;
231 __raw_writel(reg, MXC_CCM_CCMR);
234 static int _clk_serial_pll_enable(struct clk *clk)
236 u32 reg;
238 reg = __raw_readl(MXC_CCM_CCMR);
239 reg |= MXC_CCM_CCMR_SPE;
240 __raw_writel(reg, MXC_CCM_CCMR);
242 /* No lock bit on MX31, so using max time from spec */
243 udelay(80);
245 return 0;
248 static void _clk_serial_pll_disable(struct clk *clk)
250 u32 reg;
252 reg = __raw_readl(MXC_CCM_CCMR);
253 reg &= ~MXC_CCM_CCMR_SPE;
254 __raw_writel(reg, MXC_CCM_CCMR);
257 #define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
258 #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
259 #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
261 static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
263 u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
265 if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
266 return clk_get_rate(&serial_pll_clk);
267 else
268 return clk_get_rate(&mcu_pll_clk);
271 static unsigned long _clk_hclk_get_rate(struct clk *clk)
273 unsigned long max_pdf;
275 max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
276 MXC_CCM_PDR0_MAX_PODF_OFFSET);
277 return clk_get_rate(clk->parent) / (max_pdf + 1);
280 static unsigned long _clk_ipg_get_rate(struct clk *clk)
282 unsigned long ipg_pdf;
284 ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
285 MXC_CCM_PDR0_IPG_PODF_OFFSET);
286 return clk_get_rate(clk->parent) / (ipg_pdf + 1);
289 static unsigned long _clk_nfc_get_rate(struct clk *clk)
291 unsigned long nfc_pdf;
293 nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
294 MXC_CCM_PDR0_NFC_PODF_OFFSET);
295 return clk_get_rate(clk->parent) / (nfc_pdf + 1);
298 static unsigned long _clk_hsp_get_rate(struct clk *clk)
300 unsigned long hsp_pdf;
302 hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
303 MXC_CCM_PDR0_HSP_PODF_OFFSET);
304 return clk_get_rate(clk->parent) / (hsp_pdf + 1);
307 static unsigned long _clk_usb_get_rate(struct clk *clk)
309 unsigned long usb_pdf, usb_prepdf;
311 usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
312 MXC_CCM_PDR1_USB_PODF_OFFSET);
313 usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
314 MXC_CCM_PDR1_USB_PRDF_OFFSET);
315 return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
318 static unsigned long _clk_csi_get_rate(struct clk *clk)
320 u32 reg, pre, post;
322 reg = __raw_readl(MXC_CCM_PDR0);
323 pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
324 MXC_CCM_PDR0_CSI_PRDF_OFFSET;
325 pre++;
326 post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
327 MXC_CCM_PDR0_CSI_PODF_OFFSET;
328 post++;
329 return clk_get_rate(clk->parent) / (pre * post);
332 static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
334 u32 pre, post, parent = clk_get_rate(clk->parent);
335 u32 div = parent / rate;
337 if (parent % rate)
338 div++;
340 __calc_pre_post_dividers(div, &pre, &post);
342 return parent / (pre * post);
345 static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
347 u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
349 div = parent / rate;
351 if ((parent / div) != rate)
352 return -EINVAL;
354 __calc_pre_post_dividers(div, &pre, &post);
356 /* Set CSI clock divider */
357 reg = __raw_readl(MXC_CCM_PDR0) &
358 ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
359 reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
360 reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
361 __raw_writel(reg, MXC_CCM_PDR0);
363 return 0;
366 static unsigned long _clk_per_get_rate(struct clk *clk)
368 unsigned long per_pdf;
370 per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
371 MXC_CCM_PDR0_PER_PODF_OFFSET);
372 return clk_get_rate(clk->parent) / (per_pdf + 1);
375 static unsigned long _clk_ssi1_get_rate(struct clk *clk)
377 unsigned long ssi1_pdf, ssi1_prepdf;
379 ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
380 MXC_CCM_PDR1_SSI1_PODF_OFFSET);
381 ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
382 MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
383 return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
386 static unsigned long _clk_ssi2_get_rate(struct clk *clk)
388 unsigned long ssi2_pdf, ssi2_prepdf;
390 ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
391 MXC_CCM_PDR1_SSI2_PODF_OFFSET);
392 ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
393 MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
394 return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
397 static unsigned long _clk_firi_get_rate(struct clk *clk)
399 unsigned long firi_pdf, firi_prepdf;
401 firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
402 MXC_CCM_PDR1_FIRI_PODF_OFFSET);
403 firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
404 MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
405 return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
408 static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
410 u32 pre, post;
411 u32 parent = clk_get_rate(clk->parent);
412 u32 div = parent / rate;
414 if (parent % rate)
415 div++;
417 __calc_pre_post_dividers(div, &pre, &post);
419 return parent / (pre * post);
423 static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
425 u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
427 div = parent / rate;
429 if ((parent / div) != rate)
430 return -EINVAL;
432 __calc_pre_post_dividers(div, &pre, &post);
434 /* Set FIRI clock divider */
435 reg = __raw_readl(MXC_CCM_PDR1) &
436 ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
437 reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
438 reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
439 __raw_writel(reg, MXC_CCM_PDR1);
441 return 0;
444 static unsigned long _clk_mbx_get_rate(struct clk *clk)
446 return clk_get_rate(clk->parent) / 2;
449 static unsigned long _clk_mstick1_get_rate(struct clk *clk)
451 unsigned long msti_pdf;
453 msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
454 MXC_CCM_PDR2_MST1_PDF_OFFSET);
455 return clk_get_rate(clk->parent) / (msti_pdf + 1);
458 static unsigned long _clk_mstick2_get_rate(struct clk *clk)
460 unsigned long msti_pdf;
462 msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
463 MXC_CCM_PDR2_MST2_PDF_OFFSET);
464 return clk_get_rate(clk->parent) / (msti_pdf + 1);
467 static unsigned long ckih_rate;
469 static unsigned long clk_ckih_get_rate(struct clk *clk)
471 return ckih_rate;
474 static struct clk ckih_clk = {
475 .name = "ckih",
476 .get_rate = clk_ckih_get_rate,
479 static unsigned long clk_ckil_get_rate(struct clk *clk)
481 return CKIL_CLK_FREQ;
484 static struct clk ckil_clk = {
485 .name = "ckil",
486 .get_rate = clk_ckil_get_rate,
489 static struct clk mcu_pll_clk = {
490 .name = "mcu_pll",
491 .parent = &ckih_clk,
492 .set_rate = _clk_pll_set_rate,
493 .get_rate = _clk_pll_get_rate,
496 static struct clk mcu_main_clk = {
497 .name = "mcu_main_clk",
498 .parent = &mcu_pll_clk,
499 .get_rate = _clk_mcu_main_get_rate,
502 static struct clk serial_pll_clk = {
503 .name = "serial_pll",
504 .parent = &ckih_clk,
505 .set_rate = _clk_pll_set_rate,
506 .get_rate = _clk_pll_get_rate,
507 .enable = _clk_serial_pll_enable,
508 .disable = _clk_serial_pll_disable,
511 static struct clk usb_pll_clk = {
512 .name = "usb_pll",
513 .parent = &ckih_clk,
514 .set_rate = _clk_pll_set_rate,
515 .get_rate = _clk_pll_get_rate,
516 .enable = _clk_usb_pll_enable,
517 .disable = _clk_usb_pll_disable,
520 static struct clk ahb_clk = {
521 .name = "ahb_clk",
522 .parent = &mcu_main_clk,
523 .get_rate = _clk_hclk_get_rate,
526 static struct clk per_clk = {
527 .name = "per_clk",
528 .parent = &usb_pll_clk,
529 .get_rate = _clk_per_get_rate,
532 static struct clk perclk_clk = {
533 .name = "perclk_clk",
534 .parent = &ipg_clk,
537 static struct clk cspi_clk[] = {
539 .name = "cspi_clk",
540 .id = 0,
541 .parent = &ipg_clk,
542 .enable = _clk_enable,
543 .enable_reg = MXC_CCM_CGR2,
544 .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
545 .disable = _clk_disable,},
547 .name = "cspi_clk",
548 .id = 1,
549 .parent = &ipg_clk,
550 .enable = _clk_enable,
551 .enable_reg = MXC_CCM_CGR2,
552 .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
553 .disable = _clk_disable,},
555 .name = "cspi_clk",
556 .id = 2,
557 .parent = &ipg_clk,
558 .enable = _clk_enable,
559 .enable_reg = MXC_CCM_CGR0,
560 .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
561 .disable = _clk_disable,},
564 static struct clk ipg_clk = {
565 .name = "ipg_clk",
566 .parent = &ahb_clk,
567 .get_rate = _clk_ipg_get_rate,
570 static struct clk emi_clk = {
571 .name = "emi_clk",
572 .parent = &ahb_clk,
573 .enable = _clk_enable,
574 .enable_reg = MXC_CCM_CGR2,
575 .enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
576 .disable = _clk_emi_disable,
579 static struct clk gpt_clk = {
580 .name = "gpt_clk",
581 .parent = &perclk_clk,
582 .enable = _clk_enable,
583 .enable_reg = MXC_CCM_CGR0,
584 .enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
585 .disable = _clk_disable,
588 static struct clk pwm_clk = {
589 .name = "pwm_clk",
590 .parent = &perclk_clk,
591 .enable = _clk_enable,
592 .enable_reg = MXC_CCM_CGR0,
593 .enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
594 .disable = _clk_disable,
597 static struct clk epit_clk[] = {
599 .name = "epit_clk",
600 .id = 0,
601 .parent = &perclk_clk,
602 .enable = _clk_enable,
603 .enable_reg = MXC_CCM_CGR0,
604 .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
605 .disable = _clk_disable,},
607 .name = "epit_clk",
608 .id = 1,
609 .parent = &perclk_clk,
610 .enable = _clk_enable,
611 .enable_reg = MXC_CCM_CGR0,
612 .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
613 .disable = _clk_disable,},
616 static struct clk nfc_clk = {
617 .name = "nfc_clk",
618 .parent = &ahb_clk,
619 .get_rate = _clk_nfc_get_rate,
622 static struct clk scc_clk = {
623 .name = "scc_clk",
624 .parent = &ipg_clk,
627 static struct clk ipu_clk = {
628 .name = "ipu_clk",
629 .parent = &mcu_main_clk,
630 .get_rate = _clk_hsp_get_rate,
631 .enable = _clk_enable,
632 .enable_reg = MXC_CCM_CGR1,
633 .enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
634 .disable = _clk_disable,
637 static struct clk kpp_clk = {
638 .name = "kpp_clk",
639 .parent = &ipg_clk,
640 .enable = _clk_enable,
641 .enable_reg = MXC_CCM_CGR1,
642 .enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
643 .disable = _clk_disable,
646 static struct clk wdog_clk = {
647 .name = "wdog_clk",
648 .parent = &ipg_clk,
649 .enable = _clk_enable,
650 .enable_reg = MXC_CCM_CGR1,
651 .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
652 .disable = _clk_disable,
654 static struct clk rtc_clk = {
655 .name = "rtc_clk",
656 .parent = &ipg_clk,
657 .enable = _clk_enable,
658 .enable_reg = MXC_CCM_CGR1,
659 .enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
660 .disable = _clk_disable,
663 static struct clk usb_clk[] = {
665 .name = "usb_clk",
666 .parent = &usb_pll_clk,
667 .get_rate = _clk_usb_get_rate,},
669 .name = "usb_ahb_clk",
670 .parent = &ahb_clk,
671 .enable = _clk_enable,
672 .enable_reg = MXC_CCM_CGR1,
673 .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
674 .disable = _clk_disable,},
677 static struct clk csi_clk = {
678 .name = "csi_clk",
679 .parent = &serial_pll_clk,
680 .get_rate = _clk_csi_get_rate,
681 .round_rate = _clk_csi_round_rate,
682 .set_rate = _clk_csi_set_rate,
683 .enable = _clk_enable,
684 .enable_reg = MXC_CCM_CGR1,
685 .enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
686 .disable = _clk_disable,
689 static struct clk uart_clk[] = {
691 .name = "uart_clk",
692 .id = 0,
693 .parent = &perclk_clk,
694 .enable = _clk_enable,
695 .enable_reg = MXC_CCM_CGR0,
696 .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
697 .disable = _clk_disable,},
699 .name = "uart_clk",
700 .id = 1,
701 .parent = &perclk_clk,
702 .enable = _clk_enable,
703 .enable_reg = MXC_CCM_CGR0,
704 .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
705 .disable = _clk_disable,},
707 .name = "uart_clk",
708 .id = 2,
709 .parent = &perclk_clk,
710 .enable = _clk_enable,
711 .enable_reg = MXC_CCM_CGR1,
712 .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
713 .disable = _clk_disable,},
715 .name = "uart_clk",
716 .id = 3,
717 .parent = &perclk_clk,
718 .enable = _clk_enable,
719 .enable_reg = MXC_CCM_CGR1,
720 .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
721 .disable = _clk_disable,},
723 .name = "uart_clk",
724 .id = 4,
725 .parent = &perclk_clk,
726 .enable = _clk_enable,
727 .enable_reg = MXC_CCM_CGR1,
728 .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
729 .disable = _clk_disable,},
732 static struct clk i2c_clk[] = {
734 .name = "i2c_clk",
735 .id = 0,
736 .parent = &perclk_clk,
737 .enable = _clk_enable,
738 .enable_reg = MXC_CCM_CGR0,
739 .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
740 .disable = _clk_disable,},
742 .name = "i2c_clk",
743 .id = 1,
744 .parent = &perclk_clk,
745 .enable = _clk_enable,
746 .enable_reg = MXC_CCM_CGR0,
747 .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
748 .disable = _clk_disable,},
750 .name = "i2c_clk",
751 .id = 2,
752 .parent = &perclk_clk,
753 .enable = _clk_enable,
754 .enable_reg = MXC_CCM_CGR0,
755 .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
756 .disable = _clk_disable,},
759 static struct clk owire_clk = {
760 .name = "owire_clk",
761 .parent = &perclk_clk,
762 .enable_reg = MXC_CCM_CGR1,
763 .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
764 .enable = _clk_enable,
765 .disable = _clk_disable,
768 static struct clk sdhc_clk[] = {
770 .name = "sdhc_clk",
771 .id = 0,
772 .parent = &perclk_clk,
773 .enable = _clk_enable,
774 .enable_reg = MXC_CCM_CGR0,
775 .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
776 .disable = _clk_disable,},
778 .name = "sdhc_clk",
779 .id = 1,
780 .parent = &perclk_clk,
781 .enable = _clk_enable,
782 .enable_reg = MXC_CCM_CGR0,
783 .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
784 .disable = _clk_disable,},
787 static struct clk ssi_clk[] = {
789 .name = "ssi_clk",
790 .parent = &serial_pll_clk,
791 .get_rate = _clk_ssi1_get_rate,
792 .enable = _clk_enable,
793 .enable_reg = MXC_CCM_CGR0,
794 .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
795 .disable = _clk_disable,},
797 .name = "ssi_clk",
798 .id = 1,
799 .parent = &serial_pll_clk,
800 .get_rate = _clk_ssi2_get_rate,
801 .enable = _clk_enable,
802 .enable_reg = MXC_CCM_CGR2,
803 .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
804 .disable = _clk_disable,},
807 static struct clk firi_clk = {
808 .name = "firi_clk",
809 .parent = &usb_pll_clk,
810 .round_rate = _clk_firi_round_rate,
811 .set_rate = _clk_firi_set_rate,
812 .get_rate = _clk_firi_get_rate,
813 .enable = _clk_enable,
814 .enable_reg = MXC_CCM_CGR2,
815 .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
816 .disable = _clk_disable,
819 static struct clk ata_clk = {
820 .name = "ata_clk",
821 .parent = &ipg_clk,
822 .enable = _clk_enable,
823 .enable_reg = MXC_CCM_CGR0,
824 .enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
825 .disable = _clk_disable,
828 static struct clk mbx_clk = {
829 .name = "mbx_clk",
830 .parent = &ahb_clk,
831 .enable = _clk_enable,
832 .enable_reg = MXC_CCM_CGR2,
833 .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
834 .get_rate = _clk_mbx_get_rate,
837 static struct clk vpu_clk = {
838 .name = "vpu_clk",
839 .parent = &ahb_clk,
840 .enable = _clk_enable,
841 .enable_reg = MXC_CCM_CGR2,
842 .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
843 .get_rate = _clk_mbx_get_rate,
846 static struct clk rtic_clk = {
847 .name = "rtic_clk",
848 .parent = &ahb_clk,
849 .enable = _clk_enable,
850 .enable_reg = MXC_CCM_CGR2,
851 .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
852 .disable = _clk_disable,
855 static struct clk rng_clk = {
856 .name = "rng_clk",
857 .parent = &ipg_clk,
858 .enable = _clk_enable,
859 .enable_reg = MXC_CCM_CGR0,
860 .enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
861 .disable = _clk_disable,
864 static struct clk sdma_clk[] = {
866 .name = "sdma_ahb_clk",
867 .parent = &ahb_clk,
868 .enable = _clk_enable,
869 .enable_reg = MXC_CCM_CGR0,
870 .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
871 .disable = _clk_disable,},
873 .name = "sdma_ipg_clk",
874 .parent = &ipg_clk,}
877 static struct clk mpeg4_clk = {
878 .name = "mpeg4_clk",
879 .parent = &ahb_clk,
880 .enable = _clk_enable,
881 .enable_reg = MXC_CCM_CGR1,
882 .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
883 .disable = _clk_disable,
886 static struct clk vl2cc_clk = {
887 .name = "vl2cc_clk",
888 .parent = &ahb_clk,
889 .enable = _clk_enable,
890 .enable_reg = MXC_CCM_CGR1,
891 .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
892 .disable = _clk_disable,
895 static struct clk mstick_clk[] = {
897 .name = "mstick_clk",
898 .id = 0,
899 .parent = &usb_pll_clk,
900 .get_rate = _clk_mstick1_get_rate,
901 .enable = _clk_enable,
902 .enable_reg = MXC_CCM_CGR1,
903 .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
904 .disable = _clk_disable,},
906 .name = "mstick_clk",
907 .id = 1,
908 .parent = &usb_pll_clk,
909 .get_rate = _clk_mstick2_get_rate,
910 .enable = _clk_enable,
911 .enable_reg = MXC_CCM_CGR1,
912 .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
913 .disable = _clk_disable,},
916 static struct clk iim_clk = {
917 .name = "iim_clk",
918 .parent = &ipg_clk,
919 .enable = _clk_enable,
920 .enable_reg = MXC_CCM_CGR0,
921 .enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
922 .disable = _clk_disable,
925 static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
927 u32 div, parent = clk_get_rate(clk->parent);
929 div = parent / rate;
930 if (parent % rate)
931 div++;
933 if (div > 8)
934 div = 16;
935 else if (div > 4)
936 div = 8;
937 else if (div > 2)
938 div = 4;
940 return parent / div;
943 static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
945 u32 reg, div, parent = clk_get_rate(clk->parent);
947 div = parent / rate;
949 if (div == 16)
950 div = 4;
951 else if (div == 8)
952 div = 3;
953 else if (div == 4)
954 div = 2;
955 else if (div == 2)
956 div = 1;
957 else if (div == 1)
958 div = 0;
959 else
960 return -EINVAL;
962 reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
963 reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
964 __raw_writel(reg, MXC_CCM_COSR);
966 return 0;
969 static unsigned long _clk_cko1_get_rate(struct clk *clk)
971 u32 div;
973 div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
974 MXC_CCM_COSR_CLKOUTDIV_OFFSET;
976 return clk_get_rate(clk->parent) / (1 << div);
979 static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
981 u32 reg;
983 reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
985 if (parent == &mcu_main_clk)
986 reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
987 else if (parent == &ipg_clk)
988 reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
989 else if (parent == &usb_pll_clk)
990 reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
991 else if (parent == mcu_main_clk.parent)
992 reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
993 else if (parent == &ahb_clk)
994 reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
995 else if (parent == &serial_pll_clk)
996 reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
997 else if (parent == &ckih_clk)
998 reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
999 else if (parent == &emi_clk)
1000 reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
1001 else if (parent == &ipu_clk)
1002 reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
1003 else if (parent == &nfc_clk)
1004 reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
1005 else if (parent == &uart_clk[0])
1006 reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
1007 else
1008 return -EINVAL;
1010 __raw_writel(reg, MXC_CCM_COSR);
1012 return 0;
1015 static int _clk_cko1_enable(struct clk *clk)
1017 u32 reg;
1019 reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
1020 __raw_writel(reg, MXC_CCM_COSR);
1022 return 0;
1025 static void _clk_cko1_disable(struct clk *clk)
1027 u32 reg;
1029 reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
1030 __raw_writel(reg, MXC_CCM_COSR);
1033 static struct clk cko1_clk = {
1034 .name = "cko1_clk",
1035 .get_rate = _clk_cko1_get_rate,
1036 .set_rate = _clk_cko1_set_rate,
1037 .round_rate = _clk_cko1_round_rate,
1038 .set_parent = _clk_cko1_set_parent,
1039 .enable = _clk_cko1_enable,
1040 .disable = _clk_cko1_disable,
1043 static struct clk *mxc_clks[] = {
1044 &ckih_clk,
1045 &ckil_clk,
1046 &mcu_pll_clk,
1047 &usb_pll_clk,
1048 &serial_pll_clk,
1049 &mcu_main_clk,
1050 &ahb_clk,
1051 &per_clk,
1052 &perclk_clk,
1053 &cko1_clk,
1054 &emi_clk,
1055 &cspi_clk[0],
1056 &cspi_clk[1],
1057 &cspi_clk[2],
1058 &ipg_clk,
1059 &gpt_clk,
1060 &pwm_clk,
1061 &wdog_clk,
1062 &rtc_clk,
1063 &epit_clk[0],
1064 &epit_clk[1],
1065 &nfc_clk,
1066 &ipu_clk,
1067 &kpp_clk,
1068 &usb_clk[0],
1069 &usb_clk[1],
1070 &csi_clk,
1071 &uart_clk[0],
1072 &uart_clk[1],
1073 &uart_clk[2],
1074 &uart_clk[3],
1075 &uart_clk[4],
1076 &i2c_clk[0],
1077 &i2c_clk[1],
1078 &i2c_clk[2],
1079 &owire_clk,
1080 &sdhc_clk[0],
1081 &sdhc_clk[1],
1082 &ssi_clk[0],
1083 &ssi_clk[1],
1084 &firi_clk,
1085 &ata_clk,
1086 &rtic_clk,
1087 &rng_clk,
1088 &sdma_clk[0],
1089 &sdma_clk[1],
1090 &mstick_clk[0],
1091 &mstick_clk[1],
1092 &scc_clk,
1093 &iim_clk,
1096 int __init mxc_clocks_init(unsigned long fref)
1098 u32 reg;
1099 struct clk **clkp;
1101 ckih_rate = fref;
1103 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1104 clk_register(*clkp);
1106 if (cpu_is_mx31()) {
1107 clk_register(&mpeg4_clk);
1108 clk_register(&mbx_clk);
1109 } else {
1110 clk_register(&vpu_clk);
1111 clk_register(&vl2cc_clk);
1114 /* Turn off all possible clocks */
1115 __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
1116 __raw_writel(0, MXC_CCM_CGR1);
1118 __raw_writel(MXC_CCM_CGR2_EMI_MASK |
1119 MXC_CCM_CGR2_IPMUX1_MASK |
1120 MXC_CCM_CGR2_IPMUX2_MASK |
1121 MXC_CCM_CGR2_MXCCLKENSEL_MASK | /* for MX32 */
1122 MXC_CCM_CGR2_CHIKCAMPEN_MASK | /* for MX32 */
1123 MXC_CCM_CGR2_OVRVPUBUSY_MASK | /* for MX32 */
1124 1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
1125 MX32, but still required to be set */
1126 MXC_CCM_CGR2);
1128 clk_disable(&cko1_clk);
1129 clk_disable(&usb_pll_clk);
1131 pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
1133 clk_enable(&gpt_clk);
1134 clk_enable(&emi_clk);
1135 clk_enable(&iim_clk);
1137 clk_enable(&serial_pll_clk);
1139 if (mx31_revision() >= CHIP_REV_2_0) {
1140 reg = __raw_readl(MXC_CCM_PMCR1);
1141 /* No PLL restart on DVFS switch; enable auto EMI handshake */
1142 reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
1143 __raw_writel(reg, MXC_CCM_PMCR1);
1146 return 0;