summaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorVincent Guittot <vincent.guittot@stericsson.com>2011-04-11 14:37:04 +0200
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 15:56:12 +0200
commit594d18437bd58f550f82b12d779653b1f18dad23 (patch)
tree7ca43192c1539fbe1d97c2808c28b2b49722b2da /drivers/cpufreq
parent7759be585e6774826da8fb0d12daf7164292fdcc (diff)
ux500: pm: add use-case governor
Signed-off-by: Vincent Guittot <vincent.guittot@stericsson.com> Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> [ANDROID]: ux500: pm: update sysfs interface for usecase governor A separate sysfs node is added fro each use-case. It is now possible to enable multiple use-cases simultaneously. If multiple use-cases are enabled, each configuration (of all enabled uses-caes) is compared and the configuration which is requesting highest performance is selected. Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> [ANDROID]: ux500: pm: usecase-gov Act on interrupts per s If the number of interrupts per seconds are above a certain level, exit from the asked mode. [ANDROID]: ux500: pm: update low-power-audio config in usecse-governor Update low-power-audio configuration to plug-out second cpu. This makes auto, voice-call and low-power-audio configurations to be same. Auto mode is activated by default (without any user space interaction). This makes voice-call and low-power-audio configurations redundant. However, analysis work is still on going for adding other settings that may become part of usecase governor so keeping all configurations in there for now. Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> [ANDROID]: ux500: pm: update usecase governor dependencies in Kconfig [ANDROID]: ARM: ux500: pm: usecase gov depends on PM Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> [ANDROID]: ux500: pm: minor code cleanup in UC governor Signed-off-by: Martin Persson <martin.persson@stericsson.com> [ANDROID] ux500: pm: disable auto mode in usecase governor In absence of auto mode there is no need to schedule work on early suspend so schedule work only when needed. Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> [ANDROID]: pm: force ondemand governor to choose higher frequency In stead of overriding frequency selected by ondemand governor in u8500_cpufreq_target(), force ondemand governor to select higher frequency when wlan and usb workaround is enabled. ANDROID tag is used to keep the patch internal. Otherwise it does not have any Android dependency. Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> [ANDROID]: ARM: u8500: usecaseg: Tiny code clean-up Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> arm: ux500: halve the frequencies of some clocks in vc use case This patch adds a new APE OPP (50% with ACLK and DMACLK frequencies at 25%) which is used during the voice call use case. Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> Signed-off-by: Mattias Nilsson <mattias.i.nilsson@stericsson.com> ux500: pm: Add min cpufreq to UC governor Add a minimum cpu frequency limit to each use case in the use case governor. Signed-off-by: Martin Persson <martin.persson@stericsson.com> ux500: pm: allow usecase governor to force cpu idle states Also update low-power-audio configuration to force ApSleep state. ux500: pm: move use case definitions to a header file ux500: pm: add pl310 prefetch control in use-case governor ux500: pm: cosmetic changes in use-case governor Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c8
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c45
2 files changed, 48 insertions, 5 deletions
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index a5bbbf60ae8..bcef88a89b0 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -390,6 +390,10 @@ static struct attribute_group dbs_attr_group = {
.name = "ondemand",
};
+/*** delete after deprecation time ***/
+extern bool wlan_mode_on;
+extern bool usb_mode_on;
+
/************************** sysfs end ************************/
static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
@@ -494,7 +498,9 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
}
/* Check for frequency increase */
- if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
+ if ((max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) ||
+ /* A work around for wlan and usb performance issues */
+ (usb_mode_on || wlan_mode_on)) {
/* If switching to max speed, apply sampling_down_factor */
if (policy->cur < policy->max)
this_dbs_info->rate_mult =
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 4b863110bd8..629b0b88e6c 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -58,6 +58,10 @@ static enum arm_opp idx2opp[] = {
#define WLAN_PROBE_DELAY 3000 /* 3 seconds */
#define WLAN_LIMIT (3000/3) /* If we have more than 1000 irqs per second */
+#define USB_PROBE_DELAY 1000 /* 1 seconds */
+#define USB_LIMIT (200) /* If we have more than 200 irqs per second */
+static struct delayed_work work_usb_workaround;
+bool usb_mode_on;
static struct delayed_work work_wlan_workaround;
bool wlan_mode_on;
@@ -84,6 +88,40 @@ static void wlan_load(struct work_struct *work)
msecs_to_jiffies(WLAN_PROBE_DELAY));
}
+static void usb_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_USBOTG, cpu);
+
+ if ((num_irqs > old_num_irqs) &&
+ (num_irqs - old_num_irqs) > USB_LIMIT)
+ usb_mode_on = true;
+ else
+ usb_mode_on = false;
+
+ old_num_irqs = num_irqs;
+
+ schedule_delayed_work_on(0,
+ &work_usb_workaround,
+ msecs_to_jiffies(USB_PROBE_DELAY));
+}
+
+void cpufreq_usb_connect_notify(bool connect)
+{
+ if (connect) {
+ schedule_delayed_work_on(0,
+ &work_usb_workaround,
+ msecs_to_jiffies(USB_PROBE_DELAY));
+ } else {
+ cancel_delayed_work_sync(&work_usb_workaround);
+ usb_mode_on = false;
+ }
+}
+
static struct freq_attr *db8500_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
@@ -107,10 +145,6 @@ 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)) {
@@ -169,6 +203,9 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
&work_wlan_workaround,
msecs_to_jiffies(WLAN_PROBE_DELAY));
+ INIT_DELAYED_WORK_DEFERRABLE(&work_usb_workaround,
+ usb_load);
+
pr_info("db8500-cpufreq : Available frequencies:\n");
while (freq_table[i].frequency != CPUFREQ_TABLE_END)
pr_info(" %d Mhz\n", freq_table[i++].frequency/1000);