ARM: S5PV310: Adds clkset_aclk for removing clkset_aclk_xxx
[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 /* Core list of CMU_CORE side */
154
155 static struct clk *clkset_corebus_list[] = {
156         [0] = &clk_mout_mpll.clk,
157         [1] = &clk_sclk_apll.clk,
158 };
159
160 static struct clksrc_sources clkset_mout_corebus = {
161         .sources        = clkset_corebus_list,
162         .nr_sources     = ARRAY_SIZE(clkset_corebus_list),
163 };
164
165 static struct clksrc_clk clk_mout_corebus = {
166         .clk    = {
167                 .name           = "mout_corebus",
168                 .id             = -1,
169         },
170         .sources        = &clkset_mout_corebus,
171         .reg_src        = { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 },
172 };
173
174 static struct clksrc_clk clk_sclk_dmc = {
175         .clk    = {
176                 .name           = "sclk_dmc",
177                 .id             = -1,
178                 .parent         = &clk_mout_corebus.clk,
179         },
180         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 },
181 };
182
183 static struct clksrc_clk clk_aclk_cored = {
184         .clk    = {
185                 .name           = "aclk_cored",
186                 .id             = -1,
187                 .parent         = &clk_sclk_dmc.clk,
188         },
189         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 },
190 };
191
192 static struct clksrc_clk clk_aclk_corep = {
193         .clk    = {
194                 .name           = "aclk_corep",
195                 .id             = -1,
196                 .parent         = &clk_aclk_cored.clk,
197         },
198         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 },
199 };
200
201 static struct clksrc_clk clk_aclk_acp = {
202         .clk    = {
203                 .name           = "aclk_acp",
204                 .id             = -1,
205                 .parent         = &clk_mout_corebus.clk,
206         },
207         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 },
208 };
209
210 static struct clksrc_clk clk_pclk_acp = {
211         .clk    = {
212                 .name           = "pclk_acp",
213                 .id             = -1,
214                 .parent         = &clk_aclk_acp.clk,
215         },
216         .reg_div        = { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 },
217 };
218
219 /* Core list of CMU_TOP side */
220
221 static struct clk *clkset_aclk_top_list[] = {
222         [0] = &clk_mout_mpll.clk,
223         [1] = &clk_sclk_apll.clk,
224 };
225
226 static struct clksrc_sources clkset_aclk = {
227         .sources        = clkset_aclk_top_list,
228         .nr_sources     = ARRAY_SIZE(clkset_aclk_top_list),
229 };
230
231 static struct clksrc_clk clk_aclk_200 = {
232         .clk    = {
233                 .name           = "aclk_200",
234                 .id             = -1,
235         },
236         .sources        = &clkset_aclk,
237         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
238         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
239 };
240
241 static struct clksrc_clk clk_aclk_100 = {
242         .clk    = {
243                 .name           = "aclk_100",
244                 .id             = -1,
245         },
246         .sources        = &clkset_aclk,
247         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
248         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
249 };
250
251 static struct clksrc_clk clk_aclk_160 = {
252         .clk    = {
253                 .name           = "aclk_160",
254                 .id             = -1,
255         },
256         .sources        = &clkset_aclk,
257         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
258         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
259 };
260
261 static struct clksrc_clk clk_aclk_133 = {
262         .clk    = {
263                 .name           = "aclk_133",
264                 .id             = -1,
265         },
266         .sources        = &clkset_aclk,
267         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
268         .reg_div        = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
269 };
270
271 static struct clk *clkset_vpllsrc_list[] = {
272         [0] = &clk_fin_vpll,
273         [1] = &clk_sclk_hdmi27m,
274 };
275
276 static struct clksrc_sources clkset_vpllsrc = {
277         .sources        = clkset_vpllsrc_list,
278         .nr_sources     = ARRAY_SIZE(clkset_vpllsrc_list),
279 };
280
281 static struct clksrc_clk clk_vpllsrc = {
282         .clk    = {
283                 .name           = "vpll_src",
284                 .id             = -1,
285         },
286         .sources        = &clkset_vpllsrc,
287         .reg_src        = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
288 };
289
290 static struct clk *clkset_sclk_vpll_list[] = {
291         [0] = &clk_vpllsrc.clk,
292         [1] = &clk_fout_vpll,
293 };
294
295 static struct clksrc_sources clkset_sclk_vpll = {
296         .sources        = clkset_sclk_vpll_list,
297         .nr_sources     = ARRAY_SIZE(clkset_sclk_vpll_list),
298 };
299
300 static struct clksrc_clk clk_sclk_vpll = {
301         .clk    = {
302                 .name           = "sclk_vpll",
303                 .id             = -1,
304         },
305         .sources        = &clkset_sclk_vpll,
306         .reg_src        = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
307 };
308
309 static struct clk init_clocks_disable[] = {
310         {
311                 .name           = "timers",
312                 .id             = -1,
313                 .parent         = &clk_aclk_100.clk,
314                 .enable         = s5pv310_clk_ip_peril_ctrl,
315                 .ctrlbit        = (1<<24),
316         }
317 };
318
319 static struct clk init_clocks[] = {
320         {
321                 .name           = "uart",
322                 .id             = 0,
323                 .enable         = s5pv310_clk_ip_peril_ctrl,
324                 .ctrlbit        = (1 << 0),
325         }, {
326                 .name           = "uart",
327                 .id             = 1,
328                 .enable         = s5pv310_clk_ip_peril_ctrl,
329                 .ctrlbit        = (1 << 1),
330         }, {
331                 .name           = "uart",
332                 .id             = 2,
333                 .enable         = s5pv310_clk_ip_peril_ctrl,
334                 .ctrlbit        = (1 << 2),
335         }, {
336                 .name           = "uart",
337                 .id             = 3,
338                 .enable         = s5pv310_clk_ip_peril_ctrl,
339                 .ctrlbit        = (1 << 3),
340         }, {
341                 .name           = "uart",
342                 .id             = 4,
343                 .enable         = s5pv310_clk_ip_peril_ctrl,
344                 .ctrlbit        = (1 << 4),
345         }, {
346                 .name           = "uart",
347                 .id             = 5,
348                 .enable         = s5pv310_clk_ip_peril_ctrl,
349                 .ctrlbit        = (1 << 5),
350         }
351 };
352
353 static struct clk *clkset_group_list[] = {
354         [0] = &clk_ext_xtal_mux,
355         [1] = &clk_xusbxti,
356         [2] = &clk_sclk_hdmi27m,
357         [6] = &clk_mout_mpll.clk,
358         [7] = &clk_mout_epll.clk,
359         [8] = &clk_sclk_vpll.clk,
360 };
361
362 static struct clksrc_sources clkset_group = {
363         .sources        = clkset_group_list,
364         .nr_sources     = ARRAY_SIZE(clkset_group_list),
365 };
366
367 static struct clksrc_clk clksrcs[] = {
368         {
369                 .clk    = {
370                         .name           = "uclk1",
371                         .id             = 0,
372                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
373                         .ctrlbit        = (1 << 0),
374                 },
375                 .sources = &clkset_group,
376                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
377                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
378         }, {
379                 .clk            = {
380                         .name           = "uclk1",
381                         .id             = 1,
382                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
383                         .ctrlbit        = (1 << 4),
384                 },
385                 .sources = &clkset_group,
386                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
387                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
388         }, {
389                 .clk            = {
390                         .name           = "uclk1",
391                         .id             = 2,
392                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
393                         .ctrlbit        = (1 << 8),
394                 },
395                 .sources = &clkset_group,
396                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
397                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
398         }, {
399                 .clk            = {
400                         .name           = "uclk1",
401                         .id             = 3,
402                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
403                         .ctrlbit        = (1 << 12),
404                 },
405                 .sources = &clkset_group,
406                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
407                 .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
408         }, {
409                 .clk            = {
410                         .name           = "sclk_pwm",
411                         .id             = -1,
412                         .enable         = s5pv310_clksrc_mask_peril0_ctrl,
413                         .ctrlbit        = (1 << 24),
414                 },
415                 .sources = &clkset_group,
416                 .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
417                 .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
418         },
419 };
420
421 /* Clock initialization code */
422 static struct clksrc_clk *sysclks[] = {
423         &clk_mout_apll,
424         &clk_sclk_apll,
425         &clk_mout_epll,
426         &clk_mout_mpll,
427         &clk_moutcore,
428         &clk_coreclk,
429         &clk_armclk,
430         &clk_aclk_corem0,
431         &clk_aclk_cores,
432         &clk_aclk_corem1,
433         &clk_periphclk,
434         &clk_mout_corebus,
435         &clk_sclk_dmc,
436         &clk_aclk_cored,
437         &clk_aclk_corep,
438         &clk_aclk_acp,
439         &clk_pclk_acp,
440         &clk_vpllsrc,
441         &clk_sclk_vpll,
442         &clk_aclk_200,
443         &clk_aclk_100,
444         &clk_aclk_160,
445         &clk_aclk_133,
446 };
447
448 void __init_or_cpufreq s5pv310_setup_clocks(void)
449 {
450         struct clk *xtal_clk;
451         unsigned long apll;
452         unsigned long mpll;
453         unsigned long epll;
454         unsigned long vpll;
455         unsigned long vpllsrc;
456         unsigned long xtal;
457         unsigned long armclk;
458         unsigned long sclk_dmc;
459         unsigned int ptr;
460
461         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
462
463         xtal_clk = clk_get(NULL, "xtal");
464         BUG_ON(IS_ERR(xtal_clk));
465
466         xtal = clk_get_rate(xtal_clk);
467         clk_put(xtal_clk);
468
469         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
470
471         apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
472         mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
473         epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
474                                 __raw_readl(S5P_EPLL_CON1), pll_4600);
475
476         vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
477         vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
478                                 __raw_readl(S5P_VPLL_CON1), pll_4650);
479
480         clk_fout_apll.rate = apll;
481         clk_fout_mpll.rate = mpll;
482         clk_fout_epll.rate = epll;
483         clk_fout_vpll.rate = vpll;
484
485         printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
486                         apll, mpll, epll, vpll);
487
488         armclk = clk_get_rate(&clk_armclk.clk);
489         sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
490
491         printk(KERN_INFO "S5PV310: ARMCLK=%ld, DMC=%ld\n", armclk, sclk_dmc);
492
493         clk_f.rate = armclk;
494         clk_h.rate = sclk_dmc;
495
496         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
497                 s3c_set_clksrc(&clksrcs[ptr], true);
498 }
499
500 static struct clk *clks[] __initdata = {
501         /* Nothing here yet */
502 };
503
504 void __init s5pv310_register_clocks(void)
505 {
506         struct clk *clkp;
507         int ret;
508         int ptr;
509
510         ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
511         if (ret > 0)
512                 printk(KERN_ERR "Failed to register %u clocks\n", ret);
513
514         for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
515                 s3c_register_clksrc(sysclks[ptr], 1);
516
517         s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
518         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
519
520         clkp = init_clocks_disable;
521         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
522                 ret = s3c24xx_register_clock(clkp);
523                 if (ret < 0) {
524                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
525                                clkp->name, ret);
526                 }
527                 (clkp->enable)(clkp, 0);
528         }
529
530         s3c_pwmclk_init();
531 }