bc0458e6d4207bf578031558082c1eb1386147a3
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-s5p6440 / clock.c
1 /* linux/arch/arm/mach-s5p6440/clock.c
2  *
3  * Copyright (c) 2009 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com/
5  *
6  * S5P6440 - Clock 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 version 2 as
10  * published by the Free Software Foundation.
11 */
12
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/list.h>
17 #include <linux/errno.h>
18 #include <linux/err.h>
19 #include <linux/clk.h>
20 #include <linux/sysdev.h>
21 #include <linux/io.h>
22
23 #include <mach/hardware.h>
24 #include <mach/map.h>
25
26 #include <plat/cpu-freq.h>
27 #include <mach/regs-clock.h>
28 #include <plat/clock.h>
29 #include <plat/cpu.h>
30 #include <plat/clock-clksrc.h>
31 #include <plat/s5p-clock.h>
32 #include <plat/pll.h>
33 #include <plat/s5p6440.h>
34
35 /* APLL Mux output clock */
36 static struct clksrc_clk clk_mout_apll = {
37         .clk    = {
38                 .name           = "mout_apll",
39                 .id             = -1,
40         },
41         .sources        = &clk_src_apll,
42         .reg_src        = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
43 };
44
45 static int s5p6440_epll_enable(struct clk *clk, int enable)
46 {
47         unsigned int ctrlbit = clk->ctrlbit;
48         unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
49
50         if (enable)
51                 __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
52         else
53                 __raw_writel(epll_con, S5P_EPLL_CON);
54
55         return 0;
56 }
57
58 static unsigned long s5p6440_epll_get_rate(struct clk *clk)
59 {
60         return clk->rate;
61 }
62
63 static u32 epll_div[][5] = {
64         { 36000000,     0,      48, 1, 4 },
65         { 48000000,     0,      32, 1, 3 },
66         { 60000000,     0,      40, 1, 3 },
67         { 72000000,     0,      48, 1, 3 },
68         { 84000000,     0,      28, 1, 2 },
69         { 96000000,     0,      32, 1, 2 },
70         { 32768000,     45264,  43, 1, 4 },
71         { 45158000,     6903,   30, 1, 3 },
72         { 49152000,     50332,  32, 1, 3 },
73         { 67738000,     10398,  45, 1, 3 },
74         { 73728000,     9961,   49, 1, 3 }
75 };
76
77 static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
78 {
79         unsigned int epll_con, epll_con_k;
80         unsigned int i;
81
82         if (clk->rate == rate)  /* Return if nothing changed */
83                 return 0;
84
85         epll_con = __raw_readl(S5P_EPLL_CON);
86         epll_con_k = __raw_readl(S5P_EPLL_CON_K);
87
88         epll_con_k &= ~(PLL90XX_KDIV_MASK);
89         epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
90
91         for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
92                  if (epll_div[i][0] == rate) {
93                         epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
94                         epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
95                                     (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
96                                     (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
97                         break;
98                 }
99         }
100
101         if (i == ARRAY_SIZE(epll_div)) {
102                 printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
103                 return -EINVAL;
104         }
105
106         __raw_writel(epll_con, S5P_EPLL_CON);
107         __raw_writel(epll_con_k, S5P_EPLL_CON_K);
108
109         clk->rate = rate;
110
111         return 0;
112 }
113
114 static struct clk_ops s5p6440_epll_ops = {
115         .get_rate = s5p6440_epll_get_rate,
116         .set_rate = s5p6440_epll_set_rate,
117 };
118
119 static struct clksrc_clk clk_mout_epll = {
120         .clk    = {
121                 .name           = "mout_epll",
122                 .id             = -1,
123         },
124         .sources        = &clk_src_epll,
125         .reg_src        = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 },
126 };
127
128 static struct clksrc_clk clk_mout_mpll = {
129         .clk = {
130                 .name           = "mout_mpll",
131                 .id             = -1,
132         },
133         .sources        = &clk_src_mpll,
134         .reg_src        = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
135 };
136
137 static struct clk clk_h_low = {
138         .name           = "hclk_low",
139         .id             = -1,
140         .rate           = 0,
141         .parent         = NULL,
142         .ctrlbit        = 0,
143         .ops            = &clk_ops_def_setrate,
144 };
145
146 static struct clk clk_p_low = {
147         .name           = "pclk_low",
148         .id             = -1,
149         .rate           = 0,
150         .parent         = NULL,
151         .ctrlbit        = 0,
152         .ops            = &clk_ops_def_setrate,
153 };
154
155 enum perf_level {
156         L0 = 532*1000,
157         L1 = 266*1000,
158         L2 = 133*1000,
159 };
160
161 static const u32 clock_table[][3] = {
162         /*{ARM_CLK, DIVarm, DIVhclk}*/
163         {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)},
164         {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)},
165         {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)},
166 };
167
168 static unsigned long s5p6440_armclk_get_rate(struct clk *clk)
169 {
170         unsigned long rate = clk_get_rate(clk->parent);
171         u32 clkdiv;
172
173         /* divisor mask starts at bit0, so no need to shift */
174         clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
175
176         return rate / (clkdiv + 1);
177 }
178
179 static unsigned long s5p6440_armclk_round_rate(struct clk *clk,
180                                                 unsigned long rate)
181 {
182         u32 iter;
183
184         for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
185                 if (rate > clock_table[iter][0])
186                         return clock_table[iter-1][0];
187         }
188
189         return clock_table[ARRAY_SIZE(clock_table) - 1][0];
190 }
191
192 static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate)
193 {
194         u32 round_tmp;
195         u32 iter;
196         u32 clk_div0_tmp;
197         u32 cur_rate = clk->ops->get_rate(clk);
198         unsigned long flags;
199
200         round_tmp = clk->ops->round_rate(clk, rate);
201         if (round_tmp == cur_rate)
202                 return 0;
203
204
205         for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
206                 if (round_tmp == clock_table[iter][0])
207                         break;
208         }
209
210         if (iter >= ARRAY_SIZE(clock_table))
211                 iter = ARRAY_SIZE(clock_table) - 1;
212
213         local_irq_save(flags);
214         if (cur_rate > round_tmp) {
215                 /* Frequency Down */
216                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
217                 clk_div0_tmp |= clock_table[iter][1];
218                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
219
220                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
221                                 ~(S5P_CLKDIV0_HCLK_MASK);
222                 clk_div0_tmp |= clock_table[iter][2];
223                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
224
225
226         } else {
227                 /* Frequency Up */
228                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
229                                 ~(S5P_CLKDIV0_HCLK_MASK);
230                 clk_div0_tmp |= clock_table[iter][2];
231                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
232
233                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
234                 clk_div0_tmp |= clock_table[iter][1];
235                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
236                 }
237         local_irq_restore(flags);
238
239         clk->rate = clock_table[iter][0];
240
241         return 0;
242 }
243
244 static struct clk_ops s5p6440_clkarm_ops = {
245         .get_rate       = s5p6440_armclk_get_rate,
246         .set_rate       = s5p6440_armclk_set_rate,
247         .round_rate     = s5p6440_armclk_round_rate,
248 };
249
250 static struct clksrc_clk clk_armclk = {
251         .clk    = {
252                 .name   = "armclk",
253                 .id     = 1,
254                 .parent = &clk_mout_apll.clk,
255                 .ops    = &s5p6440_clkarm_ops,
256         },
257         .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
258 };
259
260 static struct clksrc_clk clk_dout_mpll = {
261         .clk    = {
262                 .name   = "dout_mpll",
263                 .id     = -1,
264                 .parent = &clk_mout_mpll.clk,
265         },
266         .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
267 };
268
269 static struct clksrc_clk clk_hclk = {
270         .clk    = {
271                 .name   = "clk_hclk",
272                 .id     = -1,
273                 .parent = &clk_armclk.clk,
274         },
275         .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
276 };
277
278 int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
279 {
280         unsigned long flags;
281         u32 val;
282
283         /* can't rely on clock lock, this register has other usages */
284         local_irq_save(flags);
285
286         val = __raw_readl(S5P_OTHERS);
287         if (enable)
288                 val |= S5P_OTHERS_USB_SIG_MASK;
289         else
290                 val &= ~S5P_OTHERS_USB_SIG_MASK;
291
292         __raw_writel(val, S5P_OTHERS);
293
294         local_irq_restore(flags);
295
296         return 0;
297 }
298
299 static int s5p6440_pclk_ctrl(struct clk *clk, int enable)
300 {
301         return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable);
302 }
303
304 static int s5p6440_hclk0_ctrl(struct clk *clk, int enable)
305 {
306         return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable);
307 }
308
309 static int s5p6440_hclk1_ctrl(struct clk *clk, int enable)
310 {
311         return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable);
312 }
313
314 static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
315 {
316         return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
317 }
318
319 static int s5p6440_mem_ctrl(struct clk *clk, int enable)
320 {
321         return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
322 }
323
324 /*
325  * The following clocks will be disabled during clock initialization. It is
326  * recommended to keep the following clocks disabled until the driver requests
327  * for enabling the clock.
328  */
329 static struct clk init_clocks_disable[] = {
330         {
331                 .name           = "nand",
332                 .id             = -1,
333                 .parent         = &clk_hclk.clk,
334                 .enable         = s5p6440_mem_ctrl,
335                 .ctrlbit        = S5P_CLKCON_MEM0_HCLK_NFCON,
336         }, {
337                 .name           = "adc",
338                 .id             = -1,
339                 .parent         = &clk_p_low,
340                 .enable         = s5p6440_pclk_ctrl,
341                 .ctrlbit        = S5P_CLKCON_PCLK_TSADC,
342         }, {
343                 .name           = "i2c",
344                 .id             = -1,
345                 .parent         = &clk_p_low,
346                 .enable         = s5p6440_pclk_ctrl,
347                 .ctrlbit        = S5P_CLKCON_PCLK_IIC0,
348         }, {
349                 .name           = "i2s_v40",
350                 .id             = 0,
351                 .parent         = &clk_p_low,
352                 .enable         = s5p6440_pclk_ctrl,
353                 .ctrlbit        = S5P_CLKCON_PCLK_IIS2,
354         }, {
355                 .name           = "spi",
356                 .id             = 0,
357                 .parent         = &clk_p_low,
358                 .enable         = s5p6440_pclk_ctrl,
359                 .ctrlbit        = S5P_CLKCON_PCLK_SPI0,
360         }, {
361                 .name           = "spi",
362                 .id             = 1,
363                 .parent         = &clk_p_low,
364                 .enable         = s5p6440_pclk_ctrl,
365                 .ctrlbit        = S5P_CLKCON_PCLK_SPI1,
366         }, {
367                 .name           = "sclk_spi_48",
368                 .id             = 0,
369                 .parent         = &clk_48m,
370                 .enable         = s5p6440_sclk_ctrl,
371                 .ctrlbit        = S5P_CLKCON_SCLK0_SPI0_48,
372         }, {
373                 .name           = "sclk_spi_48",
374                 .id             = 1,
375                 .parent         = &clk_48m,
376                 .enable         = s5p6440_sclk_ctrl,
377                 .ctrlbit        = S5P_CLKCON_SCLK0_SPI1_48,
378         }, {
379                 .name           = "mmc_48m",
380                 .id             = 0,
381                 .parent         = &clk_48m,
382                 .enable         = s5p6440_sclk_ctrl,
383                 .ctrlbit        = S5P_CLKCON_SCLK0_MMC0_48,
384         }, {
385                 .name           = "mmc_48m",
386                 .id             = 1,
387                 .parent         = &clk_48m,
388                 .enable         = s5p6440_sclk_ctrl,
389                 .ctrlbit        = S5P_CLKCON_SCLK0_MMC1_48,
390         }, {
391                 .name           = "mmc_48m",
392                 .id             = 2,
393                 .parent         = &clk_48m,
394                 .enable         = s5p6440_sclk_ctrl,
395                 .ctrlbit        = S5P_CLKCON_SCLK0_MMC2_48,
396         }, {
397                 .name           = "otg",
398                 .id             = -1,
399                 .parent         = &clk_h_low,
400                 .enable         = s5p6440_hclk0_ctrl,
401                 .ctrlbit        = S5P_CLKCON_HCLK0_USB
402         }, {
403                 .name           = "post",
404                 .id             = -1,
405                 .parent         = &clk_h_low,
406                 .enable         = s5p6440_hclk0_ctrl,
407                 .ctrlbit        = S5P_CLKCON_HCLK0_POST0
408         }, {
409                 .name           = "lcd",
410                 .id             = -1,
411                 .parent         = &clk_h_low,
412                 .enable         = s5p6440_hclk1_ctrl,
413                 .ctrlbit        = S5P_CLKCON_HCLK1_DISPCON,
414         }, {
415                 .name           = "hsmmc",
416                 .id             = 0,
417                 .parent         = &clk_h_low,
418                 .enable         = s5p6440_hclk0_ctrl,
419                 .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC0,
420         }, {
421                 .name           = "hsmmc",
422                 .id             = 1,
423                 .parent         = &clk_h_low,
424                 .enable         = s5p6440_hclk0_ctrl,
425                 .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC1,
426         }, {
427                 .name           = "hsmmc",
428                 .id             = 2,
429                 .parent         = &clk_h_low,
430                 .enable         = s5p6440_hclk0_ctrl,
431                 .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC2,
432         }, {
433                 .name           = "rtc",
434                 .id             = -1,
435                 .parent         = &clk_p_low,
436                 .enable         = s5p6440_pclk_ctrl,
437                 .ctrlbit        = S5P_CLKCON_PCLK_RTC,
438         }, {
439                 .name           = "watchdog",
440                 .id             = -1,
441                 .parent         = &clk_p_low,
442                 .enable         = s5p6440_pclk_ctrl,
443                 .ctrlbit        = S5P_CLKCON_PCLK_WDT,
444         }, {
445                 .name           = "timers",
446                 .id             = -1,
447                 .parent         = &clk_p_low,
448                 .enable         = s5p6440_pclk_ctrl,
449                 .ctrlbit        = S5P_CLKCON_PCLK_PWM,
450         }
451 };
452
453 /*
454  * The following clocks will be enabled during clock initialization.
455  */
456 static struct clk init_clocks[] = {
457         {
458                 .name           = "gpio",
459                 .id             = -1,
460                 .parent         = &clk_p_low,
461                 .enable         = s5p6440_pclk_ctrl,
462                 .ctrlbit        = S5P_CLKCON_PCLK_GPIO,
463         }, {
464                 .name           = "uart",
465                 .id             = 0,
466                 .parent         = &clk_p_low,
467                 .enable         = s5p6440_pclk_ctrl,
468                 .ctrlbit        = S5P_CLKCON_PCLK_UART0,
469         }, {
470                 .name           = "uart",
471                 .id             = 1,
472                 .parent         = &clk_p_low,
473                 .enable         = s5p6440_pclk_ctrl,
474                 .ctrlbit        = S5P_CLKCON_PCLK_UART1,
475         }, {
476                 .name           = "uart",
477                 .id             = 2,
478                 .parent         = &clk_p_low,
479                 .enable         = s5p6440_pclk_ctrl,
480                 .ctrlbit        = S5P_CLKCON_PCLK_UART2,
481         }, {
482                 .name           = "uart",
483                 .id             = 3,
484                 .parent         = &clk_p_low,
485                 .enable         = s5p6440_pclk_ctrl,
486                 .ctrlbit        = S5P_CLKCON_PCLK_UART3,
487         }
488 };
489
490 static struct clk clk_iis_cd_v40 = {
491         .name           = "iis_cdclk_v40",
492         .id             = -1,
493 };
494
495 static struct clk clk_pcm_cd = {
496         .name           = "pcm_cdclk",
497         .id             = -1,
498 };
499
500 static struct clk *clkset_spi_mmc_list[] = {
501         &clk_mout_epll.clk,
502         &clk_dout_mpll.clk,
503         &clk_fin_epll,
504 };
505
506 static struct clksrc_sources clkset_spi_mmc = {
507         .sources        = clkset_spi_mmc_list,
508         .nr_sources     = ARRAY_SIZE(clkset_spi_mmc_list),
509 };
510
511 static struct clk *clkset_uart_list[] = {
512         &clk_mout_epll.clk,
513         &clk_dout_mpll.clk,
514 };
515
516 static struct clksrc_sources clkset_uart = {
517         .sources        = clkset_uart_list,
518         .nr_sources     = ARRAY_SIZE(clkset_uart_list),
519 };
520
521 static struct clksrc_clk clksrcs[] = {
522         {
523                 .clk    = {
524                         .name           = "mmc_bus",
525                         .id             = 0,
526                         .ctrlbit        = S5P_CLKCON_SCLK0_MMC0,
527                         .enable         = s5p6440_sclk_ctrl,
528                 },
529                 .sources = &clkset_spi_mmc,
530                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
531                 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
532         }, {
533                 .clk    = {
534                         .name           = "mmc_bus",
535                         .id             = 1,
536                         .ctrlbit        = S5P_CLKCON_SCLK0_MMC1,
537                         .enable         = s5p6440_sclk_ctrl,
538                 },
539                 .sources = &clkset_spi_mmc,
540                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
541                 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
542         }, {
543                 .clk    = {
544                         .name           = "mmc_bus",
545                         .id             = 2,
546                         .ctrlbit        = S5P_CLKCON_SCLK0_MMC2,
547                         .enable         = s5p6440_sclk_ctrl,
548                 },
549                 .sources = &clkset_spi_mmc,
550                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
551                 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
552         }, {
553                 .clk    = {
554                         .name           = "uclk1",
555                         .id             = -1,
556                         .ctrlbit        = S5P_CLKCON_SCLK0_UART,
557                         .enable         = s5p6440_sclk_ctrl,
558                 },
559                 .sources = &clkset_uart,
560                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 },
561                 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
562         }, {
563                 .clk    = {
564                         .name           = "spi_epll",
565                         .id             = 0,
566                         .ctrlbit        = S5P_CLKCON_SCLK0_SPI0,
567                         .enable         = s5p6440_sclk_ctrl,
568                 },
569                 .sources = &clkset_spi_mmc,
570                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
571                 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
572         }, {
573                 .clk    = {
574                         .name           = "spi_epll",
575                         .id             = 1,
576                         .ctrlbit        = S5P_CLKCON_SCLK0_SPI1,
577                         .enable         = s5p6440_sclk_ctrl,
578                 },
579                 .sources = &clkset_spi_mmc,
580                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
581                 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
582         }
583 };
584
585 /* Clock initialisation code */
586 static struct clksrc_clk *sysclks[] = {
587         &clk_mout_apll,
588         &clk_mout_epll,
589         &clk_mout_mpll,
590         &clk_dout_mpll,
591         &clk_armclk,
592         &clk_hclk,
593 };
594
595 void __init_or_cpufreq s5p6440_setup_clocks(void)
596 {
597         struct clk *xtal_clk;
598         unsigned long xtal;
599         unsigned long fclk;
600         unsigned long hclk;
601         unsigned long hclk_low;
602         unsigned long pclk;
603         unsigned long pclk_low;
604         unsigned long epll;
605         unsigned long apll;
606         unsigned long mpll;
607         unsigned int ptr;
608         u32 clkdiv0;
609         u32 clkdiv3;
610
611         /* Set S5P6440 functions for clk_fout_epll */
612         clk_fout_epll.enable = s5p6440_epll_enable;
613         clk_fout_epll.ops = &s5p6440_epll_ops;
614
615         /* Set S5P6440 functions for arm clock */
616         clk_48m.enable = s5p6440_clk48m_ctrl;
617
618         clkdiv0 = __raw_readl(S5P_CLK_DIV0);
619         clkdiv3 = __raw_readl(S5P_CLK_DIV3);
620
621         xtal_clk = clk_get(NULL, "ext_xtal");
622         BUG_ON(IS_ERR(xtal_clk));
623
624         xtal = clk_get_rate(xtal_clk);
625         clk_put(xtal_clk);
626
627         epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON),
628                                 __raw_readl(S5P_EPLL_CON_K));
629         mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
630         apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
631
632         clk_fout_mpll.rate = mpll;
633         clk_fout_epll.rate = epll;
634         clk_fout_apll.rate = apll;
635
636         printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
637                         " E=%ld.%ldMHz\n",
638                         print_mhz(apll), print_mhz(mpll), print_mhz(epll));
639
640         fclk = clk_get_rate(&clk_armclk.clk);
641         hclk = clk_get_rate(&clk_hclk.clk);
642         pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK);
643
644         if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) {
645                 /* Asynchronous mode */
646                 hclk_low = mpll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
647         } else {
648                 /* Synchronous mode */
649                 hclk_low = apll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
650         }
651
652         pclk_low = hclk_low / GET_DIV(clkdiv3, S5P_CLKDIV3_PCLK_LOW);
653
654         printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
655                         " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
656                         print_mhz(hclk), print_mhz(hclk_low),
657                         print_mhz(pclk), print_mhz(pclk_low));
658
659         clk_f.rate = fclk;
660         clk_h.rate = hclk;
661         clk_p.rate = pclk;
662         clk_h_low.rate = hclk_low;
663         clk_p_low.rate = pclk_low;
664
665         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
666                 s3c_set_clksrc(&clksrcs[ptr], true);
667 }
668
669 static struct clk *clks[] __initdata = {
670         &clk_ext,
671         &clk_iis_cd_v40,
672         &clk_pcm_cd,
673         &clk_p_low,
674         &clk_h_low,
675 };
676
677 void __init s5p6440_register_clocks(void)
678 {
679         struct clk *clkp;
680         int ret;
681         int ptr;
682
683         ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
684         if (ret > 0)
685                 printk(KERN_ERR "Failed to register %u clocks\n", ret);
686
687         for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
688                 s3c_register_clksrc(sysclks[ptr], 1);
689
690         s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
691         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
692
693         clkp = init_clocks_disable;
694         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
695
696                 ret = s3c24xx_register_clock(clkp);
697                 if (ret < 0) {
698                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
699                                clkp->name, ret);
700                 }
701                 (clkp->enable)(clkp, 0);
702         }
703
704         s3c_pwmclk_init();
705 }