Merge branch 'for-rmk' of git://git.pengutronix.de/git/ukl/linux-2.6 into devel
[pandora-kernel.git] / 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 <mach/hardware.h>
28 #include <asm/div64.h>
29
30 #include "crm_regs.h"
31
32 #define PRE_DIV_MIN_FREQ    10000000 /* Minimum Frequency after Predivider */
33
34 static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
35 {
36         u32 min_pre, temp_pre, old_err, err;
37
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;
49                         }
50                         err = temp_pre - err;
51                         if (err < old_err) {
52                                 old_err = err;
53                                 *pre = temp_pre;
54                         }
55                 }
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;
63         }
64 }
65
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;
73
74 static int _clk_enable(struct clk *clk)
75 {
76         u32 reg;
77
78         reg = __raw_readl(clk->enable_reg);
79         reg |= 3 << clk->enable_shift;
80         __raw_writel(reg, clk->enable_reg);
81
82         return 0;
83 }
84
85 static void _clk_disable(struct clk *clk)
86 {
87         u32 reg;
88
89         reg = __raw_readl(clk->enable_reg);
90         reg &= ~(3 << clk->enable_shift);
91         __raw_writel(reg, clk->enable_reg);
92 }
93
94 static void _clk_emi_disable(struct clk *clk)
95 {
96         u32 reg;
97
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);
102 }
103
104 static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
105 {
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);
113
114         while (((ref_freq / pd) * 10) > rate)
115                 pd++;
116
117         if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
118                 return -EINVAL;
119
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;
124
125         /* pick a mfd value that will work
126          * then solve for mfn */
127         mfd = ref_freq / 50000;
128
129         /*
130          *          pll_freq * pd * mfd
131          *   mfn = --------------------  -  (mfi * mfd)
132          *           2 * ref_freq
133          */
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);
139
140         mfn = mfn & 0x3ff;
141         pd--;
142         mfd--;
143
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);
148
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);
155
156         return 0;
157 }
158
159 static unsigned long _clk_pll_get_rate(struct clk *clk)
160 {
161         long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
162         unsigned long reg, ccmr;
163         s64 temp;
164         unsigned int prcs;
165
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);
172
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;
186         }
187
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;
193
194         if (mfn >= 0x200) {
195                 mfn |= 0xFFFFFE00;
196                 mfn_abs = -mfn;
197         }
198
199         ref_clk *= 2;
200         ref_clk /= pdf + 1;
201
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;
207
208         return temp;
209 }
210
211 static int _clk_usb_pll_enable(struct clk *clk)
212 {
213         u32 reg;
214
215         reg = __raw_readl(MXC_CCM_CCMR);
216         reg |= MXC_CCM_CCMR_UPE;
217         __raw_writel(reg, MXC_CCM_CCMR);
218
219         /* No lock bit on MX31, so using max time from spec */
220         udelay(80);
221
222         return 0;
223 }
224
225 static void _clk_usb_pll_disable(struct clk *clk)
226 {
227         u32 reg;
228
229         reg = __raw_readl(MXC_CCM_CCMR);
230         reg &= ~MXC_CCM_CCMR_UPE;
231         __raw_writel(reg, MXC_CCM_CCMR);
232 }
233
234 static int _clk_serial_pll_enable(struct clk *clk)
235 {
236         u32 reg;
237
238         reg = __raw_readl(MXC_CCM_CCMR);
239         reg |= MXC_CCM_CCMR_SPE;
240         __raw_writel(reg, MXC_CCM_CCMR);
241
242         /* No lock bit on MX31, so using max time from spec */
243         udelay(80);
244
245         return 0;
246 }
247
248 static void _clk_serial_pll_disable(struct clk *clk)
249 {
250         u32 reg;
251
252         reg = __raw_readl(MXC_CCM_CCMR);
253         reg &= ~MXC_CCM_CCMR_SPE;
254         __raw_writel(reg, MXC_CCM_CCMR);
255 }
256
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)
260
261 static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
262 {
263         u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
264
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);
269 }
270
271 static unsigned long _clk_hclk_get_rate(struct clk *clk)
272 {
273         unsigned long max_pdf;
274
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);
278 }
279
280 static unsigned long _clk_ipg_get_rate(struct clk *clk)
281 {
282         unsigned long ipg_pdf;
283
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);
287 }
288
289 static unsigned long _clk_nfc_get_rate(struct clk *clk)
290 {
291         unsigned long nfc_pdf;
292
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);
296 }
297
298 static unsigned long _clk_hsp_get_rate(struct clk *clk)
299 {
300         unsigned long hsp_pdf;
301
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);
305 }
306
307 static unsigned long _clk_usb_get_rate(struct clk *clk)
308 {
309         unsigned long usb_pdf, usb_prepdf;
310
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);
316 }
317
318 static unsigned long _clk_csi_get_rate(struct clk *clk)
319 {
320         u32 reg, pre, post;
321
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);
330 }
331
332 static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
333 {
334         u32 pre, post, parent = clk_get_rate(clk->parent);
335         u32 div = parent / rate;
336
337         if (parent % rate)
338                 div++;
339
340         __calc_pre_post_dividers(div, &pre, &post);
341
342         return parent / (pre * post);
343 }
344
345 static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
346 {
347         u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
348
349         div = parent / rate;
350
351         if ((parent / div) != rate)
352                 return -EINVAL;
353
354         __calc_pre_post_dividers(div, &pre, &post);
355
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);
362
363         return 0;
364 }
365
366 static unsigned long _clk_per_get_rate(struct clk *clk)
367 {
368         unsigned long per_pdf;
369
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);
373 }
374
375 static unsigned long _clk_ssi1_get_rate(struct clk *clk)
376 {
377         unsigned long ssi1_pdf, ssi1_prepdf;
378
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);
384 }
385
386 static unsigned long _clk_ssi2_get_rate(struct clk *clk)
387 {
388         unsigned long ssi2_pdf, ssi2_prepdf;
389
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);
395 }
396
397 static unsigned long _clk_firi_get_rate(struct clk *clk)
398 {
399         unsigned long firi_pdf, firi_prepdf;
400
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);
406 }
407
408 static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
409 {
410         u32 pre, post;
411         u32 parent = clk_get_rate(clk->parent);
412         u32 div = parent / rate;
413
414         if (parent % rate)
415                 div++;
416
417         __calc_pre_post_dividers(div, &pre, &post);
418
419         return parent / (pre * post);
420
421 }
422
423 static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
424 {
425         u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
426
427         div = parent / rate;
428
429         if ((parent / div) != rate)
430                 return -EINVAL;
431
432         __calc_pre_post_dividers(div, &pre, &post);
433
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);
440
441         return 0;
442 }
443
444 static unsigned long _clk_mbx_get_rate(struct clk *clk)
445 {
446         return clk_get_rate(clk->parent) / 2;
447 }
448
449 static unsigned long _clk_mstick1_get_rate(struct clk *clk)
450 {
451         unsigned long msti_pdf;
452
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);
456 }
457
458 static unsigned long _clk_mstick2_get_rate(struct clk *clk)
459 {
460         unsigned long msti_pdf;
461
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);
465 }
466
467 static unsigned long ckih_rate;
468
469 static unsigned long clk_ckih_get_rate(struct clk *clk)
470 {
471         return ckih_rate;
472 }
473
474 static struct clk ckih_clk = {
475         .name = "ckih",
476         .get_rate = clk_ckih_get_rate,
477 };
478
479 static unsigned long clk_ckil_get_rate(struct clk *clk)
480 {
481         return CKIL_CLK_FREQ;
482 }
483
484 static struct clk ckil_clk = {
485         .name = "ckil",
486         .get_rate = clk_ckil_get_rate,
487 };
488
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,
494 };
495
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,
500 };
501
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,
509 };
510
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,
518 };
519
520 static struct clk ahb_clk = {
521         .name = "ahb_clk",
522         .parent = &mcu_main_clk,
523         .get_rate = _clk_hclk_get_rate,
524 };
525
526 static struct clk per_clk = {
527         .name = "per_clk",
528         .parent = &usb_pll_clk,
529         .get_rate = _clk_per_get_rate,
530 };
531
532 static struct clk perclk_clk = {
533         .name = "perclk_clk",
534         .parent = &ipg_clk,
535 };
536
537 static struct clk cspi_clk[] = {
538         {
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,},
546         {
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,},
554         {
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,},
562 };
563
564 static struct clk ipg_clk = {
565         .name = "ipg_clk",
566         .parent = &ahb_clk,
567         .get_rate = _clk_ipg_get_rate,
568 };
569
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,
577 };
578
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,
586 };
587
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,
595 };
596
597 static struct clk epit_clk[] = {
598         {
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,},
606         {
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,},
614 };
615
616 static struct clk nfc_clk = {
617         .name = "nfc_clk",
618         .parent = &ahb_clk,
619         .get_rate = _clk_nfc_get_rate,
620 };
621
622 static struct clk scc_clk = {
623         .name = "scc_clk",
624         .parent = &ipg_clk,
625 };
626
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,
635 };
636
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,
644 };
645
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,
653 };
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,
661 };
662
663 static struct clk usb_clk[] = {
664         {
665          .name = "usb_clk",
666          .parent = &usb_pll_clk,
667          .get_rate = _clk_usb_get_rate,},
668         {
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,},
675 };
676
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,
687 };
688
689 static struct clk uart_clk[] = {
690         {
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,},
698         {
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,},
706         {
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,},
714         {
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,},
722         {
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,},
730 };
731
732 static struct clk i2c_clk[] = {
733         {
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,},
741         {
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,},
749         {
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,},
757 };
758
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,
766 };
767
768 static struct clk sdhc_clk[] = {
769         {
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,},
777         {
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,},
785 };
786
787 static struct clk ssi_clk[] = {
788         {
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,},
796         {
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,},
805 };
806
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,
817 };
818
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,
826 };
827
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,
835 };
836
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,
844 };
845
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,
853 };
854
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,
862 };
863
864 static struct clk sdma_clk[] = {
865         {
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,},
872         {
873          .name = "sdma_ipg_clk",
874          .parent = &ipg_clk,}
875 };
876
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,
884 };
885
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,
893 };
894
895 static struct clk mstick_clk[] = {
896         {
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,},
905         {
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,},
914 };
915
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,
923 };
924
925 static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
926 {
927         u32 div, parent = clk_get_rate(clk->parent);
928
929         div = parent / rate;
930         if (parent % rate)
931                 div++;
932
933         if (div > 8)
934                 div = 16;
935         else if (div > 4)
936                 div = 8;
937         else if (div > 2)
938                 div = 4;
939
940         return parent / div;
941 }
942
943 static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
944 {
945         u32 reg, div, parent = clk_get_rate(clk->parent);
946
947         div = parent / rate;
948
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;
961
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);
965
966         return 0;
967 }
968
969 static unsigned long _clk_cko1_get_rate(struct clk *clk)
970 {
971         u32 div;
972
973         div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
974             MXC_CCM_COSR_CLKOUTDIV_OFFSET;
975
976         return clk_get_rate(clk->parent) / (1 << div);
977 }
978
979 static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
980 {
981         u32 reg;
982
983         reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
984
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;
1009
1010         __raw_writel(reg, MXC_CCM_COSR);
1011
1012         return 0;
1013 }
1014
1015 static int _clk_cko1_enable(struct clk *clk)
1016 {
1017         u32 reg;
1018
1019         reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
1020         __raw_writel(reg, MXC_CCM_COSR);
1021
1022         return 0;
1023 }
1024
1025 static void _clk_cko1_disable(struct clk *clk)
1026 {
1027         u32 reg;
1028
1029         reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
1030         __raw_writel(reg, MXC_CCM_COSR);
1031 }
1032
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,
1041 };
1042
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,
1094 };
1095
1096 int __init mxc_clocks_init(unsigned long fref)
1097 {
1098         u32 reg;
1099         struct clk **clkp;
1100
1101         ckih_rate = fref;
1102
1103         for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1104                 clk_register(*clkp);
1105
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);
1112         }
1113
1114         /* Turn off all possible clocks */
1115         __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
1116         __raw_writel(0, MXC_CCM_CGR1);
1117
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);
1127
1128         clk_disable(&cko1_clk);
1129         clk_disable(&usb_pll_clk);
1130
1131         pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
1132
1133         clk_enable(&gpt_clk);
1134         clk_enable(&emi_clk);
1135         clk_enable(&iim_clk);
1136
1137         clk_enable(&serial_pll_clk);
1138
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);
1144         }
1145
1146         return 0;
1147 }
1148