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