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