Merge branches 'core/softlockup', 'core/softirq', 'core/resources', 'core/printk...
[linux-2.6] / arch / arm / mach-mx3 / clock.c
1 /*
2  * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3  * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
4  *
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.
13  *
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.
18  */
19
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 <asm/div64.h>
28
29 #include "crm_regs.h"
30
31 #define PRE_DIV_MIN_FREQ    10000000 /* Minimum Frequency after Predivider */
32
33 static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
34 {
35         u32 min_pre, temp_pre, old_err, err;
36
37         if (div >= 512) {
38                 *pre = 8;
39                 *post = 64;
40         } else if (div >= 64) {
41                 min_pre = (div - 1) / 64 + 1;
42                 old_err = 8;
43                 for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
44                         err = div % temp_pre;
45                         if (err == 0) {
46                                 *pre = temp_pre;
47                                 break;
48                         }
49                         err = temp_pre - err;
50                         if (err < old_err) {
51                                 old_err = err;
52                                 *pre = temp_pre;
53                         }
54                 }
55                 *post = (div + *pre - 1) / *pre;
56         } else if (div <= 8) {
57                 *pre = div;
58                 *post = 1;
59         } else {
60                 *pre = 1;
61                 *post = div;
62         }
63 }
64
65 static struct clk mcu_pll_clk;
66 static struct clk mcu_main_clk;
67 static struct clk usb_pll_clk;
68 static struct clk serial_pll_clk;
69 static struct clk ipg_clk;
70 static struct clk ckih_clk;
71 static struct clk ahb_clk;
72
73 static int _clk_enable(struct clk *clk)
74 {
75         u32 reg;
76
77         reg = __raw_readl(clk->enable_reg);
78         reg |= 3 << clk->enable_shift;
79         __raw_writel(reg, clk->enable_reg);
80
81         return 0;
82 }
83
84 static void _clk_disable(struct clk *clk)
85 {
86         u32 reg;
87
88         reg = __raw_readl(clk->enable_reg);
89         reg &= ~(3 << clk->enable_shift);
90         __raw_writel(reg, clk->enable_reg);
91 }
92
93 static void _clk_emi_disable(struct clk *clk)
94 {
95         u32 reg;
96
97         reg = __raw_readl(clk->enable_reg);
98         reg &= ~(3 << clk->enable_shift);
99         reg |= (1 << clk->enable_shift);
100         __raw_writel(reg, clk->enable_reg);
101 }
102
103 static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
104 {
105         u32 reg;
106         signed long pd = 1;     /* Pre-divider */
107         signed long mfi;        /* Multiplication Factor (Integer part) */
108         signed long mfn;        /* Multiplication Factor (Integer part) */
109         signed long mfd;        /* Multiplication Factor (Denominator Part) */
110         signed long tmp;
111         u32 ref_freq = clk_get_rate(clk->parent);
112
113         while (((ref_freq / pd) * 10) > rate)
114                 pd++;
115
116         if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
117                 return -EINVAL;
118
119         /* the ref_freq/2 in the following is to round up */
120         mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
121         if (mfi < 5 || mfi > 15)
122                 return -EINVAL;
123
124         /* pick a mfd value that will work
125          * then solve for mfn */
126         mfd = ref_freq / 50000;
127
128         /*
129          *          pll_freq * pd * mfd
130          *   mfn = --------------------  -  (mfi * mfd)
131          *           2 * ref_freq
132          */
133         /* the tmp/2 is for rounding */
134         tmp = ref_freq / 10000;
135         mfn =
136             ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
137             (mfi * mfd);
138
139         mfn = mfn & 0x3ff;
140         pd--;
141         mfd--;
142
143         /* Change the Pll value */
144         reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
145             (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
146             (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
147
148         if (clk == &mcu_pll_clk)
149                 __raw_writel(reg, MXC_CCM_MPCTL);
150         else if (clk == &usb_pll_clk)
151                 __raw_writel(reg, MXC_CCM_UPCTL);
152         else if (clk == &serial_pll_clk)
153                 __raw_writel(reg, MXC_CCM_SRPCTL);
154
155         return 0;
156 }
157
158 static unsigned long _clk_pll_get_rate(struct clk *clk)
159 {
160         long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
161         unsigned long reg, ccmr;
162         s64 temp;
163         unsigned int prcs;
164
165         ccmr = __raw_readl(MXC_CCM_CCMR);
166         prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
167         if (prcs == 0x1)
168                 ref_clk = CKIL_CLK_FREQ * 1024;
169         else
170                 ref_clk = clk_get_rate(&ckih_clk);
171
172         if (clk == &mcu_pll_clk) {
173                 if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
174                         return ref_clk;
175                 if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
176                         return ref_clk;
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);
182         else {
183                 BUG();
184                 return 0;
185         }
186
187         pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
188         mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
189         mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
190         mfi = (mfi <= 5) ? 5 : mfi;
191         mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
192
193         if (mfn >= 0x200) {
194                 mfn |= 0xFFFFFE00;
195                 mfn_abs = -mfn;
196         }
197
198         ref_clk *= 2;
199         ref_clk /= pdf + 1;
200
201         temp = (u64) ref_clk * mfn_abs;
202         do_div(temp, mfd + 1);
203         if (mfn < 0)
204                 temp = -temp;
205         temp = (ref_clk * mfi) + temp;
206
207         return temp;
208 }
209
210 static int _clk_usb_pll_enable(struct clk *clk)
211 {
212         u32 reg;
213
214         reg = __raw_readl(MXC_CCM_CCMR);
215         reg |= MXC_CCM_CCMR_UPE;
216         __raw_writel(reg, MXC_CCM_CCMR);
217
218         /* No lock bit on MX31, so using max time from spec */
219         udelay(80);
220
221         return 0;
222 }
223
224 static void _clk_usb_pll_disable(struct clk *clk)
225 {
226         u32 reg;
227
228         reg = __raw_readl(MXC_CCM_CCMR);
229         reg &= ~MXC_CCM_CCMR_UPE;
230         __raw_writel(reg, MXC_CCM_CCMR);
231 }
232
233 static int _clk_serial_pll_enable(struct clk *clk)
234 {
235         u32 reg;
236
237         reg = __raw_readl(MXC_CCM_CCMR);
238         reg |= MXC_CCM_CCMR_SPE;
239         __raw_writel(reg, MXC_CCM_CCMR);
240
241         /* No lock bit on MX31, so using max time from spec */
242         udelay(80);
243
244         return 0;
245 }
246
247 static void _clk_serial_pll_disable(struct clk *clk)
248 {
249         u32 reg;
250
251         reg = __raw_readl(MXC_CCM_CCMR);
252         reg &= ~MXC_CCM_CCMR_SPE;
253         __raw_writel(reg, MXC_CCM_CCMR);
254 }
255
256 #define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
257 #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
258 #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
259
260 static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
261 {
262         u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
263
264         if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
265                 return clk_get_rate(&serial_pll_clk);
266         else
267                 return clk_get_rate(&mcu_pll_clk);
268 }
269
270 static unsigned long _clk_hclk_get_rate(struct clk *clk)
271 {
272         unsigned long max_pdf;
273
274         max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
275                        MXC_CCM_PDR0_MAX_PODF_OFFSET);
276         return clk_get_rate(clk->parent) / (max_pdf + 1);
277 }
278
279 static unsigned long _clk_ipg_get_rate(struct clk *clk)
280 {
281         unsigned long ipg_pdf;
282
283         ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
284                        MXC_CCM_PDR0_IPG_PODF_OFFSET);
285         return clk_get_rate(clk->parent) / (ipg_pdf + 1);
286 }
287
288 static unsigned long _clk_nfc_get_rate(struct clk *clk)
289 {
290         unsigned long nfc_pdf;
291
292         nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
293                        MXC_CCM_PDR0_NFC_PODF_OFFSET);
294         return clk_get_rate(clk->parent) / (nfc_pdf + 1);
295 }
296
297 static unsigned long _clk_hsp_get_rate(struct clk *clk)
298 {
299         unsigned long hsp_pdf;
300
301         hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
302                        MXC_CCM_PDR0_HSP_PODF_OFFSET);
303         return clk_get_rate(clk->parent) / (hsp_pdf + 1);
304 }
305
306 static unsigned long _clk_usb_get_rate(struct clk *clk)
307 {
308         unsigned long usb_pdf, usb_prepdf;
309
310         usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
311                        MXC_CCM_PDR1_USB_PODF_OFFSET);
312         usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
313                           MXC_CCM_PDR1_USB_PRDF_OFFSET);
314         return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
315 }
316
317 static unsigned long _clk_csi_get_rate(struct clk *clk)
318 {
319         u32 reg, pre, post;
320
321         reg = __raw_readl(MXC_CCM_PDR0);
322         pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
323             MXC_CCM_PDR0_CSI_PRDF_OFFSET;
324         pre++;
325         post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
326             MXC_CCM_PDR0_CSI_PODF_OFFSET;
327         post++;
328         return clk_get_rate(clk->parent) / (pre * post);
329 }
330
331 static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
332 {
333         u32 pre, post, parent = clk_get_rate(clk->parent);
334         u32 div = parent / rate;
335
336         if (parent % rate)
337                 div++;
338
339         __calc_pre_post_dividers(div, &pre, &post);
340
341         return parent / (pre * post);
342 }
343
344 static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
345 {
346         u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
347
348         div = parent / rate;
349
350         if ((parent / div) != rate)
351                 return -EINVAL;
352
353         __calc_pre_post_dividers(div, &pre, &post);
354
355         /* Set CSI clock divider */
356         reg = __raw_readl(MXC_CCM_PDR0) &
357             ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
358         reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
359         reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
360         __raw_writel(reg, MXC_CCM_PDR0);
361
362         return 0;
363 }
364
365 static unsigned long _clk_per_get_rate(struct clk *clk)
366 {
367         unsigned long per_pdf;
368
369         per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
370                        MXC_CCM_PDR0_PER_PODF_OFFSET);
371         return clk_get_rate(clk->parent) / (per_pdf + 1);
372 }
373
374 static unsigned long _clk_ssi1_get_rate(struct clk *clk)
375 {
376         unsigned long ssi1_pdf, ssi1_prepdf;
377
378         ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
379                         MXC_CCM_PDR1_SSI1_PODF_OFFSET);
380         ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
381                            MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
382         return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
383 }
384
385 static unsigned long _clk_ssi2_get_rate(struct clk *clk)
386 {
387         unsigned long ssi2_pdf, ssi2_prepdf;
388
389         ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
390                         MXC_CCM_PDR1_SSI2_PODF_OFFSET);
391         ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
392                            MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
393         return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
394 }
395
396 static unsigned long _clk_firi_get_rate(struct clk *clk)
397 {
398         unsigned long firi_pdf, firi_prepdf;
399
400         firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
401                         MXC_CCM_PDR1_FIRI_PODF_OFFSET);
402         firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
403                            MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
404         return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
405 }
406
407 static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
408 {
409         u32 pre, post;
410         u32 parent = clk_get_rate(clk->parent);
411         u32 div = parent / rate;
412
413         if (parent % rate)
414                 div++;
415
416         __calc_pre_post_dividers(div, &pre, &post);
417
418         return parent / (pre * post);
419
420 }
421
422 static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
423 {
424         u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
425
426         div = parent / rate;
427
428         if ((parent / div) != rate)
429                 return -EINVAL;
430
431         __calc_pre_post_dividers(div, &pre, &post);
432
433         /* Set FIRI clock divider */
434         reg = __raw_readl(MXC_CCM_PDR1) &
435             ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
436         reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
437         reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
438         __raw_writel(reg, MXC_CCM_PDR1);
439
440         return 0;
441 }
442
443 static unsigned long _clk_mbx_get_rate(struct clk *clk)
444 {
445         return clk_get_rate(clk->parent) / 2;
446 }
447
448 static unsigned long _clk_mstick1_get_rate(struct clk *clk)
449 {
450         unsigned long msti_pdf;
451
452         msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
453                         MXC_CCM_PDR2_MST1_PDF_OFFSET);
454         return clk_get_rate(clk->parent) / (msti_pdf + 1);
455 }
456
457 static unsigned long _clk_mstick2_get_rate(struct clk *clk)
458 {
459         unsigned long msti_pdf;
460
461         msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
462                         MXC_CCM_PDR2_MST2_PDF_OFFSET);
463         return clk_get_rate(clk->parent) / (msti_pdf + 1);
464 }
465
466 static unsigned long ckih_rate;
467
468 static unsigned long clk_ckih_get_rate(struct clk *clk)
469 {
470         return ckih_rate;
471 }
472
473 static struct clk ckih_clk = {
474         .name = "ckih",
475         .get_rate = clk_ckih_get_rate,
476 };
477
478 static unsigned long clk_ckil_get_rate(struct clk *clk)
479 {
480         return CKIL_CLK_FREQ;
481 }
482
483 static struct clk ckil_clk = {
484         .name = "ckil",
485         .get_rate = clk_ckil_get_rate,
486 };
487
488 static struct clk mcu_pll_clk = {
489         .name = "mcu_pll",
490         .parent = &ckih_clk,
491         .set_rate = _clk_pll_set_rate,
492         .get_rate = _clk_pll_get_rate,
493 };
494
495 static struct clk mcu_main_clk = {
496         .name = "mcu_main_clk",
497         .parent = &mcu_pll_clk,
498         .get_rate = _clk_mcu_main_get_rate,
499 };
500
501 static struct clk serial_pll_clk = {
502         .name = "serial_pll",
503         .parent = &ckih_clk,
504         .set_rate = _clk_pll_set_rate,
505         .get_rate = _clk_pll_get_rate,
506         .enable = _clk_serial_pll_enable,
507         .disable = _clk_serial_pll_disable,
508 };
509
510 static struct clk usb_pll_clk = {
511         .name = "usb_pll",
512         .parent = &ckih_clk,
513         .set_rate = _clk_pll_set_rate,
514         .get_rate = _clk_pll_get_rate,
515         .enable = _clk_usb_pll_enable,
516         .disable = _clk_usb_pll_disable,
517 };
518
519 static struct clk ahb_clk = {
520         .name = "ahb_clk",
521         .parent = &mcu_main_clk,
522         .get_rate = _clk_hclk_get_rate,
523 };
524
525 static struct clk per_clk = {
526         .name = "per_clk",
527         .parent = &usb_pll_clk,
528         .get_rate = _clk_per_get_rate,
529 };
530
531 static struct clk perclk_clk = {
532         .name = "perclk_clk",
533         .parent = &ipg_clk,
534 };
535
536 static struct clk cspi_clk[] = {
537         {
538          .name = "cspi_clk",
539          .id = 0,
540          .parent = &ipg_clk,
541          .enable = _clk_enable,
542          .enable_reg = MXC_CCM_CGR2,
543          .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
544          .disable = _clk_disable,},
545         {
546          .name = "cspi_clk",
547          .id = 1,
548          .parent = &ipg_clk,
549          .enable = _clk_enable,
550          .enable_reg = MXC_CCM_CGR2,
551          .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
552          .disable = _clk_disable,},
553         {
554          .name = "cspi_clk",
555          .id = 2,
556          .parent = &ipg_clk,
557          .enable = _clk_enable,
558          .enable_reg = MXC_CCM_CGR0,
559          .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
560          .disable = _clk_disable,},
561 };
562
563 static struct clk ipg_clk = {
564         .name = "ipg_clk",
565         .parent = &ahb_clk,
566         .get_rate = _clk_ipg_get_rate,
567 };
568
569 static struct clk emi_clk = {
570         .name = "emi_clk",
571         .parent = &ahb_clk,
572         .enable = _clk_enable,
573         .enable_reg = MXC_CCM_CGR2,
574         .enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
575         .disable = _clk_emi_disable,
576 };
577
578 static struct clk gpt_clk = {
579         .name = "gpt_clk",
580         .parent = &perclk_clk,
581         .enable = _clk_enable,
582         .enable_reg = MXC_CCM_CGR0,
583         .enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
584         .disable = _clk_disable,
585 };
586
587 static struct clk pwm_clk = {
588         .name = "pwm_clk",
589         .parent = &perclk_clk,
590         .enable = _clk_enable,
591         .enable_reg = MXC_CCM_CGR0,
592         .enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
593         .disable = _clk_disable,
594 };
595
596 static struct clk epit_clk[] = {
597         {
598          .name = "epit_clk",
599          .id = 0,
600          .parent = &perclk_clk,
601          .enable = _clk_enable,
602          .enable_reg = MXC_CCM_CGR0,
603          .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
604          .disable = _clk_disable,},
605         {
606          .name = "epit_clk",
607          .id = 1,
608          .parent = &perclk_clk,
609          .enable = _clk_enable,
610          .enable_reg = MXC_CCM_CGR0,
611          .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
612          .disable = _clk_disable,},
613 };
614
615 static struct clk nfc_clk = {
616         .name = "nfc_clk",
617         .parent = &ahb_clk,
618         .get_rate = _clk_nfc_get_rate,
619 };
620
621 static struct clk scc_clk = {
622         .name = "scc_clk",
623         .parent = &ipg_clk,
624 };
625
626 static struct clk ipu_clk = {
627         .name = "ipu_clk",
628         .parent = &mcu_main_clk,
629         .get_rate = _clk_hsp_get_rate,
630         .enable = _clk_enable,
631         .enable_reg = MXC_CCM_CGR1,
632         .enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
633         .disable = _clk_disable,
634 };
635
636 static struct clk kpp_clk = {
637         .name = "kpp_clk",
638         .parent = &ipg_clk,
639         .enable = _clk_enable,
640         .enable_reg = MXC_CCM_CGR1,
641         .enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
642         .disable = _clk_disable,
643 };
644
645 static struct clk wdog_clk = {
646         .name = "wdog_clk",
647         .parent = &ipg_clk,
648         .enable = _clk_enable,
649         .enable_reg = MXC_CCM_CGR1,
650         .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
651         .disable = _clk_disable,
652 };
653 static struct clk rtc_clk = {
654         .name = "rtc_clk",
655         .parent = &ipg_clk,
656         .enable = _clk_enable,
657         .enable_reg = MXC_CCM_CGR1,
658         .enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
659         .disable = _clk_disable,
660 };
661
662 static struct clk usb_clk[] = {
663         {
664          .name = "usb_clk",
665          .parent = &usb_pll_clk,
666          .get_rate = _clk_usb_get_rate,},
667         {
668          .name = "usb_ahb_clk",
669          .parent = &ahb_clk,
670          .enable = _clk_enable,
671          .enable_reg = MXC_CCM_CGR1,
672          .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
673          .disable = _clk_disable,},
674 };
675
676 static struct clk csi_clk = {
677         .name = "csi_clk",
678         .parent = &serial_pll_clk,
679         .get_rate = _clk_csi_get_rate,
680         .round_rate = _clk_csi_round_rate,
681         .set_rate = _clk_csi_set_rate,
682         .enable = _clk_enable,
683         .enable_reg = MXC_CCM_CGR1,
684         .enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
685         .disable = _clk_disable,
686 };
687
688 static struct clk uart_clk[] = {
689         {
690          .name = "uart_clk",
691          .id = 0,
692          .parent = &perclk_clk,
693          .enable = _clk_enable,
694          .enable_reg = MXC_CCM_CGR0,
695          .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
696          .disable = _clk_disable,},
697         {
698          .name = "uart_clk",
699          .id = 1,
700          .parent = &perclk_clk,
701          .enable = _clk_enable,
702          .enable_reg = MXC_CCM_CGR0,
703          .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
704          .disable = _clk_disable,},
705         {
706          .name = "uart_clk",
707          .id = 2,
708          .parent = &perclk_clk,
709          .enable = _clk_enable,
710          .enable_reg = MXC_CCM_CGR1,
711          .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
712          .disable = _clk_disable,},
713         {
714          .name = "uart_clk",
715          .id = 3,
716          .parent = &perclk_clk,
717          .enable = _clk_enable,
718          .enable_reg = MXC_CCM_CGR1,
719          .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
720          .disable = _clk_disable,},
721         {
722          .name = "uart_clk",
723          .id = 4,
724          .parent = &perclk_clk,
725          .enable = _clk_enable,
726          .enable_reg = MXC_CCM_CGR1,
727          .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
728          .disable = _clk_disable,},
729 };
730
731 static struct clk i2c_clk[] = {
732         {
733          .name = "i2c_clk",
734          .id = 0,
735          .parent = &perclk_clk,
736          .enable = _clk_enable,
737          .enable_reg = MXC_CCM_CGR0,
738          .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
739          .disable = _clk_disable,},
740         {
741          .name = "i2c_clk",
742          .id = 1,
743          .parent = &perclk_clk,
744          .enable = _clk_enable,
745          .enable_reg = MXC_CCM_CGR0,
746          .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
747          .disable = _clk_disable,},
748         {
749          .name = "i2c_clk",
750          .id = 2,
751          .parent = &perclk_clk,
752          .enable = _clk_enable,
753          .enable_reg = MXC_CCM_CGR0,
754          .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
755          .disable = _clk_disable,},
756 };
757
758 static struct clk owire_clk = {
759         .name = "owire_clk",
760         .parent = &perclk_clk,
761         .enable_reg = MXC_CCM_CGR1,
762         .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
763         .enable = _clk_enable,
764         .disable = _clk_disable,
765 };
766
767 static struct clk sdhc_clk[] = {
768         {
769          .name = "sdhc_clk",
770          .id = 0,
771          .parent = &perclk_clk,
772          .enable = _clk_enable,
773          .enable_reg = MXC_CCM_CGR0,
774          .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
775          .disable = _clk_disable,},
776         {
777          .name = "sdhc_clk",
778          .id = 1,
779          .parent = &perclk_clk,
780          .enable = _clk_enable,
781          .enable_reg = MXC_CCM_CGR0,
782          .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
783          .disable = _clk_disable,},
784 };
785
786 static struct clk ssi_clk[] = {
787         {
788          .name = "ssi_clk",
789          .parent = &serial_pll_clk,
790          .get_rate = _clk_ssi1_get_rate,
791          .enable = _clk_enable,
792          .enable_reg = MXC_CCM_CGR0,
793          .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
794          .disable = _clk_disable,},
795         {
796          .name = "ssi_clk",
797          .id = 1,
798          .parent = &serial_pll_clk,
799          .get_rate = _clk_ssi2_get_rate,
800          .enable = _clk_enable,
801          .enable_reg = MXC_CCM_CGR2,
802          .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
803          .disable = _clk_disable,},
804 };
805
806 static struct clk firi_clk = {
807         .name = "firi_clk",
808         .parent = &usb_pll_clk,
809         .round_rate = _clk_firi_round_rate,
810         .set_rate = _clk_firi_set_rate,
811         .get_rate = _clk_firi_get_rate,
812         .enable = _clk_enable,
813         .enable_reg = MXC_CCM_CGR2,
814         .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
815         .disable = _clk_disable,
816 };
817
818 static struct clk ata_clk = {
819         .name = "ata_clk",
820         .parent = &ipg_clk,
821         .enable = _clk_enable,
822         .enable_reg = MXC_CCM_CGR0,
823         .enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
824         .disable = _clk_disable,
825 };
826
827 static struct clk mbx_clk = {
828         .name = "mbx_clk",
829         .parent = &ahb_clk,
830         .enable = _clk_enable,
831         .enable_reg = MXC_CCM_CGR2,
832         .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
833         .get_rate = _clk_mbx_get_rate,
834 };
835
836 static struct clk vpu_clk = {
837         .name = "vpu_clk",
838         .parent = &ahb_clk,
839         .enable = _clk_enable,
840         .enable_reg = MXC_CCM_CGR2,
841         .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
842         .get_rate = _clk_mbx_get_rate,
843 };
844
845 static struct clk rtic_clk = {
846         .name = "rtic_clk",
847         .parent = &ahb_clk,
848         .enable = _clk_enable,
849         .enable_reg = MXC_CCM_CGR2,
850         .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
851         .disable = _clk_disable,
852 };
853
854 static struct clk rng_clk = {
855         .name = "rng_clk",
856         .parent = &ipg_clk,
857         .enable = _clk_enable,
858         .enable_reg = MXC_CCM_CGR0,
859         .enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
860         .disable = _clk_disable,
861 };
862
863 static struct clk sdma_clk[] = {
864         {
865          .name = "sdma_ahb_clk",
866          .parent = &ahb_clk,
867          .enable = _clk_enable,
868          .enable_reg = MXC_CCM_CGR0,
869          .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
870          .disable = _clk_disable,},
871         {
872          .name = "sdma_ipg_clk",
873          .parent = &ipg_clk,}
874 };
875
876 static struct clk mpeg4_clk = {
877         .name = "mpeg4_clk",
878         .parent = &ahb_clk,
879         .enable = _clk_enable,
880         .enable_reg = MXC_CCM_CGR1,
881         .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
882         .disable = _clk_disable,
883 };
884
885 static struct clk vl2cc_clk = {
886         .name = "vl2cc_clk",
887         .parent = &ahb_clk,
888         .enable = _clk_enable,
889         .enable_reg = MXC_CCM_CGR1,
890         .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
891         .disable = _clk_disable,
892 };
893
894 static struct clk mstick_clk[] = {
895         {
896          .name = "mstick_clk",
897          .id = 0,
898          .parent = &usb_pll_clk,
899          .get_rate = _clk_mstick1_get_rate,
900          .enable = _clk_enable,
901          .enable_reg = MXC_CCM_CGR1,
902          .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
903          .disable = _clk_disable,},
904         {
905          .name = "mstick_clk",
906          .id = 1,
907          .parent = &usb_pll_clk,
908          .get_rate = _clk_mstick2_get_rate,
909          .enable = _clk_enable,
910          .enable_reg = MXC_CCM_CGR1,
911          .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
912          .disable = _clk_disable,},
913 };
914
915 static struct clk iim_clk = {
916         .name = "iim_clk",
917         .parent = &ipg_clk,
918         .enable = _clk_enable,
919         .enable_reg = MXC_CCM_CGR0,
920         .enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
921         .disable = _clk_disable,
922 };
923
924 static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
925 {
926         u32 div, parent = clk_get_rate(clk->parent);
927
928         div = parent / rate;
929         if (parent % rate)
930                 div++;
931
932         if (div > 8)
933                 div = 16;
934         else if (div > 4)
935                 div = 8;
936         else if (div > 2)
937                 div = 4;
938
939         return parent / div;
940 }
941
942 static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
943 {
944         u32 reg, div, parent = clk_get_rate(clk->parent);
945
946         div = parent / rate;
947
948         if (div == 16)
949                 div = 4;
950         else if (div == 8)
951                 div = 3;
952         else if (div == 4)
953                 div = 2;
954         else if (div == 2)
955                 div = 1;
956         else if (div == 1)
957                 div = 0;
958         else
959                 return -EINVAL;
960
961         reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
962         reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
963         __raw_writel(reg, MXC_CCM_COSR);
964
965         return 0;
966 }
967
968 static unsigned long _clk_cko1_get_rate(struct clk *clk)
969 {
970         u32 div;
971
972         div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
973             MXC_CCM_COSR_CLKOUTDIV_OFFSET;
974
975         return clk_get_rate(clk->parent) / (1 << div);
976 }
977
978 static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
979 {
980         u32 reg;
981
982         reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
983
984         if (parent == &mcu_main_clk)
985                 reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
986         else if (parent == &ipg_clk)
987                 reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
988         else if (parent == &usb_pll_clk)
989                 reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
990         else if (parent == mcu_main_clk.parent)
991                 reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
992         else if (parent == &ahb_clk)
993                 reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
994         else if (parent == &serial_pll_clk)
995                 reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
996         else if (parent == &ckih_clk)
997                 reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
998         else if (parent == &emi_clk)
999                 reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
1000         else if (parent == &ipu_clk)
1001                 reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
1002         else if (parent == &nfc_clk)
1003                 reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
1004         else if (parent == &uart_clk[0])
1005                 reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
1006         else
1007                 return -EINVAL;
1008
1009         __raw_writel(reg, MXC_CCM_COSR);
1010
1011         return 0;
1012 }
1013
1014 static int _clk_cko1_enable(struct clk *clk)
1015 {
1016         u32 reg;
1017
1018         reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
1019         __raw_writel(reg, MXC_CCM_COSR);
1020
1021         return 0;
1022 }
1023
1024 static void _clk_cko1_disable(struct clk *clk)
1025 {
1026         u32 reg;
1027
1028         reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
1029         __raw_writel(reg, MXC_CCM_COSR);
1030 }
1031
1032 static struct clk cko1_clk = {
1033         .name = "cko1_clk",
1034         .get_rate = _clk_cko1_get_rate,
1035         .set_rate = _clk_cko1_set_rate,
1036         .round_rate = _clk_cko1_round_rate,
1037         .set_parent = _clk_cko1_set_parent,
1038         .enable = _clk_cko1_enable,
1039         .disable = _clk_cko1_disable,
1040 };
1041
1042 static struct clk *mxc_clks[] = {
1043         &ckih_clk,
1044         &ckil_clk,
1045         &mcu_pll_clk,
1046         &usb_pll_clk,
1047         &serial_pll_clk,
1048         &mcu_main_clk,
1049         &ahb_clk,
1050         &per_clk,
1051         &perclk_clk,
1052         &cko1_clk,
1053         &emi_clk,
1054         &cspi_clk[0],
1055         &cspi_clk[1],
1056         &cspi_clk[2],
1057         &ipg_clk,
1058         &gpt_clk,
1059         &pwm_clk,
1060         &wdog_clk,
1061         &rtc_clk,
1062         &epit_clk[0],
1063         &epit_clk[1],
1064         &nfc_clk,
1065         &ipu_clk,
1066         &kpp_clk,
1067         &usb_clk[0],
1068         &usb_clk[1],
1069         &csi_clk,
1070         &uart_clk[0],
1071         &uart_clk[1],
1072         &uart_clk[2],
1073         &uart_clk[3],
1074         &uart_clk[4],
1075         &i2c_clk[0],
1076         &i2c_clk[1],
1077         &i2c_clk[2],
1078         &owire_clk,
1079         &sdhc_clk[0],
1080         &sdhc_clk[1],
1081         &ssi_clk[0],
1082         &ssi_clk[1],
1083         &firi_clk,
1084         &ata_clk,
1085         &rtic_clk,
1086         &rng_clk,
1087         &sdma_clk[0],
1088         &sdma_clk[1],
1089         &mstick_clk[0],
1090         &mstick_clk[1],
1091         &scc_clk,
1092         &iim_clk,
1093 };
1094
1095 int __init mxc_clocks_init(unsigned long fref)
1096 {
1097         u32 reg;
1098         struct clk **clkp;
1099
1100         ckih_rate = fref;
1101
1102         for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1103                 clk_register(*clkp);
1104
1105         if (cpu_is_mx31()) {
1106                 clk_register(&mpeg4_clk);
1107                 clk_register(&mbx_clk);
1108         } else {
1109                 clk_register(&vpu_clk);
1110                 clk_register(&vl2cc_clk);
1111         }
1112
1113         /* Turn off all possible clocks */
1114         __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
1115         __raw_writel(0, MXC_CCM_CGR1);
1116
1117         __raw_writel(MXC_CCM_CGR2_EMI_MASK |
1118                      MXC_CCM_CGR2_IPMUX1_MASK |
1119                      MXC_CCM_CGR2_IPMUX2_MASK |
1120                      MXC_CCM_CGR2_MXCCLKENSEL_MASK |    /* for MX32 */
1121                      MXC_CCM_CGR2_CHIKCAMPEN_MASK |     /* for MX32 */
1122                      MXC_CCM_CGR2_OVRVPUBUSY_MASK |     /* for MX32 */
1123                      1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
1124                                            MX32, but still required to be set */
1125                      MXC_CCM_CGR2);
1126
1127         clk_disable(&cko1_clk);
1128         clk_disable(&usb_pll_clk);
1129
1130         pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
1131
1132         clk_enable(&gpt_clk);
1133         clk_enable(&emi_clk);
1134         clk_enable(&iim_clk);
1135
1136         clk_enable(&serial_pll_clk);
1137
1138         if (mx31_revision() >= CHIP_REV_2_0) {
1139                 reg = __raw_readl(MXC_CCM_PMCR1);
1140                 /* No PLL restart on DVFS switch; enable auto EMI handshake */
1141                 reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
1142                 __raw_writel(reg, MXC_CCM_PMCR1);
1143         }
1144
1145         return 0;
1146 }
1147