From: Tony Lindgren Date: Mon, 9 May 2005 20:03:13 +0000 (-0700) Subject: ARM: OMAP: Add cpufreq support X-Git-Tag: v2.6.13-omap1~189 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=6ccf5bd02b6e0f300d4046bddc31f7a6ec9f1ad3;p=linux-2.6-omap-h63xx.git ARM: OMAP: Add cpufreq support Sync with linux-omap tree. Adds cpufreq support for OMAP. Does not yet include changing memory timings. Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bf397a9f8ac..b5a8ea63f5c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -489,7 +489,7 @@ config XIP_PHYS_ADDR endmenu -if (ARCH_SA1100 || ARCH_INTEGRATOR) +if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP1) menu "CPU Frequency scaling" diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 2490db59839..167f42dccc1 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o # Power Management obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_CPU_FREQ) += cpu-omap.o diff --git a/arch/arm/mach-omap/cpu-omap.c b/arch/arm/mach-omap/cpu-omap.c new file mode 100644 index 00000000000..9f38bc45a50 --- /dev/null +++ b/arch/arm/mach-omap/cpu-omap.c @@ -0,0 +1,128 @@ +/* + * linux/arch/arm/mach-omap/cpu-omap.c + * + * CPU frequency scaling for OMAP + * + * Copyright (C) 2005 Nokia Corporation + * Written by Tony Lindgren + * + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* TODO: Add support for SDRAM timing changes */ + +int omap_verify_speed(struct cpufreq_policy *policy) +{ + struct clk * mpu_clk; + + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + mpu_clk = clk_get(NULL, "mpu"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + clk_put(mpu_clk); + + return 0; +} + +unsigned int omap_getspeed(unsigned int cpu) +{ + struct clk * mpu_clk; + unsigned long rate; + + if (cpu) + return 0; + + mpu_clk = clk_get(NULL, "mpu"); + if (IS_ERR(mpu_clk)) + return 0; + rate = clk_get_rate(mpu_clk) / 1000; + clk_put(mpu_clk); + + return rate; +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct clk * mpu_clk; + struct cpufreq_freqs freqs; + int ret = 0; + + mpu_clk = clk_get(NULL, "mpu"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + freqs.old = omap_getspeed(0); + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; + freqs.cpu = 0; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + ret = clk_set_rate(mpu_clk, target_freq * 1000); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + clk_put(mpu_clk); + + return ret; +} + +static int __init omap_cpu_init(struct cpufreq_policy *policy) +{ + struct clk * mpu_clk; + + mpu_clk = clk_get(NULL, "mpu"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + if (policy->cpu != 0) + return -EINVAL; + policy->cur = policy->min = policy->max = omap_getspeed(0); + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, 216000000) / 1000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + clk_put(mpu_clk); + + return 0; +} + +static struct cpufreq_driver omap_driver = { + .flags = CPUFREQ_STICKY, + .verify = omap_verify_speed, + .target = omap_target, + .get = omap_getspeed, + .init = omap_cpu_init, + .name = "omap", +}; + +static int __init omap_cpufreq_init(void) +{ + return cpufreq_register_driver(&omap_driver); +} + +arch_initcall(omap_cpufreq_init);