aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-s3c2410/cpu-freq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 17:48:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 17:48:14 -0700
commit2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac (patch)
tree9c0927ed1d540e5fd704c1f82689870786514655 /arch/arm/mach-s3c2410/cpu-freq.c
parent2195d2818c37bdf263865f1e9effccdd9fc5f9d4 (diff)
parent87d721ad7a37b7650dd710c88dd5c6a5bf9fe996 (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (257 commits) [ARM] Update mach-types ARM: 5636/1: Move vendor enum to AMBA include ARM: Fix pfn_valid() for sparse memory [ARM] orion5x: Add LaCie NAS 2Big Network support [ARM] pxa/sharpsl_pm: zaurus c3000 aka spitz: fix resume ARM: 5686/1: at91: Correct AC97 reset line in at91sam9263ek board ARM: 5640/1: This patch modifies the support of AC97 on the at91sam9263 ek board ARM: 5689/1: Update default config of HP Jornada 700-series machines ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() with highmem ARM: 5688/1: ks8695_serial: disable_irq() lockup ARM: 5687/1: fix an oops with highmem ARM: 5684/1: Add nuc960 platform to w90x900 ARM: 5683/1: Add nuc950 platform to w90x900 ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform ARM: 5626/1: add suspend/resume functions to amba-pl011 serial driver ARM: 5625/1: fix hard coded 4K resource size in amba bus detection MMC: MMCI: convert realview MMC to use gpiolib ARM: 5685/1: Make MMCI driver compile without gpiolib ARM: implement highpte ARM: Show FIQ in /proc/interrupts on CONFIG_FIQ ... Fix up trivial conflict in arch/arm/kernel/signal.c. It was due to the TIF_NOTIFY_RESUME addition in commit d0420c83f ("KEYS: Extend TIF_NOTIFY_RESUME to (almost) all architectures") and follow-ups.
Diffstat (limited to 'arch/arm/mach-s3c2410/cpu-freq.c')
-rw-r--r--arch/arm/mach-s3c2410/cpu-freq.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2410/cpu-freq.c b/arch/arm/mach-s3c2410/cpu-freq.c
new file mode 100644
index 00000000000..9d1186877d0
--- /dev/null
+++ b/arch/arm/mach-s3c2410/cpu-freq.c
@@ -0,0 +1,159 @@
+/* linux/arch/arm/mach-s3c2410/cpu-freq.c
+ *
+ * Copyright (c) 2006,2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 CPU Frequency scaling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/cpufreq.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu-freq-core.h>
+
+/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
+
+static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg)
+{
+ u32 clkdiv = 0;
+
+ if (cfg->divs.h_divisor == 2)
+ clkdiv |= S3C2410_CLKDIVN_HDIVN;
+
+ if (cfg->divs.p_divisor != cfg->divs.h_divisor)
+ clkdiv |= S3C2410_CLKDIVN_PDIVN;
+
+ __raw_writel(clkdiv, S3C2410_CLKDIVN);
+}
+
+static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
+{
+ unsigned long hclk, fclk, pclk;
+ unsigned int hdiv, pdiv;
+ unsigned long hclk_max;
+
+ fclk = cfg->freq.fclk;
+ hclk_max = cfg->max.hclk;
+
+ cfg->freq.armclk = fclk;
+
+ s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n",
+ __func__, fclk, hclk_max);
+
+ hdiv = (fclk > cfg->max.hclk) ? 2 : 1;
+ hclk = fclk / hdiv;
+
+ if (hclk > cfg->max.hclk) {
+ s3c_freq_dbg("%s: hclk too big\n", __func__);
+ return -EINVAL;
+ }
+
+ pdiv = (hclk > cfg->max.pclk) ? 2 : 1;
+ pclk = hclk / pdiv;
+
+ if (pclk > cfg->max.pclk) {
+ s3c_freq_dbg("%s: pclk too big\n", __func__);
+ return -EINVAL;
+ }
+
+ pdiv *= hdiv;
+
+ /* record the result */
+ cfg->divs.p_divisor = pdiv;
+ cfg->divs.h_divisor = hdiv;
+
+ return 0 ;
+}
+
+static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
+ .max = {
+ .fclk = 200000000,
+ .hclk = 100000000,
+ .pclk = 50000000,
+ },
+
+ /* transition latency is about 5ms worst-case, so
+ * set 10ms to be sure */
+ .latency = 10000000,
+
+ .locktime_m = 150,
+ .locktime_u = 150,
+ .locktime_bits = 12,
+
+ .need_pll = 1,
+
+ .name = "s3c2410",
+ .calc_iotiming = s3c2410_iotiming_calc,
+ .set_iotiming = s3c2410_iotiming_set,
+ .get_iotiming = s3c2410_iotiming_get,
+ .resume_clocks = s3c2410_setup_clocks,
+
+ .set_fvco = s3c2410_set_fvco,
+ .set_refresh = s3c2410_cpufreq_setrefresh,
+ .set_divs = s3c2410_cpufreq_setdivs,
+ .calc_divs = s3c2410_cpufreq_calcdivs,
+
+ .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
+};
+
+static int s3c2410_cpufreq_add(struct sys_device *sysdev)
+{
+ return s3c_cpufreq_register(&s3c2410_cpufreq_info);
+}
+
+static struct sysdev_driver s3c2410_cpufreq_driver = {
+ .add = s3c2410_cpufreq_add,
+};
+
+static int __init s3c2410_cpufreq_init(void)
+{
+ return sysdev_driver_register(&s3c2410_sysclass,
+ &s3c2410_cpufreq_driver);
+}
+
+arch_initcall(s3c2410_cpufreq_init);
+
+static int s3c2410a_cpufreq_add(struct sys_device *sysdev)
+{
+ /* alter the maximum freq settings for S3C2410A. If a board knows
+ * it only has a maximum of 200, then it should register its own
+ * limits. */
+
+ s3c2410_cpufreq_info.max.fclk = 266000000;
+ s3c2410_cpufreq_info.max.hclk = 133000000;
+ s3c2410_cpufreq_info.max.pclk = 66500000;
+ s3c2410_cpufreq_info.name = "s3c2410a";
+
+ return s3c2410_cpufreq_add(sysdev);
+}
+
+static struct sysdev_driver s3c2410a_cpufreq_driver = {
+ .add = s3c2410a_cpufreq_add,
+};
+
+static int __init s3c2410a_cpufreq_init(void)
+{
+ return sysdev_driver_register(&s3c2410a_sysclass,
+ &s3c2410a_cpufreq_driver);
+}
+
+arch_initcall(s3c2410a_cpufreq_init);