1 /* linux/arch/arm/mach-s5pv210/clock.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * S5PV210 - Clock support
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.
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>
25 #include <plat/cpu-freq.h>
26 #include <mach/regs-clock.h>
27 #include <plat/clock.h>
30 #include <plat/s5p-clock.h>
31 #include <plat/clock-clksrc.h>
32 #include <plat/s5pv210.h>
34 static struct clksrc_clk clk_mout_apll = {
39 .sources = &clk_src_apll,
40 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
43 static struct clksrc_clk clk_mout_epll = {
48 .sources = &clk_src_epll,
49 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
52 static struct clksrc_clk clk_mout_mpll = {
57 .sources = &clk_src_mpll,
58 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
61 static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
63 return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
66 static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
68 return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
71 static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
73 return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
76 static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
78 return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
81 static struct clk clk_h200 = {
86 static struct clk clk_h100 = {
91 static struct clk clk_h166 = {
96 static struct clk clk_h133 = {
101 static struct clk clk_p100 = {
106 static struct clk clk_p83 = {
111 static struct clk clk_p66 = {
116 static struct clk *sys_clks[] = {
126 static struct clk init_clocks_disable[] = {
131 .enable = s5pv210_clk_ip0_ctrl,
137 .enable = s5pv210_clk_ip1_ctrl,
143 .enable = s5pv210_clk_ip1_ctrl,
149 .enable = s5pv210_clk_ip1_ctrl,
155 .enable = s5pv210_clk_ip1_ctrl,
161 .enable = s5pv210_clk_ip2_ctrl,
167 .enable = s5pv210_clk_ip2_ctrl,
173 .enable = s5pv210_clk_ip2_ctrl,
179 .enable = s5pv210_clk_ip2_ctrl,
185 .enable = s5pv210_clk_ip3_ctrl,
191 .enable = s5pv210_clk_ip3_ctrl,
197 .enable = s5pv210_clk_ip3_ctrl,
203 .enable = s5pv210_clk_ip3_ctrl,
209 .enable = s5pv210_clk_ip3_ctrl,
215 .enable = s5pv210_clk_ip3_ctrl,
221 .enable = s5pv210_clk_ip3_ctrl,
227 .enable = s5pv210_clk_ip3_ctrl,
233 .enable = s5pv210_clk_ip3_ctrl,
239 .enable = s5pv210_clk_ip3_ctrl,
245 .enable = s5pv210_clk_ip3_ctrl,
251 .enable = s5pv210_clk_ip3_ctrl,
257 .enable = s5pv210_clk_ip3_ctrl,
263 .enable = s5pv210_clk_ip3_ctrl,
269 .enable = s5pv210_clk_ip3_ctrl,
274 static struct clk init_clocks[] = {
279 .enable = s5pv210_clk_ip3_ctrl,
285 .enable = s5pv210_clk_ip3_ctrl,
291 .enable = s5pv210_clk_ip3_ctrl,
297 .enable = s5pv210_clk_ip3_ctrl,
302 static struct clk *clkset_uart_list[] = {
303 [6] = &clk_mout_mpll.clk,
304 [7] = &clk_mout_epll.clk,
307 static struct clksrc_sources clkset_uart = {
308 .sources = clkset_uart_list,
309 .nr_sources = ARRAY_SIZE(clkset_uart_list),
312 static struct clksrc_clk clksrcs[] = {
318 .enable = s5pv210_clk_ip3_ctrl,
320 .sources = &clkset_uart,
321 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
322 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
326 /* Clock initialisation code */
327 static struct clksrc_clk *sysclks[] = {
333 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
335 void __init_or_cpufreq s5pv210_setup_clocks(void)
337 struct clk *xtal_clk;
339 unsigned long armclk;
340 unsigned long hclk200;
341 unsigned long hclk166;
342 unsigned long hclk133;
343 unsigned long pclk100;
344 unsigned long pclk83;
345 unsigned long pclk66;
350 u32 clkdiv0, clkdiv1;
352 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
354 clkdiv0 = __raw_readl(S5P_CLK_DIV0);
355 clkdiv1 = __raw_readl(S5P_CLK_DIV1);
357 printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
358 __func__, clkdiv0, clkdiv1);
360 xtal_clk = clk_get(NULL, "xtal");
361 BUG_ON(IS_ERR(xtal_clk));
363 xtal = clk_get_rate(xtal_clk);
366 printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
368 apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
369 mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
370 epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
372 printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld",
375 armclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_APLL);
376 if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK)
377 hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
379 hclk200 = armclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
381 if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) {
382 hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
383 hclk166 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
385 hclk166 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
387 if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) {
388 hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
389 hclk133 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
391 hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
393 pclk100 = hclk200 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100);
394 pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83);
395 pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66);
397 printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \
398 HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
399 armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66);
401 clk_fout_apll.rate = apll;
402 clk_fout_mpll.rate = mpll;
403 clk_fout_epll.rate = epll;
406 clk_h.rate = hclk133;
408 clk_p66.rate = pclk66;
409 clk_p83.rate = pclk83;
410 clk_h133.rate = hclk133;
411 clk_h166.rate = hclk166;
412 clk_h200.rate = hclk200;
414 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
415 s3c_set_clksrc(&clksrcs[ptr], true);
418 static struct clk *clks[] __initdata = {
421 void __init s5pv210_register_clocks(void)
427 ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
429 printk(KERN_ERR "Failed to register %u clocks\n", ret);
431 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
432 s3c_register_clksrc(sysclks[ptr], 1);
434 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
435 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
437 ret = s3c24xx_register_clocks(sys_clks, ARRAY_SIZE(sys_clks));
439 printk(KERN_ERR "Failed to register system clocks\n");
441 clkp = init_clocks_disable;
442 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
443 ret = s3c24xx_register_clock(clkp);
445 printk(KERN_ERR "Failed to register clock %s (%d)\n",
448 (clkp->enable)(clkp, 0);