aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2410
diff options
context:
space:
mode:
authorBen Dooks <ben@simtec.co.uk>2009-07-30 18:23:27 -0400
committerBen Dooks <ben-linux@fluff.org>2009-07-30 18:22:52 -0400
commita24c091db988551e2c350cfde9eb80ab6e791ffb (patch)
tree487a86d71ed0a97c27c25de9e618e7db25066c8e /arch/arm/mach-s3c2410
parent831a6fcb9393960b35173fa2e0f835b710152fff (diff)
ARM: S3C2410: CPUFREQ: Add core support.
Add core support for frequency scaling on the S3C2410 SoC. Signed-off-by: Ben Dooks <ben@simtec.co.uk> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm/mach-s3c2410')
-rw-r--r--arch/arm/mach-s3c2410/Kconfig11
-rw-r--r--arch/arm/mach-s3c2410/Makefile1
-rw-r--r--arch/arm/mach-s3c2410/cpu-freq.c157
3 files changed, 169 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 41bb65d5b91f..a7f70e18ccb4 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -12,6 +12,7 @@ config CPU_S3C2410
12 select S3C2410_GPIO 12 select S3C2410_GPIO
13 select CPU_LLSERIAL_S3C2410 13 select CPU_LLSERIAL_S3C2410
14 select S3C2410_PM if PM 14 select S3C2410_PM if PM
15 select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
15 help 16 help
16 Support for S3C2410 and S3C2410A family from the S3C24XX line 17 Support for S3C2410 and S3C2410A family from the S3C24XX line
17 of Samsung Mobile CPUs. 18 of Samsung Mobile CPUs.
@@ -45,6 +46,15 @@ config MACH_BAST_IDE
45 Internal node for machines with an BAST style IDE 46 Internal node for machines with an BAST style IDE
46 interface 47 interface
47 48
49# cpu frequency scaling support
50
51config S3C2410_CPUFREQ
52 bool
53 depends on CPU_FREQ_S3C24XX && CPU_S3C2410
54 select S3C2410_CPUFREQ_UTILS
55 help
56 CPU Frequency scaling support for S3C2410
57
48menu "S3C2410 Machines" 58menu "S3C2410 Machines"
49 59
50config ARCH_SMDK2410 60config ARCH_SMDK2410
@@ -79,6 +89,7 @@ config MACH_N30
79config ARCH_BAST 89config ARCH_BAST
80 bool "Simtec Electronics BAST (EB2410ITX)" 90 bool "Simtec Electronics BAST (EB2410ITX)"
81 select CPU_S3C2410 91 select CPU_S3C2410
92 select S3C2410_IOTIMING if S3C2410_CPUFREQ
82 select PM_SIMTEC if PM 93 select PM_SIMTEC if PM
83 select SIMTEC_NOR 94 select SIMTEC_NOR
84 select MACH_BAST_IDE 95 select MACH_BAST_IDE
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index fca02f82711c..cc25eb0eb2cd 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
15obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o 15obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
16obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o 16obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
17obj-$(CONFIG_S3C2410_GPIO) += gpio.o 17obj-$(CONFIG_S3C2410_GPIO) += gpio.o
18obj-$(CONFIG_S3C2410_CPUFREQ) += cpu-freq.o
18 19
19# Machine support 20# Machine support
20 21
diff --git a/arch/arm/mach-s3c2410/cpu-freq.c b/arch/arm/mach-s3c2410/cpu-freq.c
new file mode 100644
index 000000000000..f2cbdbab0df6
--- /dev/null
+++ b/arch/arm/mach-s3c2410/cpu-freq.c
@@ -0,0 +1,157 @@
1/* linux/arch/arm/mach-s3c2410/cpu-freq.c
2 *
3 * Copyright (c) 2006,2008 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C2410 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/sysdev.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
29#include <plat/cpu.h>
30#include <plat/clock.h>
31#include <plat/cpu-freq-core.h>
32
33/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
34
35static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg)
36{
37 u32 clkdiv = 0;
38
39 if (cfg->divs.h_divisor == 2)
40 clkdiv |= S3C2410_CLKDIVN_HDIVN;
41
42 if (cfg->divs.p_divisor != cfg->divs.h_divisor)
43 clkdiv |= S3C2410_CLKDIVN_PDIVN;
44
45 __raw_writel(clkdiv, S3C2410_CLKDIVN);
46}
47
48static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
49{
50 unsigned long hclk, fclk, pclk;
51 unsigned int hdiv, pdiv;
52 unsigned long hclk_max;
53
54 fclk = cfg->freq.fclk;
55 hclk_max = cfg->max.hclk;
56
57 cfg->freq.armclk = fclk;
58
59 s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n",
60 __func__, fclk, hclk_max);
61
62 hdiv = (fclk > cfg->max.hclk) ? 2 : 1;
63 hclk = fclk / hdiv;
64
65 if (hclk > cfg->max.hclk) {
66 s3c_freq_dbg("%s: hclk too big\n", __func__);
67 return -EINVAL;
68 }
69
70 pdiv = (hclk > cfg->max.pclk) ? 2 : 1;
71 pclk = hclk / pdiv;
72
73 if (pclk > cfg->max.pclk) {
74 s3c_freq_dbg("%s: pclk too big\n", __func__);
75 return -EINVAL;
76 }
77
78 pdiv *= hdiv;
79
80 /* record the result */
81 cfg->divs.p_divisor = pdiv;
82 cfg->divs.h_divisor = hdiv;
83
84 return 0 ;
85}
86
87static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
88 .max = {
89 .fclk = 200000000,
90 .hclk = 100000000,
91 .pclk = 50000000,
92 },
93
94 /* transition latency is about 5ms worst-case, so
95 * set 10ms to be sure */
96 .latency = 10000000,
97
98 .locktime_m = 150,
99 .locktime_u = 150,
100 .locktime_bits = 12,
101
102 .need_pll = 1,
103
104 .name = "s3c2410",
105 .calc_iotiming = s3c2410_iotiming_calc,
106 .set_iotiming = s3c2410_iotiming_set,
107 .get_iotiming = s3c2410_iotiming_get,
108 .resume_clocks = s3c2410_setup_clocks,
109
110 .set_fvco = s3c2410_set_fvco,
111 .set_refresh = s3c2410_cpufreq_setrefresh,
112 .set_divs = s3c2410_cpufreq_setdivs,
113 .calc_divs = s3c2410_cpufreq_calcdivs,
114};
115
116static int s3c2410_cpufreq_add(struct sys_device *sysdev)
117{
118 return s3c_cpufreq_register(&s3c2410_cpufreq_info);
119}
120
121static struct sysdev_driver s3c2410_cpufreq_driver = {
122 .add = s3c2410_cpufreq_add,
123};
124
125static int __init s3c2410_cpufreq_init(void)
126{
127 return sysdev_driver_register(&s3c2410_sysclass,
128 &s3c2410_cpufreq_driver);
129}
130
131arch_initcall(s3c2410_cpufreq_init);
132
133static int s3c2410a_cpufreq_add(struct sys_device *sysdev)
134{
135 /* alter the maximum freq settings for S3C2410A. If a board knows
136 * it only has a maximum of 200, then it should register its own
137 * limits. */
138
139 s3c2410_cpufreq_info.max.fclk = 266000000;
140 s3c2410_cpufreq_info.max.hclk = 133000000;
141 s3c2410_cpufreq_info.max.pclk = 66500000;
142 s3c2410_cpufreq_info.name = "s3c2410a";
143
144 return s3c2410_cpufreq_add(sysdev);
145}
146
147static struct sysdev_driver s3c2410a_cpufreq_driver = {
148 .add = s3c2410a_cpufreq_add,
149};
150
151static int __init s3c2410a_cpufreq_init(void)
152{
153 return sysdev_driver_register(&s3c2410a_sysclass,
154 &s3c2410a_cpufreq_driver);
155}
156
157arch_initcall(s3c2410a_cpufreq_init);