ARM: S5P6440: Rename clkset_mmc_spi to clkset_group1
[pandora-kernel.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 enum perf_level {
138         L0 = 532*1000,
139         L1 = 266*1000,
140         L2 = 133*1000,
141 };
142
143 static const u32 clock_table[][3] = {
144         /*{ARM_CLK, DIVarm, DIVhclk}*/
145         {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)},
146         {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)},
147         {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)},
148 };
149
150 static unsigned long s5p6440_armclk_get_rate(struct clk *clk)
151 {
152         unsigned long rate = clk_get_rate(clk->parent);
153         u32 clkdiv;
154
155         /* divisor mask starts at bit0, so no need to shift */
156         clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
157
158         return rate / (clkdiv + 1);
159 }
160
161 static unsigned long s5p6440_armclk_round_rate(struct clk *clk,
162                                                 unsigned long rate)
163 {
164         u32 iter;
165
166         for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
167                 if (rate > clock_table[iter][0])
168                         return clock_table[iter-1][0];
169         }
170
171         return clock_table[ARRAY_SIZE(clock_table) - 1][0];
172 }
173
174 static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate)
175 {
176         u32 round_tmp;
177         u32 iter;
178         u32 clk_div0_tmp;
179         u32 cur_rate = clk->ops->get_rate(clk);
180         unsigned long flags;
181
182         round_tmp = clk->ops->round_rate(clk, rate);
183         if (round_tmp == cur_rate)
184                 return 0;
185
186
187         for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
188                 if (round_tmp == clock_table[iter][0])
189                         break;
190         }
191
192         if (iter >= ARRAY_SIZE(clock_table))
193                 iter = ARRAY_SIZE(clock_table) - 1;
194
195         local_irq_save(flags);
196         if (cur_rate > round_tmp) {
197                 /* Frequency Down */
198                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
199                 clk_div0_tmp |= clock_table[iter][1];
200                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
201
202                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
203                                 ~(S5P_CLKDIV0_HCLK_MASK);
204                 clk_div0_tmp |= clock_table[iter][2];
205                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
206
207
208         } else {
209                 /* Frequency Up */
210                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
211                                 ~(S5P_CLKDIV0_HCLK_MASK);
212                 clk_div0_tmp |= clock_table[iter][2];
213                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
214
215                 clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
216                 clk_div0_tmp |= clock_table[iter][1];
217                 __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
218                 }
219         local_irq_restore(flags);
220
221         clk->rate = clock_table[iter][0];
222
223         return 0;
224 }
225
226 static struct clk_ops s5p6440_clkarm_ops = {
227         .get_rate       = s5p6440_armclk_get_rate,
228         .set_rate       = s5p6440_armclk_set_rate,
229         .round_rate     = s5p6440_armclk_round_rate,
230 };
231
232 static struct clksrc_clk clk_armclk = {
233         .clk    = {
234                 .name   = "armclk",
235                 .id     = 1,
236                 .parent = &clk_mout_apll.clk,
237                 .ops    = &s5p6440_clkarm_ops,
238         },
239         .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
240 };
241
242 static struct clksrc_clk clk_dout_mpll = {
243         .clk    = {
244                 .name   = "dout_mpll",
245                 .id     = -1,
246                 .parent = &clk_mout_mpll.clk,
247         },
248         .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
249 };
250
251 static struct clksrc_clk clk_hclk = {
252         .clk    = {
253                 .name   = "clk_hclk",
254                 .id     = -1,
255                 .parent = &clk_armclk.clk,
256         },
257         .reg_div        = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
258 };
259
260 static struct clksrc_clk clk_pclk = {
261         .clk    = {
262                 .name   = "clk_pclk",
263                 .id     = -1,
264                 .parent = &clk_hclk.clk,
265         },
266         .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 },
267 };
268
269 static struct clk *clkset_hclklow_list[] = {
270         &clk_mout_apll.clk,
271         &clk_mout_mpll.clk,
272 };
273
274 static struct clksrc_sources clkset_hclklow = {
275         .sources        = clkset_hclklow_list,
276         .nr_sources     = ARRAY_SIZE(clkset_hclklow_list),
277 };
278
279 static struct clksrc_clk clk_hclk_low = {
280         .clk = {
281                 .name   = "hclk_low",
282                 .id     = -1,
283         },
284         .sources        = &clkset_hclklow,
285         .reg_src        = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 },
286         .reg_div        = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
287 };
288
289 static struct clksrc_clk clk_pclk_low = {
290         .clk    = {
291                 .name   = "pclk_low",
292                 .id     = -1,
293                 .parent = &clk_hclk_low.clk,
294         },
295         .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
296 };
297
298 int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
299 {
300         unsigned long flags;
301         u32 val;
302
303         /* can't rely on clock lock, this register has other usages */
304         local_irq_save(flags);
305
306         val = __raw_readl(S5P_OTHERS);
307         if (enable)
308                 val |= S5P_OTHERS_USB_SIG_MASK;
309         else
310                 val &= ~S5P_OTHERS_USB_SIG_MASK;
311
312         __raw_writel(val, S5P_OTHERS);
313
314         local_irq_restore(flags);
315
316         return 0;
317 }
318
319 static int s5p6440_pclk_ctrl(struct clk *clk, int enable)
320 {
321         return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable);
322 }
323
324 static int s5p6440_hclk0_ctrl(struct clk *clk, int enable)
325 {
326         return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable);
327 }
328
329 static int s5p6440_hclk1_ctrl(struct clk *clk, int enable)
330 {
331         return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable);
332 }
333
334 static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
335 {
336         return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
337 }
338
339 static int s5p6440_mem_ctrl(struct clk *clk, int enable)
340 {
341         return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
342 }
343
344 /*
345  * The following clocks will be disabled during clock initialization. It is
346  * recommended to keep the following clocks disabled until the driver requests
347  * for enabling the clock.
348  */
349 static struct clk init_clocks_disable[] = {
350         {
351                 .name           = "nand",
352                 .id             = -1,
353                 .parent         = &clk_hclk.clk,
354                 .enable         = s5p6440_mem_ctrl,
355                 .ctrlbit        = S5P_CLKCON_MEM0_HCLK_NFCON,
356         }, {
357                 .name           = "adc",
358                 .id             = -1,
359                 .parent         = &clk_pclk_low.clk,
360                 .enable         = s5p6440_pclk_ctrl,
361                 .ctrlbit        = S5P_CLKCON_PCLK_TSADC,
362         }, {
363                 .name           = "i2c",
364                 .id             = -1,
365                 .parent         = &clk_pclk_low.clk,
366                 .enable         = s5p6440_pclk_ctrl,
367                 .ctrlbit        = S5P_CLKCON_PCLK_IIC0,
368         }, {
369                 .name           = "i2s_v40",
370                 .id             = 0,
371                 .parent         = &clk_pclk_low.clk,
372                 .enable         = s5p6440_pclk_ctrl,
373                 .ctrlbit        = S5P_CLKCON_PCLK_IIS2,
374         }, {
375                 .name           = "spi",
376                 .id             = 0,
377                 .parent         = &clk_pclk_low.clk,
378                 .enable         = s5p6440_pclk_ctrl,
379                 .ctrlbit        = S5P_CLKCON_PCLK_SPI0,
380         }, {
381                 .name           = "spi",
382                 .id             = 1,
383                 .parent         = &clk_pclk_low.clk,
384                 .enable         = s5p6440_pclk_ctrl,
385                 .ctrlbit        = S5P_CLKCON_PCLK_SPI1,
386         }, {
387                 .name           = "sclk_spi_48",
388                 .id             = 0,
389                 .parent         = &clk_48m,
390                 .enable         = s5p6440_sclk_ctrl,
391                 .ctrlbit        = S5P_CLKCON_SCLK0_SPI0_48,
392         }, {
393                 .name           = "sclk_spi_48",
394                 .id             = 1,
395                 .parent         = &clk_48m,
396                 .enable         = s5p6440_sclk_ctrl,
397                 .ctrlbit        = S5P_CLKCON_SCLK0_SPI1_48,
398         }, {
399                 .name           = "mmc_48m",
400                 .id             = 0,
401                 .parent         = &clk_48m,
402                 .enable         = s5p6440_sclk_ctrl,
403                 .ctrlbit        = S5P_CLKCON_SCLK0_MMC0_48,
404         }, {
405                 .name           = "mmc_48m",
406                 .id             = 1,
407                 .parent         = &clk_48m,
408                 .enable         = s5p6440_sclk_ctrl,
409                 .ctrlbit        = S5P_CLKCON_SCLK0_MMC1_48,
410         }, {
411                 .name           = "mmc_48m",
412                 .id             = 2,
413                 .parent         = &clk_48m,
414                 .enable         = s5p6440_sclk_ctrl,
415                 .ctrlbit        = S5P_CLKCON_SCLK0_MMC2_48,
416         }, {
417                 .name           = "otg",
418                 .id             = -1,
419                 .parent         = &clk_hclk_low.clk,
420                 .enable         = s5p6440_hclk0_ctrl,
421                 .ctrlbit        = S5P_CLKCON_HCLK0_USB
422         }, {
423                 .name           = "post",
424                 .id             = -1,
425                 .parent         = &clk_hclk_low.clk,
426                 .enable         = s5p6440_hclk0_ctrl,
427                 .ctrlbit        = S5P_CLKCON_HCLK0_POST0
428         }, {
429                 .name           = "lcd",
430                 .id             = -1,
431                 .parent         = &clk_hclk_low.clk,
432                 .enable         = s5p6440_hclk1_ctrl,
433                 .ctrlbit        = S5P_CLKCON_HCLK1_DISPCON,
434         }, {
435                 .name           = "hsmmc",
436                 .id             = 0,
437                 .parent         = &clk_hclk_low.clk,
438                 .enable         = s5p6440_hclk0_ctrl,
439                 .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC0,
440         }, {
441                 .name           = "hsmmc",
442                 .id             = 1,
443                 .parent         = &clk_hclk_low.clk,
444                 .enable         = s5p6440_hclk0_ctrl,
445                 .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC1,
446         }, {
447                 .name           = "hsmmc",
448                 .id             = 2,
449                 .parent         = &clk_hclk_low.clk,
450                 .enable         = s5p6440_hclk0_ctrl,
451                 .ctrlbit        = S5P_CLKCON_HCLK0_HSMMC2,
452         }, {
453                 .name           = "rtc",
454                 .id             = -1,
455                 .parent         = &clk_pclk_low.clk,
456                 .enable         = s5p6440_pclk_ctrl,
457                 .ctrlbit        = S5P_CLKCON_PCLK_RTC,
458         }, {
459                 .name           = "watchdog",
460                 .id             = -1,
461                 .parent         = &clk_pclk_low.clk,
462                 .enable         = s5p6440_pclk_ctrl,
463                 .ctrlbit        = S5P_CLKCON_PCLK_WDT,
464         }, {
465                 .name           = "timers",
466                 .id             = -1,
467                 .parent         = &clk_pclk_low.clk,
468                 .enable         = s5p6440_pclk_ctrl,
469                 .ctrlbit        = S5P_CLKCON_PCLK_PWM,
470         }, {
471                 .name           = "hclk_fimgvg",
472                 .id             = -1,
473                 .parent         = &clk_hclk.clk,
474                 .enable         = s5p6440_hclk1_ctrl,
475                 .ctrlbit        = (1 << 2),
476         }, {
477                 .name           = "tsi",
478                 .id             = -1,
479                 .parent         = &clk_hclk_low.clk,
480                 .enable         = s5p6440_hclk1_ctrl,
481                 .ctrlbit        = (1 << 0),
482         }, {
483                 .name           = "pclk_fimgvg",
484                 .id             = -1,
485                 .parent         = &clk_pclk.clk,
486                 .enable         = s5p6440_pclk_ctrl,
487                 .ctrlbit        = (1 << 31),
488         }, {
489                 .name           = "dmc0",
490                 .id             = -1,
491                 .parent         = &clk_pclk.clk,
492                 .enable         = s5p6440_pclk_ctrl,
493                 .ctrlbit        = (1 << 30),
494         }, {
495                 .name           = "etm",
496                 .id             = -1,
497                 .parent         = &clk_pclk.clk,
498                 .enable         = s5p6440_pclk_ctrl,
499                 .ctrlbit        = (1 << 29),
500         }, {
501                 .name           = "dsim",
502                 .id             = -1,
503                 .parent         = &clk_pclk_low.clk,
504                 .enable         = s5p6440_pclk_ctrl,
505                 .ctrlbit        = (1 << 28),
506         }, {
507                 .name           = "gps",
508                 .id             = -1,
509                 .parent         = &clk_pclk_low.clk,
510                 .enable         = s5p6440_pclk_ctrl,
511                 .ctrlbit        = (1 << 25),
512         }, {
513                 .name           = "pcm",
514                 .id             = -1,
515                 .parent         = &clk_pclk_low.clk,
516                 .enable         = s5p6440_pclk_ctrl,
517                 .ctrlbit        = (1 << 8),
518         }, {
519                 .name           = "irom",
520                 .id             = -1,
521                 .parent         = &clk_hclk.clk,
522                 .enable         = s5p6440_hclk0_ctrl,
523                 .ctrlbit        = (1 << 25),
524         }, {
525                 .name           = "dma",
526                 .id             = -1,
527                 .parent         = &clk_hclk_low.clk,
528                 .enable         = s5p6440_hclk0_ctrl,
529                 .ctrlbit        = (1 << 12),
530         }, {
531                 .name           = "2d",
532                 .id             = -1,
533                 .parent         = &clk_hclk.clk,
534                 .enable         = s5p6440_hclk0_ctrl,
535                 .ctrlbit        = (1 << 8),
536         },
537 };
538
539 /*
540  * The following clocks will be enabled during clock initialization.
541  */
542 static struct clk init_clocks[] = {
543         {
544                 .name           = "gpio",
545                 .id             = -1,
546                 .parent         = &clk_pclk_low.clk,
547                 .enable         = s5p6440_pclk_ctrl,
548                 .ctrlbit        = S5P_CLKCON_PCLK_GPIO,
549         }, {
550                 .name           = "uart",
551                 .id             = 0,
552                 .parent         = &clk_pclk_low.clk,
553                 .enable         = s5p6440_pclk_ctrl,
554                 .ctrlbit        = S5P_CLKCON_PCLK_UART0,
555         }, {
556                 .name           = "uart",
557                 .id             = 1,
558                 .parent         = &clk_pclk_low.clk,
559                 .enable         = s5p6440_pclk_ctrl,
560                 .ctrlbit        = S5P_CLKCON_PCLK_UART1,
561         }, {
562                 .name           = "uart",
563                 .id             = 2,
564                 .parent         = &clk_pclk_low.clk,
565                 .enable         = s5p6440_pclk_ctrl,
566                 .ctrlbit        = S5P_CLKCON_PCLK_UART2,
567         }, {
568                 .name           = "uart",
569                 .id             = 3,
570                 .parent         = &clk_pclk_low.clk,
571                 .enable         = s5p6440_pclk_ctrl,
572                 .ctrlbit        = S5P_CLKCON_PCLK_UART3,
573         }, {
574                 .name           = "mem",
575                 .id             = -1,
576                 .parent         = &clk_hclk.clk,
577                 .enable         = s5p6440_hclk0_ctrl,
578                 .ctrlbit        = (1 << 21),
579         }, {
580                 .name           = "intc",
581                 .id             = -1,
582                 .parent         = &clk_hclk.clk,
583                 .enable         = s5p6440_hclk0_ctrl,
584                 .ctrlbit        = (1 << 1),
585         },
586 };
587
588 static struct clk clk_iis_cd_v40 = {
589         .name           = "iis_cdclk_v40",
590         .id             = -1,
591 };
592
593 static struct clk clk_pcm_cd = {
594         .name           = "pcm_cdclk",
595         .id             = -1,
596 };
597
598 static struct clk *clkset_group1_list[] = {
599         &clk_mout_epll.clk,
600         &clk_dout_mpll.clk,
601         &clk_fin_epll,
602 };
603
604 static struct clksrc_sources clkset_group1 = {
605         .sources        = clkset_group1_list,
606         .nr_sources     = ARRAY_SIZE(clkset_group1_list),
607 };
608
609 static struct clk *clkset_uart_list[] = {
610         &clk_mout_epll.clk,
611         &clk_dout_mpll.clk,
612 };
613
614 static struct clksrc_sources clkset_uart = {
615         .sources        = clkset_uart_list,
616         .nr_sources     = ARRAY_SIZE(clkset_uart_list),
617 };
618
619 static struct clksrc_clk clksrcs[] = {
620         {
621                 .clk    = {
622                         .name           = "mmc_bus",
623                         .id             = 0,
624                         .ctrlbit        = S5P_CLKCON_SCLK0_MMC0,
625                         .enable         = s5p6440_sclk_ctrl,
626                 },
627                 .sources = &clkset_group1,
628                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
629                 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
630         }, {
631                 .clk    = {
632                         .name           = "mmc_bus",
633                         .id             = 1,
634                         .ctrlbit        = S5P_CLKCON_SCLK0_MMC1,
635                         .enable         = s5p6440_sclk_ctrl,
636                 },
637                 .sources = &clkset_group1,
638                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
639                 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
640         }, {
641                 .clk    = {
642                         .name           = "mmc_bus",
643                         .id             = 2,
644                         .ctrlbit        = S5P_CLKCON_SCLK0_MMC2,
645                         .enable         = s5p6440_sclk_ctrl,
646                 },
647                 .sources = &clkset_group1,
648                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
649                 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
650         }, {
651                 .clk    = {
652                         .name           = "uclk1",
653                         .id             = -1,
654                         .ctrlbit        = S5P_CLKCON_SCLK0_UART,
655                         .enable         = s5p6440_sclk_ctrl,
656                 },
657                 .sources = &clkset_uart,
658                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 },
659                 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
660         }, {
661                 .clk    = {
662                         .name           = "spi_epll",
663                         .id             = 0,
664                         .ctrlbit        = S5P_CLKCON_SCLK0_SPI0,
665                         .enable         = s5p6440_sclk_ctrl,
666                 },
667                 .sources = &clkset_group1,
668                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
669                 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
670         }, {
671                 .clk    = {
672                         .name           = "spi_epll",
673                         .id             = 1,
674                         .ctrlbit        = S5P_CLKCON_SCLK0_SPI1,
675                         .enable         = s5p6440_sclk_ctrl,
676                 },
677                 .sources = &clkset_group1,
678                 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
679                 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
680         }
681 };
682
683 /* Clock initialisation code */
684 static struct clksrc_clk *sysclks[] = {
685         &clk_mout_apll,
686         &clk_mout_epll,
687         &clk_mout_mpll,
688         &clk_dout_mpll,
689         &clk_armclk,
690         &clk_hclk,
691         &clk_pclk,
692         &clk_hclk_low,
693         &clk_pclk_low,
694 };
695
696 void __init_or_cpufreq s5p6440_setup_clocks(void)
697 {
698         struct clk *xtal_clk;
699         unsigned long xtal;
700         unsigned long fclk;
701         unsigned long hclk;
702         unsigned long hclk_low;
703         unsigned long pclk;
704         unsigned long pclk_low;
705         unsigned long epll;
706         unsigned long apll;
707         unsigned long mpll;
708         unsigned int ptr;
709
710         /* Set S5P6440 functions for clk_fout_epll */
711         clk_fout_epll.enable = s5p6440_epll_enable;
712         clk_fout_epll.ops = &s5p6440_epll_ops;
713
714         clk_48m.enable = s5p6440_clk48m_ctrl;
715
716         xtal_clk = clk_get(NULL, "ext_xtal");
717         BUG_ON(IS_ERR(xtal_clk));
718
719         xtal = clk_get_rate(xtal_clk);
720         clk_put(xtal_clk);
721
722         epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON),
723                                 __raw_readl(S5P_EPLL_CON_K));
724         mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
725         apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
726
727         clk_fout_mpll.rate = mpll;
728         clk_fout_epll.rate = epll;
729         clk_fout_apll.rate = apll;
730
731         printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
732                         " E=%ld.%ldMHz\n",
733                         print_mhz(apll), print_mhz(mpll), print_mhz(epll));
734
735         fclk = clk_get_rate(&clk_armclk.clk);
736         hclk = clk_get_rate(&clk_hclk.clk);
737         pclk = clk_get_rate(&clk_pclk.clk);
738         hclk_low = clk_get_rate(&clk_hclk_low.clk);
739         pclk_low = clk_get_rate(&clk_pclk_low.clk);
740
741         printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
742                         " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
743                         print_mhz(hclk), print_mhz(hclk_low),
744                         print_mhz(pclk), print_mhz(pclk_low));
745
746         clk_f.rate = fclk;
747         clk_h.rate = hclk;
748         clk_p.rate = pclk;
749
750         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
751                 s3c_set_clksrc(&clksrcs[ptr], true);
752 }
753
754 static struct clk *clks[] __initdata = {
755         &clk_ext,
756         &clk_iis_cd_v40,
757         &clk_pcm_cd,
758 };
759
760 void __init s5p6440_register_clocks(void)
761 {
762         struct clk *clkp;
763         int ret;
764         int ptr;
765
766         ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
767         if (ret > 0)
768                 printk(KERN_ERR "Failed to register %u clocks\n", ret);
769
770         for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
771                 s3c_register_clksrc(sysclks[ptr], 1);
772
773         s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
774         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
775
776         clkp = init_clocks_disable;
777         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
778
779                 ret = s3c24xx_register_clock(clkp);
780                 if (ret < 0) {
781                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
782                                clkp->name, ret);
783                 }
784                 (clkp->enable)(clkp, 0);
785         }
786
787         s3c_pwmclk_init();
788 }