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