diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-07-01 16:41:10 +0200 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 12:16:57 +0200 |
commit | a60dd09403b6289b760fa39dcf5318c9fad80654 (patch) | |
tree | f9a1f37757ba5a54fa39db94509390e0d9a4a010 | |
parent | 7d767f007ad2f15d669a54533d79391e11964c39 (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/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpufreq-db8500.c | 109 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpufreq.c | 149 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpufreq.h | 12 | ||||
-rw-r--r-- | drivers/cpufreq/db8500-cpufreq.c | 70 |
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) |