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