mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-07-16 14:27:48 +00:00
linux 3.0: initial recipe that will track 3.0rc till 3.0 final
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
+84
@@ -0,0 +1,84 @@
|
||||
From e029940bc6c0ff4ad3c8e2b4f31d0a3de78eff32 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 25 May 2011 00:43:26 -0700
|
||||
Subject: [PATCH 01/19] PM: OPP: introduce function to free cpufreq table
|
||||
|
||||
cpufreq table allocated by opp_init_cpufreq_table is better
|
||||
freed by OPP layer itself. This allows future modifications to
|
||||
the table handling to be transparent to the users.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Acked-by: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
Documentation/power/opp.txt | 2 ++
|
||||
drivers/base/power/opp.c | 17 +++++++++++++++++
|
||||
include/linux/opp.h | 8 ++++++++
|
||||
3 files changed, 27 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
|
||||
index 5ae70a1..3035d00 100644
|
||||
--- a/Documentation/power/opp.txt
|
||||
+++ b/Documentation/power/opp.txt
|
||||
@@ -321,6 +321,8 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
|
||||
addition to CONFIG_PM as power management feature is required to
|
||||
dynamically scale voltage and frequency in a system.
|
||||
|
||||
+opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table
|
||||
+
|
||||
7. Data Structures
|
||||
==================
|
||||
Typically an SoC contains multiple voltage domains which are variable. Each
|
||||
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
|
||||
index 56a6899..5cc1232 100644
|
||||
--- a/drivers/base/power/opp.c
|
||||
+++ b/drivers/base/power/opp.c
|
||||
@@ -625,4 +625,21 @@ int opp_init_cpufreq_table(struct device *dev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * opp_free_cpufreq_table() - free the cpufreq table
|
||||
+ * @dev: device for which we do this operation
|
||||
+ * @table: table to free
|
||||
+ *
|
||||
+ * Free up the table allocated by opp_init_cpufreq_table
|
||||
+ */
|
||||
+void opp_free_cpufreq_table(struct device *dev,
|
||||
+ struct cpufreq_frequency_table **table)
|
||||
+{
|
||||
+ if (!table)
|
||||
+ return;
|
||||
+
|
||||
+ kfree(*table);
|
||||
+ *table = NULL;
|
||||
+}
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
diff --git a/include/linux/opp.h b/include/linux/opp.h
|
||||
index 5449945..7020e97 100644
|
||||
--- a/include/linux/opp.h
|
||||
+++ b/include/linux/opp.h
|
||||
@@ -94,12 +94,20 @@ static inline int opp_disable(struct device *dev, unsigned long freq)
|
||||
#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
|
||||
int opp_init_cpufreq_table(struct device *dev,
|
||||
struct cpufreq_frequency_table **table);
|
||||
+void opp_free_cpufreq_table(struct device *dev,
|
||||
+ struct cpufreq_frequency_table **table);
|
||||
#else
|
||||
static inline int opp_init_cpufreq_table(struct device *dev,
|
||||
struct cpufreq_frequency_table **table)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
+
|
||||
+static inline
|
||||
+void opp_free_cpufreq_table(struct device *dev,
|
||||
+ struct cpufreq_frequency_table **table)
|
||||
+{
|
||||
+}
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
#endif /* __LINUX_OPP_H__ */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
From 895fc8961297666b46b4cd3f8c01010051d2164e Mon Sep 17 00:00:00 2001
|
||||
From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
Date: Wed, 11 Aug 2010 17:02:43 -0700
|
||||
Subject: [PATCH 02/19] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index da4f68d..cd09d4b 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void)
|
||||
return cpufreq_register_driver(&omap_driver);
|
||||
}
|
||||
|
||||
-arch_initcall(omap_cpufreq_init);
|
||||
+late_initcall(omap_cpufreq_init);
|
||||
|
||||
/*
|
||||
* if ever we want to remove this, upon cleanup call:
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
From 62bd1b0f18ee6c6bad1573c2f06e74b0abc418a3 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Date: Wed, 11 Aug 2010 17:05:38 -0700
|
||||
Subject: [PATCH 03/19] OMAP: CPUfreq: ensure policy is fully initialized
|
||||
|
||||
Ensure policy min/max/cur values are initialized when OMAP
|
||||
CPUfreq driver starts.
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index cd09d4b..1b36664 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
VERY_HI_RATE) / 1000;
|
||||
}
|
||||
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
/* FIXME: what's the actual transition time? */
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
From afa9b062a33a9d9d2d9077cc519e1375b8338e39 Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Mon, 10 Nov 2008 17:00:25 +0530
|
||||
Subject: [PATCH 04/19] OMAP3 PM: CPUFreq driver for OMAP3
|
||||
|
||||
CPUFreq driver for OMAP3
|
||||
|
||||
With additional fixes and cleanups from Tero Kristo:
|
||||
- Fix rate calculation bug in omap3_select_table_rate
|
||||
- Refreshed DVFS VDD1 control against latest clock fw
|
||||
|
||||
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
|
||||
OMAP3: PM: CPUFreq: Fix omap_getspeed.
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
|
||||
Make sure omap cpufreq driver initializes after cpufreq framework and governors
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
|
||||
merge: CPUFreq: remove obsolete funcs
|
||||
|
||||
OMAP3 clock: Update cpufreq driver
|
||||
|
||||
This patch removes all refrences to virtual clock
|
||||
nodes in CPUFreq driver.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
|
||||
Signed-off-by: Jean Pihet <jpihet@mvista.com>
|
||||
|
||||
PM: Prevent direct cpufreq scaling during initialization
|
||||
|
||||
It is seen that the OMAP specific cpufreq initialization code tries to
|
||||
scale the MPU frequency to the highest possible without taking care of
|
||||
the voltage level. On power on reset the power IC does not provide the
|
||||
necessary voltage for the highest available MPU frequency (that would
|
||||
satisfy all Si families). This potentially is an window of opportunity
|
||||
for things to go wrong.
|
||||
|
||||
Signed-off-by: Romit Dasgupta <romit@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP3: PM: enable 600MHz (overdrive) OPP
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
omap3: introduce cpufreq
|
||||
|
||||
OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only.
|
||||
|
||||
With this patch, omap opp layer now has its compilation flags
|
||||
bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c.
|
||||
|
||||
A new file has been created to contain cpu freq code related to
|
||||
OMAP3: cpufreq34xx.c
|
||||
|
||||
OMAP34xx and OMAP36xx family OPPs are made available
|
||||
|
||||
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
Signed-off-by: Paul Walmsley <paul@pwsan.com>
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Signed-off-by: Romit Dasgupta <romit@ti.com>
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
|
||||
omap3: cpufreq: allow default opp table init
|
||||
|
||||
For board files which choose to override the defaults, the existing
|
||||
mechanism will work, for boards that would like to work with defaults,
|
||||
allow init_common_hw to call init_opp_table to initialize if not
|
||||
already initialized. this will allow all omap boards which have opp
|
||||
tables predefined for a silicon to use the same.
|
||||
|
||||
Originally reported for overo:
|
||||
http://marc.info/?t=127265269400004&r=1&w=2
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Reported-by: Peter Tseng <tsenpet09@gmail.com>
|
||||
Cc: Cliff Brake <cliff.brake@gmail.com>
|
||||
Cc: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP2: update OPP data to be device based
|
||||
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP3: CPUfreq: update to device-based OPP API
|
||||
|
||||
Update usage of OPP API to use new device-based API. This requires
|
||||
getting the 'struct device' for the MPU and using that with the OPP
|
||||
API.
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
omap3: opp: make independent of cpufreq
|
||||
|
||||
Make opp3xx data which is registered with the opp layer
|
||||
dependent purely on CONFIG_PM as opp layer and pm.c users
|
||||
are CONFIG_PM dependent not cpufreq dependent.
|
||||
so we rename the data definition to opp3xxx_data.c (inline with what
|
||||
we have for omap2), also move the build definition to be under
|
||||
the existing CONFIG_PM build instead of CPUFREQ.
|
||||
|
||||
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
Cc: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Cc: Paul Walmsley <paul@pwsan.com>
|
||||
Cc: Rajendra Nayak <rnayak@ti.com>
|
||||
Cc: Sanjeev Premi <premi@ti.com>
|
||||
Cc: Thara Gopinath <thara@ti.com>
|
||||
Cc: Tony Lindgren <tony@atomide.com>
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/clock.h | 14 +++++++++++++-
|
||||
arch/arm/mach-omap2/clock34xx.c | 2 ++
|
||||
arch/arm/plat-omap/cpu-omap.c | 34 +++++++++++++++++++++++++++++++---
|
||||
3 files changed, 46 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
|
||||
index e10ff2b..0a07e50 100644
|
||||
--- a/arch/arm/mach-omap2/clock.h
|
||||
+++ b/arch/arm/mach-omap2/clock.h
|
||||
@@ -141,7 +141,9 @@ extern const struct clksel_rate gpt_sys_rates[];
|
||||
extern const struct clksel_rate gfx_l3_rates[];
|
||||
extern const struct clksel_rate dsp_ick_rates[];
|
||||
|
||||
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
|
||||
+#ifdef CONFIG_CPU_FREQ
|
||||
+
|
||||
+#ifdef CONFIG_ARCH_OMAP2
|
||||
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
#else
|
||||
@@ -149,6 +151,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
|
||||
#define omap2_clk_exit_cpufreq_table 0
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP3
|
||||
+extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
+extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
+#else
|
||||
+#define omap3_clk_init_cpufreq_table 0
|
||||
+#define omap3_clk_exit_cpufreq_table 0
|
||||
+#endif
|
||||
+
|
||||
+#endif /* CONFIG_CPU_FREQ */
|
||||
+
|
||||
extern const struct clkops clkops_omap2_iclk_dflt_wait;
|
||||
extern const struct clkops clkops_omap2_iclk_dflt;
|
||||
extern const struct clkops clkops_omap2_iclk_idle_only;
|
||||
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
|
||||
index 1fc96b9..119e135 100644
|
||||
--- a/arch/arm/mach-omap2/clock34xx.c
|
||||
+++ b/arch/arm/mach-omap2/clock34xx.c
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index 1b36664..f0f9430 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -8,6 +8,10 @@
|
||||
*
|
||||
* Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
*
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.com>
|
||||
+ *
|
||||
* 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.
|
||||
@@ -26,12 +30,19 @@
|
||||
#include <plat/clock.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+#include <plat/omap-pm.h>
|
||||
+#include <plat/opp.h>
|
||||
+#endif
|
||||
+
|
||||
#define VERY_HI_RATE 900000000
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define MPU_CLK "mpu"
|
||||
+#elif CONFIG_ARCH_OMAP3
|
||||
+#define MPU_CLK "arm_fck"
|
||||
#else
|
||||
#define MPU_CLK "virt_prcm_set"
|
||||
#endif
|
||||
@@ -73,7 +84,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
+#ifdef CONFIG_ARCH_OMAP1
|
||||
struct cpufreq_freqs freqs;
|
||||
+#endif
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+ unsigned long freq;
|
||||
+ struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
+#endif
|
||||
int ret = 0;
|
||||
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
@@ -83,13 +100,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (target_freq > policy->max)
|
||||
target_freq = policy->max;
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP1
|
||||
freqs.old = omap_getspeed(0);
|
||||
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);
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
|
||||
@@ -97,7 +114,11 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
#endif
|
||||
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
-
|
||||
+#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+ freq = target_freq * 1000;
|
||||
+ if (opp_find_freq_ceil(mpu_dev, &freq))
|
||||
+ omap_pm_cpu_set_freq(freq);
|
||||
+#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -114,7 +135,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
+ if (!cpu_is_omap34xx()) {
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+ } else {
|
||||
+ struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
+
|
||||
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+ }
|
||||
+
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
if (!result)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
From c93327d36f0dc4ea6693fcae54c561eb8bafdd1e Mon Sep 17 00:00:00 2001
|
||||
From: Silesh C V <silesh@ti.com>
|
||||
Date: Wed, 29 Sep 2010 14:52:54 +0530
|
||||
Subject: [PATCH 05/19] OMAP: PM: CPUFREQ: Fix conditional compilation
|
||||
|
||||
Fix conditional compilation. A conditional expresiion
|
||||
should follow "#elif", in this case #elif clause should
|
||||
check whether CONFIG_ARCH_OMAP3 is defined or not
|
||||
(ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for
|
||||
the value of the macro.
|
||||
|
||||
Signed-off-by: Silesh C V <silesh@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index f0f9430..c3ac065 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -41,7 +41,7 @@ static struct cpufreq_frequency_table *freq_table;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define MPU_CLK "mpu"
|
||||
-#elif CONFIG_ARCH_OMAP3
|
||||
+#elif defined(CONFIG_ARCH_OMAP3)
|
||||
#define MPU_CLK "arm_fck"
|
||||
#else
|
||||
#define MPU_CLK "virt_prcm_set"
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
From b8246b5d5edc98155628ba88510bc7e67baf7acf Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Date: Tue, 16 Nov 2010 11:48:41 -0800
|
||||
Subject: [PATCH 06/19] cpufreq: fixup after new OPP layer merged
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index c3ac065..9cd2709 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <plat/clock.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
#include <plat/omap-pm.h>
|
||||
-#include <plat/opp.h>
|
||||
+#include <plat/common.h>
|
||||
#endif
|
||||
|
||||
#define VERY_HI_RATE 900000000
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+673
@@ -0,0 +1,673 @@
|
||||
From 9f9061d3e98aa6db7d5c3feabd5a2d93eb3cb737 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Mon, 14 Mar 2011 17:08:48 +0530
|
||||
Subject: [PATCH 07/19] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers.
|
||||
|
||||
This patch is an attempt to cleanup the #ifdeferry in the
|
||||
omap CPUfreq drivers.
|
||||
|
||||
The split betwenn OMAP1 and OMAP2PLUS is logical because
|
||||
- OMAP1 doesn't support opp layer.
|
||||
- OMAP1 build is seperate from omap2plus.
|
||||
|
||||
Includes minor header/copyright updates reported by Todd Poynor.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
Cc: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
Cc: Todd Poynor <toddpoynor@google.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap1/Makefile | 3 +
|
||||
arch/arm/mach-omap1/omap1-cpufreq.c | 175 ++++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/Makefile | 3 +
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++
|
||||
arch/arm/plat-omap/Makefile | 1 -
|
||||
arch/arm/plat-omap/cpu-omap.c | 204 -------------------------------
|
||||
6 files changed, 382 insertions(+), 205 deletions(-)
|
||||
create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
|
||||
|
||||
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
|
||||
index 5b114d1..9600410 100644
|
||||
--- a/arch/arm/mach-omap1/Makefile
|
||||
+++ b/arch/arm/mach-omap1/Makefile
|
||||
@@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
|
||||
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
|
||||
|
||||
+# CPUFREQ driver
|
||||
+obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o
|
||||
+
|
||||
# Power Management
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o
|
||||
|
||||
diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..7c5216e
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
@@ -0,0 +1,175 @@
|
||||
+/*
|
||||
+ * OMAP1 cpufreq driver
|
||||
+ *
|
||||
+ * CPU frequency scaling for OMAP
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Nokia Corporation
|
||||
+ * Written by Tony Lindgren <tony@atomide.com>
|
||||
+ *
|
||||
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
+ *
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Rajendra Nayak <rnayak@ti.com>
|
||||
+ *
|
||||
+ * 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/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
+
|
||||
+#include <asm/system.h>
|
||||
+
|
||||
+#include <plat/clock.h>
|
||||
+#include <plat/omap-pm.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+
|
||||
+#define VERY_HI_RATE 900000000
|
||||
+
|
||||
+static struct cpufreq_frequency_table *freq_table;
|
||||
+static struct clk *mpu_clk;
|
||||
+
|
||||
+static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (freq_table)
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
+
|
||||
+ if (policy->cpu)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+
|
||||
+ 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);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int omap_getspeed(unsigned int cpu)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+
|
||||
+ if (cpu)
|
||||
+ return 0;
|
||||
+
|
||||
+ rate = clk_get_rate(mpu_clk) / 1000;
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static int omap_target(struct cpufreq_policy *policy,
|
||||
+ unsigned int target_freq,
|
||||
+ unsigned int relation)
|
||||
+{
|
||||
+ struct cpufreq_freqs freqs;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.old = omap_getspeed(0);
|
||||
+ 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);
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
+#endif
|
||||
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __init omap_cpu_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+
|
||||
+ if (freq_table) {
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table,
|
||||
+ policy->cpu);
|
||||
+ } else {
|
||||
+ 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->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
+ /* FIXME: what's the actual transition time? */
|
||||
+ policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ clk_put(mpu_clk);
|
||||
+ 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,
|
||||
+ .target = omap_target,
|
||||
+ .get = omap_getspeed,
|
||||
+ .init = omap_cpu_init,
|
||||
+ .exit = omap_cpu_exit,
|
||||
+ .name = "omap1",
|
||||
+ .attr = omap_cpufreq_attr,
|
||||
+};
|
||||
+
|
||||
+static int __init omap_cpufreq_init(void)
|
||||
+{
|
||||
+ return cpufreq_register_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit omap_cpufreq_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
|
||||
index b148077..5024064 100644
|
||||
--- a/arch/arm/mach-omap2/Makefile
|
||||
+++ b/arch/arm/mach-omap2/Makefile
|
||||
@@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
|
||||
endif
|
||||
|
||||
+# CPUFREQ driver
|
||||
+obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o
|
||||
+
|
||||
# Power Management
|
||||
ifeq ($(CONFIG_PM),y)
|
||||
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..27f641b
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -0,0 +1,201 @@
|
||||
+/*
|
||||
+ * OMAP2PLUS cpufreq driver
|
||||
+ *
|
||||
+ * CPU frequency scaling for OMAP
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Nokia Corporation
|
||||
+ * Written by Tony Lindgren <tony@atomide.com>
|
||||
+ *
|
||||
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
+ *
|
||||
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.com>
|
||||
+ *
|
||||
+ * 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/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
+
|
||||
+#include <asm/system.h>
|
||||
+#include <asm/smp_plat.h>
|
||||
+
|
||||
+#include <plat/clock.h>
|
||||
+#include <plat/omap-pm.h>
|
||||
+#include <plat/common.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+
|
||||
+#define VERY_HI_RATE 900000000
|
||||
+
|
||||
+static struct cpufreq_frequency_table *freq_table;
|
||||
+static struct clk *mpu_clk;
|
||||
+
|
||||
+static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (freq_table)
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
+
|
||||
+ if (policy->cpu)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+
|
||||
+ 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);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int omap_getspeed(unsigned int cpu)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+
|
||||
+ if (cpu)
|
||||
+ return 0;
|
||||
+
|
||||
+ rate = clk_get_rate(mpu_clk) / 1000;
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static int omap_target(struct cpufreq_policy *policy,
|
||||
+ unsigned int target_freq,
|
||||
+ unsigned int relation)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct cpufreq_freqs freqs;
|
||||
+
|
||||
+ /* Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.old = omap_getspeed(0);
|
||||
+ 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);
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
+#endif
|
||||
+
|
||||
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
+
|
||||
+ /*
|
||||
+ * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
|
||||
+ * won't get updated when UP machine cpufreq build with
|
||||
+ * CONFIG_SMP enabled. Below code is added only to manage that
|
||||
+ * scenario
|
||||
+ */
|
||||
+ if (!is_smp())
|
||||
+ loops_per_jiffy =
|
||||
+ cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ struct device *mpu_dev;
|
||||
+
|
||||
+ if (cpu_is_omap24xx())
|
||||
+ mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ mpu_dev = omap2_get_mpuss_device();
|
||||
+ if (!mpu_dev) {
|
||||
+ pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ if (freq_table) {
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table,
|
||||
+ policy->cpu);
|
||||
+ } else {
|
||||
+ 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->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
+ /* FIXME: what's the actual transition time? */
|
||||
+ policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ clk_put(mpu_clk);
|
||||
+ 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,
|
||||
+ .target = omap_target,
|
||||
+ .get = omap_getspeed,
|
||||
+ .init = omap_cpu_init,
|
||||
+ .exit = omap_cpu_exit,
|
||||
+ .name = "omap2plus",
|
||||
+ .attr = omap_cpufreq_attr,
|
||||
+};
|
||||
+
|
||||
+static int __init omap_cpufreq_init(void)
|
||||
+{
|
||||
+ return cpufreq_register_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit omap_cpufreq_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
|
||||
index f0233e6..4ef7493 100644
|
||||
--- a/arch/arm/plat-omap/Makefile
|
||||
+++ b/arch/arm/plat-omap/Makefile
|
||||
@@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
|
||||
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
|
||||
|
||||
-obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
|
||||
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
deleted file mode 100644
|
||||
index 9cd2709..0000000
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ /dev/null
|
||||
@@ -1,204 +0,0 @@
|
||||
-/*
|
||||
- * linux/arch/arm/plat-omap/cpu-omap.c
|
||||
- *
|
||||
- * CPU frequency scaling for OMAP
|
||||
- *
|
||||
- * Copyright (C) 2005 Nokia Corporation
|
||||
- * Written by Tony Lindgren <tony@atomide.com>
|
||||
- *
|
||||
- * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
- *
|
||||
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
- * Updated to support OMAP3
|
||||
- * Rajendra Nayak <rnayak@ti.com>
|
||||
- *
|
||||
- * 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/types.h>
|
||||
-#include <linux/kernel.h>
|
||||
-#include <linux/sched.h>
|
||||
-#include <linux/cpufreq.h>
|
||||
-#include <linux/delay.h>
|
||||
-#include <linux/init.h>
|
||||
-#include <linux/err.h>
|
||||
-#include <linux/clk.h>
|
||||
-#include <linux/io.h>
|
||||
-#include <linux/opp.h>
|
||||
-
|
||||
-#include <mach/hardware.h>
|
||||
-#include <plat/clock.h>
|
||||
-#include <asm/system.h>
|
||||
-
|
||||
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
-#include <plat/omap-pm.h>
|
||||
-#include <plat/common.h>
|
||||
-#endif
|
||||
-
|
||||
-#define VERY_HI_RATE 900000000
|
||||
-
|
||||
-static struct cpufreq_frequency_table *freq_table;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
-#define MPU_CLK "mpu"
|
||||
-#elif defined(CONFIG_ARCH_OMAP3)
|
||||
-#define MPU_CLK "arm_fck"
|
||||
-#else
|
||||
-#define MPU_CLK "virt_prcm_set"
|
||||
-#endif
|
||||
-
|
||||
-static struct clk *mpu_clk;
|
||||
-
|
||||
-/* TODO: Add support for SDRAM timing changes */
|
||||
-
|
||||
-static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- if (freq_table)
|
||||
- return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
-
|
||||
- if (policy->cpu)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
- policy->cpuinfo.max_freq);
|
||||
-
|
||||
- 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);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static unsigned int omap_getspeed(unsigned int cpu)
|
||||
-{
|
||||
- unsigned long rate;
|
||||
-
|
||||
- if (cpu)
|
||||
- return 0;
|
||||
-
|
||||
- rate = clk_get_rate(mpu_clk) / 1000;
|
||||
- return rate;
|
||||
-}
|
||||
-
|
||||
-static int omap_target(struct cpufreq_policy *policy,
|
||||
- unsigned int target_freq,
|
||||
- unsigned int relation)
|
||||
-{
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
- struct cpufreq_freqs freqs;
|
||||
-#endif
|
||||
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
- unsigned long freq;
|
||||
- struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
-#endif
|
||||
- int ret = 0;
|
||||
-
|
||||
- /* Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
- if (target_freq < policy->min)
|
||||
- target_freq = policy->min;
|
||||
- if (target_freq > policy->max)
|
||||
- target_freq = policy->max;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
- freqs.old = omap_getspeed(0);
|
||||
- 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);
|
||||
-#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);
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
-#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
- freq = target_freq * 1000;
|
||||
- if (opp_find_freq_ceil(mpu_dev, &freq))
|
||||
- omap_pm_cpu_set_freq(freq);
|
||||
-#endif
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int __cpuinit 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);
|
||||
-
|
||||
- if (!cpu_is_omap34xx()) {
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
- } else {
|
||||
- struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
-
|
||||
- opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
- }
|
||||
-
|
||||
- if (freq_table) {
|
||||
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
- cpufreq_frequency_table_get_attr(freq_table,
|
||||
- policy->cpu);
|
||||
- } else {
|
||||
- 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->min = policy->cpuinfo.min_freq;
|
||||
- policy->max = policy->cpuinfo.max_freq;
|
||||
- policy->cur = omap_getspeed(0);
|
||||
-
|
||||
- /* FIXME: what's the actual transition time? */
|
||||
- policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- clk_exit_cpufreq_table(&freq_table);
|
||||
- clk_put(mpu_clk);
|
||||
- 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,
|
||||
- .target = omap_target,
|
||||
- .get = omap_getspeed,
|
||||
- .init = omap_cpu_init,
|
||||
- .exit = omap_cpu_exit,
|
||||
- .name = "omap",
|
||||
- .attr = omap_cpufreq_attr,
|
||||
-};
|
||||
-
|
||||
-static int __init omap_cpufreq_init(void)
|
||||
-{
|
||||
- return cpufreq_register_driver(&omap_driver);
|
||||
-}
|
||||
-
|
||||
-late_initcall(omap_cpufreq_init);
|
||||
-
|
||||
-/*
|
||||
- * if ever we want to remove this, upon cleanup call:
|
||||
- *
|
||||
- * cpufreq_unregister_driver()
|
||||
- * cpufreq_frequency_table_put_attr()
|
||||
- */
|
||||
-
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
From f5dc16c8178d0c0bcad795f8ebc71934c4028472 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Mon, 14 Mar 2011 17:08:49 +0530
|
||||
Subject: [PATCH 08/19] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430
|
||||
|
||||
On OMAP SMP configuartion, both processors share the voltage
|
||||
and clock. So both CPUs needs to be scaled together and hence
|
||||
needs software co-ordination.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
cc: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++-----
|
||||
1 files changed, 62 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 27f641b..3730f96 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -26,9 +26,11 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/cpu.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/smp_plat.h>
|
||||
+#include <asm/cpu.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/omap-pm.h>
|
||||
@@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu)
|
||||
{
|
||||
unsigned long rate;
|
||||
|
||||
- if (cpu)
|
||||
+ if (cpu >= NR_CPUS)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(mpu_clk) / 1000;
|
||||
@@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
- int ret = 0;
|
||||
+ int i, ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
+ /* Changes not allowed until all CPUs are online */
|
||||
+ if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
+ return ret;
|
||||
+
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
* (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
if (target_freq < policy->min)
|
||||
@@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (target_freq > policy->max)
|
||||
target_freq = policy->max;
|
||||
|
||||
- freqs.old = omap_getspeed(0);
|
||||
+ freqs.old = omap_getspeed(policy->cpu);
|
||||
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
- freqs.cpu = 0;
|
||||
+ freqs.cpu = policy->cpu;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
return ret;
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ if (!is_smp()) {
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ goto set_freq;
|
||||
+ }
|
||||
+
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ }
|
||||
|
||||
+set_freq:
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
#endif
|
||||
@@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
* CONFIG_SMP enabled. Below code is added only to manage that
|
||||
* scenario
|
||||
*/
|
||||
- if (!is_smp())
|
||||
+ freqs.new = omap_getspeed(policy->cpu);
|
||||
+ if (!is_smp()) {
|
||||
loops_per_jiffy =
|
||||
cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ goto skip_lpj;
|
||||
+ }
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+#ifdef CONFIG_SMP
|
||||
+ /*
|
||||
+ * Note that loops_per_jiffy is not updated on SMP systems in
|
||||
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
|
||||
+ * on frequency transition. We need to update all dependent CPUs.
|
||||
+ */
|
||||
+ for_each_cpu(i, policy->cpus)
|
||||
+ per_cpu(cpu_data, i).loops_per_jiffy =
|
||||
+ cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy,
|
||||
+ freqs.old, freqs.new);
|
||||
+#endif
|
||||
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ }
|
||||
+
|
||||
+skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
struct device *mpu_dev;
|
||||
+ static cpumask_var_t cpumask;
|
||||
|
||||
if (cpu_is_omap24xx())
|
||||
mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
@@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
if (IS_ERR(mpu_clk))
|
||||
return PTR_ERR(mpu_clk);
|
||||
|
||||
- if (policy->cpu != 0)
|
||||
+ if (policy->cpu >= NR_CPUS)
|
||||
return -EINVAL;
|
||||
|
||||
- policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
-
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
mpu_dev = omap2_get_mpuss_device();
|
||||
+
|
||||
if (!mpu_dev) {
|
||||
pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
return -EINVAL;
|
||||
@@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
- policy->cur = omap_getspeed(0);
|
||||
+ policy->cur = omap_getspeed(policy->cpu);
|
||||
+
|
||||
+ /*
|
||||
+ * On OMAP SMP configuartion, both processors share the voltage
|
||||
+ * and clock. So both CPUs needs to be scaled together and hence
|
||||
+ * needs software co-ordination. Use cpufreq affected_cpus
|
||||
+ * interface to handle this scenario. Additional is_smp() check
|
||||
+ * is to keep SMP_ON_UP build working.
|
||||
+ */
|
||||
+ if (is_smp()) {
|
||||
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
|
||||
+ cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
|
||||
+ cpumask_copy(policy->cpus, cpumask);
|
||||
+ }
|
||||
|
||||
/* FIXME: what's the actual transition time? */
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
From 07367b4c3afd8e881c4cf50ef35d081c4ac252b8 Mon Sep 17 00:00:00 2001
|
||||
From: Jarkko Nikula <jhnikula@gmail.com>
|
||||
Date: Thu, 14 Apr 2011 16:21:58 +0300
|
||||
Subject: [PATCH 09/19] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4
|
||||
|
||||
Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly
|
||||
trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available.
|
||||
|
||||
Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 3730f96..a725d90 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -161,7 +161,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
else if (cpu_is_omap34xx())
|
||||
mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
- else if (cpu_is_omap34xx())
|
||||
+ else if (cpu_is_omap44xx())
|
||||
mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
|
||||
if (IS_ERR(mpu_clk))
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
From 4d3e024c2f7f0334874bbb2a168b62e91cb2517a Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 25 May 2011 16:38:46 -0700
|
||||
Subject: [PATCH 10/19] OMAP2+: cpufreq: move clk name decision to init
|
||||
|
||||
Clk name does'nt need to dynamically detected during clk init.
|
||||
move them off to driver initialization, if we dont have a clk name,
|
||||
there is no point in registering the driver anyways. The actual clk
|
||||
get and put is left at cpu_init and exit functions.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 20 +++++++++++++-------
|
||||
1 files changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index a725d90..c46d0cd 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
static struct clk *mpu_clk;
|
||||
+static char *mpu_clk_name;
|
||||
|
||||
static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
{
|
||||
@@ -157,13 +158,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
struct device *mpu_dev;
|
||||
static cpumask_var_t cpumask;
|
||||
|
||||
- if (cpu_is_omap24xx())
|
||||
- mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
- else if (cpu_is_omap34xx())
|
||||
- mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
- else if (cpu_is_omap44xx())
|
||||
- mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
-
|
||||
+ mpu_clk = clk_get(NULL, mpu_clk_name);
|
||||
if (IS_ERR(mpu_clk))
|
||||
return PTR_ERR(mpu_clk);
|
||||
|
||||
@@ -238,6 +233,17 @@ static struct cpufreq_driver omap_driver = {
|
||||
|
||||
static int __init omap_cpufreq_init(void)
|
||||
{
|
||||
+ if (cpu_is_omap24xx())
|
||||
+ mpu_clk_name = "virt_prcm_set";
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk_name = "dpll1_ck";
|
||||
+ else if (cpu_is_omap44xx())
|
||||
+ mpu_clk_name = "dpll_mpu_ck";
|
||||
+
|
||||
+ if (!mpu_clk_name) {
|
||||
+ pr_err("%s: unsupported Silicon?\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
return cpufreq_register_driver(&omap_driver);
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
From 85afa12ad2a6e7a23ddf4b25e78e0ce5b9f18a64 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 25 May 2011 16:38:47 -0700
|
||||
Subject: [PATCH 11/19] OMAP2+: cpufreq: deny initialization if no mpudev
|
||||
|
||||
if we do not have mpu_dev we normally fail in cpu_init. It is better
|
||||
to fail driver registration if the devices are not available.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 15 ++++++++-------
|
||||
1 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index c46d0cd..33a91ec 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -43,6 +43,7 @@
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
static struct clk *mpu_clk;
|
||||
static char *mpu_clk_name;
|
||||
+static struct device *mpu_dev;
|
||||
|
||||
static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
{
|
||||
@@ -155,7 +156,6 @@ skip_lpj:
|
||||
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
- struct device *mpu_dev;
|
||||
static cpumask_var_t cpumask;
|
||||
|
||||
mpu_clk = clk_get(NULL, mpu_clk_name);
|
||||
@@ -166,12 +166,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
- mpu_dev = omap2_get_mpuss_device();
|
||||
-
|
||||
- if (!mpu_dev) {
|
||||
- pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
|
||||
if (freq_table) {
|
||||
@@ -244,6 +238,13 @@ static int __init omap_cpufreq_init(void)
|
||||
pr_err("%s: unsupported Silicon?\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
+
|
||||
+ mpu_dev = omap2_get_mpuss_device();
|
||||
+ if (!mpu_dev) {
|
||||
+ pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
return cpufreq_register_driver(&omap_driver);
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
From 345f93655f425c87ba01e949dc038e04542d8cd4 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:17 -0700
|
||||
Subject: [PATCH 12/19] OMAP2+: cpufreq: dont support !freq_table
|
||||
|
||||
OMAP2+ all have frequency tables, hence the hacks we had for older
|
||||
silicon do not need to be carried forward. As part of this change,
|
||||
use cpufreq_frequency_table_target to find the best match for
|
||||
frequency requested.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 67 +++++++++++++++----------------
|
||||
1 files changed, 33 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 33a91ec..acf18e8 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -38,8 +38,6 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
-#define VERY_HI_RATE 900000000
|
||||
-
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
static struct clk *mpu_clk;
|
||||
static char *mpu_clk_name;
|
||||
@@ -47,20 +45,9 @@ static struct device *mpu_dev;
|
||||
|
||||
static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
{
|
||||
- if (freq_table)
|
||||
- return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
-
|
||||
- if (policy->cpu)
|
||||
+ if (!freq_table)
|
||||
return -EINVAL;
|
||||
-
|
||||
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
- policy->cpuinfo.max_freq);
|
||||
-
|
||||
- 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);
|
||||
- return 0;
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
}
|
||||
|
||||
static unsigned int omap_getspeed(unsigned int cpu)
|
||||
@@ -78,22 +65,35 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
- int i, ret = 0;
|
||||
+ unsigned int i;
|
||||
+ int ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
/* Changes not allowed until all CPUs are online */
|
||||
if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
return ret;
|
||||
|
||||
- /* Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
- if (target_freq < policy->min)
|
||||
- target_freq = policy->min;
|
||||
- if (target_freq > policy->max)
|
||||
- target_freq = policy->max;
|
||||
+ if (!freq_table) {
|
||||
+ dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
|
||||
+ policy->cpu);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
|
||||
+ relation, &i);
|
||||
+ if (ret) {
|
||||
+ dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n",
|
||||
+ __func__, policy->cpu, target_freq, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ freqs.new = freq_table[i].frequency;
|
||||
+ if (!freqs.new) {
|
||||
+ dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__,
|
||||
+ policy->cpu, target_freq);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
freqs.old = omap_getspeed(policy->cpu);
|
||||
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
freqs.cpu = policy->cpu;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
@@ -166,19 +166,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
- opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
-
|
||||
- if (freq_table) {
|
||||
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
- cpufreq_frequency_table_get_attr(freq_table,
|
||||
- policy->cpu);
|
||||
- } else {
|
||||
- policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
- policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
- VERY_HI_RATE) / 1000;
|
||||
+ result = opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ if (result) {
|
||||
+ dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
|
||||
+ __func__, policy->cpu, result);
|
||||
+ return result;
|
||||
}
|
||||
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
|
||||
+
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
policy->cur = omap_getspeed(policy->cpu);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
From 1e5757cbc79685c6294a178d1bea76a52cffcae9 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:18 -0700
|
||||
Subject: [PATCH 13/19] OMAP2+: cpufreq: only supports OPP library
|
||||
|
||||
OMAP2 is the only family using clk_[init|exit]_cpufreq_table, however,
|
||||
the cpufreq code does not currently use clk_init_cpufreq_table. As a
|
||||
result, it is unusuable for OMAP2 and only usable only on platforms
|
||||
using OPP library.
|
||||
|
||||
Remove the unbalanced clk_exit_cpufreq_table(). Any platforms where
|
||||
OPPs are not availble will fail on init because a freq table will not
|
||||
be properly initialized.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
[khilman@ti.com: changelog edits, and graceful failure mode changes]
|
||||
Acked-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 3 +--
|
||||
1 files changed, 1 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index acf18e8..3af7cda 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* OMAP2PLUS cpufreq driver
|
||||
*
|
||||
- * CPU frequency scaling for OMAP
|
||||
+ * CPU frequency scaling for OMAP using OPP information
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation
|
||||
* Written by Tony Lindgren <tony@atomide.com>
|
||||
@@ -203,7 +203,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
- clk_exit_cpufreq_table(&freq_table);
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
From bec0338ead64cdd8515ae4c94462ffbfd6ae6418 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:19 -0700
|
||||
Subject: [PATCH 14/19] OMAP2+: cpufreq: put clk if cpu_init failed
|
||||
|
||||
Release the mpu_clk in fail paths.
|
||||
|
||||
Reported-by: Todd Poynor <toddpoynor@google.com>
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 14 +++++++++++---
|
||||
1 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 3af7cda..e019297 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -162,8 +162,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
if (IS_ERR(mpu_clk))
|
||||
return PTR_ERR(mpu_clk);
|
||||
|
||||
- if (policy->cpu >= NR_CPUS)
|
||||
- return -EINVAL;
|
||||
+ if (policy->cpu >= NR_CPUS) {
|
||||
+ result = -EINVAL;
|
||||
+ goto fail_ck;
|
||||
+ }
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
result = opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
@@ -171,12 +173,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
if (result) {
|
||||
dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
|
||||
__func__, policy->cpu, result);
|
||||
- return result;
|
||||
+ goto fail_ck;
|
||||
}
|
||||
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
if (!result)
|
||||
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
|
||||
+ else
|
||||
+ goto fail_ck;
|
||||
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
@@ -199,6 +203,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
|
||||
return 0;
|
||||
+
|
||||
+fail_ck:
|
||||
+ clk_put(mpu_clk);
|
||||
+ return result;
|
||||
}
|
||||
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
From 0054f5049a4e65a359eca6fa8c6668fb047c9270 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:20 -0700
|
||||
Subject: [PATCH 15/19] OMAP2+: cpufreq: fix freq_table leak
|
||||
|
||||
We use a single frequency table for multiple CPUs. But, with
|
||||
OMAP4, since we have multiple CPUs, the cpu_init call for CPU1
|
||||
causes freq_table previously allocated for CPU0 to be overwritten.
|
||||
In addition, we dont free the table on exit path.
|
||||
|
||||
We solve this by maintaining an atomic type counter to ensure
|
||||
just a single table exists at a given time.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 22 +++++++++++++++++-----
|
||||
1 files changed, 17 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index e019297..a962a31 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <mach/hardware.h>
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
+static atomic_t freq_table_users = ATOMIC_INIT(0);
|
||||
static struct clk *mpu_clk;
|
||||
static char *mpu_clk_name;
|
||||
static struct device *mpu_dev;
|
||||
@@ -153,6 +154,12 @@ skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static inline void freq_table_free(void)
|
||||
+{
|
||||
+ if (atomic_dec_and_test(&freq_table_users))
|
||||
+ opp_free_cpufreq_table(mpu_dev, &freq_table);
|
||||
+}
|
||||
+
|
||||
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
@@ -168,7 +175,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
}
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
- result = opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ if (atomic_inc_return(&freq_table_users) == 1)
|
||||
+ result = opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
|
||||
if (result) {
|
||||
dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
|
||||
@@ -177,10 +186,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
}
|
||||
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
- cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
|
||||
- else
|
||||
- goto fail_ck;
|
||||
+ if (result)
|
||||
+ goto fail_table;
|
||||
+
|
||||
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
|
||||
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
@@ -204,6 +213,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
return 0;
|
||||
|
||||
+fail_table:
|
||||
+ freq_table_free();
|
||||
fail_ck:
|
||||
clk_put(mpu_clk);
|
||||
return result;
|
||||
@@ -211,6 +222,7 @@ fail_ck:
|
||||
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
+ freq_table_free();
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
From 255f1830ab71e130bbdffd84e61fc7a8c3791120 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Fri, 3 Jun 2011 17:46:57 +0530
|
||||
Subject: [PATCH 16/19] OMAP2+: CPUfreq: Remove superfluous check in target() for online CPU's.
|
||||
|
||||
Current OMAP2PLUS CPUfreq tagret() functions returns when all
|
||||
the CPU's are not online. This breaks CPUfreq when secondary CPUs
|
||||
are offlined on SMP system.
|
||||
|
||||
The intention of that check was just avoid CPU frequency change
|
||||
during the window when CPU becomes online but it's cpufreq_init is
|
||||
not done yet. Otherwise it can lead to notifiers being sent on
|
||||
a CPU which is not yet registered to the governor.
|
||||
|
||||
But this race conditions is already managed by the CPUfreq
|
||||
core driver by updating the available cpumask accordingly.
|
||||
|
||||
OMAP CPUFReq driver make use same cpumask for the notifiers
|
||||
so the above problem doesn't exist. In my initial implementation
|
||||
of the OMAP4 CPUFreq driver, I was using 'for_each_online_cpu()'
|
||||
for notifiers which lead me to add that check. Later I fixed
|
||||
the notifies but didn't realise that the check has become
|
||||
redundant then.
|
||||
|
||||
Fix it by removing the superfluous check in target().
|
||||
|
||||
Thanks for Nishant Menon <nm@ti.com> for reporting issue
|
||||
with hot-plug and Kevin Hilman <khilman@ti.com> for his
|
||||
comment on excessive check in target().
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Reported-by: Nishanth Menon <nm@ti.com>
|
||||
Tested-by: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
Tested-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 4 ----
|
||||
1 files changed, 0 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index a962a31..eaefa49 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -70,10 +70,6 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
int ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
- /* Changes not allowed until all CPUs are online */
|
||||
- if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
- return ret;
|
||||
-
|
||||
if (!freq_table) {
|
||||
dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
|
||||
policy->cpu);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
From 3bf92d672cb3ee7c1ec39f1f0fcf6e8dbde2ceb9 Mon Sep 17 00:00:00 2001
|
||||
From: Colin Cross <ccross@google.com>
|
||||
Date: Mon, 6 Jun 2011 21:05:29 -0500
|
||||
Subject: [PATCH 17/19] OMAP2+: cpufreq: notify even with bad boot frequency
|
||||
|
||||
Sometimes, bootloaders starts up with a frequency which is not
|
||||
in the OPP table. At cpu_init, policy->cur contains the frequency
|
||||
we pick at boot. It is possible that system might have fixed
|
||||
it's boot frequency later on as part of power initialization.
|
||||
After this condition, the first call to omap_target results in the
|
||||
following:
|
||||
|
||||
omap_getspeed(actual device frequency) != policy->cur(frequency that
|
||||
cpufreq thinks that the system is at), and it is possible that
|
||||
freqs.old == freqs.new (because the governor requested a scale down).
|
||||
|
||||
We exit without triggering the notifiers in the current code, which
|
||||
does'nt let code which depends on cpufreq_notify_transition to have
|
||||
accurate information as to what the system frequency is.
|
||||
|
||||
Instead, we do a normal transition if policy->cur is wrong, then,
|
||||
freqs.old will be the actual cpu frequency, freqs.new will be the
|
||||
actual new cpu frequency and all required notifiers have the accurate
|
||||
information.
|
||||
|
||||
Acked-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Colin Cross <ccross@google.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index eaefa49..8598928 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -93,7 +93,7 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
freqs.old = omap_getspeed(policy->cpu);
|
||||
freqs.cpu = policy->cpu;
|
||||
|
||||
- if (freqs.old == freqs.new)
|
||||
+ if (freqs.old == freqs.new && policy->cur == freqs.new)
|
||||
return ret;
|
||||
|
||||
if (!is_smp()) {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
From 6e092f78e67d722be6036131df6aa0b8b2fec879 Mon Sep 17 00:00:00 2001
|
||||
From: Todd Poynor <toddpoynor@google.com>
|
||||
Date: Tue, 7 Jun 2011 13:57:52 -0700
|
||||
Subject: [PATCH 18/19] OMAP2+: cpufreq: Enable all CPUs in shared policy mask
|
||||
|
||||
Enable all CPUs in the shared policy in the CPU init callback.
|
||||
Otherwise, the governor CPUFREQ_GOV_START event is invoked with
|
||||
a policy that only includes the first CPU, leaving other CPUs
|
||||
uninitialized by the governor.
|
||||
|
||||
Signed-off-by: Todd Poynor <toddpoynor@google.com>
|
||||
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 4 +---
|
||||
1 files changed, 1 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 8598928..1f3b2e1 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -159,7 +159,6 @@ static inline void freq_table_free(void)
|
||||
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
- static cpumask_var_t cpumask;
|
||||
|
||||
mpu_clk = clk_get(NULL, mpu_clk_name);
|
||||
if (IS_ERR(mpu_clk))
|
||||
@@ -200,8 +199,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
*/
|
||||
if (is_smp()) {
|
||||
policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
|
||||
- cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
|
||||
- cpumask_copy(policy->cpus, cpumask);
|
||||
+ cpumask_setall(policy->cpus);
|
||||
}
|
||||
|
||||
/* FIXME: what's the actual transition time? */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
From e8fa6ffc7822b7c7e81fafb112f3064f31c5c0e3 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Mon, 11 Jul 2011 23:10:04 +0530
|
||||
Subject: [PATCH 19/19] OMAP2+: CPUfreq: update lpj with reference value to avoid progressive error.
|
||||
|
||||
Adjust _both_ the per-cpu loops_per_jiffy and global lpj. Calibrate them
|
||||
with with reference to the initial values to avoid a progressively
|
||||
bigger and bigger error in the value over time.
|
||||
|
||||
While at this, re-use the notifiers for UP/SMP since on
|
||||
UP machine or UP_ON_SMP policy->cpus mask would contain only
|
||||
the boot CPU.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
[santosh.shilimkar@ti.com: re-based against omap cpufreq
|
||||
upstream branch and fixed notifiers]
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 50 ++++++++++++++++--------------
|
||||
1 files changed, 27 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 1f3b2e1..de82e87 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -38,6 +38,16 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
+#ifdef CONFIG_SMP
|
||||
+struct lpj_info {
|
||||
+ unsigned long ref;
|
||||
+ unsigned int freq;
|
||||
+};
|
||||
+
|
||||
+static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
|
||||
+static struct lpj_info global_lpj_ref;
|
||||
+#endif
|
||||
+
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
static atomic_t freq_table_users = ATOMIC_INIT(0);
|
||||
static struct clk *mpu_clk;
|
||||
@@ -96,37 +106,18 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (freqs.old == freqs.new && policy->cur == freqs.new)
|
||||
return ret;
|
||||
|
||||
- if (!is_smp()) {
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
- goto set_freq;
|
||||
- }
|
||||
-
|
||||
/* notifiers */
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
}
|
||||
|
||||
-set_freq:
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
#endif
|
||||
|
||||
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
-
|
||||
- /*
|
||||
- * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
|
||||
- * won't get updated when UP machine cpufreq build with
|
||||
- * CONFIG_SMP enabled. Below code is added only to manage that
|
||||
- * scenario
|
||||
- */
|
||||
freqs.new = omap_getspeed(policy->cpu);
|
||||
- if (!is_smp()) {
|
||||
- loops_per_jiffy =
|
||||
- cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
- goto skip_lpj;
|
||||
- }
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
@@ -134,10 +125,24 @@ set_freq:
|
||||
* cpufreq driver. So, update the per-CPU loops_per_jiffy value
|
||||
* on frequency transition. We need to update all dependent CPUs.
|
||||
*/
|
||||
- for_each_cpu(i, policy->cpus)
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ struct lpj_info *lpj = &per_cpu(lpj_ref, i);
|
||||
+ if (!lpj->freq) {
|
||||
+ lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
|
||||
+ lpj->freq = freqs.old;
|
||||
+ }
|
||||
+
|
||||
per_cpu(cpu_data, i).loops_per_jiffy =
|
||||
- cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy,
|
||||
- freqs.old, freqs.new);
|
||||
+ cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
|
||||
+ }
|
||||
+
|
||||
+ /* And don't forget to adjust the global one */
|
||||
+ if (!global_lpj_ref.freq) {
|
||||
+ global_lpj_ref.ref = loops_per_jiffy;
|
||||
+ global_lpj_ref.freq = freqs.old;
|
||||
+ }
|
||||
+ loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
|
||||
+ freqs.new);
|
||||
#endif
|
||||
|
||||
/* notifiers */
|
||||
@@ -146,7 +151,6 @@ set_freq:
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
||||
-skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
Reference in New Issue
Block a user