Merge remote branch 'alsa/devel' into topic/misc
[pandora-kernel.git] / arch / arm / mach-s5pv310 / clock.c
1 /* linux/arch/arm/mach-s5pv310/clock.c
2  *
3  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com/
5  *
6  * S5PV310 - 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/kernel.h>
14 #include <linux/err.h>
15 #include <linux/io.h>
16
17 #include <plat/cpu-freq.h>
18 #include <plat/clock.h>
19 #include <plat/cpu.h>
20 #include <plat/pll.h>
21 #include <plat/s5p-clock.h>
22 #include <plat/clock-clksrc.h>
23
24 #include <mach/map.h>
25 #include <mach/regs-clock.h>
26
27 static struct clk clk_sclk_hdmi27m = {
28         .name           = "sclk_hdmi27m",
29         .id             = -1,
30         .rate           = 27000000,
31 };
32
33 static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
34 {
35         return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
36 }
37
38 static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
39 {
40         return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
41 }
42
43 /* Core list of CMU_CPU side */
44
45 static struct clksrc_clk clk_mout_apll = {
46         .clk    = {
47                 .name           = "mout_apll",
48                 .id             = -1,
49         },
50         .sources        = &clk_src_apll,
51         .reg_src        = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
52 };
53
54 static struct clksrc_clk clk_sclk_apll = {
55         .clk    = {
56                 .name           = "sclk_apll",
57                 .id             = -1,
58                 .parent         = &clk_mout_apll.clk,
59         },
60         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
61 };
62
63 static struct clksrc_clk clk_mout_epll = {
64         .clk    = {
65                 .name           = "mout_epll",
66                 .id             = -1,
67         },
68         .sources        = &clk_src_epll,
69         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
70 };
71
72 static struct clksrc_clk clk_mout_mpll = {
73         .clk = {
74                 .name           = "mout_mpll",
75                 .id             = -1,
76         },
77         .sources        = &clk_src_mpll,
78         .reg_src        = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
79 };
80
81 static struct clk *clkset_moutcore_list[] = {
82         [0] = &clk_sclk_apll.clk,
83         [1] = &clk_mout_mpll.clk,
84 };
85
86 static struct clksrc_sources clkset_moutcore = {
87         .sources        = clkset_moutcore_list,
88         .nr_sources     = ARRAY_SIZE(clkset_moutcore_list),
89 };
90
91 static struct clksrc_clk clk_moutcore = {
92         .clk    = {
93                 .name           = "moutcore",
94                 .id             = -1,
95         },
96         .sources        = &clkset_moutcore,
97         .reg_src        = { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
98 };
99
100 static struct clksrc_clk clk_coreclk = {
101         .clk    = {
102                 .name           = "core_clk",
103                 .id             = -1,
104                 .parent         = &clk_moutcore.clk,
105         },
106         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
107 };
108
109 static struct clksrc_clk clk_armclk = {
110         .clk    = {
111                 .name           = "armclk",
112                 .id             = -1,
113                 .parent         = &clk_coreclk.clk,
114         },
115 };
116
117 static struct clksrc_clk clk_aclk_corem0 = {
118         .clk    = {
119                 .name           = "aclk_corem0",
120                 .id             = -1,
121                 .parent         = &clk_coreclk.clk,
122         },
123         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
124 };
125
126 static struct clksrc_clk clk_aclk_cores = {
127         .clk    = {
128                 .name           = "aclk_cores",
129                 .id             = -1,
130                 .parent         = &clk_coreclk.clk,
131         },
132         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
133 };
134
135 static struct clksrc_clk clk_aclk_corem1 = {
136         .clk    = {
137                 .name           = "aclk_corem1",
138                 .id             = -1,
139                 .parent         = &clk_coreclk.clk,
140         },
141         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
142 };
143
144 static struct clksrc_clk clk_periphclk = {
145         .clk    = {
146                 .name           = "periphclk",
147                 .id             = -1,
148                 .parent         = &clk_coreclk.clk,
149         },
150         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
151 };
152
153 static struct clksrc_clk clk_atclk = {
154         .clk    = {
155                 .name           = "atclk",
156                 .id             = -1,
157                 .parent         = &clk_moutcore.clk,
158         },
159         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 },
160 };
161
162 static struct clksrc_clk clk_pclk_dbg = {
163         .clk    = {
164                 .name           = "pclk_dbg",
165                 .id             = -1,
166                 .parent         = &clk_atclk.clk,
167         },
168         .reg_div        = { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 },
169 };
170
171 /* Core list of CMU_CORE side */
172
173 static struct clk *clkset_corebus_list[] = {
174         [0] = &clk_mout_mpll.clk,
175         [1] = &clk_sclk_apll.clk,
176 };
177
178 static struct clksrc_sources clkset_mout_corebus = {
179         .sources        = clkset_corebus_list,
180         .nr_sources     = ARRAY_SIZE(clkset_corebus_list),
181 };
182
183 static struct clksrc_clk clk_mout_corebus = {
184         .clk    = {
185                 .name           = "mout_corebus",
186                 .id             = -1,
187         },
188         .sources        = &clkset_mout_corebus,
189         .reg_src        = { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 },
190 };
191
192 static struct clksrc_clk clk_sclk_dmc = {
193         .clk    = {
194                 .name           = "sclk_dmc",
195                 .id             = -1,
196                 .parent         = &clk_mout_corebus.clk,
197         },
198         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 },
199 };
200
201 static struct clksrc_clk clk_aclk_cored = {
202         .clk    = {
203                 .name           = "aclk_cored",
204                 .id             = -1,
205                 .parent         = &clk_sclk_dmc.clk,
206         },
207         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 },
208 };
209
210 static struct clksrc_clk clk_aclk_corep = {
211         .clk    = {
212                 .name           = "aclk_corep",
213                 .id             = -1,
214                 .parent         = &clk_aclk_cored.clk,
215         },
216         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 },
217 };
218
219 static struct clksrc_clk clk_aclk_acp = {
220         .clk    = {
221                 .name           = "aclk_acp",
222                 .id             = -1,
223                 .parent         = &clk_mout_corebus.clk,
224         },
225         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 },
226 };
227
228 static struct clksrc_clk clk_pclk_acp = {
229         .clk    = {
230                 .name           = "pclk_acp",
231                 .id             = -1,
232                 .parent         = &clk_aclk_acp.clk,
233         },
234         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 },
235 };
236
237 /* Core list of CMU_TOP side */
238
239 static struct clk *clkset_aclk_top_list[] = {
240         [0] = &clk_mout_mpll.clk,
241         [1] = &clk_sclk_apll.clk,
242 };
243
244 static struct clksrc_sources clkset_aclk_200 = {
245         .sources        = clkset_aclk_top_list,
246         .nr_sources     = ARRAY_SIZE(clkset_aclk_top_list),
247 };
248
249 static struct clksrc_clk clk_aclk_200 = {
250         .clk    = {
251                 .name           = "aclk_200",
252                 .id             = -1,
253         },
254         .sources        = &clkset_aclk_200,
255         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
256         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
257 };
258
259 static struct clksrc_sources clkset_aclk_100 = {
260         .sources        = clkset_aclk_top_list,
261         .nr_sources     = ARRAY_SIZE(clkset_aclk_top_list),
262 };
263
264 static struct clksrc_clk clk_aclk_100 = {
265         .clk    = {
266                 .name           = "aclk_100",
267                 .id             = -1,
268         },
269         .sources        = &clkset_aclk_100,
270         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
271         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
272 };
273
274 static struct clksrc_sources clkset_aclk_160 = {
275         .sources        = clkset_aclk_top_list,
276         .nr_sources     = ARRAY_SIZE(clkset_aclk_top_list),
277 };
278
279 static struct clksrc_clk clk_aclk_160 = {
280         .clk    = {
281                 .name           = "aclk_160",
282                 .id             = -1,
283         },
284         .sources        = &clkset_aclk_160,
285         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
286         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
287 };
288
289 static struct clksrc_sources clkset_aclk_133 = {
290         .sources        = clkset_aclk_top_list,
291         .nr_sources     = ARRAY_SIZE(clkset_aclk_top_list),
292 };
293
294 static struct clksrc_clk clk_aclk_133 = {
295         .clk    = {
296                 .name           = "aclk_133",
297                 .id             = -1,
298         },
299         .sources        = &clkset_aclk_133,
300         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
301         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
302 };
303
304 static struct clk *clkset_vpllsrc_list[] = {
305         [0] = &clk_fin_vpll,
306         [1] = &clk_sclk_hdmi27m,
307 };
308
309 static struct clksrc_sources clkset_vpllsrc = {
310         .sources        = clkset_vpllsrc_list,
311         .nr_sources     = ARRAY_SIZE(clkset_vpllsrc_list),
312 };
313
314 static struct clksrc_clk clk_vpllsrc = {
315         .clk    = {
316                 .name           = "vpll_src",
317                 .id             = -1,
318         },
319         .sources        = &clkset_vpllsrc,
320         .reg_src        = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
321 };
322
323 static struct clk *clkset_sclk_vpll_list[] = {
324         [0] = &clk_vpllsrc.clk,
325         [1] = &clk_fout_vpll,
326 };
327
328 static struct clksrc_sources clkset_sclk_vpll = {
329         .sources        = clkset_sclk_vpll_list,
330         .nr_sources     = ARRAY_SIZE(clkset_sclk_vpll_list),
331 };
332
333 static struct clksrc_clk clk_sclk_vpll = {
334         .clk    = {
335                 .name           = "sclk_vpll",
336                 .id             = -1,
337         },
338         .sources        = &clkset_sclk_vpll,
339         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
340 };
341
342 static struct clk init_clocks_disable[] = {
343         {
344                 .name           = "timers",
345                 .id             = -1,
346                 .parent         = &clk_aclk_100.clk,
347                 .enable         = s5pv310_clk_ip_peril_ctrl,
348                 .ctrlbit        = (1<<24),
349         }
350 };
351
352 static struct clk init_clocks[] = {
353         {
354                 .name           = "uart",
355                 .id             = 0,
356                 .enable         = s5pv310_clk_ip_peril_ctrl,
357                 .ctrlbit        = (1 << 0),
358         }, {
359                 .name           = "uart",
360                 .id             = 1,
361                 .enable         = s5pv310_clk_ip_peril_ctrl,
362                 .ctrlbit        = (1 << 1),
363         }, {
364                 .name           = "uart",
365                 .id             = 2,
366                 .enable         = s5pv310_clk_ip_peril_ctrl,
367                 .ctrlbit        = (1 << 2),
368         }, {
369                 .name           = "uart",
370                 .id             = 3,
371                 .enable         = s5pv310_clk_ip_peril_ctrl,
372                 .ctrlbit        = (1 << 3),
373         }, {
374                 .name           = "uart",
375                 .id             = 4,
376                 .enable         = s5pv310_clk_ip_peril_ctrl,
377                 .ctrlbit        = (1 << 4),
378         }, {
379                 .name           = "uart",
380                 .id             = 5,
381                 .enable         = s5pv310_clk_ip_peril_ctrl,
382                 .ctrlbit        = (1 << 5),
383         }
384 };
385
386 static struct clk *clkset_group_list[] = {
387         [0] = &clk_ext_xtal_mux,
388         [1] = &clk_xusbxti,
389         [2] = &clk_sclk_hdmi27m,
390         [6] = &clk_mout_mpll.clk,
391         [7] = &clk_mout_epll.clk,
392         [8] = &clk_sclk_vpll.clk,
393 };
394
395 static struct clksrc_sources clkset_group = {
396         .sources        = clkset_group_list,
397         .nr_sources     = ARRAY_SIZE(clkset_group_list),
398 };
399
400 static struct clksrc_clk clksrcs[] = {
401         {
402                 .clk    = {
403                         .name           = "uclk1",
404                         .id             = 0,
405                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
406                         .ctrlbit        = (1 << 0),
407                 },
408                 .sources = &clkset_group,
409                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
410                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
411         }, {
412                 .clk            = {
413                         .name           = "uclk1",
414                         .id             = 1,
415                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
416                         .ctrlbit        = (1 << 4),
417                 },
418                 .sources = &clkset_group,
419                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
420                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
421         }, {
422                 .clk            = {
423                         .name           = "uclk1",
424                         .id             = 2,
425                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
426                         .ctrlbit        = (1 << 8),
427                 },
428                 .sources = &clkset_group,
429                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
430                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
431         }, {
432                 .clk            = {
433                         .name           = "uclk1",
434                         .id             = 3,
435                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
436                         .ctrlbit        = (1 << 12),
437                 },
438                 .sources = &clkset_group,
439                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
440                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
441         }, {
442                 .clk            = {
443                         .name           = "sclk_pwm",
444                         .id             = -1,
445                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
446                         .ctrlbit        = (1 << 24),
447                 },
448                 .sources = &clkset_group,
449                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
450                 .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
451         },
452 };
453
454 /* Clock initialization code */
455 static struct clksrc_clk *sysclks[] = {
456         &clk_mout_apll,
457         &clk_sclk_apll,
458         &clk_mout_epll,
459         &clk_mout_mpll,
460         &clk_moutcore,
461         &clk_coreclk,
462         &clk_armclk,
463         &clk_aclk_corem0,
464         &clk_aclk_cores,
465         &clk_aclk_corem1,
466         &clk_periphclk,
467         &clk_atclk,
468         &clk_pclk_dbg,
469         &clk_mout_corebus,
470         &clk_sclk_dmc,
471         &clk_aclk_cored,
472         &clk_aclk_corep,
473         &clk_aclk_acp,
474         &clk_pclk_acp,
475         &clk_vpllsrc,
476         &clk_sclk_vpll,
477         &clk_aclk_200,
478         &clk_aclk_100,
479         &clk_aclk_160,
480         &clk_aclk_133,
481 };
482
483 void __init_or_cpufreq s5pv310_setup_clocks(void)
484 {
485         struct clk *xtal_clk;
486         unsigned long apll;
487         unsigned long mpll;
488         unsigned long epll;
489         unsigned long vpll;
490         unsigned long vpllsrc;
491         unsigned long xtal;
492         unsigned long armclk;
493         unsigned long aclk_corem0;
494         unsigned long aclk_cores;
495         unsigned long aclk_corem1;
496         unsigned long periphclk;
497         unsigned long sclk_dmc;
498         unsigned long aclk_cored;
499         unsigned long aclk_corep;
500         unsigned long aclk_acp;
501         unsigned long pclk_acp;
502         unsigned int ptr;
503
504         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
505
506         xtal_clk = clk_get(NULL, "xtal");
507         BUG_ON(IS_ERR(xtal_clk));
508
509         xtal = clk_get_rate(xtal_clk);
510         clk_put(xtal_clk);
511
512         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
513
514         apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
515         mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
516         epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
517                                 __raw_readl(S5P_EPLL_CON1), pll_4600);
518
519         vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
520         vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
521                                 __raw_readl(S5P_VPLL_CON1), pll_4650);
522
523         clk_fout_apll.rate = apll;
524         clk_fout_mpll.rate = mpll;
525         clk_fout_epll.rate = epll;
526         clk_fout_vpll.rate = vpll;
527
528         printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
529                         apll, mpll, epll, vpll);
530
531         armclk = clk_get_rate(&clk_armclk.clk);
532         aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk);
533         aclk_cores = clk_get_rate(&clk_aclk_cores.clk);
534         aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk);
535         periphclk = clk_get_rate(&clk_periphclk.clk);
536         sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
537         aclk_cored = clk_get_rate(&clk_aclk_cored.clk);
538         aclk_corep = clk_get_rate(&clk_aclk_corep.clk);
539         aclk_acp = clk_get_rate(&clk_aclk_acp.clk);
540         pclk_acp = clk_get_rate(&clk_pclk_acp.clk);
541
542         printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n"
543                          "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n"
544                          "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld",
545                         armclk, aclk_corem0, aclk_cores, aclk_corem1,
546                         periphclk, sclk_dmc, aclk_cored, aclk_corep,
547                         aclk_acp, pclk_acp);
548
549         clk_f.rate = armclk;
550         clk_h.rate = sclk_dmc;
551         clk_p.rate = periphclk;
552
553         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
554                 s3c_set_clksrc(&clksrcs[ptr], true);
555 }
556
557 static struct clk *clks[] __initdata = {
558         /* Nothing here yet */
559 };
560
561 void __init s5pv310_register_clocks(void)
562 {
563         struct clk *clkp;
564         int ret;
565         int ptr;
566
567         ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
568         if (ret > 0)
569                 printk(KERN_ERR "Failed to register %u clocks\n", ret);
570
571         for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
572                 s3c_register_clksrc(sysclks[ptr], 1);
573
574         s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
575         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
576
577         clkp = init_clocks_disable;
578         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
579                 ret = s3c24xx_register_clock(clkp);
580                 if (ret < 0) {
581                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
582                                clkp->name, ret);
583                 }
584                 (clkp->enable)(clkp, 0);
585         }
586
587         s3c_pwmclk_init();
588 }