From: Kevin Hilman <khilman@mvista.com>
To: linux-omap-open-source@linux.omap.com
Subject: [PATCH/RFC] ARM: OMAP: implement CPUfreq frequency table based on PRCM table
Date: Fri, 19 Oct 2007 10:20:31 -0700 [thread overview]
Message-ID: <20071019172031.226299706@mvista.com> (raw)
This patch adds a CPUfreq frequency-table implementation for OMAP2 by
walking the PRCM rate-table for available entries and adding them to a
CPUfreq table.
CPUfreq can then be used to manage switching between all the available
entries in the PRCM rate table. Either use the CPUfreq sysfs
interface directly, (see Section 3 of Documentation/cpu-freq/user-guide.txt)
or use the cpufrequtils package:
http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html
Signed-off-by: Kevin Hilman <khilman@mvista.com>
---
arch/arm/mach-omap2/clock24xx.c | 39 ++++++++++++++++++++++++++++++
arch/arm/plat-omap/cpu-omap.c | 52 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 89 insertions(+), 2 deletions(-)
Index: dev/arch/arm/mach-omap2/clock24xx.c
===================================================================
--- dev.orig/arch/arm/mach-omap2/clock24xx.c
+++ dev/arch/arm/mach-omap2/clock24xx.c
@@ -26,6 +26,7 @@
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/cpufreq.h>
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
@@ -461,6 +462,42 @@ static int __init omap2_clk_arch_init(vo
}
arch_initcall(omap2_clk_arch_init);
+#ifdef CONFIG_CPU_FREQ
+/*
+ * Walk PRCM rate table and fillout cpufreq freq_table
+ */
+static struct cpufreq_frequency_table freq_table[16];
+struct cpufreq_frequency_table *omap2_cpufreq_table;
+
+static void omap2_cpufreq_init_table(void)
+{
+ struct prcm_config *prcm;
+ int i = 0;
+
+ for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+ if (!(prcm->flags & cpu_mask))
+ continue;
+ if (prcm->xtal_speed != sys_ck.rate)
+ continue;
+
+ /* don't put bypass rates in table */
+ if (prcm->dpll_speed == prcm->xtal_speed)
+ continue;
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = prcm->mpu_speed / 1000;
+ i++;
+ }
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ omap2_cpufreq_table = &freq_table[0];
+}
+#else
+static void omap2_cpufreq_init_table(void) {}
+#endif
+
int __init omap2_clk_init(void)
{
struct prcm_config *prcm;
@@ -520,5 +557,7 @@ int __init omap2_clk_init(void)
vclk = clk_get(NULL, "virt_prcm_set");
sclk = clk_get(NULL, "sys_ck");
+ omap2_cpufreq_init_table();
+
return 0;
}
Index: dev/arch/arm/plat-omap/cpu-omap.c
===================================================================
--- dev.orig/arch/arm/plat-omap/cpu-omap.c
+++ dev/arch/arm/plat-omap/cpu-omap.c
@@ -30,15 +30,25 @@
#ifdef CONFIG_ARCH_OMAP1
#define MPU_CLK "mpu"
#else
+
+#define USE_FREQ_TABLE
+extern struct cpufreq_frequency_table *omap2_cpufreq_table;
+static struct cpufreq_frequency_table *freq_table;
+
#define MPU_CLK "virt_prcm_set"
#endif
static struct clk *mpu_clk;
+static unsigned int omap_cur_speed;
+
/* TODO: Add support for SDRAM timing changes */
int omap_verify_speed(struct cpufreq_policy *policy)
{
+#ifdef USE_FREQ_TABLE
+ return cpufreq_frequency_table_verify(policy, freq_table);
+#else
if (policy->cpu)
return -EINVAL;
@@ -50,6 +60,7 @@ int omap_verify_speed(struct cpufreq_pol
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
return 0;
+#endif
}
unsigned int omap_getspeed(unsigned int cpu)
@@ -74,8 +85,16 @@ static int omap_target(struct cpufreq_po
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
freqs.cpu = 0;
+ if (freqs.old == freqs.new)
+ return ret;
+
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- ret = clk_set_rate(mpu_clk, target_freq * 1000);
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
+ freqs.old, freqs.new);
+#endif
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+ omap_cur_speed = freqs.new * 1000;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return ret;
@@ -83,17 +102,32 @@ static int omap_target(struct cpufreq_po
static int __init omap_cpu_init(struct cpufreq_policy *policy)
{
+ int result = 0;
+
mpu_clk = clk_get(NULL, MPU_CLK);
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->cur = omap_getspeed(0);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+#ifdef USE_FREQ_TABLE
+ freq_table = omap2_cpufreq_table;
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (!result)
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+#else
+ policy->min = omap_getspeed(0);
+ policy->max = omap_getspeed(0);
policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+#endif
+ /* If CPUFREQ_ETERNAL is used, then governers cannot be changed */
+ policy->cpuinfo.transition_latency = 10 * 1000 * 1000; /* 10 msec */
+
return 0;
}
@@ -104,6 +138,11 @@ static int omap_cpu_exit(struct cpufreq_
return 0;
}
+static struct freq_attr *omap_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
static struct cpufreq_driver omap_driver = {
.flags = CPUFREQ_STICKY,
.verify = omap_verify_speed,
@@ -112,6 +151,7 @@ static struct cpufreq_driver omap_driver
.init = omap_cpu_init,
.exit = omap_cpu_exit,
.name = "omap",
+ .attr = omap_cpufreq_attr,
};
static int __init omap_cpufreq_init(void)
@@ -120,3 +160,11 @@ static int __init omap_cpufreq_init(void
}
arch_initcall(omap_cpufreq_init);
+
+/*
+ * if ever we want to remove this, upon cleanup call:
+ *
+ * cpufreq_unregister_driver()
+ * cpufreq_frequency_table_put_attr()
+ */
+
--
next reply other threads:[~2007-10-19 17:20 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-19 17:20 Kevin Hilman [this message]
2007-11-01 12:33 ` [PATCH/RFC] ARM: OMAP: implement CPUfreq frequency table based on PRCM table Tony Lindgren
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071019172031.226299706@mvista.com \
--to=khilman@mvista.com \
--cc=linux-omap-open-source@linux.omap.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.