Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[pandora-kernel.git] / arch / arm / mach-mx2 / clock_imx21.c
1 /*
2  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4  * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  */
20
21 #include <linux/clk.h>
22 #include <linux/io.h>
23 #include <linux/module.h>
24
25 #include <mach/clock.h>
26 #include <mach/common.h>
27 #include <asm/clkdev.h>
28 #include <asm/div64.h>
29
30 #include "crm_regs.h"
31
32 static int _clk_enable(struct clk *clk)
33 {
34         u32 reg;
35
36         reg = __raw_readl(clk->enable_reg);
37         reg |= 1 << clk->enable_shift;
38         __raw_writel(reg, clk->enable_reg);
39         return 0;
40 }
41
42 static void _clk_disable(struct clk *clk)
43 {
44         u32 reg;
45
46         reg = __raw_readl(clk->enable_reg);
47         reg &= ~(1 << clk->enable_shift);
48         __raw_writel(reg, clk->enable_reg);
49 }
50
51 static int _clk_spll_enable(struct clk *clk)
52 {
53         u32 reg;
54
55         reg = __raw_readl(CCM_CSCR);
56         reg |= CCM_CSCR_SPEN;
57         __raw_writel(reg, CCM_CSCR);
58
59         while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
60                 ;
61         return 0;
62 }
63
64 static void _clk_spll_disable(struct clk *clk)
65 {
66         u32 reg;
67
68         reg = __raw_readl(CCM_CSCR);
69         reg &= ~CCM_CSCR_SPEN;
70         __raw_writel(reg, CCM_CSCR);
71 }
72
73
74 #define CSCR() (__raw_readl(CCM_CSCR))
75 #define PCDR0() (__raw_readl(CCM_PCDR0))
76 #define PCDR1() (__raw_readl(CCM_PCDR1))
77
78 static unsigned long _clk_perclkx_round_rate(struct clk *clk,
79                                              unsigned long rate)
80 {
81         u32 div;
82         unsigned long parent_rate;
83
84         parent_rate = clk_get_rate(clk->parent);
85
86         div = parent_rate / rate;
87         if (parent_rate % rate)
88                 div++;
89
90         if (div > 64)
91                 div = 64;
92
93         return parent_rate / div;
94 }
95
96 static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
97 {
98         u32 reg;
99         u32 div;
100         unsigned long parent_rate;
101
102         parent_rate = clk_get_rate(clk->parent);
103
104         if (clk->id < 0 || clk->id > 3)
105                 return -EINVAL;
106
107         div = parent_rate / rate;
108         if (div > 64 || div < 1 || ((parent_rate / div) != rate))
109                 return -EINVAL;
110         div--;
111
112         reg =
113             __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
114                                        (clk->id << 3));
115         reg |= div << (clk->id << 3);
116         __raw_writel(reg, CCM_PCDR1);
117
118         return 0;
119 }
120
121 static unsigned long _clk_usb_recalc(struct clk *clk)
122 {
123         unsigned long usb_pdf;
124         unsigned long parent_rate;
125
126         parent_rate = clk_get_rate(clk->parent);
127
128         usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
129
130         return parent_rate / (usb_pdf + 1U);
131 }
132
133 static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf)
134 {
135         unsigned long parent_rate;
136
137         parent_rate = clk_get_rate(clk->parent);
138
139         pdf = (pdf < 2) ? 124UL : pdf;  /* MX21 & MX27 TO1 */
140
141         return 2UL * parent_rate / pdf;
142 }
143
144 static unsigned long _clk_ssi1_recalc(struct clk *clk)
145 {
146         return _clk_ssix_recalc(clk,
147                 (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK)
148                 >> CCM_PCDR0_SSI1BAUDDIV_OFFSET);
149 }
150
151 static unsigned long _clk_ssi2_recalc(struct clk *clk)
152 {
153         return _clk_ssix_recalc(clk,
154                 (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
155                 CCM_PCDR0_SSI2BAUDDIV_OFFSET);
156 }
157
158 static unsigned long _clk_nfc_recalc(struct clk *clk)
159 {
160         unsigned long nfc_pdf;
161         unsigned long parent_rate;
162
163         parent_rate = clk_get_rate(clk->parent);
164
165         nfc_pdf = (PCDR0() & CCM_PCDR0_NFCDIV_MASK)
166                 >> CCM_PCDR0_NFCDIV_OFFSET;
167
168         return parent_rate / (nfc_pdf + 1);
169 }
170
171 static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
172 {
173         return clk->parent->round_rate(clk->parent, rate);
174 }
175
176 static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
177 {
178         return clk->parent->set_rate(clk->parent, rate);
179 }
180
181 static unsigned long external_high_reference; /* in Hz */
182
183 static unsigned long get_high_reference_clock_rate(struct clk *clk)
184 {
185         return external_high_reference;
186 }
187
188 /*
189  * the high frequency external clock reference
190  * Default case is 26MHz.
191  */
192 static struct clk ckih_clk = {
193         .get_rate = get_high_reference_clock_rate,
194 };
195
196 static unsigned long external_low_reference; /* in Hz */
197
198 static unsigned long get_low_reference_clock_rate(struct clk *clk)
199 {
200         return external_low_reference;
201 }
202
203 /*
204  * the low frequency external clock reference
205  * Default case is 32.768kHz.
206  */
207 static struct clk ckil_clk = {
208         .get_rate = get_low_reference_clock_rate,
209 };
210
211
212 static unsigned long _clk_fpm_recalc(struct clk *clk)
213 {
214         return clk_get_rate(clk->parent) * 512;
215 }
216
217 /* Output of frequency pre multiplier */
218 static struct clk fpm_clk = {
219         .parent = &ckil_clk,
220         .get_rate = _clk_fpm_recalc,
221 };
222
223 static unsigned long get_mpll_clk(struct clk *clk)
224 {
225         uint32_t reg;
226         unsigned long ref_clk;
227         unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
228         unsigned long long temp;
229
230         ref_clk = clk_get_rate(clk->parent);
231
232         reg = __raw_readl(CCM_MPCTL0);
233         pdf = (reg & CCM_MPCTL0_PD_MASK)  >> CCM_MPCTL0_PD_OFFSET;
234         mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
235         mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
236         mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
237
238         mfi = (mfi <= 5) ? 5 : mfi;
239         temp = 2LL * ref_clk * mfn;
240         do_div(temp, mfd + 1);
241         temp = 2LL * ref_clk * mfi + temp;
242         do_div(temp, pdf + 1);
243
244         return (unsigned long)temp;
245 }
246
247 static struct clk mpll_clk = {
248         .parent = &ckih_clk,
249         .get_rate = get_mpll_clk,
250 };
251
252 static unsigned long _clk_fclk_get_rate(struct clk *clk)
253 {
254         unsigned long parent_rate;
255         u32 div;
256
257         div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
258         parent_rate = clk_get_rate(clk->parent);
259
260         return parent_rate / (div+1);
261 }
262
263 static struct clk fclk_clk = {
264         .parent = &mpll_clk,
265         .get_rate = _clk_fclk_get_rate
266 };
267
268 static unsigned long get_spll_clk(struct clk *clk)
269 {
270         uint32_t reg;
271         unsigned long ref_clk;
272         unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
273         unsigned long long temp;
274
275         ref_clk = clk_get_rate(clk->parent);
276
277         reg = __raw_readl(CCM_SPCTL0);
278         pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
279         mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
280         mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
281         mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
282
283         mfi = (mfi <= 5) ? 5 : mfi;
284         temp = 2LL * ref_clk * mfn;
285         do_div(temp, mfd + 1);
286         temp = 2LL * ref_clk * mfi + temp;
287         do_div(temp, pdf + 1);
288
289         return (unsigned long)temp;
290 }
291
292 static struct clk spll_clk = {
293         .parent = &ckih_clk,
294         .get_rate = get_spll_clk,
295         .enable = _clk_spll_enable,
296         .disable = _clk_spll_disable,
297 };
298
299 static unsigned long get_hclk_clk(struct clk *clk)
300 {
301         unsigned long rate;
302         unsigned long bclk_pdf;
303
304         bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
305                 >> CCM_CSCR_BCLK_OFFSET;
306
307         rate = clk_get_rate(clk->parent);
308         return rate / (bclk_pdf + 1);
309 }
310
311 static struct clk hclk_clk = {
312         .parent = &fclk_clk,
313         .get_rate = get_hclk_clk,
314 };
315
316 static unsigned long get_ipg_clk(struct clk *clk)
317 {
318         unsigned long rate;
319         unsigned long ipg_pdf;
320
321         ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
322
323         rate = clk_get_rate(clk->parent);
324         return rate / (ipg_pdf + 1);
325 }
326
327 static struct clk ipg_clk = {
328         .parent = &hclk_clk,
329         .get_rate = get_ipg_clk,
330 };
331
332 static unsigned long _clk_perclkx_recalc(struct clk *clk)
333 {
334         unsigned long perclk_pdf;
335         unsigned long parent_rate;
336
337         parent_rate = clk_get_rate(clk->parent);
338
339         if (clk->id < 0 || clk->id > 3)
340                 return 0;
341
342         perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
343
344         return parent_rate / (perclk_pdf + 1);
345 }
346
347 static struct clk per_clk[] = {
348         {
349                 .id = 0,
350                 .parent = &mpll_clk,
351                 .get_rate = _clk_perclkx_recalc,
352         }, {
353                 .id = 1,
354                 .parent = &mpll_clk,
355                 .get_rate = _clk_perclkx_recalc,
356         }, {
357                 .id = 2,
358                 .parent = &mpll_clk,
359                 .round_rate = _clk_perclkx_round_rate,
360                 .set_rate = _clk_perclkx_set_rate,
361                 .get_rate = _clk_perclkx_recalc,
362                 /* Enable/Disable done via lcd_clkc[1] */
363         }, {
364                 .id = 3,
365                 .parent = &mpll_clk,
366                 .round_rate = _clk_perclkx_round_rate,
367                 .set_rate = _clk_perclkx_set_rate,
368                 .get_rate = _clk_perclkx_recalc,
369                 /* Enable/Disable done via csi_clk[1] */
370         },
371 };
372
373 static struct clk uart_ipg_clk[];
374
375 static struct clk uart_clk[] = {
376         {
377                 .id = 0,
378                 .parent = &per_clk[0],
379                 .secondary = &uart_ipg_clk[0],
380         }, {
381                 .id = 1,
382                 .parent = &per_clk[0],
383                 .secondary = &uart_ipg_clk[1],
384         }, {
385                 .id = 2,
386                 .parent = &per_clk[0],
387                 .secondary = &uart_ipg_clk[2],
388         }, {
389                 .id = 3,
390                 .parent = &per_clk[0],
391                 .secondary = &uart_ipg_clk[3],
392         },
393 };
394
395 static struct clk uart_ipg_clk[] = {
396         {
397                 .id = 0,
398                 .parent = &ipg_clk,
399                 .enable = _clk_enable,
400                 .enable_reg = CCM_PCCR_UART1_REG,
401                 .enable_shift = CCM_PCCR_UART1_OFFSET,
402                 .disable = _clk_disable,
403         }, {
404                 .id = 1,
405                 .parent = &ipg_clk,
406                 .enable = _clk_enable,
407                 .enable_reg = CCM_PCCR_UART2_REG,
408                 .enable_shift = CCM_PCCR_UART2_OFFSET,
409                 .disable = _clk_disable,
410         }, {
411                 .id = 2,
412                 .parent = &ipg_clk,
413                 .enable = _clk_enable,
414                 .enable_reg = CCM_PCCR_UART3_REG,
415                 .enable_shift = CCM_PCCR_UART3_OFFSET,
416                 .disable = _clk_disable,
417         }, {
418                 .id = 3,
419                 .parent = &ipg_clk,
420                 .enable = _clk_enable,
421                 .enable_reg = CCM_PCCR_UART4_REG,
422                 .enable_shift = CCM_PCCR_UART4_OFFSET,
423                 .disable = _clk_disable,
424         },
425 };
426
427 static struct clk gpt_ipg_clk[];
428
429 static struct clk gpt_clk[] = {
430         {
431                 .id = 0,
432                 .parent = &per_clk[0],
433                 .secondary = &gpt_ipg_clk[0],
434         }, {
435                 .id = 1,
436                 .parent = &per_clk[0],
437                 .secondary = &gpt_ipg_clk[1],
438         }, {
439                 .id = 2,
440                 .parent = &per_clk[0],
441                 .secondary = &gpt_ipg_clk[2],
442         },
443 };
444
445 static struct clk gpt_ipg_clk[] = {
446         {
447                 .id = 0,
448                 .parent = &ipg_clk,
449                 .enable = _clk_enable,
450                 .enable_reg = CCM_PCCR_GPT1_REG,
451                 .enable_shift = CCM_PCCR_GPT1_OFFSET,
452                 .disable = _clk_disable,
453         }, {
454                 .id = 1,
455                 .parent = &ipg_clk,
456                 .enable = _clk_enable,
457                 .enable_reg = CCM_PCCR_GPT2_REG,
458                 .enable_shift = CCM_PCCR_GPT2_OFFSET,
459                 .disable = _clk_disable,
460         }, {
461                 .id = 2,
462                 .parent = &ipg_clk,
463                 .enable = _clk_enable,
464                 .enable_reg = CCM_PCCR_GPT3_REG,
465                 .enable_shift = CCM_PCCR_GPT3_OFFSET,
466                 .disable = _clk_disable,
467         },
468 };
469
470 static struct clk pwm_clk[] = {
471         {
472                 .parent = &per_clk[0],
473                 .secondary = &pwm_clk[1],
474         }, {
475                 .parent = &ipg_clk,
476                 .enable = _clk_enable,
477                 .enable_reg = CCM_PCCR_PWM_REG,
478                 .enable_shift = CCM_PCCR_PWM_OFFSET,
479                 .disable = _clk_disable,
480         },
481 };
482
483 static struct clk sdhc_ipg_clk[];
484
485 static struct clk sdhc_clk[] = {
486         {
487                 .id = 0,
488                 .parent = &per_clk[1],
489                 .secondary = &sdhc_ipg_clk[0],
490         }, {
491                 .id = 1,
492                 .parent = &per_clk[1],
493                 .secondary = &sdhc_ipg_clk[1],
494         },
495 };
496
497 static struct clk sdhc_ipg_clk[] = {
498         {
499                 .id = 0,
500                 .parent = &ipg_clk,
501                 .enable = _clk_enable,
502                 .enable_reg = CCM_PCCR_SDHC1_REG,
503                 .enable_shift = CCM_PCCR_SDHC1_OFFSET,
504                 .disable = _clk_disable,
505         }, {
506                 .id = 1,
507                 .parent = &ipg_clk,
508                 .enable = _clk_enable,
509                 .enable_reg = CCM_PCCR_SDHC2_REG,
510                 .enable_shift = CCM_PCCR_SDHC2_OFFSET,
511                 .disable = _clk_disable,
512         },
513 };
514
515 static struct clk cspi_ipg_clk[];
516
517 static struct clk cspi_clk[] = {
518         {
519                 .id = 0,
520                 .parent = &per_clk[1],
521                 .secondary = &cspi_ipg_clk[0],
522         }, {
523                 .id = 1,
524                 .parent = &per_clk[1],
525                 .secondary = &cspi_ipg_clk[1],
526         }, {
527                 .id = 2,
528                 .parent = &per_clk[1],
529                 .secondary = &cspi_ipg_clk[2],
530         },
531 };
532
533 static struct clk cspi_ipg_clk[] = {
534         {
535                 .id = 0,
536                 .parent = &ipg_clk,
537                 .enable = _clk_enable,
538                 .enable_reg = CCM_PCCR_CSPI1_REG,
539                 .enable_shift = CCM_PCCR_CSPI1_OFFSET,
540                 .disable = _clk_disable,
541         }, {
542                 .id = 1,
543                 .parent = &ipg_clk,
544                 .enable = _clk_enable,
545                 .enable_reg = CCM_PCCR_CSPI2_REG,
546                 .enable_shift = CCM_PCCR_CSPI2_OFFSET,
547                 .disable = _clk_disable,
548         }, {
549                 .id = 3,
550                 .parent = &ipg_clk,
551                 .enable = _clk_enable,
552                 .enable_reg = CCM_PCCR_CSPI3_REG,
553                 .enable_shift = CCM_PCCR_CSPI3_OFFSET,
554                 .disable = _clk_disable,
555         },
556 };
557
558 static struct clk lcdc_clk[] = {
559         {
560                 .parent = &per_clk[2],
561                 .secondary = &lcdc_clk[1],
562                 .round_rate = _clk_parent_round_rate,
563                 .set_rate = _clk_parent_set_rate,
564         }, {
565                 .parent = &ipg_clk,
566                 .secondary = &lcdc_clk[2],
567                 .enable = _clk_enable,
568                 .enable_reg = CCM_PCCR_LCDC_REG,
569                 .enable_shift = CCM_PCCR_LCDC_OFFSET,
570                 .disable = _clk_disable,
571         }, {
572                 .parent = &hclk_clk,
573                 .enable = _clk_enable,
574                 .enable_reg = CCM_PCCR_HCLK_LCDC_REG,
575                 .enable_shift = CCM_PCCR_HCLK_LCDC_OFFSET,
576                 .disable = _clk_disable,
577         },
578 };
579
580 static struct clk csi_clk[] = {
581         {
582                 .parent = &per_clk[3],
583                 .secondary = &csi_clk[1],
584                 .round_rate = _clk_parent_round_rate,
585                 .set_rate = _clk_parent_set_rate,
586         }, {
587                 .parent = &hclk_clk,
588                 .enable = _clk_enable,
589                 .enable_reg = CCM_PCCR_HCLK_CSI_REG,
590                 .enable_shift = CCM_PCCR_HCLK_CSI_OFFSET,
591                 .disable = _clk_disable,
592         },
593 };
594
595 static struct clk usb_clk[] = {
596         {
597                 .parent = &spll_clk,
598                 .get_rate = _clk_usb_recalc,
599                 .enable = _clk_enable,
600                 .enable_reg = CCM_PCCR_USBOTG_REG,
601                 .enable_shift = CCM_PCCR_USBOTG_OFFSET,
602                 .disable = _clk_disable,
603         }, {
604                 .parent = &hclk_clk,
605                 .enable = _clk_enable,
606                 .enable_reg = CCM_PCCR_HCLK_USBOTG_REG,
607                 .enable_shift = CCM_PCCR_HCLK_USBOTG_OFFSET,
608                 .disable = _clk_disable,
609         }
610 };
611
612 static struct clk ssi_ipg_clk[];
613
614 static struct clk ssi_clk[] = {
615         {
616                 .id = 0,
617                 .parent = &mpll_clk,
618                 .secondary = &ssi_ipg_clk[0],
619                 .get_rate = _clk_ssi1_recalc,
620                 .enable = _clk_enable,
621                 .enable_reg = CCM_PCCR_SSI1_BAUD_REG,
622                 .enable_shift = CCM_PCCR_SSI1_BAUD_OFFSET,
623                 .disable = _clk_disable,
624         }, {
625                 .id = 1,
626                 .parent = &mpll_clk,
627                 .secondary = &ssi_ipg_clk[1],
628                 .get_rate = _clk_ssi2_recalc,
629                 .enable = _clk_enable,
630                 .enable_reg = CCM_PCCR_SSI2_BAUD_REG,
631                 .enable_shift = CCM_PCCR_SSI2_BAUD_OFFSET,
632                 .disable = _clk_disable,
633         },
634 };
635
636 static struct clk ssi_ipg_clk[] = {
637         {
638                 .id = 0,
639                 .parent = &ipg_clk,
640                 .enable = _clk_enable,
641                 .enable_reg = CCM_PCCR_SSI1_REG,
642                 .enable_shift = CCM_PCCR_SSI1_IPG_OFFSET,
643                 .disable = _clk_disable,
644         }, {
645                 .id = 1,
646                 .parent = &ipg_clk,
647                 .enable = _clk_enable,
648                 .enable_reg = CCM_PCCR_SSI2_REG,
649                 .enable_shift = CCM_PCCR_SSI2_IPG_OFFSET,
650                 .disable = _clk_disable,
651         },
652 };
653
654
655 static struct clk nfc_clk = {
656         .parent = &fclk_clk,
657         .get_rate = _clk_nfc_recalc,
658         .enable = _clk_enable,
659         .enable_reg = CCM_PCCR_NFC_REG,
660         .enable_shift = CCM_PCCR_NFC_OFFSET,
661         .disable = _clk_disable,
662 };
663
664 static struct clk dma_clk[] = {
665         {
666                 .parent = &hclk_clk,
667                 .enable = _clk_enable,
668                 .enable_reg = CCM_PCCR_DMA_REG,
669                 .enable_shift = CCM_PCCR_DMA_OFFSET,
670                 .disable = _clk_disable,
671                 .secondary = &dma_clk[1],
672         },  {
673                 .enable = _clk_enable,
674                 .enable_reg = CCM_PCCR_HCLK_DMA_REG,
675                 .enable_shift = CCM_PCCR_HCLK_DMA_OFFSET,
676                 .disable = _clk_disable,
677         },
678 };
679
680 static struct clk brom_clk = {
681         .parent = &hclk_clk,
682         .enable = _clk_enable,
683         .enable_reg = CCM_PCCR_HCLK_BROM_REG,
684         .enable_shift = CCM_PCCR_HCLK_BROM_OFFSET,
685         .disable = _clk_disable,
686 };
687
688 static struct clk emma_clk[] = {
689         {
690                 .parent = &hclk_clk,
691                 .enable = _clk_enable,
692                 .enable_reg = CCM_PCCR_EMMA_REG,
693                 .enable_shift = CCM_PCCR_EMMA_OFFSET,
694                 .disable = _clk_disable,
695                 .secondary = &emma_clk[1],
696         }, {
697                 .enable = _clk_enable,
698                 .enable_reg = CCM_PCCR_HCLK_EMMA_REG,
699                 .enable_shift = CCM_PCCR_HCLK_EMMA_OFFSET,
700                 .disable = _clk_disable,
701         }
702 };
703
704 static struct clk slcdc_clk[] = {
705         {
706                 .parent = &hclk_clk,
707                 .enable = _clk_enable,
708                 .enable_reg = CCM_PCCR_SLCDC_REG,
709                 .enable_shift = CCM_PCCR_SLCDC_OFFSET,
710                 .disable = _clk_disable,
711                 .secondary = &slcdc_clk[1],
712         }, {
713                 .enable = _clk_enable,
714                 .enable_reg = CCM_PCCR_HCLK_SLCDC_REG,
715                 .enable_shift = CCM_PCCR_HCLK_SLCDC_OFFSET,
716                 .disable = _clk_disable,
717         }
718 };
719
720 static struct clk wdog_clk = {
721         .parent = &ipg_clk,
722         .enable = _clk_enable,
723         .enable_reg = CCM_PCCR_WDT_REG,
724         .enable_shift = CCM_PCCR_WDT_OFFSET,
725         .disable = _clk_disable,
726 };
727
728 static struct clk gpio_clk = {
729         .parent = &ipg_clk,
730         .enable = _clk_enable,
731         .enable_reg = CCM_PCCR_GPIO_REG,
732         .enable_shift = CCM_PCCR_GPIO_OFFSET,
733         .disable = _clk_disable,
734 };
735
736 static struct clk i2c_clk = {
737         .id = 0,
738         .parent = &ipg_clk,
739         .enable = _clk_enable,
740         .enable_reg = CCM_PCCR_I2C1_REG,
741         .enable_shift = CCM_PCCR_I2C1_OFFSET,
742         .disable = _clk_disable,
743 };
744
745 static struct clk kpp_clk = {
746         .parent = &ipg_clk,
747         .enable = _clk_enable,
748         .enable_reg = CCM_PCCR_KPP_REG,
749         .enable_shift = CCM_PCCR_KPP_OFFSET,
750         .disable = _clk_disable,
751 };
752
753 static struct clk owire_clk = {
754         .parent = &ipg_clk,
755         .enable = _clk_enable,
756         .enable_reg = CCM_PCCR_OWIRE_REG,
757         .enable_shift = CCM_PCCR_OWIRE_OFFSET,
758         .disable = _clk_disable,
759 };
760
761 static struct clk rtc_clk = {
762         .parent = &ipg_clk,
763         .enable = _clk_enable,
764         .enable_reg = CCM_PCCR_RTC_REG,
765         .enable_shift = CCM_PCCR_RTC_OFFSET,
766         .disable = _clk_disable,
767 };
768
769 static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
770 {
771         u32 div;
772         unsigned long parent_rate;
773
774         parent_rate = clk_get_rate(clk->parent);
775         div = parent_rate / rate;
776         if (parent_rate % rate)
777                 div++;
778
779         if (div > 8)
780                 div = 8;
781
782         return parent_rate / div;
783 }
784
785 static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
786 {
787         u32 reg;
788         u32 div;
789         unsigned long parent_rate;
790
791         parent_rate = clk_get_rate(clk->parent);
792
793         div = parent_rate / rate;
794
795         if (div > 8 || div < 1 || ((parent_rate / div) != rate))
796                 return -EINVAL;
797         div--;
798
799         reg = __raw_readl(CCM_PCDR0);
800
801         if (clk->parent == &usb_clk[0]) {
802                 reg &= ~CCM_PCDR0_48MDIV_MASK;
803                 reg |= div << CCM_PCDR0_48MDIV_OFFSET;
804         }
805         __raw_writel(reg, CCM_PCDR0);
806
807         return 0;
808 }
809
810 static unsigned long _clk_clko_recalc(struct clk *clk)
811 {
812         u32 div = 0;
813         unsigned long parent_rate;
814
815         parent_rate = clk_get_rate(clk->parent);
816
817         if (clk->parent == &usb_clk[0]) /* 48M */
818                 div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_48MDIV_MASK
819                          >> CCM_PCDR0_48MDIV_OFFSET;
820         div++;
821
822         return parent_rate / div;
823 }
824
825 static struct clk clko_clk;
826
827 static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
828 {
829         u32 reg;
830
831         reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
832
833         if (parent == &ckil_clk)
834                 reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
835         else if (parent == &fpm_clk)
836                 reg |= 1 << CCM_CCSR_CLKOSEL_OFFSET;
837         else if (parent == &ckih_clk)
838                 reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
839         else if (parent == mpll_clk.parent)
840                 reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
841         else if (parent == spll_clk.parent)
842                 reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
843         else if (parent == &mpll_clk)
844                 reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
845         else if (parent == &spll_clk)
846                 reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
847         else if (parent == &fclk_clk)
848                 reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
849         else if (parent == &hclk_clk)
850                 reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
851         else if (parent == &ipg_clk)
852                 reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
853         else if (parent == &per_clk[0])
854                 reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
855         else if (parent == &per_clk[1])
856                 reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
857         else if (parent == &per_clk[2])
858                 reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
859         else if (parent == &per_clk[3])
860                 reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
861         else if (parent == &ssi_clk[0])
862                 reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
863         else if (parent == &ssi_clk[1])
864                 reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
865         else if (parent == &nfc_clk)
866                 reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
867         else if (parent == &usb_clk[0])
868                 reg |= 0x14 << CCM_CCSR_CLKOSEL_OFFSET;
869         else if (parent == &clko_clk)
870                 reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
871         else
872                 return -EINVAL;
873
874         __raw_writel(reg, CCM_CCSR);
875
876         return 0;
877 }
878
879 static struct clk clko_clk = {
880         .get_rate = _clk_clko_recalc,
881         .set_rate = _clk_clko_set_rate,
882         .round_rate = _clk_clko_round_rate,
883         .set_parent = _clk_clko_set_parent,
884 };
885
886
887 #define _REGISTER_CLOCK(d, n, c) \
888         { \
889                 .dev_id = d, \
890                 .con_id = n, \
891                 .clk = &c, \
892         },
893 static struct clk_lookup lookups[] __initdata = {
894 /* It's unlikely that any driver wants one of them directly:
895         _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
896         _REGISTER_CLOCK(NULL, "ckil", ckil_clk)
897         _REGISTER_CLOCK(NULL, "fpm", fpm_clk)
898         _REGISTER_CLOCK(NULL, "mpll", mpll_clk)
899         _REGISTER_CLOCK(NULL, "spll", spll_clk)
900         _REGISTER_CLOCK(NULL, "fclk", fclk_clk)
901         _REGISTER_CLOCK(NULL, "hclk", hclk_clk)
902         _REGISTER_CLOCK(NULL, "ipg", ipg_clk)
903 */
904         _REGISTER_CLOCK(NULL, "perclk1", per_clk[0])
905         _REGISTER_CLOCK(NULL, "perclk2", per_clk[1])
906         _REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
907         _REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
908         _REGISTER_CLOCK(NULL, "clko", clko_clk)
909         _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
910         _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
911         _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
912         _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
913         _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
914         _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
915         _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
916         _REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
917         _REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
918         _REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
919         _REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
920         _REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
921         _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
922         _REGISTER_CLOCK(NULL, "lcdc", lcdc_clk[0])
923         _REGISTER_CLOCK(NULL, "csi", csi_clk[0])
924         _REGISTER_CLOCK(NULL, "usb", usb_clk[0])
925         _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0])
926         _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1])
927         _REGISTER_CLOCK(NULL, "nfc", nfc_clk)
928         _REGISTER_CLOCK(NULL, "dma", dma_clk[0])
929         _REGISTER_CLOCK(NULL, "brom", brom_clk)
930         _REGISTER_CLOCK(NULL, "emma", emma_clk[0])
931         _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
932         _REGISTER_CLOCK(NULL, "wdog", wdog_clk)
933         _REGISTER_CLOCK(NULL, "gpio", gpio_clk)
934         _REGISTER_CLOCK(NULL, "i2c", i2c_clk)
935         _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
936         _REGISTER_CLOCK(NULL, "owire", owire_clk)
937         _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
938 };
939
940 /*
941  * must be called very early to get information about the
942  * available clock rate when the timer framework starts
943  */
944 int __init mx21_clocks_init(unsigned long lref, unsigned long href)
945 {
946         int i;
947         u32 cscr;
948
949         external_low_reference = lref;
950         external_high_reference = href;
951
952         /* detect clock reference for both system PLL */
953         cscr = CSCR();
954         if (cscr & CCM_CSCR_MCU)
955                 mpll_clk.parent = &ckih_clk;
956         else
957                 mpll_clk.parent = &fpm_clk;
958
959         if (cscr & CCM_CSCR_SP)
960                 spll_clk.parent = &ckih_clk;
961         else
962                 spll_clk.parent = &fpm_clk;
963
964         for (i = 0; i < ARRAY_SIZE(lookups); i++)
965                 clkdev_add(&lookups[i]);
966
967         /* Turn off all clock gates */
968         __raw_writel(0, CCM_PCCR0);
969         __raw_writel(CCM_PCCR_GPT1_MASK, CCM_PCCR1);
970
971         /* This turns of the serial PLL as well */
972         spll_clk.disable(&spll_clk);
973
974         /* This will propagate to all children and init all the clock rates. */
975         clk_enable(&per_clk[0]);
976         clk_enable(&gpio_clk);
977
978 #ifdef CONFIG_DEBUG_LL_CONSOLE
979         clk_enable(&uart_clk[0]);
980 #endif
981
982         mxc_timer_init(&gpt_clk[0]);
983         return 0;
984 }