Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
[sfrench/cifs-2.6.git] / arch / arm / mach-mx1 / clock.c
1 /*
2  *  Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/math64.h>
22 #include <linux/err.h>
23 #include <linux/clk.h>
24 #include <linux/io.h>
25
26 #include <mach/clock.h>
27 #include <mach/hardware.h>
28 #include "crm_regs.h"
29
30 static int _clk_enable(struct clk *clk)
31 {
32         unsigned int reg;
33
34         reg = __raw_readl(clk->enable_reg);
35         reg |= 1 << clk->enable_shift;
36         __raw_writel(reg, clk->enable_reg);
37
38         return 0;
39 }
40
41 static void _clk_disable(struct clk *clk)
42 {
43         unsigned int reg;
44
45         reg = __raw_readl(clk->enable_reg);
46         reg &= ~(1 << clk->enable_shift);
47         __raw_writel(reg, clk->enable_reg);
48 }
49
50 static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size,
51                                struct clk *parent)
52 {
53         int i;
54
55         for (i = 0; i < size; i++)
56                 if (parent == clk_arr[i])
57                         return i;
58
59         return -EINVAL;
60 }
61
62 static unsigned long
63 _clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit)
64 {
65         int div;
66         unsigned long parent_rate;
67
68         parent_rate = clk_get_rate(clk->parent);
69
70         div = parent_rate / rate;
71         if (parent_rate % rate)
72                 div++;
73
74         if (div > limit)
75                 div = limit;
76
77         return parent_rate / div;
78 }
79
80 static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
81 {
82         return clk->parent->round_rate(clk->parent, rate);
83 }
84
85 static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
86 {
87         return clk->parent->set_rate(clk->parent, rate);
88 }
89
90 /*
91  *  get the system pll clock in Hz
92  *
93  *                  mfi + mfn / (mfd +1)
94  *  f = 2 * f_ref * --------------------
95  *                        pd + 1
96  */
97 static unsigned long mx1_decode_pll(unsigned int pll, u32 f_ref)
98 {
99         unsigned long long ll;
100         unsigned long quot;
101
102         u32 mfi = (pll >> 10) & 0xf;
103         u32 mfn = pll & 0x3ff;
104         u32 mfd = (pll >> 16) & 0x3ff;
105         u32 pd =  (pll >> 26) & 0xf;
106
107         mfi = mfi <= 5 ? 5 : mfi;
108
109         ll = 2 * (unsigned long long)f_ref *
110                 ((mfi << 16) + (mfn << 16) / (mfd + 1));
111         quot = (pd + 1) * (1 << 16);
112         ll += quot / 2;
113         do_div(ll, quot);
114         return (unsigned long)ll;
115 }
116
117 static unsigned long clk16m_get_rate(struct clk *clk)
118 {
119         return 16000000;
120 }
121
122 static struct clk clk16m = {
123         .name = "CLK16M",
124         .get_rate = clk16m_get_rate,
125         .enable = _clk_enable,
126         .enable_reg = CCM_CSCR,
127         .enable_shift = CCM_CSCR_OSC_EN_SHIFT,
128         .disable = _clk_disable,
129 };
130
131 /* in Hz */
132 static unsigned long clk32_rate;
133
134 static unsigned long clk32_get_rate(struct clk *clk)
135 {
136         return clk32_rate;
137 }
138
139 static struct clk clk32 = {
140         .name = "CLK32",
141         .get_rate = clk32_get_rate,
142 };
143
144 static unsigned long clk32_premult_get_rate(struct clk *clk)
145 {
146         return clk_get_rate(clk->parent) * 512;
147 }
148
149 static struct clk clk32_premult = {
150         .name = "CLK32_premultiplier",
151         .parent = &clk32,
152         .get_rate = clk32_premult_get_rate,
153 };
154
155 static const struct clk *prem_clk_clocks[] = {
156         &clk32_premult,
157         &clk16m,
158 };
159
160 static int prem_clk_set_parent(struct clk *clk, struct clk *parent)
161 {
162         int i;
163         unsigned int reg = __raw_readl(CCM_CSCR);
164
165         i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks),
166                                 parent);
167
168         switch (i) {
169         case 0:
170                 reg &= ~CCM_CSCR_SYSTEM_SEL;
171                 break;
172         case 1:
173                 reg |= CCM_CSCR_SYSTEM_SEL;
174                 break;
175         default:
176                 return i;
177         }
178
179         __raw_writel(reg, CCM_CSCR);
180
181         return 0;
182 }
183
184 static struct clk prem_clk = {
185         .name = "prem_clk",
186         .set_parent = prem_clk_set_parent,
187 };
188
189 static unsigned long system_clk_get_rate(struct clk *clk)
190 {
191         return mx1_decode_pll(__raw_readl(CCM_SPCTL0),
192                               clk_get_rate(clk->parent));
193 }
194
195 static struct clk system_clk = {
196         .name = "system_clk",
197         .parent = &prem_clk,
198         .get_rate = system_clk_get_rate,
199 };
200
201 static unsigned long mcu_clk_get_rate(struct clk *clk)
202 {
203         return mx1_decode_pll(__raw_readl(CCM_MPCTL0),
204                               clk_get_rate(clk->parent));
205 }
206
207 static struct clk mcu_clk = {
208         .name = "mcu_clk",
209         .parent = &clk32_premult,
210         .get_rate = mcu_clk_get_rate,
211 };
212
213 static unsigned long fclk_get_rate(struct clk *clk)
214 {
215         unsigned long fclk = clk_get_rate(clk->parent);
216
217         if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC)
218                 fclk /= 2;
219
220         return fclk;
221 }
222
223 static struct clk fclk = {
224         .name = "fclk",
225         .parent = &mcu_clk,
226         .get_rate = fclk_get_rate,
227 };
228
229 /*
230  *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
231  */
232 static unsigned long hclk_get_rate(struct clk *clk)
233 {
234         return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
235                         CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1);
236 }
237
238 static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate)
239 {
240         return _clk_simple_round_rate(clk, rate, 16);
241 }
242
243 static int hclk_set_rate(struct clk *clk, unsigned long rate)
244 {
245         unsigned int div;
246         unsigned int reg;
247         unsigned long parent_rate;
248
249         parent_rate = clk_get_rate(clk->parent);
250
251         div = parent_rate / rate;
252
253         if (div > 16 || div < 1 || ((parent_rate / div) != rate))
254                 return -EINVAL;
255
256         div--;
257
258         reg = __raw_readl(CCM_CSCR);
259         reg &= ~CCM_CSCR_BCLK_MASK;
260         reg |= div << CCM_CSCR_BCLK_OFFSET;
261         __raw_writel(reg, CCM_CSCR);
262
263         return 0;
264 }
265
266 static struct clk hclk = {
267         .name = "hclk",
268         .parent = &system_clk,
269         .get_rate = hclk_get_rate,
270         .round_rate = hclk_round_rate,
271         .set_rate = hclk_set_rate,
272 };
273
274 static unsigned long clk48m_get_rate(struct clk *clk)
275 {
276         return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
277                         CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1);
278 }
279
280 static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate)
281 {
282         return _clk_simple_round_rate(clk, rate, 8);
283 }
284
285 static int clk48m_set_rate(struct clk *clk, unsigned long rate)
286 {
287         unsigned int div;
288         unsigned int reg;
289         unsigned long parent_rate;
290
291         parent_rate = clk_get_rate(clk->parent);
292
293         div = parent_rate / rate;
294
295         if (div > 8 || div < 1 || ((parent_rate / div) != rate))
296                 return -EINVAL;
297
298         div--;
299
300         reg = __raw_readl(CCM_CSCR);
301         reg &= ~CCM_CSCR_USB_MASK;
302         reg |= div << CCM_CSCR_USB_OFFSET;
303         __raw_writel(reg, CCM_CSCR);
304
305         return 0;
306 }
307
308 static struct clk clk48m = {
309         .name = "CLK48M",
310         .parent = &system_clk,
311         .get_rate = clk48m_get_rate,
312         .round_rate = clk48m_round_rate,
313         .set_rate = clk48m_set_rate,
314 };
315
316 /*
317  *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
318  */
319 static unsigned long perclk1_get_rate(struct clk *clk)
320 {
321         return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
322                         CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1);
323 }
324
325 static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate)
326 {
327         return _clk_simple_round_rate(clk, rate, 16);
328 }
329
330 static int perclk1_set_rate(struct clk *clk, unsigned long rate)
331 {
332         unsigned int div;
333         unsigned int reg;
334         unsigned long parent_rate;
335
336         parent_rate = clk_get_rate(clk->parent);
337
338         div = parent_rate / rate;
339
340         if (div > 16 || div < 1 || ((parent_rate / div) != rate))
341                 return -EINVAL;
342
343         div--;
344
345         reg = __raw_readl(CCM_PCDR);
346         reg &= ~CCM_PCDR_PCLK1_MASK;
347         reg |= div << CCM_PCDR_PCLK1_OFFSET;
348         __raw_writel(reg, CCM_PCDR);
349
350         return 0;
351 }
352
353 /*
354  *  get peripheral clock 2 ( LCD, SD, SPI[12] )
355  */
356 static unsigned long perclk2_get_rate(struct clk *clk)
357 {
358         return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
359                         CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1);
360 }
361
362 static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate)
363 {
364         return _clk_simple_round_rate(clk, rate, 16);
365 }
366
367 static int perclk2_set_rate(struct clk *clk, unsigned long rate)
368 {
369         unsigned int div;
370         unsigned int reg;
371         unsigned long parent_rate;
372
373         parent_rate = clk_get_rate(clk->parent);
374
375         div = parent_rate / rate;
376
377         if (div > 16 || div < 1 || ((parent_rate / div) != rate))
378                 return -EINVAL;
379
380         div--;
381
382         reg = __raw_readl(CCM_PCDR);
383         reg &= ~CCM_PCDR_PCLK2_MASK;
384         reg |= div << CCM_PCDR_PCLK2_OFFSET;
385         __raw_writel(reg, CCM_PCDR);
386
387         return 0;
388 }
389
390 /*
391  *  get peripheral clock 3 ( SSI )
392  */
393 static unsigned long perclk3_get_rate(struct clk *clk)
394 {
395         return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
396                         CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1);
397 }
398
399 static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate)
400 {
401         return _clk_simple_round_rate(clk, rate, 128);
402 }
403
404 static int perclk3_set_rate(struct clk *clk, unsigned long rate)
405 {
406         unsigned int div;
407         unsigned int reg;
408         unsigned long parent_rate;
409
410         parent_rate = clk_get_rate(clk->parent);
411
412         div = parent_rate / rate;
413
414         if (div > 128 || div < 1 || ((parent_rate / div) != rate))
415                 return -EINVAL;
416
417         div--;
418
419         reg = __raw_readl(CCM_PCDR);
420         reg &= ~CCM_PCDR_PCLK3_MASK;
421         reg |= div << CCM_PCDR_PCLK3_OFFSET;
422         __raw_writel(reg, CCM_PCDR);
423
424         return 0;
425 }
426
427 static struct clk perclk[] = {
428         {
429                 .name = "perclk",
430                 .id = 0,
431                 .parent = &system_clk,
432                 .get_rate = perclk1_get_rate,
433                 .round_rate = perclk1_round_rate,
434                 .set_rate = perclk1_set_rate,
435         }, {
436                 .name = "perclk",
437                 .id = 1,
438                 .parent = &system_clk,
439                 .get_rate = perclk2_get_rate,
440                 .round_rate = perclk2_round_rate,
441                 .set_rate = perclk2_set_rate,
442         }, {
443                 .name = "perclk",
444                 .id = 2,
445                 .parent = &system_clk,
446                 .get_rate = perclk3_get_rate,
447                 .round_rate = perclk3_round_rate,
448                 .set_rate = perclk3_set_rate,
449         }
450 };
451
452 static const struct clk *clko_clocks[] = {
453         &perclk[0],
454         &hclk,
455         &clk48m,
456         &clk16m,
457         &prem_clk,
458         &fclk,
459 };
460
461 static int clko_set_parent(struct clk *clk, struct clk *parent)
462 {
463         int i;
464         unsigned int reg;
465
466         i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent);
467         if (i < 0)
468                 return i;
469
470         reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK;
471         reg |= i << CCM_CSCR_CLKO_OFFSET;
472         __raw_writel(reg, CCM_CSCR);
473
474         if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) {
475                 clk->set_rate = _clk_parent_set_rate;
476                 clk->round_rate = _clk_parent_round_rate;
477         } else {
478                 clk->set_rate = NULL;
479                 clk->round_rate = NULL;
480         }
481
482         return 0;
483 }
484
485 static struct clk clko_clk = {
486         .name = "clko_clk",
487         .set_parent = clko_set_parent,
488 };
489
490 static struct clk dma_clk = {
491         .name = "dma_clk",
492         .parent = &hclk,
493         .round_rate = _clk_parent_round_rate,
494         .set_rate = _clk_parent_set_rate,
495         .enable = _clk_enable,
496         .enable_reg = SCM_GCCR,
497         .enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET,
498         .disable = _clk_disable,
499 };
500
501 static struct clk csi_clk = {
502         .name = "csi_clk",
503         .parent = &hclk,
504         .round_rate = _clk_parent_round_rate,
505         .set_rate = _clk_parent_set_rate,
506         .enable = _clk_enable,
507         .enable_reg = SCM_GCCR,
508         .enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET,
509         .disable = _clk_disable,
510 };
511
512 static struct clk mma_clk = {
513         .name = "mma_clk",
514         .parent = &hclk,
515         .round_rate = _clk_parent_round_rate,
516         .set_rate = _clk_parent_set_rate,
517         .enable = _clk_enable,
518         .enable_reg = SCM_GCCR,
519         .enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET,
520         .disable = _clk_disable,
521 };
522
523 static struct clk usbd_clk = {
524         .name = "usbd_clk",
525         .parent = &clk48m,
526         .round_rate = _clk_parent_round_rate,
527         .set_rate = _clk_parent_set_rate,
528         .enable = _clk_enable,
529         .enable_reg = SCM_GCCR,
530         .enable_shift = SCM_GCCR_USBD_CLK_EN_OFFSET,
531         .disable = _clk_disable,
532 };
533
534 static struct clk gpt_clk = {
535         .name = "gpt_clk",
536         .parent = &perclk[0],
537         .round_rate = _clk_parent_round_rate,
538         .set_rate = _clk_parent_set_rate,
539 };
540
541 static struct clk uart_clk = {
542         .name = "uart_clk",
543         .parent = &perclk[0],
544         .round_rate = _clk_parent_round_rate,
545         .set_rate = _clk_parent_set_rate,
546 };
547
548 static struct clk i2c_clk = {
549         .name = "i2c_clk",
550         .parent = &hclk,
551         .round_rate = _clk_parent_round_rate,
552         .set_rate = _clk_parent_set_rate,
553 };
554
555 static struct clk spi_clk = {
556         .name = "spi_clk",
557         .parent = &perclk[1],
558         .round_rate = _clk_parent_round_rate,
559         .set_rate = _clk_parent_set_rate,
560 };
561
562 static struct clk sdhc_clk = {
563         .name = "sdhc_clk",
564         .parent = &perclk[1],
565         .round_rate = _clk_parent_round_rate,
566         .set_rate = _clk_parent_set_rate,
567 };
568
569 static struct clk lcdc_clk = {
570         .name = "lcdc_clk",
571         .parent = &perclk[1],
572         .round_rate = _clk_parent_round_rate,
573         .set_rate = _clk_parent_set_rate,
574 };
575
576 static struct clk mshc_clk = {
577         .name = "mshc_clk",
578         .parent = &hclk,
579         .round_rate = _clk_parent_round_rate,
580         .set_rate = _clk_parent_set_rate,
581 };
582
583 static struct clk ssi_clk = {
584         .name = "ssi_clk",
585         .parent = &perclk[2],
586         .round_rate = _clk_parent_round_rate,
587         .set_rate = _clk_parent_set_rate,
588 };
589
590 static struct clk rtc_clk = {
591         .name = "rtc_clk",
592         .parent = &clk32,
593 };
594
595 static struct clk *mxc_clks[] = {
596         &clk16m,
597         &clk32,
598         &clk32_premult,
599         &prem_clk,
600         &system_clk,
601         &mcu_clk,
602         &fclk,
603         &hclk,
604         &clk48m,
605         &perclk[0],
606         &perclk[1],
607         &perclk[2],
608         &clko_clk,
609         &dma_clk,
610         &csi_clk,
611         &mma_clk,
612         &usbd_clk,
613         &gpt_clk,
614         &uart_clk,
615         &i2c_clk,
616         &spi_clk,
617         &sdhc_clk,
618         &lcdc_clk,
619         &mshc_clk,
620         &ssi_clk,
621         &rtc_clk,
622 };
623
624 int __init mxc_clocks_init(unsigned long fref)
625 {
626         struct clk **clkp;
627         unsigned int reg;
628
629         /* disable clocks we are able to */
630         __raw_writel(0, SCM_GCCR);
631
632         clk32_rate = fref;
633         reg = __raw_readl(CCM_CSCR);
634
635         /* detect clock reference for system PLL */
636         if (reg & CCM_CSCR_SYSTEM_SEL) {
637                 prem_clk.parent = &clk16m;
638         } else {
639                 /* ensure that oscillator is disabled */
640                 reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT);
641                 __raw_writel(reg, CCM_CSCR);
642                 prem_clk.parent = &clk32_premult;
643         }
644
645         /* detect reference for CLKO */
646         reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;
647         clko_clk.parent = (struct clk *)clko_clocks[reg];
648
649         for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
650                 clk_register(*clkp);
651
652         clk_enable(&hclk);
653         clk_enable(&fclk);
654
655         return 0;
656 }