summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2011-07-01 16:41:10 +0200
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 15:15:42 +0200
commitca36d68fd19bc9d5a30923b05e68aadb5fef3c62 (patch)
tree7055b93cf6747013967dab45b1b6f3b5b5f0cb23
parenta699c9e3a18ef2bc37e4e55a767f1e0288e64d0b (diff)
ux500: cpufreq: try to fix merge regressions
Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org>
-rw-r--r--arch/arm/mach-ux500/pm/Makefile4
-rw-r--r--arch/arm/mach-ux500/pm/cpufreq-db8500.c109
-rw-r--r--arch/arm/mach-ux500/pm/cpufreq.c149
-rw-r--r--arch/arm/mach-ux500/pm/cpufreq.h12
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c70
5 files changed, 62 insertions, 282 deletions
diff --git a/arch/arm/mach-ux500/pm/Makefile b/arch/arm/mach-ux500/pm/Makefile
index 6b435576560..d297ea7370b 100644
--- a/arch/arm/mach-ux500/pm/Makefile
+++ b/arch/arm/mach-ux500/pm/Makefile
@@ -6,10 +6,6 @@ obj-y := pm.o runtime.o
obj-$(CONFIG_U8500_CPUIDLE) += cpuidle.o timer.o
obj-$(CONFIG_U8500_CPUIDLE_DEBUG) += cpuidle_dbg.o
obj-$(CONFIG_UX500_CONTEXT) += context.o context_arm.o context-db8500.o context-db5500.o
-obj-$(CONFIG_U8500_CPUFREQ) += cpufreq.o
obj-$(CONFIG_UX500_SUSPEND) += suspend.o
obj-$(CONFIG_UX500_SUSPEND_DBG) += suspend_dbg.o
-ifeq ($(CONFIG_UX500_SOC_DB8500), y)
-obj-$(CONFIG_U8500_CPUFREQ) += cpufreq-db8500.o
-endif
diff --git a/arch/arm/mach-ux500/pm/cpufreq-db8500.c b/arch/arm/mach-ux500/pm/cpufreq-db8500.c
deleted file mode 100644
index b51146e00bb..00000000000
--- a/arch/arm/mach-ux500/pm/cpufreq-db8500.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * License Terms: GNU General Public License v2
- */
-
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-
-#include <mach/prcmu.h>
-
-#include "cpufreq.h"
-
-static struct cpufreq_frequency_table freq_table[] = {
- [0] = {
- .index = 0,
- .frequency = 200000,
- },
- [1] = {
- .index = 1,
- .frequency = 300000,
- },
- [2] = {
- .index = 2,
- .frequency = 600000,
- },
- [3] = {
- /* Used for MAX_OPP, if available */
- .index = 3,
- .frequency = CPUFREQ_TABLE_END,
- },
- [4] = {
- .index = 4,
- .frequency = CPUFREQ_TABLE_END,
- },
-};
-
-static enum arm_opp idx2opp[] = {
- ARM_EXTCLK,
- ARM_50_OPP,
- ARM_100_OPP,
- ARM_MAX_OPP
-};
-
-/*
- * Below is a temporary workaround for wlan performance issues
- */
-
-#include <linux/kernel_stat.h>
-#include <linux/workqueue.h>
-#include <linux/cpu.h>
-
-#include <mach/irqs.h>
-
-#define WLAN_PROBE_DELAY 3000 /* 3 seconds */
-#define WLAN_LIMIT (3000/3) /* If we have more than 1000 irqs per second */
-
-static struct delayed_work work_wlan_workaround;
-bool wlan_mode_on;
-
-static void wlan_load(struct work_struct *work)
-{
- int cpu;
- unsigned int num_irqs = 0;
- static unsigned int old_num_irqs = UINT_MAX;
-
- for_each_online_cpu(cpu)
- num_irqs += kstat_irqs_cpu(IRQ_DB8500_SDMMC1, cpu);
-
- if ((num_irqs > old_num_irqs) &&
- (num_irqs - old_num_irqs) > WLAN_LIMIT)
- wlan_mode_on = true;
- else
- wlan_mode_on = false;
-
- old_num_irqs = num_irqs;
-
- schedule_delayed_work_on(0,
- &work_wlan_workaround,
- msecs_to_jiffies(WLAN_PROBE_DELAY));
-}
-
-static int __init u8500_cpufreq_register(void)
-{
- int i = 0;
-
- BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
-
- if (!prcmu_is_u8400()) {
- freq_table[1].frequency = 400000;
- freq_table[2].frequency = 800000;
- if (prcmu_has_arm_maxopp())
- freq_table[3].frequency = 1000000;
- }
-
- INIT_DELAYED_WORK_DEFERRABLE(&work_wlan_workaround,
- wlan_load);
-
- schedule_delayed_work_on(0,
- &work_wlan_workaround,
- msecs_to_jiffies(WLAN_PROBE_DELAY));
-
- pr_info("u8500-cpufreq : Available frequencies:\n");
- while (freq_table[i].frequency != CPUFREQ_TABLE_END)
- pr_info(" %d Mhz\n", freq_table[i++].frequency/1000);
-
- return ux500_cpufreq_register(freq_table, idx2opp);
-}
-device_initcall(u8500_cpufreq_register);
diff --git a/arch/arm/mach-ux500/pm/cpufreq.c b/arch/arm/mach-ux500/pm/cpufreq.c
deleted file mode 100644
index 0c28eb79906..00000000000
--- a/arch/arm/mach-ux500/pm/cpufreq.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics 2009
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- * Author: Sundar Iyer <sundar.iyer@stericsson.com>
- * Author: Martin Persson <martin.persson@stericsson.com>
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include <mach/hardware.h>
-#include <mach/prcmu.h>
-#include <mach/prcmu-regs.h>
-
-static struct cpufreq_frequency_table *freq_table;
-static enum arm_opp *idx2opp;
-
-static struct freq_attr *u8500_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
- return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
-extern bool wlan_mode_on;
-
-static int u8500_cpufreq_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- struct cpufreq_freqs freqs;
- unsigned int idx;
-
- /* scale the target frequency to one of the extremes supported */
- if (target_freq < policy->cpuinfo.min_freq)
- target_freq = policy->cpuinfo.min_freq;
- if (target_freq > policy->cpuinfo.max_freq)
- target_freq = policy->cpuinfo.max_freq;
-
- /* A work around for wlan performance issues */
- if (wlan_mode_on)
- target_freq = policy->cpuinfo.max_freq;
-
- /* Lookup the next frequency */
- if (cpufreq_frequency_table_target
- (policy, freq_table, target_freq, relation, &idx)) {
- return -EINVAL;
- }
-
- freqs.old = policy->cur;
- freqs.new = freq_table[idx].frequency;
- freqs.cpu = policy->cpu;
-
- if (freqs.old == freqs.new)
- return 0;
-
- /* pre-change notification */
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /* request the PRCM unit for opp change */
- if (prcmu_set_arm_opp(idx2opp[idx])) {
- pr_err("u8500-cpufreq: Failed to set OPP level\n");
- return -EINVAL;
- }
-
- /* post change notification */
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return 0;
-}
-
-static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
-{
- int i;
- /* request the prcm to get the current ARM opp */
- for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
- ;
- return freq_table[i].frequency;
-}
-
-static int __cpuinit u8500_cpufreq_init(struct cpufreq_policy *policy)
-{
- int res;
- int i;
-
- /* get policy fields based on the table */
- res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
- if (!res)
- cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
- else {
- pr_err("u8500-cpufreq : Failed to read policy table\n");
- return res;
- }
-
- policy->min = policy->cpuinfo.min_freq;
- policy->max = policy->cpuinfo.max_freq;
- policy->cur = u8500_cpufreq_getspeed(policy->cpu);
-
- for (i = 0; freq_table[i].frequency != policy->cur; i++)
- ;
-
- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
- /*
- * FIXME : Need to take time measurement across the target()
- * function with no/some/all drivers in the notification
- * list.
- */
- policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
-
- /* policy sharing between dual CPUs */
- cpumask_copy(policy->cpus, &cpu_present_map);
-
- policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
-
- return 0;
-}
-
-static struct cpufreq_driver u8500_cpufreq_driver = {
- .flags = CPUFREQ_STICKY,
- .verify = u8500_cpufreq_verify_speed,
- .target = u8500_cpufreq_target,
- .get = u8500_cpufreq_getspeed,
- .init = u8500_cpufreq_init,
- .name = "U8500",
- .attr = u8500_cpufreq_attr,
-};
-
-int __init
-ux500_cpufreq_register(struct cpufreq_frequency_table *table,
- enum arm_opp *idx2opplist)
-{
- freq_table = table;
- idx2opp = idx2opplist;
-
- if (cpu_is_u8500v1() || ux500_is_svp())
- return -ENODEV;
-
- pr_info("cpufreq for u8500 started\n");
- return cpufreq_register_driver(&u8500_cpufreq_driver);
-}
diff --git a/arch/arm/mach-ux500/pm/cpufreq.h b/arch/arm/mach-ux500/pm/cpufreq.h
deleted file mode 100644
index dc8744078f5..00000000000
--- a/arch/arm/mach-ux500/pm/cpufreq.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * License Terms: GNU General Public License v2
- */
-#ifndef __UX500_PM_CPUFREQ_H
-#define __UX500_PM_CPUFREQ_H
-
-extern int ux500_cpufreq_register(struct cpufreq_frequency_table *freq_table,
- enum arm_opp *idx2opp);
-
-#endif
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index d90456a809f..298962fd5ee 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -18,29 +18,72 @@
static struct cpufreq_frequency_table freq_table[] = {
[0] = {
.index = 0,
- .frequency = 300000,
+ .frequency = 200000,
},
[1] = {
.index = 1,
- .frequency = 600000,
+ .frequency = 300000,
},
[2] = {
- /* Used for MAX_OPP, if available */
.index = 2,
- .frequency = CPUFREQ_TABLE_END,
+ .frequency = 600000,
},
[3] = {
+ /* Used for MAX_OPP, if available */
.index = 3,
.frequency = CPUFREQ_TABLE_END,
},
+ [4] = {
+ .index = 4,
+ .frequency = CPUFREQ_TABLE_END,
+ },
};
static enum arm_opp idx2opp[] = {
+ ARM_EXTCLK,
ARM_50_OPP,
ARM_100_OPP,
ARM_MAX_OPP
};
+/*
+ * Below is a temporary workaround for wlan performance issues
+ */
+
+#include <linux/kernel_stat.h>
+#include <linux/workqueue.h>
+#include <linux/cpu.h>
+
+#include <mach/irqs.h>
+
+#define WLAN_PROBE_DELAY 3000 /* 3 seconds */
+#define WLAN_LIMIT (3000/3) /* If we have more than 1000 irqs per second */
+
+static struct delayed_work work_wlan_workaround;
+bool wlan_mode_on;
+
+static void wlan_load(struct work_struct *work)
+{
+ int cpu;
+ unsigned int num_irqs = 0;
+ static unsigned int old_num_irqs = UINT_MAX;
+
+ for_each_online_cpu(cpu)
+ num_irqs += kstat_irqs_cpu(IRQ_DB8500_SDMMC1, cpu);
+
+ if ((num_irqs > old_num_irqs) &&
+ (num_irqs - old_num_irqs) > WLAN_LIMIT)
+ wlan_mode_on = true;
+ else
+ wlan_mode_on = false;
+
+ old_num_irqs = num_irqs;
+
+ schedule_delayed_work_on(0,
+ &work_wlan_workaround,
+ msecs_to_jiffies(WLAN_PROBE_DELAY));
+}
+
static struct freq_attr *db8500_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
@@ -64,6 +107,10 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
if (target_freq > policy->cpuinfo.max_freq)
target_freq = policy->cpuinfo.max_freq;
+ /* A work around for wlan performance issues */
+ if (wlan_mode_on)
+ target_freq = policy->cpuinfo.max_freq;
+
/* Lookup the next frequency */
if (cpufreq_frequency_table_target
(policy, freq_table, target_freq, relation, &idx)) {
@@ -108,13 +155,20 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
- if (cpu_is_u8500v2() && !prcmu_is_u8400()) {
- freq_table[0].frequency = 400000;
- freq_table[1].frequency = 800000;
+ if (!prcmu_is_u8400()) {
+ freq_table[1].frequency = 400000;
+ freq_table[2].frequency = 800000;
if (prcmu_has_arm_maxopp())
- freq_table[2].frequency = 1000000;
+ freq_table[3].frequency = 1000000;
}
+ INIT_DELAYED_WORK_DEFERRABLE(&work_wlan_workaround,
+ wlan_load);
+
+ schedule_delayed_work_on(0,
+ &work_wlan_workaround,
+ msecs_to_jiffies(WLAN_PROBE_DELAY));
+
/* get policy fields based on the table */
res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (!res)