diff options
author | Olof Johansson <olof@lixom.net> | 2013-02-05 19:14:35 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-02-05 19:14:35 -0500 |
commit | 7dcbeef7926fefa53b0466a27c90238744fb11d8 (patch) | |
tree | 86d7406fb86068b6f5177fa8d9446ffe7403841a /arch/arm/mach-s3c24xx | |
parent | f0390669d13b0a1592fc7906445b4f6c8ec5af23 (diff) | |
parent | acf2d41d8595829eb0ac7bf6891f4875a78d4d6e (diff) |
Merge branch 'next/cleanup-s3c24xx' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/cleanup
From Kukjin Kim:
Basically, this patch merges mach-s3c2410, mach-s3c2412 and mach-s3c2440
into mach-s3c24xx.
* 'next/cleanup-s3c24xx' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung:
ARM: S3C24XX: Move mach-s3c2440/ pll into mach-s3c24xx/
ARM: S3C24XX: Move mach-s3c2440/ cpufreq driver into mach-s3c24xx/
ARM: S3C24XX: Move mach-s3c2412/ cpufreq driver into mach-s3c24xx/
ARM: S3C2412: Remove useless codes mach-s3c2412/gpio.c
ARM: S3C24XX: Move mach-s3c2410/ pll into mach-s3c24xx/
ARM: S3C24XX: Move mach-s3c2410/ cpufreq into mach-s3c24xx/
Diffstat (limited to 'arch/arm/mach-s3c24xx')
-rw-r--r-- | arch/arm/mach-s3c24xx/Kconfig | 56 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/cpufreq-s3c2410.c | 160 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/cpufreq-s3c2412.c | 257 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/cpufreq-s3c2440.c | 312 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/include/mach/hardware.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/pll-s3c2410.c | 96 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c | 98 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c | 125 |
9 files changed, 1110 insertions, 6 deletions
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 25df14a9e268..67df58bdc096 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig | |||
@@ -127,6 +127,20 @@ config S3C2410_PM | |||
127 | 127 | ||
128 | if CPU_S3C2410 | 128 | if CPU_S3C2410 |
129 | 129 | ||
130 | config S3C2410_CPUFREQ | ||
131 | bool | ||
132 | depends on CPU_FREQ_S3C24XX && CPU_S3C2410 | ||
133 | select S3C2410_CPUFREQ_UTILS | ||
134 | help | ||
135 | CPU Frequency scaling support for S3C2410 | ||
136 | |||
137 | config S3C2410_PLL | ||
138 | bool | ||
139 | depends on S3C2410_CPUFREQ && CPU_FREQ_S3C24XX_PLL | ||
140 | default y | ||
141 | help | ||
142 | Select the PLL table for the S3C2410 | ||
143 | |||
130 | config S3C24XX_SIMTEC_NOR | 144 | config S3C24XX_SIMTEC_NOR |
131 | bool | 145 | bool |
132 | help | 146 | help |
@@ -266,6 +280,14 @@ config CPU_S3C2412_ONLY | |||
266 | !CPU_S3C2443 && CPU_S3C2412 | 280 | !CPU_S3C2443 && CPU_S3C2412 |
267 | default y | 281 | default y |
268 | 282 | ||
283 | config S3C2412_CPUFREQ | ||
284 | bool | ||
285 | depends on CPU_FREQ_S3C24XX && CPU_S3C2412 | ||
286 | default y | ||
287 | select S3C2412_IOTIMING | ||
288 | help | ||
289 | CPU Frequency scaling support for S3C2412 and S3C2413 SoC CPUs. | ||
290 | |||
269 | config S3C2412_DMA | 291 | config S3C2412_DMA |
270 | bool | 292 | bool |
271 | help | 293 | help |
@@ -365,11 +387,45 @@ endif # CPU_S3C2416 | |||
365 | 387 | ||
366 | if CPU_S3C2440 | 388 | if CPU_S3C2440 |
367 | 389 | ||
390 | config S3C2440_CPUFREQ | ||
391 | bool "S3C2440/S3C2442 CPU Frequency scaling support" | ||
392 | depends on CPU_FREQ_S3C24XX && (CPU_S3C2440 || CPU_S3C2442) | ||
393 | default y | ||
394 | select S3C2410_CPUFREQ_UTILS | ||
395 | help | ||
396 | CPU Frequency scaling support for S3C2440 and S3C2442 SoC CPUs. | ||
397 | |||
368 | config S3C2440_DMA | 398 | config S3C2440_DMA |
369 | bool | 399 | bool |
370 | help | 400 | help |
371 | Support for S3C2440 specific DMA code5A | 401 | Support for S3C2440 specific DMA code5A |
372 | 402 | ||
403 | config S3C2440_XTAL_12000000 | ||
404 | bool | ||
405 | help | ||
406 | Indicate that the build needs to support 12MHz system | ||
407 | crystal. | ||
408 | |||
409 | config S3C2440_XTAL_16934400 | ||
410 | bool | ||
411 | help | ||
412 | Indicate that the build needs to support 16.9344MHz system | ||
413 | crystal. | ||
414 | |||
415 | config S3C2440_PLL_12000000 | ||
416 | bool | ||
417 | depends on S3C2440_CPUFREQ && S3C2440_XTAL_12000000 | ||
418 | default y if CPU_FREQ_S3C24XX_PLL | ||
419 | help | ||
420 | PLL tables for S3C2440 or S3C2442 CPUs with 12MHz crystals. | ||
421 | |||
422 | config S3C2440_PLL_16934400 | ||
423 | bool | ||
424 | depends on S3C2440_CPUFREQ && S3C2440_XTAL_16934400 | ||
425 | default y if CPU_FREQ_S3C24XX_PLL | ||
426 | help | ||
427 | PLL tables for S3C2440 or S3C2442 CPUs with 16.934MHz crystals. | ||
428 | |||
373 | comment "S3C2440 Boards" | 429 | comment "S3C2440 Boards" |
374 | 430 | ||
375 | # | 431 | # |
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 0ab6ab15da4c..08b87cdb98b7 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile | |||
@@ -17,10 +17,13 @@ obj- := | |||
17 | obj-y += common.o | 17 | obj-y += common.o |
18 | 18 | ||
19 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o | 19 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o |
20 | obj-$(CONFIG_S3C2410_CPUFREQ) += cpufreq-s3c2410.o | ||
20 | obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o | 21 | obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o |
22 | obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o | ||
21 | obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o | 23 | obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o |
22 | 24 | ||
23 | obj-$(CONFIG_CPU_S3C2412) += s3c2412.o irq-s3c2412.o clock-s3c2412.o | 25 | obj-$(CONFIG_CPU_S3C2412) += s3c2412.o irq-s3c2412.o clock-s3c2412.o |
26 | obj-$(CONFIG_S3C2412_CPUFREQ) += cpufreq-s3c2412.o | ||
24 | obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o | 27 | obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o |
25 | obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o | 28 | obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o |
26 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o | 29 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o |
@@ -31,7 +34,10 @@ obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o | |||
31 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o | 34 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o |
32 | obj-$(CONFIG_CPU_S3C2442) += s3c2442.o | 35 | obj-$(CONFIG_CPU_S3C2442) += s3c2442.o |
33 | obj-$(CONFIG_CPU_S3C244X) += s3c244x.o irq-s3c244x.o clock-s3c244x.o | 36 | obj-$(CONFIG_CPU_S3C244X) += s3c244x.o irq-s3c244x.o clock-s3c244x.o |
37 | obj-$(CONFIG_S3C2440_CPUFREQ) += cpufreq-s3c2440.o | ||
34 | obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o | 38 | obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o |
39 | obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o | ||
40 | obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o | ||
35 | 41 | ||
36 | obj-$(CONFIG_CPU_S3C2443) += s3c2443.o irq-s3c2443.o clock-s3c2443.o | 42 | obj-$(CONFIG_CPU_S3C2443) += s3c2443.o irq-s3c2443.o clock-s3c2443.o |
37 | 43 | ||
diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c b/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c new file mode 100644 index 000000000000..cfa0dd8723ec --- /dev/null +++ b/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006-2008 Simtec Electronics | ||
3 | * http://armlinux.simtec.co.uk/ | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410 CPU Frequency scaling | ||
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/interrupt.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/cpufreq.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/map.h> | ||
25 | |||
26 | #include <mach/regs-clock.h> | ||
27 | |||
28 | #include <plat/cpu.h> | ||
29 | #include <plat/clock.h> | ||
30 | #include <plat/cpu-freq-core.h> | ||
31 | |||
32 | /* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */ | ||
33 | |||
34 | static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) | ||
35 | { | ||
36 | u32 clkdiv = 0; | ||
37 | |||
38 | if (cfg->divs.h_divisor == 2) | ||
39 | clkdiv |= S3C2410_CLKDIVN_HDIVN; | ||
40 | |||
41 | if (cfg->divs.p_divisor != cfg->divs.h_divisor) | ||
42 | clkdiv |= S3C2410_CLKDIVN_PDIVN; | ||
43 | |||
44 | __raw_writel(clkdiv, S3C2410_CLKDIVN); | ||
45 | } | ||
46 | |||
47 | static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) | ||
48 | { | ||
49 | unsigned long hclk, fclk, pclk; | ||
50 | unsigned int hdiv, pdiv; | ||
51 | unsigned long hclk_max; | ||
52 | |||
53 | fclk = cfg->freq.fclk; | ||
54 | hclk_max = cfg->max.hclk; | ||
55 | |||
56 | cfg->freq.armclk = fclk; | ||
57 | |||
58 | s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n", | ||
59 | __func__, fclk, hclk_max); | ||
60 | |||
61 | hdiv = (fclk > cfg->max.hclk) ? 2 : 1; | ||
62 | hclk = fclk / hdiv; | ||
63 | |||
64 | if (hclk > cfg->max.hclk) { | ||
65 | s3c_freq_dbg("%s: hclk too big\n", __func__); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | pdiv = (hclk > cfg->max.pclk) ? 2 : 1; | ||
70 | pclk = hclk / pdiv; | ||
71 | |||
72 | if (pclk > cfg->max.pclk) { | ||
73 | s3c_freq_dbg("%s: pclk too big\n", __func__); | ||
74 | return -EINVAL; | ||
75 | } | ||
76 | |||
77 | pdiv *= hdiv; | ||
78 | |||
79 | /* record the result */ | ||
80 | cfg->divs.p_divisor = pdiv; | ||
81 | cfg->divs.h_divisor = hdiv; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static struct s3c_cpufreq_info s3c2410_cpufreq_info = { | ||
87 | .max = { | ||
88 | .fclk = 200000000, | ||
89 | .hclk = 100000000, | ||
90 | .pclk = 50000000, | ||
91 | }, | ||
92 | |||
93 | /* transition latency is about 5ms worst-case, so | ||
94 | * set 10ms to be sure */ | ||
95 | .latency = 10000000, | ||
96 | |||
97 | .locktime_m = 150, | ||
98 | .locktime_u = 150, | ||
99 | .locktime_bits = 12, | ||
100 | |||
101 | .need_pll = 1, | ||
102 | |||
103 | .name = "s3c2410", | ||
104 | .calc_iotiming = s3c2410_iotiming_calc, | ||
105 | .set_iotiming = s3c2410_iotiming_set, | ||
106 | .get_iotiming = s3c2410_iotiming_get, | ||
107 | .resume_clocks = s3c2410_setup_clocks, | ||
108 | |||
109 | .set_fvco = s3c2410_set_fvco, | ||
110 | .set_refresh = s3c2410_cpufreq_setrefresh, | ||
111 | .set_divs = s3c2410_cpufreq_setdivs, | ||
112 | .calc_divs = s3c2410_cpufreq_calcdivs, | ||
113 | |||
114 | .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), | ||
115 | }; | ||
116 | |||
117 | static int s3c2410_cpufreq_add(struct device *dev, | ||
118 | struct subsys_interface *sif) | ||
119 | { | ||
120 | return s3c_cpufreq_register(&s3c2410_cpufreq_info); | ||
121 | } | ||
122 | |||
123 | static struct subsys_interface s3c2410_cpufreq_interface = { | ||
124 | .name = "s3c2410_cpufreq", | ||
125 | .subsys = &s3c2410_subsys, | ||
126 | .add_dev = s3c2410_cpufreq_add, | ||
127 | }; | ||
128 | |||
129 | static int __init s3c2410_cpufreq_init(void) | ||
130 | { | ||
131 | return subsys_interface_register(&s3c2410_cpufreq_interface); | ||
132 | } | ||
133 | arch_initcall(s3c2410_cpufreq_init); | ||
134 | |||
135 | static int s3c2410a_cpufreq_add(struct device *dev, | ||
136 | struct subsys_interface *sif) | ||
137 | { | ||
138 | /* alter the maximum freq settings for S3C2410A. If a board knows | ||
139 | * it only has a maximum of 200, then it should register its own | ||
140 | * limits. */ | ||
141 | |||
142 | s3c2410_cpufreq_info.max.fclk = 266000000; | ||
143 | s3c2410_cpufreq_info.max.hclk = 133000000; | ||
144 | s3c2410_cpufreq_info.max.pclk = 66500000; | ||
145 | s3c2410_cpufreq_info.name = "s3c2410a"; | ||
146 | |||
147 | return s3c2410_cpufreq_add(dev, sif); | ||
148 | } | ||
149 | |||
150 | static struct subsys_interface s3c2410a_cpufreq_interface = { | ||
151 | .name = "s3c2410a_cpufreq", | ||
152 | .subsys = &s3c2410a_subsys, | ||
153 | .add_dev = s3c2410a_cpufreq_add, | ||
154 | }; | ||
155 | |||
156 | static int __init s3c2410a_cpufreq_init(void) | ||
157 | { | ||
158 | return subsys_interface_register(&s3c2410a_cpufreq_interface); | ||
159 | } | ||
160 | arch_initcall(s3c2410a_cpufreq_init); | ||
diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2412.c b/arch/arm/mach-s3c24xx/cpufreq-s3c2412.c new file mode 100644 index 000000000000..c8f05f309eee --- /dev/null +++ b/arch/arm/mach-s3c24xx/cpufreq-s3c2412.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Copyright 2008 Simtec Electronics | ||
3 | * http://armlinux.simtec.co.uk/ | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2412 CPU Frequency scalling | ||
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/interrupt.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/cpufreq.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <asm/mach/arch.h> | ||
25 | #include <asm/mach/map.h> | ||
26 | |||
27 | #include <mach/regs-clock.h> | ||
28 | #include <mach/regs-s3c2412-mem.h> | ||
29 | |||
30 | #include <plat/cpu.h> | ||
31 | #include <plat/clock.h> | ||
32 | #include <plat/cpu-freq-core.h> | ||
33 | |||
34 | /* our clock resources. */ | ||
35 | static struct clk *xtal; | ||
36 | static struct clk *fclk; | ||
37 | static struct clk *hclk; | ||
38 | static struct clk *armclk; | ||
39 | |||
40 | /* HDIV: 1, 2, 3, 4, 6, 8 */ | ||
41 | |||
42 | static int s3c2412_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) | ||
43 | { | ||
44 | unsigned int hdiv, pdiv, armdiv, dvs; | ||
45 | unsigned long hclk, fclk, armclk, armdiv_clk; | ||
46 | unsigned long hclk_max; | ||
47 | |||
48 | fclk = cfg->freq.fclk; | ||
49 | armclk = cfg->freq.armclk; | ||
50 | hclk_max = cfg->max.hclk; | ||
51 | |||
52 | /* We can't run hclk above armclk as at the best we have to | ||
53 | * have armclk and hclk in dvs mode. */ | ||
54 | |||
55 | if (hclk_max > armclk) | ||
56 | hclk_max = armclk; | ||
57 | |||
58 | s3c_freq_dbg("%s: fclk=%lu, armclk=%lu, hclk_max=%lu\n", | ||
59 | __func__, fclk, armclk, hclk_max); | ||
60 | s3c_freq_dbg("%s: want f=%lu, arm=%lu, h=%lu, p=%lu\n", | ||
61 | __func__, cfg->freq.fclk, cfg->freq.armclk, | ||
62 | cfg->freq.hclk, cfg->freq.pclk); | ||
63 | |||
64 | armdiv = fclk / armclk; | ||
65 | |||
66 | if (armdiv < 1) | ||
67 | armdiv = 1; | ||
68 | if (armdiv > 2) | ||
69 | armdiv = 2; | ||
70 | |||
71 | cfg->divs.arm_divisor = armdiv; | ||
72 | armdiv_clk = fclk / armdiv; | ||
73 | |||
74 | hdiv = armdiv_clk / hclk_max; | ||
75 | if (hdiv < 1) | ||
76 | hdiv = 1; | ||
77 | |||
78 | cfg->freq.hclk = hclk = armdiv_clk / hdiv; | ||
79 | |||
80 | /* set dvs depending on whether we reached armclk or not. */ | ||
81 | cfg->divs.dvs = dvs = armclk < armdiv_clk; | ||
82 | |||
83 | /* update the actual armclk we achieved. */ | ||
84 | cfg->freq.armclk = dvs ? hclk : armdiv_clk; | ||
85 | |||
86 | s3c_freq_dbg("%s: armclk %lu, hclk %lu, armdiv %d, hdiv %d, dvs %d\n", | ||
87 | __func__, armclk, hclk, armdiv, hdiv, cfg->divs.dvs); | ||
88 | |||
89 | if (hdiv > 4) | ||
90 | goto invalid; | ||
91 | |||
92 | pdiv = (hclk > cfg->max.pclk) ? 2 : 1; | ||
93 | |||
94 | if ((hclk / pdiv) > cfg->max.pclk) | ||
95 | pdiv++; | ||
96 | |||
97 | cfg->freq.pclk = hclk / pdiv; | ||
98 | |||
99 | s3c_freq_dbg("%s: pdiv %d\n", __func__, pdiv); | ||
100 | |||
101 | if (pdiv > 2) | ||
102 | goto invalid; | ||
103 | |||
104 | pdiv *= hdiv; | ||
105 | |||
106 | /* store the result, and then return */ | ||
107 | |||
108 | cfg->divs.h_divisor = hdiv * armdiv; | ||
109 | cfg->divs.p_divisor = pdiv * armdiv; | ||
110 | |||
111 | return 0; | ||
112 | |||
113 | invalid: | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | static void s3c2412_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) | ||
118 | { | ||
119 | unsigned long clkdiv; | ||
120 | unsigned long olddiv; | ||
121 | |||
122 | olddiv = clkdiv = __raw_readl(S3C2410_CLKDIVN); | ||
123 | |||
124 | /* clear off current clock info */ | ||
125 | |||
126 | clkdiv &= ~S3C2412_CLKDIVN_ARMDIVN; | ||
127 | clkdiv &= ~S3C2412_CLKDIVN_HDIVN_MASK; | ||
128 | clkdiv &= ~S3C2412_CLKDIVN_PDIVN; | ||
129 | |||
130 | if (cfg->divs.arm_divisor == 2) | ||
131 | clkdiv |= S3C2412_CLKDIVN_ARMDIVN; | ||
132 | |||
133 | clkdiv |= ((cfg->divs.h_divisor / cfg->divs.arm_divisor) - 1); | ||
134 | |||
135 | if (cfg->divs.p_divisor != cfg->divs.h_divisor) | ||
136 | clkdiv |= S3C2412_CLKDIVN_PDIVN; | ||
137 | |||
138 | s3c_freq_dbg("%s: div %08lx => %08lx\n", __func__, olddiv, clkdiv); | ||
139 | __raw_writel(clkdiv, S3C2410_CLKDIVN); | ||
140 | |||
141 | clk_set_parent(armclk, cfg->divs.dvs ? hclk : fclk); | ||
142 | } | ||
143 | |||
144 | static void s3c2412_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) | ||
145 | { | ||
146 | struct s3c_cpufreq_board *board = cfg->board; | ||
147 | unsigned long refresh; | ||
148 | |||
149 | s3c_freq_dbg("%s: refresh %u ns, hclk %lu\n", __func__, | ||
150 | board->refresh, cfg->freq.hclk); | ||
151 | |||
152 | /* Reduce both the refresh time (in ns) and the frequency (in MHz) | ||
153 | * by 10 each to ensure that we do not overflow 32 bit numbers. This | ||
154 | * should work for HCLK up to 133MHz and refresh period up to 30usec. | ||
155 | */ | ||
156 | |||
157 | refresh = (board->refresh / 10); | ||
158 | refresh *= (cfg->freq.hclk / 100); | ||
159 | refresh /= (1 * 1000 * 1000); /* 10^6 */ | ||
160 | |||
161 | s3c_freq_dbg("%s: setting refresh 0x%08lx\n", __func__, refresh); | ||
162 | __raw_writel(refresh, S3C2412_REFRESH); | ||
163 | } | ||
164 | |||
165 | /* set the default cpu frequency information, based on an 200MHz part | ||
166 | * as we have no other way of detecting the speed rating in software. | ||
167 | */ | ||
168 | |||
169 | static struct s3c_cpufreq_info s3c2412_cpufreq_info = { | ||
170 | .max = { | ||
171 | .fclk = 200000000, | ||
172 | .hclk = 100000000, | ||
173 | .pclk = 50000000, | ||
174 | }, | ||
175 | |||
176 | .latency = 5000000, /* 5ms */ | ||
177 | |||
178 | .locktime_m = 150, | ||
179 | .locktime_u = 150, | ||
180 | .locktime_bits = 16, | ||
181 | |||
182 | .name = "s3c2412", | ||
183 | .set_refresh = s3c2412_cpufreq_setrefresh, | ||
184 | .set_divs = s3c2412_cpufreq_setdivs, | ||
185 | .calc_divs = s3c2412_cpufreq_calcdivs, | ||
186 | |||
187 | .calc_iotiming = s3c2412_iotiming_calc, | ||
188 | .set_iotiming = s3c2412_iotiming_set, | ||
189 | .get_iotiming = s3c2412_iotiming_get, | ||
190 | |||
191 | .resume_clocks = s3c2412_setup_clocks, | ||
192 | |||
193 | .debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs), | ||
194 | }; | ||
195 | |||
196 | static int s3c2412_cpufreq_add(struct device *dev, | ||
197 | struct subsys_interface *sif) | ||
198 | { | ||
199 | unsigned long fclk_rate; | ||
200 | |||
201 | hclk = clk_get(NULL, "hclk"); | ||
202 | if (IS_ERR(hclk)) { | ||
203 | printk(KERN_ERR "%s: cannot find hclk clock\n", __func__); | ||
204 | return -ENOENT; | ||
205 | } | ||
206 | |||
207 | fclk = clk_get(NULL, "fclk"); | ||
208 | if (IS_ERR(fclk)) { | ||
209 | printk(KERN_ERR "%s: cannot find fclk clock\n", __func__); | ||
210 | goto err_fclk; | ||
211 | } | ||
212 | |||
213 | fclk_rate = clk_get_rate(fclk); | ||
214 | if (fclk_rate > 200000000) { | ||
215 | printk(KERN_INFO | ||
216 | "%s: fclk %ld MHz, assuming 266MHz capable part\n", | ||
217 | __func__, fclk_rate / 1000000); | ||
218 | s3c2412_cpufreq_info.max.fclk = 266000000; | ||
219 | s3c2412_cpufreq_info.max.hclk = 133000000; | ||
220 | s3c2412_cpufreq_info.max.pclk = 66000000; | ||
221 | } | ||
222 | |||
223 | armclk = clk_get(NULL, "armclk"); | ||
224 | if (IS_ERR(armclk)) { | ||
225 | printk(KERN_ERR "%s: cannot find arm clock\n", __func__); | ||
226 | goto err_armclk; | ||
227 | } | ||
228 | |||
229 | xtal = clk_get(NULL, "xtal"); | ||
230 | if (IS_ERR(xtal)) { | ||
231 | printk(KERN_ERR "%s: cannot find xtal clock\n", __func__); | ||
232 | goto err_xtal; | ||
233 | } | ||
234 | |||
235 | return s3c_cpufreq_register(&s3c2412_cpufreq_info); | ||
236 | |||
237 | err_xtal: | ||
238 | clk_put(armclk); | ||
239 | err_armclk: | ||
240 | clk_put(fclk); | ||
241 | err_fclk: | ||
242 | clk_put(hclk); | ||
243 | |||
244 | return -ENOENT; | ||
245 | } | ||
246 | |||
247 | static struct subsys_interface s3c2412_cpufreq_interface = { | ||
248 | .name = "s3c2412_cpufreq", | ||
249 | .subsys = &s3c2412_subsys, | ||
250 | .add_dev = s3c2412_cpufreq_add, | ||
251 | }; | ||
252 | |||
253 | static int s3c2412_cpufreq_init(void) | ||
254 | { | ||
255 | return subsys_interface_register(&s3c2412_cpufreq_interface); | ||
256 | } | ||
257 | arch_initcall(s3c2412_cpufreq_init); | ||
diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2440.c b/arch/arm/mach-s3c24xx/cpufreq-s3c2440.c new file mode 100644 index 000000000000..72b2cc8a5a85 --- /dev/null +++ b/arch/arm/mach-s3c24xx/cpufreq-s3c2440.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006-2009 Simtec Electronics | ||
3 | * http://armlinux.simtec.co.uk/ | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * Vincent Sanders <vince@simtec.co.uk> | ||
6 | * | ||
7 | * S3C2440/S3C2442 CPU Frequency scaling | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/ioport.h> | ||
18 | #include <linux/cpufreq.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #include <mach/hardware.h> | ||
26 | |||
27 | #include <asm/mach/arch.h> | ||
28 | #include <asm/mach/map.h> | ||
29 | |||
30 | #include <mach/regs-clock.h> | ||
31 | |||
32 | #include <plat/cpu.h> | ||
33 | #include <plat/cpu-freq-core.h> | ||
34 | #include <plat/clock.h> | ||
35 | |||
36 | static struct clk *xtal; | ||
37 | static struct clk *fclk; | ||
38 | static struct clk *hclk; | ||
39 | static struct clk *armclk; | ||
40 | |||
41 | /* HDIV: 1, 2, 3, 4, 6, 8 */ | ||
42 | |||
43 | static inline int within_khz(unsigned long a, unsigned long b) | ||
44 | { | ||
45 | long diff = a - b; | ||
46 | |||
47 | return (diff >= -1000 && diff <= 1000); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * s3c2440_cpufreq_calcdivs - calculate divider settings | ||
52 | * @cfg: The cpu frequency settings. | ||
53 | * | ||
54 | * Calcualte the divider values for the given frequency settings | ||
55 | * specified in @cfg. The values are stored in @cfg for later use | ||
56 | * by the relevant set routine if the request settings can be reached. | ||
57 | */ | ||
58 | int s3c2440_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) | ||
59 | { | ||
60 | unsigned int hdiv, pdiv; | ||
61 | unsigned long hclk, fclk, armclk; | ||
62 | unsigned long hclk_max; | ||
63 | |||
64 | fclk = cfg->freq.fclk; | ||
65 | armclk = cfg->freq.armclk; | ||
66 | hclk_max = cfg->max.hclk; | ||
67 | |||
68 | s3c_freq_dbg("%s: fclk is %lu, armclk %lu, max hclk %lu\n", | ||
69 | __func__, fclk, armclk, hclk_max); | ||
70 | |||
71 | if (armclk > fclk) { | ||
72 | printk(KERN_WARNING "%s: armclk > fclk\n", __func__); | ||
73 | armclk = fclk; | ||
74 | } | ||
75 | |||
76 | /* if we are in DVS, we need HCLK to be <= ARMCLK */ | ||
77 | if (armclk < fclk && armclk < hclk_max) | ||
78 | hclk_max = armclk; | ||
79 | |||
80 | for (hdiv = 1; hdiv < 9; hdiv++) { | ||
81 | if (hdiv == 5 || hdiv == 7) | ||
82 | hdiv++; | ||
83 | |||
84 | hclk = (fclk / hdiv); | ||
85 | if (hclk <= hclk_max || within_khz(hclk, hclk_max)) | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | s3c_freq_dbg("%s: hclk %lu, div %d\n", __func__, hclk, hdiv); | ||
90 | |||
91 | if (hdiv > 8) | ||
92 | goto invalid; | ||
93 | |||
94 | pdiv = (hclk > cfg->max.pclk) ? 2 : 1; | ||
95 | |||
96 | if ((hclk / pdiv) > cfg->max.pclk) | ||
97 | pdiv++; | ||
98 | |||
99 | s3c_freq_dbg("%s: pdiv %d\n", __func__, pdiv); | ||
100 | |||
101 | if (pdiv > 2) | ||
102 | goto invalid; | ||
103 | |||
104 | pdiv *= hdiv; | ||
105 | |||
106 | /* calculate a valid armclk */ | ||
107 | |||
108 | if (armclk < hclk) | ||
109 | armclk = hclk; | ||
110 | |||
111 | /* if we're running armclk lower than fclk, this really means | ||
112 | * that the system should go into dvs mode, which means that | ||
113 | * armclk is connected to hclk. */ | ||
114 | if (armclk < fclk) { | ||
115 | cfg->divs.dvs = 1; | ||
116 | armclk = hclk; | ||
117 | } else | ||
118 | cfg->divs.dvs = 0; | ||
119 | |||
120 | cfg->freq.armclk = armclk; | ||
121 | |||
122 | /* store the result, and then return */ | ||
123 | |||
124 | cfg->divs.h_divisor = hdiv; | ||
125 | cfg->divs.p_divisor = pdiv; | ||
126 | |||
127 | return 0; | ||
128 | |||
129 | invalid: | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | |||
133 | #define CAMDIVN_HCLK_HALF (S3C2440_CAMDIVN_HCLK3_HALF | \ | ||
134 | S3C2440_CAMDIVN_HCLK4_HALF) | ||
135 | |||
136 | /** | ||
137 | * s3c2440_cpufreq_setdivs - set the cpu frequency divider settings | ||
138 | * @cfg: The cpu frequency settings. | ||
139 | * | ||
140 | * Set the divisors from the settings in @cfg, which where generated | ||
141 | * during the calculation phase by s3c2440_cpufreq_calcdivs(). | ||
142 | */ | ||
143 | static void s3c2440_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) | ||
144 | { | ||
145 | unsigned long clkdiv, camdiv; | ||
146 | |||
147 | s3c_freq_dbg("%s: divsiors: h=%d, p=%d\n", __func__, | ||
148 | cfg->divs.h_divisor, cfg->divs.p_divisor); | ||
149 | |||
150 | clkdiv = __raw_readl(S3C2410_CLKDIVN); | ||
151 | camdiv = __raw_readl(S3C2440_CAMDIVN); | ||
152 | |||
153 | clkdiv &= ~(S3C2440_CLKDIVN_HDIVN_MASK | S3C2440_CLKDIVN_PDIVN); | ||
154 | camdiv &= ~CAMDIVN_HCLK_HALF; | ||
155 | |||
156 | switch (cfg->divs.h_divisor) { | ||
157 | case 1: | ||
158 | clkdiv |= S3C2440_CLKDIVN_HDIVN_1; | ||
159 | break; | ||
160 | |||
161 | case 2: | ||
162 | clkdiv |= S3C2440_CLKDIVN_HDIVN_2; | ||
163 | break; | ||
164 | |||
165 | case 6: | ||
166 | camdiv |= S3C2440_CAMDIVN_HCLK3_HALF; | ||
167 | case 3: | ||
168 | clkdiv |= S3C2440_CLKDIVN_HDIVN_3_6; | ||
169 | break; | ||
170 | |||
171 | case 8: | ||
172 | camdiv |= S3C2440_CAMDIVN_HCLK4_HALF; | ||
173 | case 4: | ||
174 | clkdiv |= S3C2440_CLKDIVN_HDIVN_4_8; | ||
175 | break; | ||
176 | |||
177 | default: | ||
178 | BUG(); /* we don't expect to get here. */ | ||
179 | } | ||
180 | |||
181 | if (cfg->divs.p_divisor != cfg->divs.h_divisor) | ||
182 | clkdiv |= S3C2440_CLKDIVN_PDIVN; | ||
183 | |||
184 | /* todo - set pclk. */ | ||
185 | |||
186 | /* Write the divisors first with hclk intentionally halved so that | ||
187 | * when we write clkdiv we will under-frequency instead of over. We | ||
188 | * then make a short delay and remove the hclk halving if necessary. | ||
189 | */ | ||
190 | |||
191 | __raw_writel(camdiv | CAMDIVN_HCLK_HALF, S3C2440_CAMDIVN); | ||
192 | __raw_writel(clkdiv, S3C2410_CLKDIVN); | ||
193 | |||
194 | ndelay(20); | ||
195 | __raw_writel(camdiv, S3C2440_CAMDIVN); | ||
196 | |||
197 | clk_set_parent(armclk, cfg->divs.dvs ? hclk : fclk); | ||
198 | } | ||
199 | |||
200 | static int run_freq_for(unsigned long max_hclk, unsigned long fclk, | ||
201 | int *divs, | ||
202 | struct cpufreq_frequency_table *table, | ||
203 | size_t table_size) | ||
204 | { | ||
205 | unsigned long freq; | ||
206 | int index = 0; | ||
207 | int div; | ||
208 | |||
209 | for (div = *divs; div > 0; div = *divs++) { | ||
210 | freq = fclk / div; | ||
211 | |||
212 | if (freq > max_hclk && div != 1) | ||
213 | continue; | ||
214 | |||
215 | freq /= 1000; /* table is in kHz */ | ||
216 | index = s3c_cpufreq_addfreq(table, index, table_size, freq); | ||
217 | if (index < 0) | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | return index; | ||
222 | } | ||
223 | |||
224 | static int hclk_divs[] = { 1, 2, 3, 4, 6, 8, -1 }; | ||
225 | |||
226 | static int s3c2440_cpufreq_calctable(struct s3c_cpufreq_config *cfg, | ||
227 | struct cpufreq_frequency_table *table, | ||
228 | size_t table_size) | ||
229 | { | ||
230 | int ret; | ||
231 | |||
232 | WARN_ON(cfg->info == NULL); | ||
233 | WARN_ON(cfg->board == NULL); | ||
234 | |||
235 | ret = run_freq_for(cfg->info->max.hclk, | ||
236 | cfg->info->max.fclk, | ||
237 | hclk_divs, | ||
238 | table, table_size); | ||
239 | |||
240 | s3c_freq_dbg("%s: returning %d\n", __func__, ret); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | struct s3c_cpufreq_info s3c2440_cpufreq_info = { | ||
246 | .max = { | ||
247 | .fclk = 400000000, | ||
248 | .hclk = 133333333, | ||
249 | .pclk = 66666666, | ||
250 | }, | ||
251 | |||
252 | .locktime_m = 300, | ||
253 | .locktime_u = 300, | ||
254 | .locktime_bits = 16, | ||
255 | |||
256 | .name = "s3c244x", | ||
257 | .calc_iotiming = s3c2410_iotiming_calc, | ||
258 | .set_iotiming = s3c2410_iotiming_set, | ||
259 | .get_iotiming = s3c2410_iotiming_get, | ||
260 | .set_fvco = s3c2410_set_fvco, | ||
261 | |||
262 | .set_refresh = s3c2410_cpufreq_setrefresh, | ||
263 | .set_divs = s3c2440_cpufreq_setdivs, | ||
264 | .calc_divs = s3c2440_cpufreq_calcdivs, | ||
265 | .calc_freqtable = s3c2440_cpufreq_calctable, | ||
266 | |||
267 | .resume_clocks = s3c244x_setup_clocks, | ||
268 | |||
269 | .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), | ||
270 | }; | ||
271 | |||
272 | static int s3c2440_cpufreq_add(struct device *dev, | ||
273 | struct subsys_interface *sif) | ||
274 | { | ||
275 | xtal = s3c_cpufreq_clk_get(NULL, "xtal"); | ||
276 | hclk = s3c_cpufreq_clk_get(NULL, "hclk"); | ||
277 | fclk = s3c_cpufreq_clk_get(NULL, "fclk"); | ||
278 | armclk = s3c_cpufreq_clk_get(NULL, "armclk"); | ||
279 | |||
280 | if (IS_ERR(xtal) || IS_ERR(hclk) || IS_ERR(fclk) || IS_ERR(armclk)) { | ||
281 | printk(KERN_ERR "%s: failed to get clocks\n", __func__); | ||
282 | return -ENOENT; | ||
283 | } | ||
284 | |||
285 | return s3c_cpufreq_register(&s3c2440_cpufreq_info); | ||
286 | } | ||
287 | |||
288 | static struct subsys_interface s3c2440_cpufreq_interface = { | ||
289 | .name = "s3c2440_cpufreq", | ||
290 | .subsys = &s3c2440_subsys, | ||
291 | .add_dev = s3c2440_cpufreq_add, | ||
292 | }; | ||
293 | |||
294 | static int s3c2440_cpufreq_init(void) | ||
295 | { | ||
296 | return subsys_interface_register(&s3c2440_cpufreq_interface); | ||
297 | } | ||
298 | |||
299 | /* arch_initcall adds the clocks we need, so use subsys_initcall. */ | ||
300 | subsys_initcall(s3c2440_cpufreq_init); | ||
301 | |||
302 | static struct subsys_interface s3c2442_cpufreq_interface = { | ||
303 | .name = "s3c2442_cpufreq", | ||
304 | .subsys = &s3c2442_subsys, | ||
305 | .add_dev = s3c2440_cpufreq_add, | ||
306 | }; | ||
307 | |||
308 | static int s3c2442_cpufreq_init(void) | ||
309 | { | ||
310 | return subsys_interface_register(&s3c2442_cpufreq_interface); | ||
311 | } | ||
312 | subsys_initcall(s3c2442_cpufreq_init); | ||
diff --git a/arch/arm/mach-s3c24xx/include/mach/hardware.h b/arch/arm/mach-s3c24xx/include/mach/hardware.h index aef5631eac58..a6cc14a092fc 100644 --- a/arch/arm/mach-s3c24xx/include/mach/hardware.h +++ b/arch/arm/mach-s3c24xx/include/mach/hardware.h | |||
@@ -23,12 +23,6 @@ extern int s3c2440_set_dsc(unsigned int pin, unsigned int value); | |||
23 | 23 | ||
24 | #endif /* CONFIG_CPU_S3C2440 */ | 24 | #endif /* CONFIG_CPU_S3C2440 */ |
25 | 25 | ||
26 | #ifdef CONFIG_CPU_S3C2412 | ||
27 | |||
28 | extern int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state); | ||
29 | |||
30 | #endif /* CONFIG_CPU_S3C2412 */ | ||
31 | |||
32 | #endif /* __ASSEMBLY__ */ | 26 | #endif /* __ASSEMBLY__ */ |
33 | 27 | ||
34 | #include <asm/sizes.h> | 28 | #include <asm/sizes.h> |
diff --git a/arch/arm/mach-s3c24xx/pll-s3c2410.c b/arch/arm/mach-s3c24xx/pll-s3c2410.c new file mode 100644 index 000000000000..dcf3420a3271 --- /dev/null +++ b/arch/arm/mach-s3c24xx/pll-s3c2410.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006-2007 Simtec Electronics | ||
3 | * http://armlinux.simtec.co.uk/ | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * Vincent Sanders <vince@arm.linux.org.uk> | ||
6 | * | ||
7 | * S3C2410 CPU PLL tables | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/err.h> | ||
31 | |||
32 | #include <plat/cpu.h> | ||
33 | #include <plat/cpu-freq-core.h> | ||
34 | |||
35 | static struct cpufreq_frequency_table pll_vals_12MHz[] = { | ||
36 | { .frequency = 34000000, .index = PLLVAL(82, 2, 3), }, | ||
37 | { .frequency = 45000000, .index = PLLVAL(82, 1, 3), }, | ||
38 | { .frequency = 51000000, .index = PLLVAL(161, 3, 3), }, | ||
39 | { .frequency = 48000000, .index = PLLVAL(120, 2, 3), }, | ||
40 | { .frequency = 56000000, .index = PLLVAL(142, 2, 3), }, | ||
41 | { .frequency = 68000000, .index = PLLVAL(82, 2, 2), }, | ||
42 | { .frequency = 79000000, .index = PLLVAL(71, 1, 2), }, | ||
43 | { .frequency = 85000000, .index = PLLVAL(105, 2, 2), }, | ||
44 | { .frequency = 90000000, .index = PLLVAL(112, 2, 2), }, | ||
45 | { .frequency = 101000000, .index = PLLVAL(127, 2, 2), }, | ||
46 | { .frequency = 113000000, .index = PLLVAL(105, 1, 2), }, | ||
47 | { .frequency = 118000000, .index = PLLVAL(150, 2, 2), }, | ||
48 | { .frequency = 124000000, .index = PLLVAL(116, 1, 2), }, | ||
49 | { .frequency = 135000000, .index = PLLVAL(82, 2, 1), }, | ||
50 | { .frequency = 147000000, .index = PLLVAL(90, 2, 1), }, | ||
51 | { .frequency = 152000000, .index = PLLVAL(68, 1, 1), }, | ||
52 | { .frequency = 158000000, .index = PLLVAL(71, 1, 1), }, | ||
53 | { .frequency = 170000000, .index = PLLVAL(77, 1, 1), }, | ||
54 | { .frequency = 180000000, .index = PLLVAL(82, 1, 1), }, | ||
55 | { .frequency = 186000000, .index = PLLVAL(85, 1, 1), }, | ||
56 | { .frequency = 192000000, .index = PLLVAL(88, 1, 1), }, | ||
57 | { .frequency = 203000000, .index = PLLVAL(161, 3, 1), }, | ||
58 | |||
59 | /* 2410A extras */ | ||
60 | |||
61 | { .frequency = 210000000, .index = PLLVAL(132, 2, 1), }, | ||
62 | { .frequency = 226000000, .index = PLLVAL(105, 1, 1), }, | ||
63 | { .frequency = 266000000, .index = PLLVAL(125, 1, 1), }, | ||
64 | { .frequency = 268000000, .index = PLLVAL(126, 1, 1), }, | ||
65 | { .frequency = 270000000, .index = PLLVAL(127, 1, 1), }, | ||
66 | }; | ||
67 | |||
68 | static int s3c2410_plls_add(struct device *dev, struct subsys_interface *sif) | ||
69 | { | ||
70 | return s3c_plltab_register(pll_vals_12MHz, ARRAY_SIZE(pll_vals_12MHz)); | ||
71 | } | ||
72 | |||
73 | static struct subsys_interface s3c2410_plls_interface = { | ||
74 | .name = "s3c2410_plls", | ||
75 | .subsys = &s3c2410_subsys, | ||
76 | .add_dev = s3c2410_plls_add, | ||
77 | }; | ||
78 | |||
79 | static int __init s3c2410_pll_init(void) | ||
80 | { | ||
81 | return subsys_interface_register(&s3c2410_plls_interface); | ||
82 | |||
83 | } | ||
84 | arch_initcall(s3c2410_pll_init); | ||
85 | |||
86 | static struct subsys_interface s3c2410a_plls_interface = { | ||
87 | .name = "s3c2410a_plls", | ||
88 | .subsys = &s3c2410a_subsys, | ||
89 | .add_dev = s3c2410_plls_add, | ||
90 | }; | ||
91 | |||
92 | static int __init s3c2410a_pll_init(void) | ||
93 | { | ||
94 | return subsys_interface_register(&s3c2410a_plls_interface); | ||
95 | } | ||
96 | arch_initcall(s3c2410a_pll_init); | ||
diff --git a/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c b/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c new file mode 100644 index 000000000000..673781758319 --- /dev/null +++ b/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006-2007 Simtec Electronics | ||
3 | * http://armlinux.simtec.co.uk/ | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * Vincent Sanders <vince@arm.linux.org.uk> | ||
6 | * | ||
7 | * S3C2440/S3C2442 CPU PLL tables (12MHz Crystal) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/err.h> | ||
19 | |||
20 | #include <plat/cpu.h> | ||
21 | #include <plat/cpu-freq-core.h> | ||
22 | |||
23 | static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = { | ||
24 | { .frequency = 75000000, .index = PLLVAL(0x75, 3, 3), }, /* FVco 600.000000 */ | ||
25 | { .frequency = 80000000, .index = PLLVAL(0x98, 4, 3), }, /* FVco 640.000000 */ | ||
26 | { .frequency = 90000000, .index = PLLVAL(0x70, 2, 3), }, /* FVco 720.000000 */ | ||
27 | { .frequency = 100000000, .index = PLLVAL(0x5c, 1, 3), }, /* FVco 800.000000 */ | ||
28 | { .frequency = 110000000, .index = PLLVAL(0x66, 1, 3), }, /* FVco 880.000000 */ | ||
29 | { .frequency = 120000000, .index = PLLVAL(0x70, 1, 3), }, /* FVco 960.000000 */ | ||
30 | { .frequency = 150000000, .index = PLLVAL(0x75, 3, 2), }, /* FVco 600.000000 */ | ||
31 | { .frequency = 160000000, .index = PLLVAL(0x98, 4, 2), }, /* FVco 640.000000 */ | ||
32 | { .frequency = 170000000, .index = PLLVAL(0x4d, 1, 2), }, /* FVco 680.000000 */ | ||
33 | { .frequency = 180000000, .index = PLLVAL(0x70, 2, 2), }, /* FVco 720.000000 */ | ||
34 | { .frequency = 190000000, .index = PLLVAL(0x57, 1, 2), }, /* FVco 760.000000 */ | ||
35 | { .frequency = 200000000, .index = PLLVAL(0x5c, 1, 2), }, /* FVco 800.000000 */ | ||
36 | { .frequency = 210000000, .index = PLLVAL(0x84, 2, 2), }, /* FVco 840.000000 */ | ||
37 | { .frequency = 220000000, .index = PLLVAL(0x66, 1, 2), }, /* FVco 880.000000 */ | ||
38 | { .frequency = 230000000, .index = PLLVAL(0x6b, 1, 2), }, /* FVco 920.000000 */ | ||
39 | { .frequency = 240000000, .index = PLLVAL(0x70, 1, 2), }, /* FVco 960.000000 */ | ||
40 | { .frequency = 300000000, .index = PLLVAL(0x75, 3, 1), }, /* FVco 600.000000 */ | ||
41 | { .frequency = 310000000, .index = PLLVAL(0x93, 4, 1), }, /* FVco 620.000000 */ | ||
42 | { .frequency = 320000000, .index = PLLVAL(0x98, 4, 1), }, /* FVco 640.000000 */ | ||
43 | { .frequency = 330000000, .index = PLLVAL(0x66, 2, 1), }, /* FVco 660.000000 */ | ||
44 | { .frequency = 340000000, .index = PLLVAL(0x4d, 1, 1), }, /* FVco 680.000000 */ | ||
45 | { .frequency = 350000000, .index = PLLVAL(0xa7, 4, 1), }, /* FVco 700.000000 */ | ||
46 | { .frequency = 360000000, .index = PLLVAL(0x70, 2, 1), }, /* FVco 720.000000 */ | ||
47 | { .frequency = 370000000, .index = PLLVAL(0xb1, 4, 1), }, /* FVco 740.000000 */ | ||
48 | { .frequency = 380000000, .index = PLLVAL(0x57, 1, 1), }, /* FVco 760.000000 */ | ||
49 | { .frequency = 390000000, .index = PLLVAL(0x7a, 2, 1), }, /* FVco 780.000000 */ | ||
50 | { .frequency = 400000000, .index = PLLVAL(0x5c, 1, 1), }, /* FVco 800.000000 */ | ||
51 | }; | ||
52 | |||
53 | static int s3c2440_plls12_add(struct device *dev, struct subsys_interface *sif) | ||
54 | { | ||
55 | struct clk *xtal_clk; | ||
56 | unsigned long xtal; | ||
57 | |||
58 | xtal_clk = clk_get(NULL, "xtal"); | ||
59 | if (IS_ERR(xtal_clk)) | ||
60 | return PTR_ERR(xtal_clk); | ||
61 | |||
62 | xtal = clk_get_rate(xtal_clk); | ||
63 | clk_put(xtal_clk); | ||
64 | |||
65 | if (xtal == 12000000) { | ||
66 | printk(KERN_INFO "Using PLL table for 12MHz crystal\n"); | ||
67 | return s3c_plltab_register(s3c2440_plls_12, | ||
68 | ARRAY_SIZE(s3c2440_plls_12)); | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct subsys_interface s3c2440_plls12_interface = { | ||
75 | .name = "s3c2440_plls12", | ||
76 | .subsys = &s3c2440_subsys, | ||
77 | .add_dev = s3c2440_plls12_add, | ||
78 | }; | ||
79 | |||
80 | static int __init s3c2440_pll_12mhz(void) | ||
81 | { | ||
82 | return subsys_interface_register(&s3c2440_plls12_interface); | ||
83 | |||
84 | } | ||
85 | arch_initcall(s3c2440_pll_12mhz); | ||
86 | |||
87 | static struct subsys_interface s3c2442_plls12_interface = { | ||
88 | .name = "s3c2442_plls12", | ||
89 | .subsys = &s3c2442_subsys, | ||
90 | .add_dev = s3c2440_plls12_add, | ||
91 | }; | ||
92 | |||
93 | static int __init s3c2442_pll_12mhz(void) | ||
94 | { | ||
95 | return subsys_interface_register(&s3c2442_plls12_interface); | ||
96 | |||
97 | } | ||
98 | arch_initcall(s3c2442_pll_12mhz); | ||
diff --git a/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c b/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c new file mode 100644 index 000000000000..debfa106289b --- /dev/null +++ b/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006-2008 Simtec Electronics | ||
3 | * http://armlinux.simtec.co.uk/ | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * Vincent Sanders <vince@arm.linux.org.uk> | ||
6 | * | ||
7 | * S3C2440/S3C2442 CPU PLL tables (16.93444MHz Crystal) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/err.h> | ||
19 | |||
20 | #include <plat/cpu.h> | ||
21 | #include <plat/cpu-freq-core.h> | ||
22 | |||
23 | static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = { | ||
24 | { .frequency = 78019200, .index = PLLVAL(121, 5, 3), }, /* FVco 624.153600 */ | ||
25 | { .frequency = 84067200, .index = PLLVAL(131, 5, 3), }, /* FVco 672.537600 */ | ||
26 | { .frequency = 90115200, .index = PLLVAL(141, 5, 3), }, /* FVco 720.921600 */ | ||
27 | { .frequency = 96163200, .index = PLLVAL(151, 5, 3), }, /* FVco 769.305600 */ | ||
28 | { .frequency = 102135600, .index = PLLVAL(185, 6, 3), }, /* FVco 817.084800 */ | ||
29 | { .frequency = 108259200, .index = PLLVAL(171, 5, 3), }, /* FVco 866.073600 */ | ||
30 | { .frequency = 114307200, .index = PLLVAL(127, 3, 3), }, /* FVco 914.457600 */ | ||
31 | { .frequency = 120234240, .index = PLLVAL(134, 3, 3), }, /* FVco 961.873920 */ | ||
32 | { .frequency = 126161280, .index = PLLVAL(141, 3, 3), }, /* FVco 1009.290240 */ | ||
33 | { .frequency = 132088320, .index = PLLVAL(148, 3, 3), }, /* FVco 1056.706560 */ | ||
34 | { .frequency = 138015360, .index = PLLVAL(155, 3, 3), }, /* FVco 1104.122880 */ | ||
35 | { .frequency = 144789120, .index = PLLVAL(163, 3, 3), }, /* FVco 1158.312960 */ | ||
36 | { .frequency = 150100363, .index = PLLVAL(187, 9, 2), }, /* FVco 600.401454 */ | ||
37 | { .frequency = 156038400, .index = PLLVAL(121, 5, 2), }, /* FVco 624.153600 */ | ||
38 | { .frequency = 162086400, .index = PLLVAL(126, 5, 2), }, /* FVco 648.345600 */ | ||
39 | { .frequency = 168134400, .index = PLLVAL(131, 5, 2), }, /* FVco 672.537600 */ | ||
40 | { .frequency = 174048000, .index = PLLVAL(177, 7, 2), }, /* FVco 696.192000 */ | ||
41 | { .frequency = 180230400, .index = PLLVAL(141, 5, 2), }, /* FVco 720.921600 */ | ||
42 | { .frequency = 186278400, .index = PLLVAL(124, 4, 2), }, /* FVco 745.113600 */ | ||
43 | { .frequency = 192326400, .index = PLLVAL(151, 5, 2), }, /* FVco 769.305600 */ | ||
44 | { .frequency = 198132480, .index = PLLVAL(109, 3, 2), }, /* FVco 792.529920 */ | ||
45 | { .frequency = 204271200, .index = PLLVAL(185, 6, 2), }, /* FVco 817.084800 */ | ||
46 | { .frequency = 210268800, .index = PLLVAL(141, 4, 2), }, /* FVco 841.075200 */ | ||
47 | { .frequency = 216518400, .index = PLLVAL(171, 5, 2), }, /* FVco 866.073600 */ | ||
48 | { .frequency = 222264000, .index = PLLVAL(97, 2, 2), }, /* FVco 889.056000 */ | ||
49 | { .frequency = 228614400, .index = PLLVAL(127, 3, 2), }, /* FVco 914.457600 */ | ||
50 | { .frequency = 234259200, .index = PLLVAL(158, 4, 2), }, /* FVco 937.036800 */ | ||
51 | { .frequency = 240468480, .index = PLLVAL(134, 3, 2), }, /* FVco 961.873920 */ | ||
52 | { .frequency = 246960000, .index = PLLVAL(167, 4, 2), }, /* FVco 987.840000 */ | ||
53 | { .frequency = 252322560, .index = PLLVAL(141, 3, 2), }, /* FVco 1009.290240 */ | ||
54 | { .frequency = 258249600, .index = PLLVAL(114, 2, 2), }, /* FVco 1032.998400 */ | ||
55 | { .frequency = 264176640, .index = PLLVAL(148, 3, 2), }, /* FVco 1056.706560 */ | ||
56 | { .frequency = 270950400, .index = PLLVAL(120, 2, 2), }, /* FVco 1083.801600 */ | ||
57 | { .frequency = 276030720, .index = PLLVAL(155, 3, 2), }, /* FVco 1104.122880 */ | ||
58 | { .frequency = 282240000, .index = PLLVAL(92, 1, 2), }, /* FVco 1128.960000 */ | ||
59 | { .frequency = 289578240, .index = PLLVAL(163, 3, 2), }, /* FVco 1158.312960 */ | ||
60 | { .frequency = 294235200, .index = PLLVAL(131, 2, 2), }, /* FVco 1176.940800 */ | ||
61 | { .frequency = 300200727, .index = PLLVAL(187, 9, 1), }, /* FVco 600.401454 */ | ||
62 | { .frequency = 306358690, .index = PLLVAL(191, 9, 1), }, /* FVco 612.717380 */ | ||
63 | { .frequency = 312076800, .index = PLLVAL(121, 5, 1), }, /* FVco 624.153600 */ | ||
64 | { .frequency = 318366720, .index = PLLVAL(86, 3, 1), }, /* FVco 636.733440 */ | ||
65 | { .frequency = 324172800, .index = PLLVAL(126, 5, 1), }, /* FVco 648.345600 */ | ||
66 | { .frequency = 330220800, .index = PLLVAL(109, 4, 1), }, /* FVco 660.441600 */ | ||
67 | { .frequency = 336268800, .index = PLLVAL(131, 5, 1), }, /* FVco 672.537600 */ | ||
68 | { .frequency = 342074880, .index = PLLVAL(93, 3, 1), }, /* FVco 684.149760 */ | ||
69 | { .frequency = 348096000, .index = PLLVAL(177, 7, 1), }, /* FVco 696.192000 */ | ||
70 | { .frequency = 355622400, .index = PLLVAL(118, 4, 1), }, /* FVco 711.244800 */ | ||
71 | { .frequency = 360460800, .index = PLLVAL(141, 5, 1), }, /* FVco 720.921600 */ | ||
72 | { .frequency = 366206400, .index = PLLVAL(165, 6, 1), }, /* FVco 732.412800 */ | ||
73 | { .frequency = 372556800, .index = PLLVAL(124, 4, 1), }, /* FVco 745.113600 */ | ||
74 | { .frequency = 378201600, .index = PLLVAL(126, 4, 1), }, /* FVco 756.403200 */ | ||
75 | { .frequency = 384652800, .index = PLLVAL(151, 5, 1), }, /* FVco 769.305600 */ | ||
76 | { .frequency = 391608000, .index = PLLVAL(177, 6, 1), }, /* FVco 783.216000 */ | ||
77 | { .frequency = 396264960, .index = PLLVAL(109, 3, 1), }, /* FVco 792.529920 */ | ||
78 | { .frequency = 402192000, .index = PLLVAL(87, 2, 1), }, /* FVco 804.384000 */ | ||
79 | }; | ||
80 | |||
81 | static int s3c2440_plls169344_add(struct device *dev, | ||
82 | struct subsys_interface *sif) | ||
83 | { | ||
84 | struct clk *xtal_clk; | ||
85 | unsigned long xtal; | ||
86 | |||
87 | xtal_clk = clk_get(NULL, "xtal"); | ||
88 | if (IS_ERR(xtal_clk)) | ||
89 | return PTR_ERR(xtal_clk); | ||
90 | |||
91 | xtal = clk_get_rate(xtal_clk); | ||
92 | clk_put(xtal_clk); | ||
93 | |||
94 | if (xtal == 169344000) { | ||
95 | printk(KERN_INFO "Using PLL table for 16.9344MHz crystal\n"); | ||
96 | return s3c_plltab_register(s3c2440_plls_169344, | ||
97 | ARRAY_SIZE(s3c2440_plls_169344)); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static struct subsys_interface s3c2440_plls169344_interface = { | ||
104 | .name = "s3c2440_plls169344", | ||
105 | .subsys = &s3c2440_subsys, | ||
106 | .add_dev = s3c2440_plls169344_add, | ||
107 | }; | ||
108 | |||
109 | static int __init s3c2440_pll_16934400(void) | ||
110 | { | ||
111 | return subsys_interface_register(&s3c2440_plls169344_interface); | ||
112 | } | ||
113 | arch_initcall(s3c2440_pll_16934400); | ||
114 | |||
115 | static struct subsys_interface s3c2442_plls169344_interface = { | ||
116 | .name = "s3c2442_plls169344", | ||
117 | .subsys = &s3c2442_subsys, | ||
118 | .add_dev = s3c2440_plls169344_add, | ||
119 | }; | ||
120 | |||
121 | static int __init s3c2442_pll_16934400(void) | ||
122 | { | ||
123 | return subsys_interface_register(&s3c2442_plls169344_interface); | ||
124 | } | ||
125 | arch_initcall(s3c2442_pll_16934400); | ||