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