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