mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-07-21 03:17:18 +00:00
linux-mainline 3.2: kernel recipe based on mainline 3.2.16 with additional patches for e.g. beagleboard on top
This patchset is managed in https://github.com/beagleboard/kernel/tree/beagleboard-3.2 by Robert Nelson and myself. Tested on beagleboard-xM/Angstrom Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> Signed-off-by: Denys Dmytriyenko <denys@ti.com>
This commit is contained in:
committed by
Denys Dmytriyenko
parent
aff1018e66
commit
4e18d70247
+422
@@ -0,0 +1,422 @@
|
||||
From 9c613a8ca7cebad1d7fa4376b80a82adcdc7269e Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Wed, 11 Aug 2010 17:02:43 -0700
|
||||
Subject: [PATCH 01/11] cpufreq: OMAP: cleanup for multi-SoC support, move
|
||||
into drivers/cpufreq
|
||||
|
||||
Move OMAP cpufreq driver from arch/arm/mach-omap2 into
|
||||
drivers/cpufreq, along with a few cleanups:
|
||||
|
||||
- generalize support for better handling of different SoCs in the OMAP
|
||||
- use OPP layer instead of OMAP clock internals for frequency table init
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
[khilman@ti.com: move to drivers]
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
arch/arm/plat-omap/Makefile | 1 -
|
||||
arch/arm/plat-omap/cpu-omap.c | 171 ------------------------------------
|
||||
drivers/cpufreq/Makefile | 1 +
|
||||
drivers/cpufreq/omap-cpufreq.c | 188 ++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 189 insertions(+), 172 deletions(-)
|
||||
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
|
||||
create mode 100644 drivers/cpufreq/omap-cpufreq.c
|
||||
|
||||
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
|
||||
index 9852622..a53eca3 100644
|
||||
--- a/arch/arm/plat-omap/Makefile
|
||||
+++ b/arch/arm/plat-omap/Makefile
|
||||
@@ -19,7 +19,6 @@ obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
|
||||
|
||||
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.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 da4f68d..0000000
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ /dev/null
|
||||
@@ -1,171 +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
|
||||
- *
|
||||
- * 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 <mach/hardware.h>
|
||||
-#include <plat/clock.h>
|
||||
-#include <asm/system.h>
|
||||
-
|
||||
-#define VERY_HI_RATE 900000000
|
||||
-
|
||||
-static struct cpufreq_frequency_table *freq_table;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
-#define MPU_CLK "mpu"
|
||||
-#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)
|
||||
-{
|
||||
- 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
|
||||
- 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);
|
||||
-
|
||||
- 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);
|
||||
-
|
||||
- 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;
|
||||
- }
|
||||
-
|
||||
- /* 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);
|
||||
-}
|
||||
-
|
||||
-arch_initcall(omap_cpufreq_init);
|
||||
-
|
||||
-/*
|
||||
- * if ever we want to remove this, upon cleanup call:
|
||||
- *
|
||||
- * cpufreq_unregister_driver()
|
||||
- * cpufreq_frequency_table_put_attr()
|
||||
- */
|
||||
-
|
||||
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
|
||||
index a48bc02..ce75fcb 100644
|
||||
--- a/drivers/cpufreq/Makefile
|
||||
+++ b/drivers/cpufreq/Makefile
|
||||
@@ -43,6 +43,7 @@ obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
|
||||
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
|
||||
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
|
||||
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
|
||||
+obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o
|
||||
|
||||
##################################################################################
|
||||
# PowerPC platform drivers
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..a6b2be7
|
||||
--- /dev/null
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -0,0 +1,188 @@
|
||||
+/*
|
||||
+ * 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.
|
||||
+ * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar
|
||||
+ *
|
||||
+ * 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);
|
||||
+
|
||||
+ 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_omap44xx())
|
||||
+ 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 = "omap",
|
||||
+ .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 OMAP SoCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
--
|
||||
1.7.7.4
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
From 87d979c9823e18b22acda61e1ad885d27b123c36 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Wed, 21 Sep 2011 16:53:00 -0700
|
||||
Subject: [PATCH 02/11] cpufreq: OMAP: Add SMP support for OMAP4+
|
||||
|
||||
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.
|
||||
|
||||
Also, 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.
|
||||
|
||||
Based on initial SMP support by Santosh Shilimkar.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
[khilman@ti.com: due to overlap/rework, combined original Santosh patch
|
||||
and Russell's rework]
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 81 +++++++++++++++++++++++++++++++++++-----
|
||||
1 files changed, 71 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index a6b2be7..1953f9d 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -23,9 +23,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>
|
||||
@@ -35,6 +37,16 @@
|
||||
|
||||
#define VERY_HI_RATE 900000000
|
||||
|
||||
+#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 struct clk *mpu_clk;
|
||||
|
||||
@@ -60,7 +72,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;
|
||||
@@ -71,7 +83,7 @@ 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;
|
||||
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
@@ -81,22 +93,57 @@ 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);
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ 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);
|
||||
+ freqs.new = omap_getspeed(policy->cpu);
|
||||
+
|
||||
+#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) {
|
||||
+ 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(lpj->ref, lpj->freq, freqs.new);
|
||||
+ }
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ /* 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 */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -105,6 +152,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");
|
||||
@@ -116,12 +164,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;
|
||||
@@ -141,7 +189,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.7.7.4
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
From ed54323b7c150554e68cb02d90dd36b60fe4e275 Mon Sep 17 00:00:00 2001
|
||||
From: Todd Poynor <toddpoynor@google.com>
|
||||
Date: Tue, 7 Jun 2011 13:57:52 -0700
|
||||
Subject: [PATCH 03/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 4 +---
|
||||
1 files changed, 1 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index 1953f9d..3f5a816 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -152,7 +152,6 @@ 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");
|
||||
@@ -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.7.7.4
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
From 0661a55786b8ee53e388e1608eb56e4661273c6b Mon Sep 17 00:00:00 2001
|
||||
From: Colin Cross <ccross@google.com>
|
||||
Date: Mon, 6 Jun 2011 21:05:29 -0500
|
||||
Subject: [PATCH 04/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index 3f5a816..0a5d95c 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -97,7 +97,7 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
freqs.cpu = policy->cpu;
|
||||
|
||||
- if (freqs.old == freqs.new)
|
||||
+ if (freqs.old == freqs.new && policy->cur == freqs.new)
|
||||
return ret;
|
||||
|
||||
/* notifiers */
|
||||
--
|
||||
1.7.7.4
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
From 37b0a6ccc284854592918359f825371c36a801ab Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 25 May 2011 16:38:46 -0700
|
||||
Subject: [PATCH 05/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 20 +++++++++++++-------
|
||||
1 files changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index 0a5d95c..3651825 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -49,6 +49,7 @@ static struct lpj_info global_lpj_ref;
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -153,13 +154,7 @@ 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_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);
|
||||
|
||||
@@ -233,6 +228,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.7.7.4
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
From 6e85de6b5c1d71d372c23bf1f5c2388b9560f42f Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 25 May 2011 16:38:47 -0700
|
||||
Subject: [PATCH 06/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 15 ++++++++-------
|
||||
1 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index 3651825..dda32fd 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -50,6 +50,7 @@ static struct lpj_info global_lpj_ref;
|
||||
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)
|
||||
{
|
||||
@@ -152,7 +153,6 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
- struct device *mpu_dev;
|
||||
|
||||
mpu_clk = clk_get(NULL, mpu_clk_name);
|
||||
if (IS_ERR(mpu_clk))
|
||||
@@ -162,12 +162,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) {
|
||||
@@ -239,6 +233,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.7.7.4
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
From 01d968ec96c7d6e9ba21a287e2836687be31d669 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:17 -0700
|
||||
Subject: [PATCH 07/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 67 +++++++++++++++++++--------------------
|
||||
1 files changed, 33 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index dda32fd..eecb096 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -35,8 +35,6 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
-#define VERY_HI_RATE 900000000
|
||||
-
|
||||
#ifdef CONFIG_SMP
|
||||
struct lpj_info {
|
||||
unsigned long ref;
|
||||
@@ -54,20 +52,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)
|
||||
@@ -85,18 +72,31 @@ 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;
|
||||
|
||||
- /* 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 && policy->cur == freqs.new)
|
||||
@@ -162,19 +162,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.7.7.4
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
From 508bd6dae63589ea98c38f031e98dcad2fa18976 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:18 -0700
|
||||
Subject: [PATCH 08/11] cpufreq: OMAP: 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]
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 3 +--
|
||||
1 files changed, 1 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index eecb096..8f778b9 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * 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>
|
||||
@@ -198,7 +198,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.7.7.4
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
From 7f37af0e32e0bc99fc7459bfd3a6748c44b7d563 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:19 -0700
|
||||
Subject: [PATCH 09/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 14 +++++++++++---
|
||||
1 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index 8f778b9..8c54192 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -158,8 +158,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);
|
||||
@@ -167,12 +169,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;
|
||||
@@ -194,6 +198,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.7.7.4
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
From eacc1163972fc46357883d58adab8b2d237c2598 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 26 May 2011 19:39:20 -0700
|
||||
Subject: [PATCH 10/11] cpufreq: OMAP: 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: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 22 +++++++++++++++++-----
|
||||
1 files changed, 17 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index 8c54192..ad94b4f 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -46,6 +46,7 @@ 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;
|
||||
static char *mpu_clk_name;
|
||||
static struct device *mpu_dev;
|
||||
@@ -150,6 +151,12 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
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;
|
||||
@@ -164,7 +171,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",
|
||||
@@ -173,10 +182,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;
|
||||
@@ -199,6 +208,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;
|
||||
@@ -206,6 +217,7 @@ fail_ck:
|
||||
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
+ freq_table_free();
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.7.7.4
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
From 492ddcd5eb9b88526903716293342b312595292a Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@ti.com>
|
||||
Date: Fri, 30 Sep 2011 10:41:26 -0700
|
||||
Subject: [PATCH 11/11] cpufreq: OMAP: fixup for omap_device changes, include
|
||||
<linux/module.h>
|
||||
|
||||
Minor fixups to work starting with v3.2:
|
||||
- use the new omap_device API for getting a device by name.
|
||||
- need to include <linux/module.h>
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
---
|
||||
drivers/cpufreq/omap-cpufreq.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
|
||||
index ad94b4f..5d04c57 100644
|
||||
--- a/drivers/cpufreq/omap-cpufreq.c
|
||||
+++ b/drivers/cpufreq/omap-cpufreq.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/opp.h>
|
||||
#include <linux/cpu.h>
|
||||
+#include <linux/module.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/smp_plat.h>
|
||||
@@ -32,6 +33,7 @@
|
||||
#include <plat/clock.h>
|
||||
#include <plat/omap-pm.h>
|
||||
#include <plat/common.h>
|
||||
+#include <plat/omap_device.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
@@ -252,7 +254,7 @@ static int __init omap_cpufreq_init(void)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- mpu_dev = omap2_get_mpuss_device();
|
||||
+ mpu_dev = omap_device_get_by_hwmod_name("mpu");
|
||||
if (!mpu_dev) {
|
||||
pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
return -EINVAL;
|
||||
--
|
||||
1.7.7.4
|
||||
|
||||
Reference in New Issue
Block a user