Merge branch 'iommu-fixes-2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / arm / mach-s3c2443 / clock.c
1 /* linux/arch/arm/mach-s3c2443/clock.c
2  *
3  * Copyright (c) 2007 Simtec Electronics
4  *      Ben Dooks <ben@simtec.co.uk>
5  *
6  * S3C2443 Clock control support
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/list.h>
27 #include <linux/errno.h>
28 #include <linux/err.h>
29 #include <linux/sysdev.h>
30 #include <linux/clk.h>
31 #include <linux/mutex.h>
32 #include <linux/delay.h>
33 #include <linux/serial_core.h>
34 #include <linux/io.h>
35
36 #include <asm/mach/map.h>
37
38 #include <mach/hardware.h>
39
40 #include <mach/regs-s3c2443-clock.h>
41
42 #include <plat/s3c2443.h>
43 #include <plat/clock.h>
44 #include <plat/cpu.h>
45
46 /* We currently have to assume that the system is running
47  * from the XTPll input, and that all ***REFCLKs are being
48  * fed from it, as we cannot read the state of OM[4] from
49  * software.
50  *
51  * It would be possible for each board initialisation to
52  * set the correct muxing at initialisation
53 */
54
55 static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
56 {
57         unsigned int clocks = clk->ctrlbit;
58         unsigned long clkcon;
59
60         clkcon = __raw_readl(S3C2443_HCLKCON);
61
62         if (enable)
63                 clkcon |= clocks;
64         else
65                 clkcon &= ~clocks;
66
67         __raw_writel(clkcon, S3C2443_HCLKCON);
68
69         return 0;
70 }
71
72 static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
73 {
74         unsigned int clocks = clk->ctrlbit;
75         unsigned long clkcon;
76
77         clkcon = __raw_readl(S3C2443_PCLKCON);
78
79         if (enable)
80                 clkcon |= clocks;
81         else
82                 clkcon &= ~clocks;
83
84         __raw_writel(clkcon, S3C2443_PCLKCON);
85
86         return 0;
87 }
88
89 static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
90 {
91         unsigned int clocks = clk->ctrlbit;
92         unsigned long clkcon;
93
94         clkcon = __raw_readl(S3C2443_SCLKCON);
95
96         if (enable)
97                 clkcon |= clocks;
98         else
99                 clkcon &= ~clocks;
100
101         __raw_writel(clkcon, S3C2443_SCLKCON);
102
103         return 0;
104 }
105
106 static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
107                                               unsigned long rate,
108                                               unsigned int max)
109 {
110         unsigned long parent_rate = clk_get_rate(clk->parent);
111         int div;
112
113         if (rate > parent_rate)
114                 return parent_rate;
115
116         /* note, we remove the +/- 1 calculations as they cancel out */
117
118         div = (rate / parent_rate);
119
120         if (div < 1)
121                 div = 1;
122         else if (div > max)
123                 div = max;
124
125         return parent_rate / div;
126 }
127
128 static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
129                                                unsigned long rate)
130 {
131         return s3c2443_roundrate_clksrc(clk, rate, 4);
132 }
133
134 static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
135                                                 unsigned long rate)
136 {
137         return s3c2443_roundrate_clksrc(clk, rate, 16);
138 }
139
140 static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
141                                                  unsigned long rate)
142 {
143         return s3c2443_roundrate_clksrc(clk, rate, 256);
144 }
145
146 /* clock selections */
147
148 /* CPU EXTCLK input */
149 static struct clk clk_ext = {
150         .name           = "ext",
151         .id             = -1,
152 };
153
154 static struct clk clk_mpllref = {
155         .name           = "mpllref",
156         .parent         = &clk_xtal,
157         .id             = -1,
158 };
159
160 #if 0
161 static struct clk clk_mpll = {
162         .name           = "mpll",
163         .parent         = &clk_mpllref,
164         .id             = -1,
165 };
166 #endif
167
168 static struct clk clk_epllref;
169
170 static struct clk clk_epll = {
171         .name           = "epll",
172         .parent         = &clk_epllref,
173         .id             = -1,
174 };
175
176 static struct clk clk_i2s_ext = {
177         .name           = "i2s-ext",
178         .id             = -1,
179 };
180
181 static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
182 {
183         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
184
185         clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
186
187         if (parent == &clk_xtal)
188                 clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
189         else if (parent == &clk_ext)
190                 clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
191         else if (parent != &clk_mpllref)
192                 return -EINVAL;
193
194         __raw_writel(clksrc, S3C2443_CLKSRC);
195         clk->parent = parent;
196
197         return 0;
198 }
199
200 static struct clk clk_epllref = {
201         .name           = "epllref",
202         .id             = -1,
203         .set_parent     = s3c2443_setparent_epllref,
204 };
205
206 static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
207 {
208         unsigned long parent_rate = clk_get_rate(clk->parent);
209         unsigned long div = __raw_readl(S3C2443_CLKDIV0);
210
211         div  &= S3C2443_CLKDIV0_EXTDIV_MASK;
212         div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1);       /* x2 */
213
214         return parent_rate / (div + 1);
215 }
216
217 static struct clk clk_mdivclk = {
218         .name           = "mdivclk",
219         .parent         = &clk_mpllref,
220         .id             = -1,
221         .get_rate       = s3c2443_getrate_mdivclk,
222 };
223
224 static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
225 {
226         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
227
228         clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
229                     S3C2443_CLKSRC_EXTCLK_DIV);
230
231         if (parent == &clk_mpll)
232                 clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
233         else if (parent == &clk_mdivclk)
234                 clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
235         else if (parent != &clk_mpllref)
236                 return -EINVAL;
237
238         __raw_writel(clksrc, S3C2443_CLKSRC);
239         clk->parent = parent;
240
241         return 0;
242 }
243
244 static struct clk clk_msysclk = {
245         .name           = "msysclk",
246         .parent         = &clk_xtal,
247         .id             = -1,
248         .set_parent     = s3c2443_setparent_msysclk,
249 };
250
251 /* armdiv
252  *
253  * this clock is sourced from msysclk and can have a number of
254  * divider values applied to it to then be fed into armclk.
255 */
256
257 static struct clk clk_armdiv = {
258         .name           = "armdiv",
259         .id             = -1,
260         .parent         = &clk_msysclk,
261 };
262
263 /* armclk
264  *
265  * this is the clock fed into the ARM core itself, either from
266  * armdiv or from hclk.
267  */
268
269 static int s3c2443_setparent_armclk(struct clk *clk, struct clk *parent)
270 {
271         unsigned long clkdiv0;
272
273         clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
274
275         if (parent == &clk_armdiv)
276                 clkdiv0 &= ~S3C2443_CLKDIV0_DVS;
277         else if (parent == &clk_h)
278                 clkdiv0 |= S3C2443_CLKDIV0_DVS;
279         else
280                 return -EINVAL;
281
282         __raw_writel(clkdiv0, S3C2443_CLKDIV0);
283         return 0;
284 }
285
286 static struct clk clk_arm = {
287         .name           = "armclk",
288         .id             = -1,
289         .set_parent     = s3c2443_setparent_armclk,
290 };
291
292 /* esysclk
293  *
294  * this is sourced from either the EPLL or the EPLLref clock
295 */
296
297 static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
298 {
299         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
300
301         if (parent == &clk_epll)
302                 clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
303         else if (parent == &clk_epllref)
304                 clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
305         else
306                 return -EINVAL;
307
308         __raw_writel(clksrc, S3C2443_CLKSRC);
309         clk->parent = parent;
310
311         return 0;
312 }
313
314 static struct clk clk_esysclk = {
315         .name           = "esysclk",
316         .parent         = &clk_epll,
317         .id             = -1,
318         .set_parent     = s3c2443_setparent_esysclk,
319 };
320
321 /* uartclk
322  *
323  * UART baud-rate clock sourced from esysclk via a divisor
324 */
325
326 static unsigned long s3c2443_getrate_uart(struct clk *clk)
327 {
328         unsigned long parent_rate = clk_get_rate(clk->parent);
329         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
330
331         div &= S3C2443_CLKDIV1_UARTDIV_MASK;
332         div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
333
334         return parent_rate / (div + 1);
335 }
336
337
338 static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
339 {
340         unsigned long parent_rate = clk_get_rate(clk->parent);
341         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
342
343         rate = s3c2443_roundrate_clksrc16(clk, rate);
344         rate = parent_rate / rate;
345
346         clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
347         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
348
349         __raw_writel(clkdivn, S3C2443_CLKDIV1);
350         return 0;
351 }
352
353 static struct clk clk_uart = {
354         .name           = "uartclk",
355         .id             = -1,
356         .parent         = &clk_esysclk,
357         .get_rate       = s3c2443_getrate_uart,
358         .set_rate       = s3c2443_setrate_uart,
359         .round_rate     = s3c2443_roundrate_clksrc16,
360 };
361
362 /* hsspi
363  *
364  * high-speed spi clock, sourced from esysclk
365 */
366
367 static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
368 {
369         unsigned long parent_rate = clk_get_rate(clk->parent);
370         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
371
372         div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
373         div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
374
375         return parent_rate / (div + 1);
376 }
377
378
379 static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
380 {
381         unsigned long parent_rate = clk_get_rate(clk->parent);
382         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
383
384         rate = s3c2443_roundrate_clksrc4(clk, rate);
385         rate = parent_rate / rate;
386
387         clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
388         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
389
390         __raw_writel(clkdivn, S3C2443_CLKDIV1);
391         return 0;
392 }
393
394 static struct clk clk_hsspi = {
395         .name           = "hsspi",
396         .id             = -1,
397         .parent         = &clk_esysclk,
398         .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
399         .enable         = s3c2443_clkcon_enable_s,
400         .get_rate       = s3c2443_getrate_hsspi,
401         .set_rate       = s3c2443_setrate_hsspi,
402         .round_rate     = s3c2443_roundrate_clksrc4,
403 };
404
405 /* usbhost
406  *
407  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
408 */
409
410 static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
411 {
412         unsigned long parent_rate = clk_get_rate(clk->parent);
413         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
414
415         div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
416         div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
417
418         return parent_rate / (div + 1);
419 }
420
421 static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
422 {
423         unsigned long parent_rate = clk_get_rate(clk->parent);
424         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
425
426         rate = s3c2443_roundrate_clksrc4(clk, rate);
427         rate = parent_rate / rate;
428
429         clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
430         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
431
432         __raw_writel(clkdivn, S3C2443_CLKDIV1);
433         return 0;
434 }
435
436 static struct clk clk_usb_bus_host = {
437         .name           = "usb-bus-host-parent",
438         .id             = -1,
439         .parent         = &clk_esysclk,
440         .ctrlbit        = S3C2443_SCLKCON_USBHOST,
441         .enable         = s3c2443_clkcon_enable_s,
442         .get_rate       = s3c2443_getrate_usbhost,
443         .set_rate       = s3c2443_setrate_usbhost,
444         .round_rate     = s3c2443_roundrate_clksrc4,
445 };
446
447 /* clk_hsmcc_div
448  *
449  * this clock is sourced from epll, and is fed through a divider,
450  * to a mux controlled by sclkcon where either it or a extclk can
451  * be fed to the hsmmc block
452 */
453
454 static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
455 {
456         unsigned long parent_rate = clk_get_rate(clk->parent);
457         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
458
459         div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
460         div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
461
462         return parent_rate / (div + 1);
463 }
464
465 static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
466 {
467         unsigned long parent_rate = clk_get_rate(clk->parent);
468         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
469
470         rate = s3c2443_roundrate_clksrc4(clk, rate);
471         rate = parent_rate / rate;
472
473         clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
474         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
475
476         __raw_writel(clkdivn, S3C2443_CLKDIV1);
477         return 0;
478 }
479
480 static struct clk clk_hsmmc_div = {
481         .name           = "hsmmc-div",
482         .id             = -1,
483         .parent         = &clk_esysclk,
484         .get_rate       = s3c2443_getrate_hsmmc_div,
485         .set_rate       = s3c2443_setrate_hsmmc_div,
486         .round_rate     = s3c2443_roundrate_clksrc4,
487 };
488
489 static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
490 {
491         unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
492
493         clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
494                     S3C2443_SCLKCON_HSMMCCLK_EPLL);
495
496         if (parent == &clk_epll)
497                 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
498         else if (parent == &clk_ext)
499                 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
500         else
501                 return -EINVAL;
502
503         if (clk->usage > 0) {
504                 __raw_writel(clksrc, S3C2443_SCLKCON);
505         }
506
507         clk->parent = parent;
508         return 0;
509 }
510
511 static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
512 {
513         return s3c2443_setparent_hsmmc(clk, clk->parent);
514 }
515
516 static struct clk clk_hsmmc = {
517         .name           = "hsmmc-if",
518         .id             = -1,
519         .parent         = &clk_hsmmc_div,
520         .enable         = s3c2443_enable_hsmmc,
521         .set_parent     = s3c2443_setparent_hsmmc,
522 };
523
524 /* i2s_eplldiv
525  *
526  * this clock is the output from the i2s divisor of esysclk
527 */
528
529 static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
530 {
531         unsigned long parent_rate = clk_get_rate(clk->parent);
532         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
533
534         div &= S3C2443_CLKDIV1_I2SDIV_MASK;
535         div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
536
537         return parent_rate / (div + 1);
538 }
539
540 static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
541 {
542         unsigned long parent_rate = clk_get_rate(clk->parent);
543         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
544
545         rate = s3c2443_roundrate_clksrc16(clk, rate);
546         rate = parent_rate / rate;
547
548         clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
549         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
550
551         __raw_writel(clkdivn, S3C2443_CLKDIV1);
552         return 0;
553 }
554
555 static struct clk clk_i2s_eplldiv = {
556         .name           = "i2s-eplldiv",
557         .id             = -1,
558         .parent         = &clk_esysclk,
559         .get_rate       = s3c2443_getrate_i2s_eplldiv,
560         .set_rate       = s3c2443_setrate_i2s_eplldiv,
561         .round_rate     = s3c2443_roundrate_clksrc16,
562 };
563
564 /* i2s-ref
565  *
566  * i2s bus reference clock, selectable from external, esysclk or epllref
567 */
568
569 static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
570 {
571         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
572
573         clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
574
575         if (parent == &clk_epllref)
576                 clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
577         else if (parent == &clk_i2s_ext)
578                 clksrc |= S3C2443_CLKSRC_I2S_EXT;
579         else if (parent != &clk_i2s_eplldiv)
580                 return -EINVAL;
581
582         clk->parent = parent;
583         __raw_writel(clksrc, S3C2443_CLKSRC);
584
585         return 0;
586 }
587
588 static struct clk clk_i2s = {
589         .name           = "i2s-if",
590         .id             = -1,
591         .parent         = &clk_i2s_eplldiv,
592         .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
593         .enable         = s3c2443_clkcon_enable_s,
594         .set_parent     = s3c2443_setparent_i2s,
595 };
596
597 /* cam-if
598  *
599  * camera interface bus-clock, divided down from esysclk
600 */
601
602 static unsigned long s3c2443_getrate_cam(struct clk *clk)
603 {
604         unsigned long parent_rate = clk_get_rate(clk->parent);
605         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
606
607         div  &= S3C2443_CLKDIV1_CAMDIV_MASK;
608         div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
609
610         return parent_rate / (div + 1);
611 }
612
613 static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
614 {
615         unsigned long parent_rate = clk_get_rate(clk->parent);
616         unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
617
618         rate = s3c2443_roundrate_clksrc16(clk, rate);
619         rate = parent_rate / rate;
620
621         clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
622         clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
623
624         __raw_writel(clkdiv1, S3C2443_CLKDIV1);
625         return 0;
626 }
627
628 static struct clk clk_cam = {
629         .name           = "camif-upll",         /* same as 2440 name */
630         .id             = -1,
631         .parent         = &clk_esysclk,
632         .ctrlbit        = S3C2443_SCLKCON_CAMCLK,
633         .enable         = s3c2443_clkcon_enable_s,
634         .get_rate       = s3c2443_getrate_cam,
635         .set_rate       = s3c2443_setrate_cam,
636         .round_rate     = s3c2443_roundrate_clksrc16,
637 };
638
639 /* display-if
640  *
641  * display interface clock, divided from esysclk
642 */
643
644 static unsigned long s3c2443_getrate_display(struct clk *clk)
645 {
646         unsigned long parent_rate = clk_get_rate(clk->parent);
647         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
648
649         div &= S3C2443_CLKDIV1_DISPDIV_MASK;
650         div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
651
652         return parent_rate / (div + 1);
653 }
654
655 static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
656 {
657         unsigned long parent_rate = clk_get_rate(clk->parent);
658         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
659
660         rate = s3c2443_roundrate_clksrc256(clk, rate);
661         rate = parent_rate / rate;
662
663         clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
664         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
665
666         __raw_writel(clkdivn, S3C2443_CLKDIV1);
667         return 0;
668 }
669
670 static struct clk clk_display = {
671         .name           = "display-if",
672         .id             = -1,
673         .parent         = &clk_esysclk,
674         .ctrlbit        = S3C2443_SCLKCON_DISPCLK,
675         .enable         = s3c2443_clkcon_enable_s,
676         .get_rate       = s3c2443_getrate_display,
677         .set_rate       = s3c2443_setrate_display,
678         .round_rate     = s3c2443_roundrate_clksrc256,
679 };
680
681 /* prediv
682  *
683  * this divides the msysclk down to pass to h/p/etc.
684  */
685
686 static unsigned long s3c2443_prediv_getrate(struct clk *clk)
687 {
688         unsigned long rate = clk_get_rate(clk->parent);
689         unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
690
691         clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK;
692         clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
693
694         return rate / (clkdiv0 + 1);
695 }
696
697 static struct clk clk_prediv = {
698         .name           = "prediv",
699         .id             = -1,
700         .parent         = &clk_msysclk,
701         .get_rate       = s3c2443_prediv_getrate,
702 };
703
704 /* standard clock definitions */
705
706 static struct clk init_clocks_disable[] = {
707         {
708                 .name           = "nand",
709                 .id             = -1,
710                 .parent         = &clk_h,
711         }, {
712                 .name           = "sdi",
713                 .id             = -1,
714                 .parent         = &clk_p,
715                 .enable         = s3c2443_clkcon_enable_p,
716                 .ctrlbit        = S3C2443_PCLKCON_SDI,
717         }, {
718                 .name           = "adc",
719                 .id             = -1,
720                 .parent         = &clk_p,
721                 .enable         = s3c2443_clkcon_enable_p,
722                 .ctrlbit        = S3C2443_PCLKCON_ADC,
723         }, {
724                 .name           = "i2c",
725                 .id             = -1,
726                 .parent         = &clk_p,
727                 .enable         = s3c2443_clkcon_enable_p,
728                 .ctrlbit        = S3C2443_PCLKCON_IIC,
729         }, {
730                 .name           = "iis",
731                 .id             = -1,
732                 .parent         = &clk_p,
733                 .enable         = s3c2443_clkcon_enable_p,
734                 .ctrlbit        = S3C2443_PCLKCON_IIS,
735         }, {
736                 .name           = "spi",
737                 .id             = 0,
738                 .parent         = &clk_p,
739                 .enable         = s3c2443_clkcon_enable_p,
740                 .ctrlbit        = S3C2443_PCLKCON_SPI0,
741         }, {
742                 .name           = "spi",
743                 .id             = 1,
744                 .parent         = &clk_p,
745                 .enable         = s3c2443_clkcon_enable_p,
746                 .ctrlbit        = S3C2443_PCLKCON_SPI1,
747         }
748 };
749
750 static struct clk init_clocks[] = {
751         {
752                 .name           = "dma",
753                 .id             = 0,
754                 .parent         = &clk_h,
755                 .enable         = s3c2443_clkcon_enable_h,
756                 .ctrlbit        = S3C2443_HCLKCON_DMA0,
757         }, {
758                 .name           = "dma",
759                 .id             = 1,
760                 .parent         = &clk_h,
761                 .enable         = s3c2443_clkcon_enable_h,
762                 .ctrlbit        = S3C2443_HCLKCON_DMA1,
763         }, {
764                 .name           = "dma",
765                 .id             = 2,
766                 .parent         = &clk_h,
767                 .enable         = s3c2443_clkcon_enable_h,
768                 .ctrlbit        = S3C2443_HCLKCON_DMA2,
769         }, {
770                 .name           = "dma",
771                 .id             = 3,
772                 .parent         = &clk_h,
773                 .enable         = s3c2443_clkcon_enable_h,
774                 .ctrlbit        = S3C2443_HCLKCON_DMA3,
775         }, {
776                 .name           = "dma",
777                 .id             = 4,
778                 .parent         = &clk_h,
779                 .enable         = s3c2443_clkcon_enable_h,
780                 .ctrlbit        = S3C2443_HCLKCON_DMA4,
781         }, {
782                 .name           = "dma",
783                 .id             = 5,
784                 .parent         = &clk_h,
785                 .enable         = s3c2443_clkcon_enable_h,
786                 .ctrlbit        = S3C2443_HCLKCON_DMA5,
787         }, {
788                 .name           = "lcd",
789                 .id             = -1,
790                 .parent         = &clk_h,
791                 .enable         = s3c2443_clkcon_enable_h,
792                 .ctrlbit        = S3C2443_HCLKCON_LCDC,
793         }, {
794                 .name           = "gpio",
795                 .id             = -1,
796                 .parent         = &clk_p,
797                 .enable         = s3c2443_clkcon_enable_p,
798                 .ctrlbit        = S3C2443_PCLKCON_GPIO,
799         }, {
800                 .name           = "usb-host",
801                 .id             = -1,
802                 .parent         = &clk_h,
803                 .enable         = s3c2443_clkcon_enable_h,
804                 .ctrlbit        = S3C2443_HCLKCON_USBH,
805         }, {
806                 .name           = "usb-device",
807                 .id             = -1,
808                 .parent         = &clk_h,
809                 .enable         = s3c2443_clkcon_enable_h,
810                 .ctrlbit        = S3C2443_HCLKCON_USBD,
811         }, {
812                 .name           = "hsmmc",
813                 .id             = -1,
814                 .parent         = &clk_h,
815                 .enable         = s3c2443_clkcon_enable_h,
816                 .ctrlbit        = S3C2443_HCLKCON_HSMMC,
817         }, {
818                 .name           = "cfc",
819                 .id             = -1,
820                 .parent         = &clk_h,
821                 .enable         = s3c2443_clkcon_enable_h,
822                 .ctrlbit        = S3C2443_HCLKCON_CFC,
823         }, {
824                 .name           = "ssmc",
825                 .id             = -1,
826                 .parent         = &clk_h,
827                 .enable         = s3c2443_clkcon_enable_h,
828                 .ctrlbit        = S3C2443_HCLKCON_SSMC,
829         }, {
830                 .name           = "timers",
831                 .id             = -1,
832                 .parent         = &clk_p,
833                 .enable         = s3c2443_clkcon_enable_p,
834                 .ctrlbit        = S3C2443_PCLKCON_PWMT,
835         }, {
836                 .name           = "uart",
837                 .id             = 0,
838                 .parent         = &clk_p,
839                 .enable         = s3c2443_clkcon_enable_p,
840                 .ctrlbit        = S3C2443_PCLKCON_UART0,
841         }, {
842                 .name           = "uart",
843                 .id             = 1,
844                 .parent         = &clk_p,
845                 .enable         = s3c2443_clkcon_enable_p,
846                 .ctrlbit        = S3C2443_PCLKCON_UART1,
847         }, {
848                 .name           = "uart",
849                 .id             = 2,
850                 .parent         = &clk_p,
851                 .enable         = s3c2443_clkcon_enable_p,
852                 .ctrlbit        = S3C2443_PCLKCON_UART2,
853         }, {
854                 .name           = "uart",
855                 .id             = 3,
856                 .parent         = &clk_p,
857                 .enable         = s3c2443_clkcon_enable_p,
858                 .ctrlbit        = S3C2443_PCLKCON_UART3,
859         }, {
860                 .name           = "rtc",
861                 .id             = -1,
862                 .parent         = &clk_p,
863                 .enable         = s3c2443_clkcon_enable_p,
864                 .ctrlbit        = S3C2443_PCLKCON_RTC,
865         }, {
866                 .name           = "watchdog",
867                 .id             = -1,
868                 .parent         = &clk_p,
869                 .ctrlbit        = S3C2443_PCLKCON_WDT,
870         }, {
871                 .name           = "usb-bus-host",
872                 .id             = -1,
873                 .parent         = &clk_usb_bus_host,
874         }, {
875                 .name           = "ac97",
876                 .id             = -1,
877                 .parent         = &clk_p,
878                 .ctrlbit        = S3C2443_PCLKCON_AC97,
879         }
880 };
881
882 /* clocks to add where we need to check their parentage */
883
884 /* s3c2443_clk_initparents
885  *
886  * Initialise the parents for the clocks that we get at start-time
887 */
888
889 static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
890 {
891         printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
892         return clk_set_parent(clk, parent);
893 }
894
895 static void __init s3c2443_clk_initparents(void)
896 {
897         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
898         struct clk *parent;
899
900         switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
901         case S3C2443_CLKSRC_EPLLREF_EXTCLK:
902                 parent = &clk_ext;
903                 break;
904
905         case S3C2443_CLKSRC_EPLLREF_XTAL:
906         default:
907                 parent = &clk_xtal;
908                 break;
909
910         case S3C2443_CLKSRC_EPLLREF_MPLLREF:
911         case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
912                 parent = &clk_mpllref;
913                 break;
914         }
915
916         clk_init_set_parent(&clk_epllref, parent);
917
918         switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
919         case S3C2443_CLKSRC_I2S_EXT:
920                 parent = &clk_i2s_ext;
921                 break;
922
923         case S3C2443_CLKSRC_I2S_EPLLDIV:
924         default:
925                 parent = &clk_i2s_eplldiv;
926                 break;
927
928         case S3C2443_CLKSRC_I2S_EPLLREF:
929         case S3C2443_CLKSRC_I2S_EPLLREF3:
930                 parent = &clk_epllref;
931         }
932
933         clk_init_set_parent(&clk_i2s, &clk_epllref);
934
935         /* esysclk source */
936
937         parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
938                 &clk_epll : &clk_epllref;
939
940         clk_init_set_parent(&clk_esysclk, parent);
941
942         /* msysclk source */
943
944         if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
945                 parent = &clk_mpll;
946         } else {
947                 parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
948                         &clk_mdivclk : &clk_mpllref;
949         }
950
951         clk_init_set_parent(&clk_msysclk, parent);
952
953         /* arm */
954
955         if (__raw_readl(S3C2443_CLKDIV0) & S3C2443_CLKDIV0_DVS)
956                 parent = &clk_h;
957         else
958                 parent = &clk_armdiv;
959
960         clk_init_set_parent(&clk_arm, parent);
961 }
962
963 /* armdiv divisor table */
964
965 static unsigned int armdiv[16] = {
966         [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 1,
967         [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 2,
968         [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 3,
969         [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 4,
970         [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 6,
971         [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 8,
972         [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 12,
973         [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 16,
974 };
975
976 static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
977 {
978         clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
979
980         return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
981 }
982
983 static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
984 {
985         clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
986
987         return clkcon0 + 1;
988 }
989
990 /* clocks to add straight away */
991
992 static struct clk *clks[] __initdata = {
993         &clk_ext,
994         &clk_epll,
995         &clk_usb_bus_host,
996         &clk_usb_bus,
997         &clk_esysclk,
998         &clk_epllref,
999         &clk_mpllref,
1000         &clk_msysclk,
1001         &clk_uart,
1002         &clk_display,
1003         &clk_cam,
1004         &clk_i2s_eplldiv,
1005         &clk_i2s,
1006         &clk_hsspi,
1007         &clk_hsmmc_div,
1008         &clk_hsmmc,
1009         &clk_armdiv,
1010         &clk_arm,
1011         &clk_prediv,
1012 };
1013
1014 void __init s3c2443_init_clocks(int xtal)
1015 {
1016         unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
1017         unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
1018         unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
1019         unsigned long pll;
1020         unsigned long fclk;
1021         unsigned long hclk;
1022         unsigned long pclk;
1023         struct clk *clkp;
1024         int ret;
1025         int ptr;
1026
1027         /* s3c2443 parents h and p clocks from prediv */
1028         clk_h.parent = &clk_prediv;
1029         clk_p.parent = &clk_prediv;
1030
1031         pll = s3c2443_get_mpll(mpllcon, xtal);
1032         clk_msysclk.rate = pll;
1033
1034         fclk = pll / s3c2443_fclk_div(clkdiv0);
1035         hclk = s3c2443_prediv_getrate(&clk_prediv);
1036         hclk /= s3c2443_get_hdiv(clkdiv0);
1037         pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
1038
1039         s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
1040
1041         printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
1042                (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
1043                print_mhz(pll), print_mhz(fclk),
1044                print_mhz(hclk), print_mhz(pclk));
1045
1046         s3c2443_clk_initparents();
1047
1048         for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
1049                 clkp = clks[ptr];
1050
1051                 ret = s3c24xx_register_clock(clkp);
1052                 if (ret < 0) {
1053                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1054                                clkp->name, ret);
1055                 }
1056         }
1057
1058         clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
1059
1060         clk_usb_bus.parent = &clk_usb_bus_host;
1061
1062         /* ensure usb bus clock is within correct rate of 48MHz */
1063
1064         if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
1065                 printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
1066                 clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
1067         }
1068
1069         printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
1070                (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
1071                print_mhz(clk_get_rate(&clk_epll)),
1072                print_mhz(clk_get_rate(&clk_usb_bus)));
1073
1074         /* register clocks from clock array */
1075
1076         clkp = init_clocks;
1077         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
1078                 ret = s3c24xx_register_clock(clkp);
1079                 if (ret < 0) {
1080                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1081                                clkp->name, ret);
1082                 }
1083         }
1084
1085         /* We must be careful disabling the clocks we are not intending to
1086          * be using at boot time, as subsystems such as the LCD which do
1087          * their own DMA requests to the bus can cause the system to lockup
1088          * if they where in the middle of requesting bus access.
1089          *
1090          * Disabling the LCD clock if the LCD is active is very dangerous,
1091          * and therefore the bootloader should be careful to not enable
1092          * the LCD clock if it is not needed.
1093         */
1094
1095         /* install (and disable) the clocks we do not need immediately */
1096
1097         clkp = init_clocks_disable;
1098         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
1099
1100                 ret = s3c24xx_register_clock(clkp);
1101                 if (ret < 0) {
1102                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1103                                clkp->name, ret);
1104                 }
1105
1106                 (clkp->enable)(clkp, 0);
1107         }
1108 }