diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-2.6.39/pm')
34 files changed, 3447 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch new file mode 100644 index 00000000..9e9a8a0b --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | From 38dd5aadc86725f6018d23679e9daa60ca0a8319 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Thu, 12 May 2011 07:59:52 -0500 | ||
| 4 | Subject: [PATCH 1/6] OMAP2+: cpufreq: free up table on exit | ||
| 5 | |||
| 6 | freq_table allocated by opp_init_cpufreq_table in omap_cpu_init | ||
| 7 | needs to be freed in omap_cpu_exit. | ||
| 8 | |||
| 9 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 3 +++ | ||
| 13 | 1 files changed, 3 insertions(+), 0 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 16 | index d53ce23..e38ebb8 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 18 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 19 | @@ -26,6 +26,7 @@ | ||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | #include <linux/opp.h> | ||
| 23 | +#include <linux/slab.h> | ||
| 24 | #include <linux/cpu.h> | ||
| 25 | |||
| 26 | #include <asm/system.h> | ||
| 27 | @@ -216,6 +217,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 28 | static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
| 29 | { | ||
| 30 | clk_exit_cpufreq_table(&freq_table); | ||
| 31 | + kfree(freq_table); | ||
| 32 | + freq_table = NULL; | ||
| 33 | clk_put(mpu_clk); | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | -- | ||
| 37 | 1.6.6.1 | ||
| 38 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch new file mode 100644 index 00000000..087724d1 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | From 5febdc0482e545c2a598f035c5e03931e0c3c808 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Thu, 12 May 2011 08:14:41 -0500 | ||
| 4 | Subject: [PATCH 2/6] OMAP2+: cpufreq: handle invalid cpufreq table | ||
| 5 | |||
| 6 | Handle the case when cpufreq_frequency_table_cpuinfo fails. freq_table | ||
| 7 | that we passed failed the internal test of cpufreq generic driver, | ||
| 8 | so we should'nt be using the freq_table as such. Instead, warn and | ||
| 9 | fallback to clock functions for validation and operation. | ||
| 10 | |||
| 11 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 12 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 13 | --- | ||
| 14 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 12 ++++++++++-- | ||
| 15 | 1 files changed, 10 insertions(+), 2 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 18 | index e38ebb8..6e3666a 100644 | ||
| 19 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 20 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 21 | @@ -182,10 +182,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 22 | |||
| 23 | if (freq_table) { | ||
| 24 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 25 | - if (!result) | ||
| 26 | + if (!result) { | ||
| 27 | cpufreq_frequency_table_get_attr(freq_table, | ||
| 28 | policy->cpu); | ||
| 29 | - } else { | ||
| 30 | + } else { | ||
| 31 | + WARN(true, "%s: fallback to clk_round(freq_table=%d)\n", | ||
| 32 | + __func__, result); | ||
| 33 | + kfree(freq_table); | ||
| 34 | + freq_table = NULL; | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + if (!freq_table) { | ||
| 39 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
| 40 | policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
| 41 | VERY_HI_RATE) / 1000; | ||
| 42 | -- | ||
| 43 | 1.6.6.1 | ||
| 44 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch new file mode 100644 index 00000000..4f4cdb14 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | From aef7e862873e6125159a18d22a2e37b1fbab2153 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Thu, 12 May 2011 16:27:45 -0700 | ||
| 4 | Subject: [PATCH 3/6] OMAP2+: cpufreq: minor comment cleanup | ||
| 5 | |||
| 6 | this should probably get squashed in.. | ||
| 7 | |||
| 8 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 9 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 10 | --- | ||
| 11 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 6 ++++-- | ||
| 12 | 1 files changed, 4 insertions(+), 2 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 15 | index 6e3666a..45f1e9e 100644 | ||
| 16 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 17 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 18 | @@ -84,8 +84,10 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 19 | if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
| 20 | return ret; | ||
| 21 | |||
| 22 | - /* Ensure desired rate is within allowed range. Some govenors | ||
| 23 | - * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
| 24 | + /* | ||
| 25 | + * Ensure desired rate is within allowed range. Some govenors | ||
| 26 | + * (ondemand) will just pass target_freq=0 to get the minimum. | ||
| 27 | + */ | ||
| 28 | if (target_freq < policy->min) | ||
| 29 | target_freq = policy->min; | ||
| 30 | if (target_freq > policy->max) | ||
| 31 | -- | ||
| 32 | 1.6.6.1 | ||
| 33 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch new file mode 100644 index 00000000..dd23c082 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | From f231980dbd0f05229f2020e59b7242872576416f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Fri, 13 May 2011 05:34:35 -0700 | ||
| 4 | Subject: [PATCH 4/6] OMAP2: cpufreq: use clk_init_cpufreq_table if OPPs not available | ||
| 5 | |||
| 6 | OMAP2 does not use OPP tables at the moment for DVFS. Currently, | ||
| 7 | we depend on opp table initialization to give us the freq_table, | ||
| 8 | which makes sense for OMAP3+. for OMAP2, we should be using | ||
| 9 | clk_init_cpufreq_table - so if the opp based frequency table | ||
| 10 | initilization fails, fall back to clk_init_cpufreq_table to give | ||
| 11 | us the table. | ||
| 12 | |||
| 13 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 14 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 15 | --- | ||
| 16 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 9 ++++++++- | ||
| 17 | 1 files changed, 8 insertions(+), 1 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 20 | index 45f1e9e..854f4b3 100644 | ||
| 21 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 22 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 23 | @@ -180,7 +180,13 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 24 | pr_warning("%s: unable to get the mpu device\n", __func__); | ||
| 25 | return -EINVAL; | ||
| 26 | } | ||
| 27 | - opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
| 28 | + | ||
| 29 | + /* | ||
| 30 | + * if we dont get cpufreq table using opp, use traditional omap2 lookup | ||
| 31 | + * as a fallback | ||
| 32 | + */ | ||
| 33 | + if (opp_init_cpufreq_table(mpu_dev, &freq_table)) | ||
| 34 | + clk_init_cpufreq_table(&freq_table); | ||
| 35 | |||
| 36 | if (freq_table) { | ||
| 37 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 38 | @@ -188,6 +194,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 39 | cpufreq_frequency_table_get_attr(freq_table, | ||
| 40 | policy->cpu); | ||
| 41 | } else { | ||
| 42 | + clk_exit_cpufreq_table(&freq_table); | ||
| 43 | WARN(true, "%s: fallback to clk_round(freq_table=%d)\n", | ||
| 44 | __func__, result); | ||
| 45 | kfree(freq_table); | ||
| 46 | -- | ||
| 47 | 1.6.6.1 | ||
| 48 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch new file mode 100644 index 00000000..504d1916 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | From 272d76bcb22b9509ccc1b59d3a62e3930d902d17 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Fri, 13 May 2011 05:43:49 -0700 | ||
| 4 | Subject: [PATCH 5/6] OMAP2+: cpufreq: use cpufreq_frequency_table_target | ||
| 5 | |||
| 6 | Use cpufreq_frequency_table_target for finding the proper target | ||
| 7 | instead of seeing if the frequency requested is divisible alone. | ||
| 8 | if we have a frequency table, we should restrict ourselves to | ||
| 9 | selecting the "approved" frequencies alone and only in the case | ||
| 10 | where the frequency table is not available should we attempt at | ||
| 11 | closest roundable clock frequency. | ||
| 12 | |||
| 13 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 14 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 15 | --- | ||
| 16 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 38 ++++++++++++++++++++++-------- | ||
| 17 | 1 files changed, 28 insertions(+), 10 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 20 | index 854f4b3..d0b4f97 100644 | ||
| 21 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 22 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 23 | @@ -77,24 +77,42 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 24 | unsigned int target_freq, | ||
| 25 | unsigned int relation) | ||
| 26 | { | ||
| 27 | - int i, ret = 0; | ||
| 28 | + unsigned int i; | ||
| 29 | + int ret = 0; | ||
| 30 | struct cpufreq_freqs freqs; | ||
| 31 | |||
| 32 | /* Changes not allowed until all CPUs are online */ | ||
| 33 | if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
| 34 | return ret; | ||
| 35 | |||
| 36 | - /* | ||
| 37 | - * Ensure desired rate is within allowed range. Some govenors | ||
| 38 | - * (ondemand) will just pass target_freq=0 to get the minimum. | ||
| 39 | - */ | ||
| 40 | - if (target_freq < policy->min) | ||
| 41 | - target_freq = policy->min; | ||
| 42 | - if (target_freq > policy->max) | ||
| 43 | - target_freq = policy->max; | ||
| 44 | + if (freq_table) { | ||
| 45 | + ret = cpufreq_frequency_table_target(policy, freq_table, | ||
| 46 | + target_freq, relation, &i); | ||
| 47 | + if (ret) { | ||
| 48 | + pr_debug("%s: cpu%d: no freq match for %d(ret=%d)\n", | ||
| 49 | + __func__, policy->cpu, target_freq, ret); | ||
| 50 | + return ret; | ||
| 51 | + } | ||
| 52 | + freqs.new = freq_table[i].frequency; | ||
| 53 | + } else { | ||
| 54 | + /* | ||
| 55 | + * Ensure desired rate is within allowed range. Some govenors | ||
| 56 | + * (ondemand) will just pass target_freq=0 to get the minimum. | ||
| 57 | + */ | ||
| 58 | + if (target_freq < policy->min) | ||
| 59 | + target_freq = policy->min; | ||
| 60 | + if (target_freq > policy->max) | ||
| 61 | + target_freq = policy->max; | ||
| 62 | + | ||
| 63 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 64 | + } | ||
| 65 | + if (!freqs.new) { | ||
| 66 | + pr_err("%s: cpu%d: no match for freq %d\n", __func__, | ||
| 67 | + policy->cpu, target_freq); | ||
| 68 | + return -EINVAL; | ||
| 69 | + } | ||
| 70 | |||
| 71 | freqs.old = omap_getspeed(policy->cpu); | ||
| 72 | - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 73 | freqs.cpu = policy->cpu; | ||
| 74 | |||
| 75 | if (freqs.old == freqs.new) | ||
| 76 | -- | ||
| 77 | 1.6.6.1 | ||
| 78 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch new file mode 100644 index 00000000..0cb4c91f --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | From 42a384af80e07534913d9002ec8d9caf5d4d305c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Wed, 18 May 2011 01:48:23 -0500 | ||
| 4 | Subject: [PATCH 6/6] OMAP2+: cpufreq: fix freq_table leak | ||
| 5 | |||
| 6 | Since we have two cpus the cpuinit call for cpu1 causes | ||
| 7 | freq_table of cpu0 to be overwritten. instead, we maintain | ||
| 8 | a counter to keep track of cpus who use the cpufreq table | ||
| 9 | allocate it once(one freq table for all CPUs) and free them | ||
| 10 | once the last user is done with it. | ||
| 11 | |||
| 12 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 13 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 14 | --- | ||
| 15 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 33 ++++++++++++++++++++++++------ | ||
| 16 | 1 files changed, 26 insertions(+), 7 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 19 | index d0b4f97..fc3d0fb 100644 | ||
| 20 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 21 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 22 | @@ -42,6 +42,9 @@ | ||
| 23 | #define VERY_HI_RATE 900000000 | ||
| 24 | |||
| 25 | static struct cpufreq_frequency_table *freq_table; | ||
| 26 | +static int freq_table_users; | ||
| 27 | +static DEFINE_MUTEX(freq_table_lock); | ||
| 28 | + | ||
| 29 | static struct clk *mpu_clk; | ||
| 30 | |||
| 31 | static int omap_verify_speed(struct cpufreq_policy *policy) | ||
| 32 | @@ -172,6 +175,18 @@ skip_lpj: | ||
| 33 | return ret; | ||
| 34 | } | ||
| 35 | |||
| 36 | +static void freq_table_free(void) | ||
| 37 | +{ | ||
| 38 | + if (!freq_table_users) | ||
| 39 | + return; | ||
| 40 | + freq_table_users--; | ||
| 41 | + if (freq_table_users) | ||
| 42 | + return; | ||
| 43 | + clk_exit_cpufreq_table(&freq_table); | ||
| 44 | + kfree(freq_table); | ||
| 45 | + freq_table = NULL; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 49 | { | ||
| 50 | int result = 0; | ||
| 51 | @@ -199,14 +214,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 52 | return -EINVAL; | ||
| 53 | } | ||
| 54 | |||
| 55 | + mutex_lock(&freq_table_lock); | ||
| 56 | /* | ||
| 57 | * if we dont get cpufreq table using opp, use traditional omap2 lookup | ||
| 58 | * as a fallback | ||
| 59 | */ | ||
| 60 | - if (opp_init_cpufreq_table(mpu_dev, &freq_table)) | ||
| 61 | - clk_init_cpufreq_table(&freq_table); | ||
| 62 | + if (!freq_table) { | ||
| 63 | + if (opp_init_cpufreq_table(mpu_dev, &freq_table)) | ||
| 64 | + clk_init_cpufreq_table(&freq_table); | ||
| 65 | + } | ||
| 66 | |||
| 67 | if (freq_table) { | ||
| 68 | + freq_table_users++; | ||
| 69 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 70 | if (!result) { | ||
| 71 | cpufreq_frequency_table_get_attr(freq_table, | ||
| 72 | @@ -215,10 +234,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 73 | clk_exit_cpufreq_table(&freq_table); | ||
| 74 | WARN(true, "%s: fallback to clk_round(freq_table=%d)\n", | ||
| 75 | __func__, result); | ||
| 76 | - kfree(freq_table); | ||
| 77 | - freq_table = NULL; | ||
| 78 | + freq_table_free(); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | + mutex_unlock(&freq_table_lock); | ||
| 82 | |||
| 83 | if (!freq_table) { | ||
| 84 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
| 85 | @@ -251,9 +270,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 86 | |||
| 87 | static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
| 88 | { | ||
| 89 | - clk_exit_cpufreq_table(&freq_table); | ||
| 90 | - kfree(freq_table); | ||
| 91 | - freq_table = NULL; | ||
| 92 | + mutex_lock(&freq_table_lock); | ||
| 93 | + freq_table_free(); | ||
| 94 | + mutex_unlock(&freq_table_lock); | ||
| 95 | clk_put(mpu_clk); | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | -- | ||
| 99 | 1.6.6.1 | ||
| 100 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch new file mode 100644 index 00000000..576cd08f --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | From 8726f3a7218b72a1003904a24bb000b3e4f9b4d1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Mike Turquette <mturquette@ti.com> | ||
| 3 | Date: Tue, 17 May 2011 09:35:54 -0500 | ||
| 4 | Subject: [PATCH 1/2] cpufreq: helpers for walking the frequency table | ||
| 5 | |||
| 6 | Two new functions for getting the next higher and next lower frequencies | ||
| 7 | in the cpufreq table, based upon a frequency supplied in kHz. | ||
| 8 | |||
| 9 | This is useful for cpufreq governors that do not target frequencies | ||
| 10 | based upon a percentage or a pre-determined value, but instead access | ||
| 11 | the cpufreq table directly. | ||
| 12 | |||
| 13 | Signed-off-by: Mike Turquette <mturquette@ti.com> | ||
| 14 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 15 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 16 | --- | ||
| 17 | drivers/cpufreq/freq_table.c | 73 ++++++++++++++++++++++++++++++++++++++++++ | ||
| 18 | include/linux/cpufreq.h | 9 +++++ | ||
| 19 | 2 files changed, 82 insertions(+), 0 deletions(-) | ||
| 20 | |||
| 21 | diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c | ||
| 22 | index 0543221..11a307b 100644 | ||
| 23 | --- a/drivers/cpufreq/freq_table.c | ||
| 24 | +++ b/drivers/cpufreq/freq_table.c | ||
| 25 | @@ -13,6 +13,7 @@ | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/cpufreq.h> | ||
| 29 | +#include <linux/err.h> | ||
| 30 | |||
| 31 | #define dprintk(msg...) \ | ||
| 32 | cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg) | ||
| 33 | @@ -174,6 +175,78 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, | ||
| 34 | } | ||
| 35 | EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); | ||
| 36 | |||
| 37 | +int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy, | ||
| 38 | + struct cpufreq_frequency_table *table, int *index) | ||
| 39 | +{ | ||
| 40 | + unsigned int cur_freq; | ||
| 41 | + unsigned int next_lowest_freq; | ||
| 42 | + int optimal_index = -1; | ||
| 43 | + int i = 0; | ||
| 44 | + | ||
| 45 | + if (!policy || IS_ERR(policy) || !table || IS_ERR(table) || | ||
| 46 | + !index || IS_ERR(index)) | ||
| 47 | + return -ENOMEM; | ||
| 48 | + | ||
| 49 | + cur_freq = policy->cur; | ||
| 50 | + next_lowest_freq = policy->min; | ||
| 51 | + | ||
| 52 | + /* we're at the lowest frequency in the table already, bail out */ | ||
| 53 | + if (cur_freq == policy->min) | ||
| 54 | + return -EINVAL; | ||
| 55 | + | ||
| 56 | + /* walk the list, find closest freq to cur_freq that is below it */ | ||
| 57 | + while(table[i].frequency != CPUFREQ_TABLE_END) { | ||
| 58 | + if (table[i].frequency < cur_freq && | ||
| 59 | + table[i].frequency >= next_lowest_freq) { | ||
| 60 | + next_lowest_freq = table[i].frequency; | ||
| 61 | + optimal_index = table[i].index; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + i++; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + *index = optimal_index; | ||
| 68 | + | ||
| 69 | + return 0; | ||
| 70 | +} | ||
| 71 | +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_lowest); | ||
| 72 | + | ||
| 73 | +int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy, | ||
| 74 | + struct cpufreq_frequency_table *table, int *index) | ||
| 75 | +{ | ||
| 76 | + unsigned int cur_freq; | ||
| 77 | + unsigned int next_higher_freq; | ||
| 78 | + int optimal_index = -1; | ||
| 79 | + int i = 0; | ||
| 80 | + | ||
| 81 | + if (!policy || IS_ERR(policy) || !table || IS_ERR(table) || | ||
| 82 | + !index || IS_ERR(index)) | ||
| 83 | + return -ENOMEM; | ||
| 84 | + | ||
| 85 | + cur_freq = policy->cur; | ||
| 86 | + next_higher_freq = policy->max; | ||
| 87 | + | ||
| 88 | + /* we're at the highest frequency in the table already, bail out */ | ||
| 89 | + if (cur_freq == policy->max) | ||
| 90 | + return -EINVAL; | ||
| 91 | + | ||
| 92 | + /* walk the list, find closest freq to cur_freq that is above it */ | ||
| 93 | + while(table[i].frequency != CPUFREQ_TABLE_END) { | ||
| 94 | + if (table[i].frequency > cur_freq && | ||
| 95 | + table[i].frequency <= next_higher_freq) { | ||
| 96 | + next_higher_freq = table[i].frequency; | ||
| 97 | + optimal_index = table[i].index; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + i++; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + *index = optimal_index; | ||
| 104 | + | ||
| 105 | + return 0; | ||
| 106 | +} | ||
| 107 | +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_highest); | ||
| 108 | + | ||
| 109 | static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); | ||
| 110 | /** | ||
| 111 | * show_available_freqs - show available frequencies for the specified CPU | ||
| 112 | diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h | ||
| 113 | index 9343dd3..a38fca8 100644 | ||
| 114 | --- a/include/linux/cpufreq.h | ||
| 115 | +++ b/include/linux/cpufreq.h | ||
| 116 | @@ -396,6 +396,15 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, | ||
| 117 | |||
| 118 | void cpufreq_frequency_table_put_attr(unsigned int cpu); | ||
| 119 | |||
| 120 | +/* the following are for use in governors, or anywhere else */ | ||
| 121 | +extern int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy, | ||
| 122 | + struct cpufreq_frequency_table *table, | ||
| 123 | + int *index); | ||
| 124 | + | ||
| 125 | +extern int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy, | ||
| 126 | + struct cpufreq_frequency_table *table, | ||
| 127 | + int *index); | ||
| 128 | + | ||
| 129 | |||
| 130 | /********************************************************************* | ||
| 131 | * UNIFIED DEBUG HELPERS * | ||
| 132 | -- | ||
| 133 | 1.6.6.1 | ||
| 134 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch new file mode 100644 index 00000000..731906cc --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch | |||
| @@ -0,0 +1,879 @@ | |||
| 1 | From e4c777d8314d7925e4895f00b3a7ebd64a4d830b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Mike Turquette <mturquette@ti.com> | ||
| 3 | Date: Tue, 17 May 2011 09:43:09 -0500 | ||
| 4 | Subject: [PATCH 2/2] cpufreq: introduce hotplug governor | ||
| 5 | |||
| 6 | The "hotplug" governor scales CPU frequency based on load, similar to | ||
| 7 | "ondemand". It scales up to the highest frequency when "up_threshold" | ||
| 8 | is crossed and scales down one frequency at a time when "down_threshold" | ||
| 9 | is crossed. Unlike those governors, target frequencies are determined | ||
| 10 | by directly accessing the CPUfreq frequency table, instead of taking | ||
| 11 | some percentage of maximum available frequency. | ||
| 12 | |||
| 13 | The key difference in the "hotplug" governor is that it will disable | ||
| 14 | auxillary CPUs when the system is very idle, and enable them again once | ||
| 15 | the system becomes busy. This is achieved by averaging load over | ||
| 16 | multiple sampling periods; if CPUs were online or offlined based on a | ||
| 17 | single sampling period then thrashing will occur. | ||
| 18 | |||
| 19 | Sysfs entries exist for "hotplug_in_sampling_periods" and for | ||
| 20 | "hotplug_out_sampling_periods" which determine how many consecutive | ||
| 21 | periods get averaged to determine if auxillery CPUs should be onlined or | ||
| 22 | offlined. Defaults are 5 periods and 20 periods respectively. | ||
| 23 | Otherwise the standard sysfs entries you might find for "ondemand" and | ||
| 24 | "conservative" governors are there. | ||
| 25 | |||
| 26 | To use this governor it is assumed that your CPUfreq driver has | ||
| 27 | populated the CPUfreq table, CONFIG_NO_HZ is enabled and | ||
| 28 | CONFIG_HOTPLUG_CPU is enabled. | ||
| 29 | |||
| 30 | Changes in V2: | ||
| 31 | Corrected default sampling periods | ||
| 32 | Optimized load history array resizing | ||
| 33 | Maintain load history when resizing array | ||
| 34 | Add locking to dbs_check_cpu | ||
| 35 | Switch from enable_nonboot_cpus to cpu_up | ||
| 36 | Switch from disable_nonboot_cpus to down_cpu | ||
| 37 | Fix some printks | ||
| 38 | Coding style around for-loops | ||
| 39 | |||
| 40 | Signed-off-by: Mike Turquette <mturquette@ti.com> | ||
| 41 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 42 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 43 | --- | ||
| 44 | Documentation/cpu-freq/governors.txt | 28 ++ | ||
| 45 | drivers/cpufreq/Kconfig | 33 ++ | ||
| 46 | drivers/cpufreq/Makefile | 1 + | ||
| 47 | drivers/cpufreq/cpufreq_hotplug.c | 705 ++++++++++++++++++++++++++++++++++ | ||
| 48 | include/linux/cpufreq.h | 3 + | ||
| 49 | 5 files changed, 770 insertions(+), 0 deletions(-) | ||
| 50 | create mode 100644 drivers/cpufreq/cpufreq_hotplug.c | ||
| 51 | |||
| 52 | diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt | ||
| 53 | index e74d0a2..c2e3d3d 100644 | ||
| 54 | --- a/Documentation/cpu-freq/governors.txt | ||
| 55 | +++ b/Documentation/cpu-freq/governors.txt | ||
| 56 | @@ -193,6 +193,34 @@ governor but for the opposite direction. For example when set to its | ||
| 57 | default value of '20' it means that if the CPU usage needs to be below | ||
| 58 | 20% between samples to have the frequency decreased. | ||
| 59 | |||
| 60 | + | ||
| 61 | +2.6 Hotplug | ||
| 62 | +----------- | ||
| 63 | + | ||
| 64 | +The CPUfreq governor "hotplug" operates similary to "ondemand" and | ||
| 65 | +"conservative". It's decisions are based primarily on CPU load. Like | ||
| 66 | +"ondemand" the "hotplug" governor will ramp up to the highest frequency | ||
| 67 | +once the run-time tunable "up_threshold" parameter is crossed. Like | ||
| 68 | +"conservative", the "hotplug" governor exports a "down_threshold" | ||
| 69 | +parameter that is also tunable at run-time. When the "down_threshold" | ||
| 70 | +is crossed the CPU transitions to the next lowest frequency in the | ||
| 71 | +CPUfreq frequency table instead of decrementing the frequency based on a | ||
| 72 | +percentage of maximum load. | ||
| 73 | + | ||
| 74 | +The main reason "hotplug" governor exists is for architectures requiring | ||
| 75 | +that only the master CPU be online in order to hit low-power states | ||
| 76 | +(C-states). OMAP4 is one such example of this. The "hotplug" governor | ||
| 77 | +is also helpful in reducing thermal output in devices with tight thermal | ||
| 78 | +constraints. | ||
| 79 | + | ||
| 80 | +Auxillary CPUs are onlined/offline based on CPU load, but the decision | ||
| 81 | +to do so is made after averaging several sampling windows. This is to | ||
| 82 | +reduce CPU hotplug "thrashing", which can be caused by normal system | ||
| 83 | +entropy and leads to lots of spurious plug-in and plug-out transitions. | ||
| 84 | +The number of sampling periods averaged together is tunable via the | ||
| 85 | +"hotplug_in_sampling_periods" and "hotplug_out_sampling_periods" | ||
| 86 | +run-time tunable parameters. | ||
| 87 | + | ||
| 88 | 3. The Governor Interface in the CPUfreq Core | ||
| 89 | ============================================= | ||
| 90 | |||
| 91 | diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig | ||
| 92 | index ca8ee80..c716a0e 100644 | ||
| 93 | --- a/drivers/cpufreq/Kconfig | ||
| 94 | +++ b/drivers/cpufreq/Kconfig | ||
| 95 | @@ -110,6 +110,19 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE | ||
| 96 | Be aware that not all cpufreq drivers support the conservative | ||
| 97 | governor. If unsure have a look at the help section of the | ||
| 98 | driver. Fallback governor will be the performance governor. | ||
| 99 | + | ||
| 100 | +config CPU_FREQ_DEFAULT_GOV_HOTPLUG | ||
| 101 | + bool "hotplug" | ||
| 102 | + select CPU_FREQ_GOV_HOTPLUG | ||
| 103 | + select CPU_FREQ_GOV_PERFORMANCE | ||
| 104 | + help | ||
| 105 | + Use the CPUFreq governor 'hotplug' as default. This allows you | ||
| 106 | + to get a full dynamic frequency capable system with CPU | ||
| 107 | + hotplug support by simply loading your cpufreq low-level | ||
| 108 | + hardware driver. Be aware that not all cpufreq drivers | ||
| 109 | + support the hotplug governor. If unsure have a look at | ||
| 110 | + the help section of the driver. Fallback governor will be the | ||
| 111 | + performance governor. | ||
| 112 | endchoice | ||
| 113 | |||
| 114 | config CPU_FREQ_GOV_PERFORMANCE | ||
| 115 | @@ -190,4 +203,24 @@ config CPU_FREQ_GOV_CONSERVATIVE | ||
| 116 | |||
| 117 | If in doubt, say N. | ||
| 118 | |||
| 119 | +config CPU_FREQ_GOV_HOTPLUG | ||
| 120 | + tristate "'hotplug' cpufreq governor" | ||
| 121 | + depends on CPU_FREQ && NO_HZ && HOTPLUG_CPU | ||
| 122 | + help | ||
| 123 | + 'hotplug' - this driver mimics the frequency scaling behavior | ||
| 124 | + in 'ondemand', but with several key differences. First is | ||
| 125 | + that frequency transitions use the CPUFreq table directly, | ||
| 126 | + instead of incrementing in a percentage of the maximum | ||
| 127 | + available frequency. Second 'hotplug' will offline auxillary | ||
| 128 | + CPUs when the system is idle, and online those CPUs once the | ||
| 129 | + system becomes busy again. This last feature is needed for | ||
| 130 | + architectures which transition to low power states when only | ||
| 131 | + the "master" CPU is online, or for thermally constrained | ||
| 132 | + devices. | ||
| 133 | + | ||
| 134 | + If you don't have one of these architectures or devices, use | ||
| 135 | + 'ondemand' instead. | ||
| 136 | + | ||
| 137 | + If in doubt, say N. | ||
| 138 | + | ||
| 139 | endif # CPU_FREQ | ||
| 140 | diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile | ||
| 141 | index 71fc3b4..05d564c 100644 | ||
| 142 | --- a/drivers/cpufreq/Makefile | ||
| 143 | +++ b/drivers/cpufreq/Makefile | ||
| 144 | @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o | ||
| 145 | obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o | ||
| 146 | obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o | ||
| 147 | obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o | ||
| 148 | +obj-$(CONFIG_CPU_FREQ_GOV_HOTPLUG) += cpufreq_hotplug.o | ||
| 149 | |||
| 150 | # CPUfreq cross-arch helpers | ||
| 151 | obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o | ||
| 152 | diff --git a/drivers/cpufreq/cpufreq_hotplug.c b/drivers/cpufreq/cpufreq_hotplug.c | ||
| 153 | new file mode 100644 | ||
| 154 | index 0000000..85aa6d2 | ||
| 155 | --- /dev/null | ||
| 156 | +++ b/drivers/cpufreq/cpufreq_hotplug.c | ||
| 157 | @@ -0,0 +1,705 @@ | ||
| 158 | +/* | ||
| 159 | + * CPUFreq hotplug governor | ||
| 160 | + * | ||
| 161 | + * Copyright (C) 2010 Texas Instruments, Inc. | ||
| 162 | + * Mike Turquette <mturquette@ti.com> | ||
| 163 | + * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 164 | + * | ||
| 165 | + * Based on ondemand governor | ||
| 166 | + * Copyright (C) 2001 Russell King | ||
| 167 | + * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>, | ||
| 168 | + * Jun Nakajima <jun.nakajima@intel.com> | ||
| 169 | + * | ||
| 170 | + * This program is free software; you can redistribute it and/or modify | ||
| 171 | + * it under the terms of the GNU General Public License version 2 as | ||
| 172 | + * published by the Free Software Foundation. | ||
| 173 | + */ | ||
| 174 | + | ||
| 175 | +#include <linux/kernel.h> | ||
| 176 | +#include <linux/module.h> | ||
| 177 | +#include <linux/init.h> | ||
| 178 | +#include <linux/cpufreq.h> | ||
| 179 | +#include <linux/cpu.h> | ||
| 180 | +#include <linux/jiffies.h> | ||
| 181 | +#include <linux/kernel_stat.h> | ||
| 182 | +#include <linux/mutex.h> | ||
| 183 | +#include <linux/hrtimer.h> | ||
| 184 | +#include <linux/tick.h> | ||
| 185 | +#include <linux/ktime.h> | ||
| 186 | +#include <linux/sched.h> | ||
| 187 | +#include <linux/err.h> | ||
| 188 | +#include <linux/slab.h> | ||
| 189 | + | ||
| 190 | +/* greater than 80% avg load across online CPUs increases frequency */ | ||
| 191 | +#define DEFAULT_UP_FREQ_MIN_LOAD (80) | ||
| 192 | + | ||
| 193 | +/* less than 20% avg load across online CPUs decreases frequency */ | ||
| 194 | +#define DEFAULT_DOWN_FREQ_MAX_LOAD (20) | ||
| 195 | + | ||
| 196 | +/* default sampling period (uSec) is bogus; 10x ondemand's default for x86 */ | ||
| 197 | +#define DEFAULT_SAMPLING_PERIOD (100000) | ||
| 198 | + | ||
| 199 | +/* default number of sampling periods to average before hotplug-in decision */ | ||
| 200 | +#define DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS (5) | ||
| 201 | + | ||
| 202 | +/* default number of sampling periods to average before hotplug-out decision */ | ||
| 203 | +#define DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS (20) | ||
| 204 | + | ||
| 205 | +static void do_dbs_timer(struct work_struct *work); | ||
| 206 | +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | ||
| 207 | + unsigned int event); | ||
| 208 | + | ||
| 209 | +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG | ||
| 210 | +static | ||
| 211 | +#endif | ||
| 212 | +struct cpufreq_governor cpufreq_gov_hotplug = { | ||
| 213 | + .name = "hotplug", | ||
| 214 | + .governor = cpufreq_governor_dbs, | ||
| 215 | + .owner = THIS_MODULE, | ||
| 216 | +}; | ||
| 217 | + | ||
| 218 | +struct cpu_dbs_info_s { | ||
| 219 | + cputime64_t prev_cpu_idle; | ||
| 220 | + cputime64_t prev_cpu_wall; | ||
| 221 | + cputime64_t prev_cpu_nice; | ||
| 222 | + struct cpufreq_policy *cur_policy; | ||
| 223 | + struct delayed_work work; | ||
| 224 | + struct cpufreq_frequency_table *freq_table; | ||
| 225 | + int cpu; | ||
| 226 | + /* | ||
| 227 | + * percpu mutex that serializes governor limit change with | ||
| 228 | + * do_dbs_timer invocation. We do not want do_dbs_timer to run | ||
| 229 | + * when user is changing the governor or limits. | ||
| 230 | + */ | ||
| 231 | + struct mutex timer_mutex; | ||
| 232 | +}; | ||
| 233 | +static DEFINE_PER_CPU(struct cpu_dbs_info_s, hp_cpu_dbs_info); | ||
| 234 | + | ||
| 235 | +static unsigned int dbs_enable; /* number of CPUs using this policy */ | ||
| 236 | + | ||
| 237 | +/* | ||
| 238 | + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on | ||
| 239 | + * different CPUs. It protects dbs_enable in governor start/stop. | ||
| 240 | + */ | ||
| 241 | +static DEFINE_MUTEX(dbs_mutex); | ||
| 242 | + | ||
| 243 | +static struct workqueue_struct *khotplug_wq; | ||
| 244 | + | ||
| 245 | +static struct dbs_tuners { | ||
| 246 | + unsigned int sampling_rate; | ||
| 247 | + unsigned int up_threshold; | ||
| 248 | + unsigned int down_threshold; | ||
| 249 | + unsigned int hotplug_in_sampling_periods; | ||
| 250 | + unsigned int hotplug_out_sampling_periods; | ||
| 251 | + unsigned int hotplug_load_index; | ||
| 252 | + unsigned int *hotplug_load_history; | ||
| 253 | + unsigned int ignore_nice; | ||
| 254 | + unsigned int io_is_busy; | ||
| 255 | +} dbs_tuners_ins = { | ||
| 256 | + .sampling_rate = DEFAULT_SAMPLING_PERIOD, | ||
| 257 | + .up_threshold = DEFAULT_UP_FREQ_MIN_LOAD, | ||
| 258 | + .down_threshold = DEFAULT_DOWN_FREQ_MAX_LOAD, | ||
| 259 | + .hotplug_in_sampling_periods = DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS, | ||
| 260 | + .hotplug_out_sampling_periods = DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS, | ||
| 261 | + .hotplug_load_index = 0, | ||
| 262 | + .ignore_nice = 0, | ||
| 263 | + .io_is_busy = 0, | ||
| 264 | +}; | ||
| 265 | + | ||
| 266 | +/* | ||
| 267 | + * A corner case exists when switching io_is_busy at run-time: comparing idle | ||
| 268 | + * times from a non-io_is_busy period to an io_is_busy period (or vice-versa) | ||
| 269 | + * will misrepresent the actual change in system idleness. We ignore this | ||
| 270 | + * corner case: enabling io_is_busy might cause freq increase and disabling | ||
| 271 | + * might cause freq decrease, which probably matches the original intent. | ||
| 272 | + */ | ||
| 273 | +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | ||
| 274 | +{ | ||
| 275 | + u64 idle_time; | ||
| 276 | + u64 iowait_time; | ||
| 277 | + | ||
| 278 | + /* cpufreq-hotplug always assumes CONFIG_NO_HZ */ | ||
| 279 | + idle_time = get_cpu_idle_time_us(cpu, wall); | ||
| 280 | + | ||
| 281 | + /* add time spent doing I/O to idle time */ | ||
| 282 | + if (dbs_tuners_ins.io_is_busy) { | ||
| 283 | + iowait_time = get_cpu_iowait_time_us(cpu, wall); | ||
| 284 | + /* cpufreq-hotplug always assumes CONFIG_NO_HZ */ | ||
| 285 | + if (iowait_time != -1ULL && idle_time >= iowait_time) | ||
| 286 | + idle_time -= iowait_time; | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + return idle_time; | ||
| 290 | +} | ||
| 291 | + | ||
| 292 | +/************************** sysfs interface ************************/ | ||
| 293 | + | ||
| 294 | +/* XXX look at global sysfs macros in cpufreq.h, can those be used here? */ | ||
| 295 | + | ||
| 296 | +/* cpufreq_hotplug Governor Tunables */ | ||
| 297 | +#define show_one(file_name, object) \ | ||
| 298 | +static ssize_t show_##file_name \ | ||
| 299 | +(struct kobject *kobj, struct attribute *attr, char *buf) \ | ||
| 300 | +{ \ | ||
| 301 | + return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ | ||
| 302 | +} | ||
| 303 | +show_one(sampling_rate, sampling_rate); | ||
| 304 | +show_one(up_threshold, up_threshold); | ||
| 305 | +show_one(down_threshold, down_threshold); | ||
| 306 | +show_one(hotplug_in_sampling_periods, hotplug_in_sampling_periods); | ||
| 307 | +show_one(hotplug_out_sampling_periods, hotplug_out_sampling_periods); | ||
| 308 | +show_one(ignore_nice_load, ignore_nice); | ||
| 309 | +show_one(io_is_busy, io_is_busy); | ||
| 310 | + | ||
| 311 | +static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, | ||
| 312 | + const char *buf, size_t count) | ||
| 313 | +{ | ||
| 314 | + unsigned int input; | ||
| 315 | + int ret; | ||
| 316 | + ret = sscanf(buf, "%u", &input); | ||
| 317 | + if (ret != 1) | ||
| 318 | + return -EINVAL; | ||
| 319 | + | ||
| 320 | + mutex_lock(&dbs_mutex); | ||
| 321 | + dbs_tuners_ins.sampling_rate = input; | ||
| 322 | + mutex_unlock(&dbs_mutex); | ||
| 323 | + | ||
| 324 | + return count; | ||
| 325 | +} | ||
| 326 | + | ||
| 327 | +static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, | ||
| 328 | + const char *buf, size_t count) | ||
| 329 | +{ | ||
| 330 | + unsigned int input; | ||
| 331 | + int ret; | ||
| 332 | + ret = sscanf(buf, "%u", &input); | ||
| 333 | + | ||
| 334 | + if (ret != 1 || input <= dbs_tuners_ins.down_threshold) { | ||
| 335 | + return -EINVAL; | ||
| 336 | + } | ||
| 337 | + | ||
| 338 | + mutex_lock(&dbs_mutex); | ||
| 339 | + dbs_tuners_ins.up_threshold = input; | ||
| 340 | + mutex_unlock(&dbs_mutex); | ||
| 341 | + | ||
| 342 | + return count; | ||
| 343 | +} | ||
| 344 | + | ||
| 345 | +static ssize_t store_down_threshold(struct kobject *a, struct attribute *b, | ||
| 346 | + const char *buf, size_t count) | ||
| 347 | +{ | ||
| 348 | + unsigned int input; | ||
| 349 | + int ret; | ||
| 350 | + ret = sscanf(buf, "%u", &input); | ||
| 351 | + | ||
| 352 | + if (ret != 1 || input >= dbs_tuners_ins.up_threshold) { | ||
| 353 | + return -EINVAL; | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + mutex_lock(&dbs_mutex); | ||
| 357 | + dbs_tuners_ins.down_threshold = input; | ||
| 358 | + mutex_unlock(&dbs_mutex); | ||
| 359 | + | ||
| 360 | + return count; | ||
| 361 | +} | ||
| 362 | + | ||
| 363 | +static ssize_t store_hotplug_in_sampling_periods(struct kobject *a, | ||
| 364 | + struct attribute *b, const char *buf, size_t count) | ||
| 365 | +{ | ||
| 366 | + unsigned int input; | ||
| 367 | + unsigned int *temp; | ||
| 368 | + unsigned int max_windows; | ||
| 369 | + int ret; | ||
| 370 | + ret = sscanf(buf, "%u", &input); | ||
| 371 | + | ||
| 372 | + if (ret != 1) | ||
| 373 | + return -EINVAL; | ||
| 374 | + | ||
| 375 | + /* already using this value, bail out */ | ||
| 376 | + if (input == dbs_tuners_ins.hotplug_in_sampling_periods) | ||
| 377 | + return count; | ||
| 378 | + | ||
| 379 | + mutex_lock(&dbs_mutex); | ||
| 380 | + ret = count; | ||
| 381 | + max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods, | ||
| 382 | + dbs_tuners_ins.hotplug_out_sampling_periods); | ||
| 383 | + | ||
| 384 | + /* no need to resize array */ | ||
| 385 | + if (input <= max_windows) { | ||
| 386 | + dbs_tuners_ins.hotplug_in_sampling_periods = input; | ||
| 387 | + goto out; | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + /* resize array */ | ||
| 391 | + temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL); | ||
| 392 | + | ||
| 393 | + if (!temp || IS_ERR(temp)) { | ||
| 394 | + ret = -ENOMEM; | ||
| 395 | + goto out; | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + memcpy(temp, dbs_tuners_ins.hotplug_load_history, | ||
| 399 | + (max_windows * sizeof(unsigned int))); | ||
| 400 | + kfree(dbs_tuners_ins.hotplug_load_history); | ||
| 401 | + | ||
| 402 | + /* replace old buffer, old number of sampling periods & old index */ | ||
| 403 | + dbs_tuners_ins.hotplug_load_history = temp; | ||
| 404 | + dbs_tuners_ins.hotplug_in_sampling_periods = input; | ||
| 405 | + dbs_tuners_ins.hotplug_load_index = max_windows; | ||
| 406 | +out: | ||
| 407 | + mutex_unlock(&dbs_mutex); | ||
| 408 | + | ||
| 409 | + return ret; | ||
| 410 | +} | ||
| 411 | + | ||
| 412 | +static ssize_t store_hotplug_out_sampling_periods(struct kobject *a, | ||
| 413 | + struct attribute *b, const char *buf, size_t count) | ||
| 414 | +{ | ||
| 415 | + unsigned int input; | ||
| 416 | + unsigned int *temp; | ||
| 417 | + unsigned int max_windows; | ||
| 418 | + int ret; | ||
| 419 | + ret = sscanf(buf, "%u", &input); | ||
| 420 | + | ||
| 421 | + if (ret != 1) | ||
| 422 | + return -EINVAL; | ||
| 423 | + | ||
| 424 | + /* already using this value, bail out */ | ||
| 425 | + if (input == dbs_tuners_ins.hotplug_out_sampling_periods) | ||
| 426 | + return count; | ||
| 427 | + | ||
| 428 | + mutex_lock(&dbs_mutex); | ||
| 429 | + ret = count; | ||
| 430 | + max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods, | ||
| 431 | + dbs_tuners_ins.hotplug_out_sampling_periods); | ||
| 432 | + | ||
| 433 | + /* no need to resize array */ | ||
| 434 | + if (input <= max_windows) { | ||
| 435 | + dbs_tuners_ins.hotplug_out_sampling_periods = input; | ||
| 436 | + goto out; | ||
| 437 | + } | ||
| 438 | + | ||
| 439 | + /* resize array */ | ||
| 440 | + temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL); | ||
| 441 | + | ||
| 442 | + if (!temp || IS_ERR(temp)) { | ||
| 443 | + ret = -ENOMEM; | ||
| 444 | + goto out; | ||
| 445 | + } | ||
| 446 | + | ||
| 447 | + memcpy(temp, dbs_tuners_ins.hotplug_load_history, | ||
| 448 | + (max_windows * sizeof(unsigned int))); | ||
| 449 | + kfree(dbs_tuners_ins.hotplug_load_history); | ||
| 450 | + | ||
| 451 | + /* replace old buffer, old number of sampling periods & old index */ | ||
| 452 | + dbs_tuners_ins.hotplug_load_history = temp; | ||
| 453 | + dbs_tuners_ins.hotplug_out_sampling_periods = input; | ||
| 454 | + dbs_tuners_ins.hotplug_load_index = max_windows; | ||
| 455 | +out: | ||
| 456 | + mutex_unlock(&dbs_mutex); | ||
| 457 | + | ||
| 458 | + return ret; | ||
| 459 | +} | ||
| 460 | + | ||
| 461 | +static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, | ||
| 462 | + const char *buf, size_t count) | ||
| 463 | +{ | ||
| 464 | + unsigned int input; | ||
| 465 | + int ret; | ||
| 466 | + | ||
| 467 | + unsigned int j; | ||
| 468 | + | ||
| 469 | + ret = sscanf(buf, "%u", &input); | ||
| 470 | + if (ret != 1) | ||
| 471 | + return -EINVAL; | ||
| 472 | + | ||
| 473 | + if (input > 1) | ||
| 474 | + input = 1; | ||
| 475 | + | ||
| 476 | + mutex_lock(&dbs_mutex); | ||
| 477 | + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ | ||
| 478 | + mutex_unlock(&dbs_mutex); | ||
| 479 | + return count; | ||
| 480 | + } | ||
| 481 | + dbs_tuners_ins.ignore_nice = input; | ||
| 482 | + | ||
| 483 | + /* we need to re-evaluate prev_cpu_idle */ | ||
| 484 | + for_each_online_cpu(j) { | ||
| 485 | + struct cpu_dbs_info_s *dbs_info; | ||
| 486 | + dbs_info = &per_cpu(hp_cpu_dbs_info, j); | ||
| 487 | + dbs_info->prev_cpu_idle = get_cpu_idle_time(j, | ||
| 488 | + &dbs_info->prev_cpu_wall); | ||
| 489 | + if (dbs_tuners_ins.ignore_nice) | ||
| 490 | + dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice; | ||
| 491 | + | ||
| 492 | + } | ||
| 493 | + mutex_unlock(&dbs_mutex); | ||
| 494 | + | ||
| 495 | + return count; | ||
| 496 | +} | ||
| 497 | + | ||
| 498 | +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, | ||
| 499 | + const char *buf, size_t count) | ||
| 500 | +{ | ||
| 501 | + unsigned int input; | ||
| 502 | + int ret; | ||
| 503 | + | ||
| 504 | + ret = sscanf(buf, "%u", &input); | ||
| 505 | + if (ret != 1) | ||
| 506 | + return -EINVAL; | ||
| 507 | + | ||
| 508 | + mutex_lock(&dbs_mutex); | ||
| 509 | + dbs_tuners_ins.io_is_busy = !!input; | ||
| 510 | + mutex_unlock(&dbs_mutex); | ||
| 511 | + | ||
| 512 | + return count; | ||
| 513 | +} | ||
| 514 | + | ||
| 515 | +define_one_global_rw(sampling_rate); | ||
| 516 | +define_one_global_rw(up_threshold); | ||
| 517 | +define_one_global_rw(down_threshold); | ||
| 518 | +define_one_global_rw(hotplug_in_sampling_periods); | ||
| 519 | +define_one_global_rw(hotplug_out_sampling_periods); | ||
| 520 | +define_one_global_rw(ignore_nice_load); | ||
| 521 | +define_one_global_rw(io_is_busy); | ||
| 522 | + | ||
| 523 | +static struct attribute *dbs_attributes[] = { | ||
| 524 | + &sampling_rate.attr, | ||
| 525 | + &up_threshold.attr, | ||
| 526 | + &down_threshold.attr, | ||
| 527 | + &hotplug_in_sampling_periods.attr, | ||
| 528 | + &hotplug_out_sampling_periods.attr, | ||
| 529 | + &ignore_nice_load.attr, | ||
| 530 | + &io_is_busy.attr, | ||
| 531 | + NULL | ||
| 532 | +}; | ||
| 533 | + | ||
| 534 | +static struct attribute_group dbs_attr_group = { | ||
| 535 | + .attrs = dbs_attributes, | ||
| 536 | + .name = "hotplug", | ||
| 537 | +}; | ||
| 538 | + | ||
| 539 | +/************************** sysfs end ************************/ | ||
| 540 | + | ||
| 541 | +static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | ||
| 542 | +{ | ||
| 543 | + /* combined load of all enabled CPUs */ | ||
| 544 | + unsigned int total_load = 0; | ||
| 545 | + /* single largest CPU load */ | ||
| 546 | + unsigned int max_load = 0; | ||
| 547 | + /* average load across all enabled CPUs */ | ||
| 548 | + unsigned int avg_load = 0; | ||
| 549 | + /* average load across multiple sampling periods for hotplug events */ | ||
| 550 | + unsigned int hotplug_in_avg_load = 0; | ||
| 551 | + unsigned int hotplug_out_avg_load = 0; | ||
| 552 | + /* number of sampling periods averaged for hotplug decisions */ | ||
| 553 | + unsigned int periods; | ||
| 554 | + | ||
| 555 | + struct cpufreq_policy *policy; | ||
| 556 | + unsigned int index = 0; | ||
| 557 | + unsigned int i, j; | ||
| 558 | + | ||
| 559 | + policy = this_dbs_info->cur_policy; | ||
| 560 | + | ||
| 561 | + /* | ||
| 562 | + * cpu load accounting | ||
| 563 | + * get highest load, total load and average load across all CPUs | ||
| 564 | + */ | ||
| 565 | + for_each_cpu(j, policy->cpus) { | ||
| 566 | + unsigned int load; | ||
| 567 | + unsigned int idle_time, wall_time; | ||
| 568 | + cputime64_t cur_wall_time, cur_idle_time; | ||
| 569 | + struct cpu_dbs_info_s *j_dbs_info; | ||
| 570 | + | ||
| 571 | + j_dbs_info = &per_cpu(hp_cpu_dbs_info, j); | ||
| 572 | + | ||
| 573 | + /* update both cur_idle_time and cur_wall_time */ | ||
| 574 | + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); | ||
| 575 | + | ||
| 576 | + /* how much wall time has passed since last iteration? */ | ||
| 577 | + wall_time = (unsigned int) cputime64_sub(cur_wall_time, | ||
| 578 | + j_dbs_info->prev_cpu_wall); | ||
| 579 | + j_dbs_info->prev_cpu_wall = cur_wall_time; | ||
| 580 | + | ||
| 581 | + /* how much idle time has passed since last iteration? */ | ||
| 582 | + idle_time = (unsigned int) cputime64_sub(cur_idle_time, | ||
| 583 | + j_dbs_info->prev_cpu_idle); | ||
| 584 | + j_dbs_info->prev_cpu_idle = cur_idle_time; | ||
| 585 | + | ||
| 586 | + if (unlikely(!wall_time || wall_time < idle_time)) | ||
| 587 | + continue; | ||
| 588 | + | ||
| 589 | + /* load is the percentage of time not spent in idle */ | ||
| 590 | + load = 100 * (wall_time - idle_time) / wall_time; | ||
| 591 | + | ||
| 592 | + /* keep track of combined load across all CPUs */ | ||
| 593 | + total_load += load; | ||
| 594 | + | ||
| 595 | + /* keep track of highest single load across all CPUs */ | ||
| 596 | + if (load > max_load) | ||
| 597 | + max_load = load; | ||
| 598 | + } | ||
| 599 | + | ||
| 600 | + /* calculate the average load across all related CPUs */ | ||
| 601 | + avg_load = total_load / num_online_cpus(); | ||
| 602 | + | ||
| 603 | + | ||
| 604 | + /* | ||
| 605 | + * hotplug load accounting | ||
| 606 | + * average load over multiple sampling periods | ||
| 607 | + */ | ||
| 608 | + | ||
| 609 | + /* how many sampling periods do we use for hotplug decisions? */ | ||
| 610 | + periods = max(dbs_tuners_ins.hotplug_in_sampling_periods, | ||
| 611 | + dbs_tuners_ins.hotplug_out_sampling_periods); | ||
| 612 | + | ||
| 613 | + /* store avg_load in the circular buffer */ | ||
| 614 | + dbs_tuners_ins.hotplug_load_history[dbs_tuners_ins.hotplug_load_index] | ||
| 615 | + = avg_load; | ||
| 616 | + | ||
| 617 | + /* compute average load across in & out sampling periods */ | ||
| 618 | + for (i = 0, j = dbs_tuners_ins.hotplug_load_index; | ||
| 619 | + i < periods; i++, j--) { | ||
| 620 | + if (i < dbs_tuners_ins.hotplug_in_sampling_periods) | ||
| 621 | + hotplug_in_avg_load += | ||
| 622 | + dbs_tuners_ins.hotplug_load_history[j]; | ||
| 623 | + if (i < dbs_tuners_ins.hotplug_out_sampling_periods) | ||
| 624 | + hotplug_out_avg_load += | ||
| 625 | + dbs_tuners_ins.hotplug_load_history[j]; | ||
| 626 | + | ||
| 627 | + if (j == 0) | ||
| 628 | + j = periods; | ||
| 629 | + } | ||
| 630 | + | ||
| 631 | + hotplug_in_avg_load = hotplug_in_avg_load / | ||
| 632 | + dbs_tuners_ins.hotplug_in_sampling_periods; | ||
| 633 | + | ||
| 634 | + hotplug_out_avg_load = hotplug_out_avg_load / | ||
| 635 | + dbs_tuners_ins.hotplug_out_sampling_periods; | ||
| 636 | + | ||
| 637 | + /* return to first element if we're at the circular buffer's end */ | ||
| 638 | + if (++dbs_tuners_ins.hotplug_load_index == periods) | ||
| 639 | + dbs_tuners_ins.hotplug_load_index = 0; | ||
| 640 | + | ||
| 641 | + /* check for frequency increase */ | ||
| 642 | + if (avg_load > dbs_tuners_ins.up_threshold) { | ||
| 643 | + /* should we enable auxillary CPUs? */ | ||
| 644 | + if (num_online_cpus() < 2 && hotplug_in_avg_load > | ||
| 645 | + dbs_tuners_ins.up_threshold) { | ||
| 646 | + /* hotplug with cpufreq is nasty | ||
| 647 | + * a call to cpufreq_governor_dbs may cause a lockup. | ||
| 648 | + * wq is not running here so its safe. | ||
| 649 | + */ | ||
| 650 | + mutex_unlock(&this_dbs_info->timer_mutex); | ||
| 651 | + cpu_up(1); | ||
| 652 | + mutex_lock(&this_dbs_info->timer_mutex); | ||
| 653 | + goto out; | ||
| 654 | + } | ||
| 655 | + | ||
| 656 | + /* increase to highest frequency supported */ | ||
| 657 | + if (policy->cur < policy->max) | ||
| 658 | + __cpufreq_driver_target(policy, policy->max, | ||
| 659 | + CPUFREQ_RELATION_H); | ||
| 660 | + | ||
| 661 | + goto out; | ||
| 662 | + } | ||
| 663 | + | ||
| 664 | + /* check for frequency decrease */ | ||
| 665 | + if (avg_load < dbs_tuners_ins.down_threshold) { | ||
| 666 | + /* are we at the minimum frequency already? */ | ||
| 667 | + if (policy->cur == policy->min) { | ||
| 668 | + /* should we disable auxillary CPUs? */ | ||
| 669 | + if (num_online_cpus() > 1 && hotplug_out_avg_load < | ||
| 670 | + dbs_tuners_ins.down_threshold) { | ||
| 671 | + mutex_unlock(&this_dbs_info->timer_mutex); | ||
| 672 | + cpu_down(1); | ||
| 673 | + mutex_lock(&this_dbs_info->timer_mutex); | ||
| 674 | + } | ||
| 675 | + goto out; | ||
| 676 | + } | ||
| 677 | + | ||
| 678 | + /* bump down to the next lowest frequency in the table */ | ||
| 679 | + if (cpufreq_frequency_table_next_lowest(policy, | ||
| 680 | + this_dbs_info->freq_table, &index)) { | ||
| 681 | + pr_err("%s: failed to get next lowest frequency\n", | ||
| 682 | + __func__); | ||
| 683 | + goto out; | ||
| 684 | + } | ||
| 685 | + | ||
| 686 | + __cpufreq_driver_target(policy, | ||
| 687 | + this_dbs_info->freq_table[index].frequency, | ||
| 688 | + CPUFREQ_RELATION_L); | ||
| 689 | + } | ||
| 690 | +out: | ||
| 691 | + return; | ||
| 692 | +} | ||
| 693 | + | ||
| 694 | +static void do_dbs_timer(struct work_struct *work) | ||
| 695 | +{ | ||
| 696 | + struct cpu_dbs_info_s *dbs_info = | ||
| 697 | + container_of(work, struct cpu_dbs_info_s, work.work); | ||
| 698 | + unsigned int cpu = dbs_info->cpu; | ||
| 699 | + | ||
| 700 | + /* We want all related CPUs to do sampling nearly on same jiffy */ | ||
| 701 | + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
| 702 | + | ||
| 703 | + mutex_lock(&dbs_info->timer_mutex); | ||
| 704 | + dbs_check_cpu(dbs_info); | ||
| 705 | + queue_delayed_work_on(cpu, khotplug_wq, &dbs_info->work, delay); | ||
| 706 | + mutex_unlock(&dbs_info->timer_mutex); | ||
| 707 | +} | ||
| 708 | + | ||
| 709 | +static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | ||
| 710 | +{ | ||
| 711 | + /* We want all related CPUs to do sampling nearly on same jiffy */ | ||
| 712 | + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
| 713 | + delay -= jiffies % delay; | ||
| 714 | + | ||
| 715 | + INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); | ||
| 716 | + queue_delayed_work_on(dbs_info->cpu, khotplug_wq, &dbs_info->work, | ||
| 717 | + delay); | ||
| 718 | +} | ||
| 719 | + | ||
| 720 | +static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | ||
| 721 | +{ | ||
| 722 | + cancel_delayed_work_sync(&dbs_info->work); | ||
| 723 | +} | ||
| 724 | + | ||
| 725 | +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | ||
| 726 | + unsigned int event) | ||
| 727 | +{ | ||
| 728 | + unsigned int cpu = policy->cpu; | ||
| 729 | + struct cpu_dbs_info_s *this_dbs_info; | ||
| 730 | + unsigned int i, j, max_periods; | ||
| 731 | + int rc; | ||
| 732 | + | ||
| 733 | + this_dbs_info = &per_cpu(hp_cpu_dbs_info, cpu); | ||
| 734 | + | ||
| 735 | + switch (event) { | ||
| 736 | + case CPUFREQ_GOV_START: | ||
| 737 | + if ((!cpu_online(cpu)) || (!policy->cur)) | ||
| 738 | + return -EINVAL; | ||
| 739 | + | ||
| 740 | + mutex_lock(&dbs_mutex); | ||
| 741 | + dbs_enable++; | ||
| 742 | + for_each_cpu(j, policy->cpus) { | ||
| 743 | + struct cpu_dbs_info_s *j_dbs_info; | ||
| 744 | + j_dbs_info = &per_cpu(hp_cpu_dbs_info, j); | ||
| 745 | + j_dbs_info->cur_policy = policy; | ||
| 746 | + | ||
| 747 | + j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, | ||
| 748 | + &j_dbs_info->prev_cpu_wall); | ||
| 749 | + if (dbs_tuners_ins.ignore_nice) { | ||
| 750 | + j_dbs_info->prev_cpu_nice = | ||
| 751 | + kstat_cpu(j).cpustat.nice; | ||
| 752 | + } | ||
| 753 | + | ||
| 754 | + max_periods = max(DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS, | ||
| 755 | + DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS); | ||
| 756 | + dbs_tuners_ins.hotplug_load_history = kmalloc( | ||
| 757 | + (sizeof(unsigned int) * max_periods), | ||
| 758 | + GFP_KERNEL); | ||
| 759 | + if (!dbs_tuners_ins.hotplug_load_history) { | ||
| 760 | + WARN_ON(1); | ||
| 761 | + return -ENOMEM; | ||
| 762 | + } | ||
| 763 | + for (i = 0; i < max_periods; i++) | ||
| 764 | + dbs_tuners_ins.hotplug_load_history[i] = 50; | ||
| 765 | + } | ||
| 766 | + this_dbs_info->cpu = cpu; | ||
| 767 | + this_dbs_info->freq_table = cpufreq_frequency_get_table(cpu); | ||
| 768 | + /* | ||
| 769 | + * Start the timerschedule work, when this governor | ||
| 770 | + * is used for first time | ||
| 771 | + */ | ||
| 772 | + if (dbs_enable == 1) { | ||
| 773 | + rc = sysfs_create_group(cpufreq_global_kobject, | ||
| 774 | + &dbs_attr_group); | ||
| 775 | + if (rc) { | ||
| 776 | + mutex_unlock(&dbs_mutex); | ||
| 777 | + return rc; | ||
| 778 | + } | ||
| 779 | + } | ||
| 780 | + mutex_unlock(&dbs_mutex); | ||
| 781 | + | ||
| 782 | + mutex_init(&this_dbs_info->timer_mutex); | ||
| 783 | + dbs_timer_init(this_dbs_info); | ||
| 784 | + break; | ||
| 785 | + | ||
| 786 | + case CPUFREQ_GOV_STOP: | ||
| 787 | + dbs_timer_exit(this_dbs_info); | ||
| 788 | + | ||
| 789 | + mutex_lock(&dbs_mutex); | ||
| 790 | + mutex_destroy(&this_dbs_info->timer_mutex); | ||
| 791 | + dbs_enable--; | ||
| 792 | + mutex_unlock(&dbs_mutex); | ||
| 793 | + if (!dbs_enable) | ||
| 794 | + sysfs_remove_group(cpufreq_global_kobject, | ||
| 795 | + &dbs_attr_group); | ||
| 796 | + kfree(dbs_tuners_ins.hotplug_load_history); | ||
| 797 | + /* | ||
| 798 | + * XXX BIG CAVEAT: Stopping the governor with CPU1 offline | ||
| 799 | + * will result in it remaining offline until the user onlines | ||
| 800 | + * it again. It is up to the user to do this (for now). | ||
| 801 | + */ | ||
| 802 | + break; | ||
| 803 | + | ||
| 804 | + case CPUFREQ_GOV_LIMITS: | ||
| 805 | + mutex_lock(&this_dbs_info->timer_mutex); | ||
| 806 | + if (policy->max < this_dbs_info->cur_policy->cur) | ||
| 807 | + __cpufreq_driver_target(this_dbs_info->cur_policy, | ||
| 808 | + policy->max, CPUFREQ_RELATION_H); | ||
| 809 | + else if (policy->min > this_dbs_info->cur_policy->cur) | ||
| 810 | + __cpufreq_driver_target(this_dbs_info->cur_policy, | ||
| 811 | + policy->min, CPUFREQ_RELATION_L); | ||
| 812 | + mutex_unlock(&this_dbs_info->timer_mutex); | ||
| 813 | + break; | ||
| 814 | + } | ||
| 815 | + return 0; | ||
| 816 | +} | ||
| 817 | + | ||
| 818 | +static int __init cpufreq_gov_dbs_init(void) | ||
| 819 | +{ | ||
| 820 | + int err; | ||
| 821 | + cputime64_t wall; | ||
| 822 | + u64 idle_time; | ||
| 823 | + int cpu = get_cpu(); | ||
| 824 | + | ||
| 825 | + idle_time = get_cpu_idle_time_us(cpu, &wall); | ||
| 826 | + put_cpu(); | ||
| 827 | + if (idle_time != -1ULL) { | ||
| 828 | + dbs_tuners_ins.up_threshold = DEFAULT_UP_FREQ_MIN_LOAD; | ||
| 829 | + } else { | ||
| 830 | + pr_err("cpufreq-hotplug: %s: assumes CONFIG_NO_HZ\n", | ||
| 831 | + __func__); | ||
| 832 | + return -EINVAL; | ||
| 833 | + } | ||
| 834 | + | ||
| 835 | + khotplug_wq = create_workqueue("khotplug"); | ||
| 836 | + if (!khotplug_wq) { | ||
| 837 | + pr_err("Creation of khotplug failed\n"); | ||
| 838 | + return -EFAULT; | ||
| 839 | + } | ||
| 840 | + err = cpufreq_register_governor(&cpufreq_gov_hotplug); | ||
| 841 | + if (err) | ||
| 842 | + destroy_workqueue(khotplug_wq); | ||
| 843 | + | ||
| 844 | + return err; | ||
| 845 | +} | ||
| 846 | + | ||
| 847 | +static void __exit cpufreq_gov_dbs_exit(void) | ||
| 848 | +{ | ||
| 849 | + cpufreq_unregister_governor(&cpufreq_gov_hotplug); | ||
| 850 | + destroy_workqueue(khotplug_wq); | ||
| 851 | +} | ||
| 852 | + | ||
| 853 | +MODULE_AUTHOR("Mike Turquette <mturquette@ti.com>"); | ||
| 854 | +MODULE_DESCRIPTION("'cpufreq_hotplug' - cpufreq governor for dynamic frequency scaling and CPU hotplugging"); | ||
| 855 | +MODULE_LICENSE("GPL"); | ||
| 856 | + | ||
| 857 | +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG | ||
| 858 | +fs_initcall(cpufreq_gov_dbs_init); | ||
| 859 | +#else | ||
| 860 | +module_init(cpufreq_gov_dbs_init); | ||
| 861 | +#endif | ||
| 862 | +module_exit(cpufreq_gov_dbs_exit); | ||
| 863 | diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h | ||
| 864 | index a38fca8..6cbc3df 100644 | ||
| 865 | --- a/include/linux/cpufreq.h | ||
| 866 | +++ b/include/linux/cpufreq.h | ||
| 867 | @@ -355,6 +355,9 @@ extern struct cpufreq_governor cpufreq_gov_ondemand; | ||
| 868 | #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) | ||
| 869 | extern struct cpufreq_governor cpufreq_gov_conservative; | ||
| 870 | #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) | ||
| 871 | +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG) | ||
| 872 | +extern struct cpufreq_governor cpufreq_gov_hotplug; | ||
| 873 | +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_hotplug) | ||
| 874 | #endif | ||
| 875 | |||
| 876 | |||
| 877 | -- | ||
| 878 | 1.6.6.1 | ||
| 879 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch new file mode 100644 index 00000000..d150dfc6 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | From 33668b07abd5e66a263cc8b4b88587646f38bed0 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
| 3 | Date: Wed, 11 Aug 2010 17:02:43 -0700 | ||
| 4 | Subject: [PATCH 1/8] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors | ||
| 5 | |||
| 6 | Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
| 7 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 8 | --- | ||
| 9 | arch/arm/plat-omap/cpu-omap.c | 2 +- | ||
| 10 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
| 11 | |||
| 12 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
| 13 | index da4f68d..cd09d4b 100644 | ||
| 14 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
| 15 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
| 16 | @@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void) | ||
| 17 | return cpufreq_register_driver(&omap_driver); | ||
| 18 | } | ||
| 19 | |||
| 20 | -arch_initcall(omap_cpufreq_init); | ||
| 21 | +late_initcall(omap_cpufreq_init); | ||
| 22 | |||
| 23 | /* | ||
| 24 | * if ever we want to remove this, upon cleanup call: | ||
| 25 | -- | ||
| 26 | 1.6.6.1 | ||
| 27 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch new file mode 100644 index 00000000..d62e04d1 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | From e89b1544450fb8410a44004e48d6b330bc39f0ce Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 3 | Date: Wed, 11 Aug 2010 17:05:38 -0700 | ||
| 4 | Subject: [PATCH 2/8] OMAP: CPUfreq: ensure policy is fully initialized | ||
| 5 | |||
| 6 | Ensure policy min/max/cur values are initialized when OMAP | ||
| 7 | CPUfreq driver starts. | ||
| 8 | |||
| 9 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 10 | --- | ||
| 11 | arch/arm/plat-omap/cpu-omap.c | 4 ++++ | ||
| 12 | 1 files changed, 4 insertions(+), 0 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
| 15 | index cd09d4b..1b36664 100644 | ||
| 16 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
| 17 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
| 18 | @@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 19 | VERY_HI_RATE) / 1000; | ||
| 20 | } | ||
| 21 | |||
| 22 | + policy->min = policy->cpuinfo.min_freq; | ||
| 23 | + policy->max = policy->cpuinfo.max_freq; | ||
| 24 | + policy->cur = omap_getspeed(0); | ||
| 25 | + | ||
| 26 | /* FIXME: what's the actual transition time? */ | ||
| 27 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
| 28 | |||
| 29 | -- | ||
| 30 | 1.6.6.1 | ||
| 31 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch new file mode 100644 index 00000000..fbe16213 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch | |||
| @@ -0,0 +1,263 @@ | |||
| 1 | From 948b868e4a83b054e8a58362238bc6cd61c0aeab Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Mon, 10 Nov 2008 17:00:25 +0530 | ||
| 4 | Subject: [PATCH 3/8] OMAP3 PM: CPUFreq driver for OMAP3 | ||
| 5 | |||
| 6 | CPUFreq driver for OMAP3 | ||
| 7 | |||
| 8 | With additional fixes and cleanups from Tero Kristo: | ||
| 9 | - Fix rate calculation bug in omap3_select_table_rate | ||
| 10 | - Refreshed DVFS VDD1 control against latest clock fw | ||
| 11 | |||
| 12 | Signed-off-by: Tero Kristo <tero.kristo@nokia.com> | ||
| 13 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 14 | |||
| 15 | OMAP3: PM: CPUFreq: Fix omap_getspeed. | ||
| 16 | |||
| 17 | Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
| 18 | |||
| 19 | Make sure omap cpufreq driver initializes after cpufreq framework and governors | ||
| 20 | |||
| 21 | Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
| 22 | |||
| 23 | merge: CPUFreq: remove obsolete funcs | ||
| 24 | |||
| 25 | OMAP3 clock: Update cpufreq driver | ||
| 26 | |||
| 27 | This patch removes all refrences to virtual clock | ||
| 28 | nodes in CPUFreq driver. | ||
| 29 | |||
| 30 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 31 | Signed-off-by: Tero Kristo <tero.kristo@nokia.com> | ||
| 32 | Signed-off-by: Jean Pihet <jpihet@mvista.com> | ||
| 33 | |||
| 34 | PM: Prevent direct cpufreq scaling during initialization | ||
| 35 | |||
| 36 | It is seen that the OMAP specific cpufreq initialization code tries to | ||
| 37 | scale the MPU frequency to the highest possible without taking care of | ||
| 38 | the voltage level. On power on reset the power IC does not provide the | ||
| 39 | necessary voltage for the highest available MPU frequency (that would | ||
| 40 | satisfy all Si families). This potentially is an window of opportunity | ||
| 41 | for things to go wrong. | ||
| 42 | |||
| 43 | Signed-off-by: Romit Dasgupta <romit@ti.com> | ||
| 44 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 45 | |||
| 46 | OMAP3: PM: enable 600MHz (overdrive) OPP | ||
| 47 | |||
| 48 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 49 | |||
| 50 | omap3: introduce cpufreq | ||
| 51 | |||
| 52 | OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only. | ||
| 53 | |||
| 54 | With this patch, omap opp layer now has its compilation flags | ||
| 55 | bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c. | ||
| 56 | |||
| 57 | A new file has been created to contain cpu freq code related to | ||
| 58 | OMAP3: cpufreq34xx.c | ||
| 59 | |||
| 60 | OMAP34xx and OMAP36xx family OPPs are made available | ||
| 61 | |||
| 62 | Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com> | ||
| 63 | Signed-off-by: Paul Walmsley <paul@pwsan.com> | ||
| 64 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 65 | Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com> | ||
| 66 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 67 | Signed-off-by: Romit Dasgupta <romit@ti.com> | ||
| 68 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 69 | |||
| 70 | omap3: cpufreq: allow default opp table init | ||
| 71 | |||
| 72 | For board files which choose to override the defaults, the existing | ||
| 73 | mechanism will work, for boards that would like to work with defaults, | ||
| 74 | allow init_common_hw to call init_opp_table to initialize if not | ||
| 75 | already initialized. this will allow all omap boards which have opp | ||
| 76 | tables predefined for a silicon to use the same. | ||
| 77 | |||
| 78 | Originally reported for overo: | ||
| 79 | http://marc.info/?t=127265269400004&r=1&w=2 | ||
| 80 | |||
| 81 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 82 | Reported-by: Peter Tseng <tsenpet09@gmail.com> | ||
| 83 | Cc: Cliff Brake <cliff.brake@gmail.com> | ||
| 84 | Cc: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 85 | |||
| 86 | OMAP2: update OPP data to be device based | ||
| 87 | |||
| 88 | Cc: Nishanth Menon <nm@ti.com> | ||
| 89 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 90 | |||
| 91 | OMAP3: CPUfreq: update to device-based OPP API | ||
| 92 | |||
| 93 | Update usage of OPP API to use new device-based API. This requires | ||
| 94 | getting the 'struct device' for the MPU and using that with the OPP | ||
| 95 | API. | ||
| 96 | |||
| 97 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 98 | |||
| 99 | omap3: opp: make independent of cpufreq | ||
| 100 | |||
| 101 | Make opp3xx data which is registered with the opp layer | ||
| 102 | dependent purely on CONFIG_PM as opp layer and pm.c users | ||
| 103 | are CONFIG_PM dependent not cpufreq dependent. | ||
| 104 | so we rename the data definition to opp3xxx_data.c (inline with what | ||
| 105 | we have for omap2), also move the build definition to be under | ||
| 106 | the existing CONFIG_PM build instead of CPUFREQ. | ||
| 107 | |||
| 108 | Cc: Eduardo Valentin <eduardo.valentin@nokia.com> | ||
| 109 | Cc: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 110 | Cc: Paul Walmsley <paul@pwsan.com> | ||
| 111 | Cc: Rajendra Nayak <rnayak@ti.com> | ||
| 112 | Cc: Sanjeev Premi <premi@ti.com> | ||
| 113 | Cc: Thara Gopinath <thara@ti.com> | ||
| 114 | Cc: Tony Lindgren <tony@atomide.com> | ||
| 115 | |||
| 116 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 117 | --- | ||
| 118 | arch/arm/mach-omap2/clock.h | 14 +++++++++++++- | ||
| 119 | arch/arm/mach-omap2/clock34xx.c | 2 ++ | ||
| 120 | arch/arm/plat-omap/cpu-omap.c | 34 +++++++++++++++++++++++++++++++--- | ||
| 121 | 3 files changed, 46 insertions(+), 4 deletions(-) | ||
| 122 | |||
| 123 | diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h | ||
| 124 | index e10ff2b..0a07e50 100644 | ||
| 125 | --- a/arch/arm/mach-omap2/clock.h | ||
| 126 | +++ b/arch/arm/mach-omap2/clock.h | ||
| 127 | @@ -141,7 +141,9 @@ extern const struct clksel_rate gpt_sys_rates[]; | ||
| 128 | extern const struct clksel_rate gfx_l3_rates[]; | ||
| 129 | extern const struct clksel_rate dsp_ick_rates[]; | ||
| 130 | |||
| 131 | -#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ) | ||
| 132 | +#ifdef CONFIG_CPU_FREQ | ||
| 133 | + | ||
| 134 | +#ifdef CONFIG_ARCH_OMAP2 | ||
| 135 | extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); | ||
| 136 | extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); | ||
| 137 | #else | ||
| 138 | @@ -149,6 +151,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) | ||
| 139 | #define omap2_clk_exit_cpufreq_table 0 | ||
| 140 | #endif | ||
| 141 | |||
| 142 | +#ifdef CONFIG_ARCH_OMAP3 | ||
| 143 | +extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); | ||
| 144 | +extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); | ||
| 145 | +#else | ||
| 146 | +#define omap3_clk_init_cpufreq_table 0 | ||
| 147 | +#define omap3_clk_exit_cpufreq_table 0 | ||
| 148 | +#endif | ||
| 149 | + | ||
| 150 | +#endif /* CONFIG_CPU_FREQ */ | ||
| 151 | + | ||
| 152 | extern const struct clkops clkops_omap2_iclk_dflt_wait; | ||
| 153 | extern const struct clkops clkops_omap2_iclk_dflt; | ||
| 154 | extern const struct clkops clkops_omap2_iclk_idle_only; | ||
| 155 | diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c | ||
| 156 | index 1fc96b9..119e135 100644 | ||
| 157 | --- a/arch/arm/mach-omap2/clock34xx.c | ||
| 158 | +++ b/arch/arm/mach-omap2/clock34xx.c | ||
| 159 | @@ -20,6 +20,8 @@ | ||
| 160 | #include <linux/kernel.h> | ||
| 161 | #include <linux/clk.h> | ||
| 162 | #include <linux/io.h> | ||
| 163 | +#include <linux/err.h> | ||
| 164 | +#include <linux/cpufreq.h> | ||
| 165 | |||
| 166 | #include <plat/clock.h> | ||
| 167 | |||
| 168 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
| 169 | index 1b36664..f0f9430 100644 | ||
| 170 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
| 171 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
| 172 | @@ -8,6 +8,10 @@ | ||
| 173 | * | ||
| 174 | * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
| 175 | * | ||
| 176 | + * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
| 177 | + * Updated to support OMAP3 | ||
| 178 | + * Rajendra Nayak <rnayak@ti.com> | ||
| 179 | + * | ||
| 180 | * This program is free software; you can redistribute it and/or modify | ||
| 181 | * it under the terms of the GNU General Public License version 2 as | ||
| 182 | * published by the Free Software Foundation. | ||
| 183 | @@ -26,12 +30,19 @@ | ||
| 184 | #include <plat/clock.h> | ||
| 185 | #include <asm/system.h> | ||
| 186 | |||
| 187 | +#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 188 | +#include <plat/omap-pm.h> | ||
| 189 | +#include <plat/opp.h> | ||
| 190 | +#endif | ||
| 191 | + | ||
| 192 | #define VERY_HI_RATE 900000000 | ||
| 193 | |||
| 194 | static struct cpufreq_frequency_table *freq_table; | ||
| 195 | |||
| 196 | #ifdef CONFIG_ARCH_OMAP1 | ||
| 197 | #define MPU_CLK "mpu" | ||
| 198 | +#elif CONFIG_ARCH_OMAP3 | ||
| 199 | +#define MPU_CLK "arm_fck" | ||
| 200 | #else | ||
| 201 | #define MPU_CLK "virt_prcm_set" | ||
| 202 | #endif | ||
| 203 | @@ -73,7 +84,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 204 | unsigned int target_freq, | ||
| 205 | unsigned int relation) | ||
| 206 | { | ||
| 207 | +#ifdef CONFIG_ARCH_OMAP1 | ||
| 208 | struct cpufreq_freqs freqs; | ||
| 209 | +#endif | ||
| 210 | +#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 211 | + unsigned long freq; | ||
| 212 | + struct device *mpu_dev = omap2_get_mpuss_device(); | ||
| 213 | +#endif | ||
| 214 | int ret = 0; | ||
| 215 | |||
| 216 | /* Ensure desired rate is within allowed range. Some govenors | ||
| 217 | @@ -83,13 +100,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 218 | if (target_freq > policy->max) | ||
| 219 | target_freq = policy->max; | ||
| 220 | |||
| 221 | +#ifdef CONFIG_ARCH_OMAP1 | ||
| 222 | freqs.old = omap_getspeed(0); | ||
| 223 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 224 | freqs.cpu = 0; | ||
| 225 | |||
| 226 | if (freqs.old == freqs.new) | ||
| 227 | return ret; | ||
| 228 | - | ||
| 229 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 230 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
| 231 | printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", | ||
| 232 | @@ -97,7 +114,11 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 233 | #endif | ||
| 234 | ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
| 235 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 236 | - | ||
| 237 | +#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 238 | + freq = target_freq * 1000; | ||
| 239 | + if (opp_find_freq_ceil(mpu_dev, &freq)) | ||
| 240 | + omap_pm_cpu_set_freq(freq); | ||
| 241 | +#endif | ||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | |||
| 245 | @@ -114,7 +135,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 246 | |||
| 247 | policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
| 248 | |||
| 249 | - clk_init_cpufreq_table(&freq_table); | ||
| 250 | + if (!cpu_is_omap34xx()) { | ||
| 251 | + clk_init_cpufreq_table(&freq_table); | ||
| 252 | + } else { | ||
| 253 | + struct device *mpu_dev = omap2_get_mpuss_device(); | ||
| 254 | + | ||
| 255 | + opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | if (freq_table) { | ||
| 259 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 260 | if (!result) | ||
| 261 | -- | ||
| 262 | 1.6.6.1 | ||
| 263 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch new file mode 100644 index 00000000..36742e43 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | From 86227f1eb341e571163464cb0a412ed2179f2541 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Silesh C V <silesh@ti.com> | ||
| 3 | Date: Wed, 29 Sep 2010 14:52:54 +0530 | ||
| 4 | Subject: [PATCH 4/8] OMAP: PM: CPUFREQ: Fix conditional compilation | ||
| 5 | |||
| 6 | Fix conditional compilation. A conditional expresiion | ||
| 7 | should follow "#elif", in this case #elif clause should | ||
| 8 | check whether CONFIG_ARCH_OMAP3 is defined or not | ||
| 9 | (ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for | ||
| 10 | the value of the macro. | ||
| 11 | |||
| 12 | Signed-off-by: Silesh C V <silesh@ti.com> | ||
| 13 | --- | ||
| 14 | arch/arm/plat-omap/cpu-omap.c | 2 +- | ||
| 15 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
| 18 | index f0f9430..c3ac065 100644 | ||
| 19 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
| 20 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
| 21 | @@ -41,7 +41,7 @@ static struct cpufreq_frequency_table *freq_table; | ||
| 22 | |||
| 23 | #ifdef CONFIG_ARCH_OMAP1 | ||
| 24 | #define MPU_CLK "mpu" | ||
| 25 | -#elif CONFIG_ARCH_OMAP3 | ||
| 26 | +#elif defined(CONFIG_ARCH_OMAP3) | ||
| 27 | #define MPU_CLK "arm_fck" | ||
| 28 | #else | ||
| 29 | #define MPU_CLK "virt_prcm_set" | ||
| 30 | -- | ||
| 31 | 1.6.6.1 | ||
| 32 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch new file mode 100644 index 00000000..7cf69325 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | From 4764137dd613362656726a15cb8184724aeb99bb Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Kevin Hilman <khilman@deeprootsystems.com> | ||
| 3 | Date: Tue, 16 Nov 2010 11:48:41 -0800 | ||
| 4 | Subject: [PATCH 5/8] cpufreq: fixup after new OPP layer merged | ||
| 5 | |||
| 6 | --- | ||
| 7 | arch/arm/plat-omap/cpu-omap.c | 3 ++- | ||
| 8 | 1 files changed, 2 insertions(+), 1 deletions(-) | ||
| 9 | |||
| 10 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
| 11 | index c3ac065..9cd2709 100644 | ||
| 12 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
| 13 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
| 14 | @@ -25,6 +25,7 @@ | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/clk.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | +#include <linux/opp.h> | ||
| 19 | |||
| 20 | #include <mach/hardware.h> | ||
| 21 | #include <plat/clock.h> | ||
| 22 | @@ -32,7 +33,7 @@ | ||
| 23 | |||
| 24 | #if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 25 | #include <plat/omap-pm.h> | ||
| 26 | -#include <plat/opp.h> | ||
| 27 | +#include <plat/common.h> | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #define VERY_HI_RATE 900000000 | ||
| 31 | -- | ||
| 32 | 1.6.6.1 | ||
| 33 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch new file mode 100644 index 00000000..cfc257e0 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch | |||
| @@ -0,0 +1,669 @@ | |||
| 1 | From e16548716c5cbc3c9885d05f1654d83d5411a3a7 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 3 | Date: Mon, 14 Mar 2011 17:08:48 +0530 | ||
| 4 | Subject: [PATCH 6/8] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers. | ||
| 5 | |||
| 6 | This patch is an attempt to cleanup the #ifdeferry in the | ||
| 7 | omap CPUfreq drivers. | ||
| 8 | |||
| 9 | The split betwenn OMAP1 and OMAP2PLUS is logical because | ||
| 10 | - OMAP1 doesn't support opp layer. | ||
| 11 | - OMAP1 build is seperate from omap2plus. | ||
| 12 | |||
| 13 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 14 | Cc: Kevin Hilman <khilman@ti.com> | ||
| 15 | Cc: Vishwanath BS <vishwanath.bs@ti.com> | ||
| 16 | --- | ||
| 17 | arch/arm/mach-omap1/Makefile | 3 + | ||
| 18 | arch/arm/mach-omap1/omap1-cpufreq.c | 176 ++++++++++++++++++++++++++ | ||
| 19 | arch/arm/mach-omap2/Makefile | 3 + | ||
| 20 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++ | ||
| 21 | arch/arm/plat-omap/Makefile | 1 - | ||
| 22 | arch/arm/plat-omap/cpu-omap.c | 204 ------------------------------- | ||
| 23 | 6 files changed, 383 insertions(+), 205 deletions(-) | ||
| 24 | create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c | ||
| 25 | create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 26 | delete mode 100644 arch/arm/plat-omap/cpu-omap.c | ||
| 27 | |||
| 28 | diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile | ||
| 29 | index af98117..e5082b0 100644 | ||
| 30 | --- a/arch/arm/mach-omap1/Makefile | ||
| 31 | +++ b/arch/arm/mach-omap1/Makefile | ||
| 32 | @@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o | ||
| 33 | |||
| 34 | obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o | ||
| 35 | |||
| 36 | +# CPUFREQ driver | ||
| 37 | +obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o | ||
| 38 | + | ||
| 39 | # Power Management | ||
| 40 | obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o | ||
| 41 | |||
| 42 | diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c | ||
| 43 | new file mode 100644 | ||
| 44 | index 0000000..682cdc8 | ||
| 45 | --- /dev/null | ||
| 46 | +++ b/arch/arm/mach-omap1/omap1-cpufreq.c | ||
| 47 | @@ -0,0 +1,176 @@ | ||
| 48 | +/* | ||
| 49 | + * OMAP1 cpufreq driver | ||
| 50 | + * | ||
| 51 | + * CPU frequency scaling for OMAP | ||
| 52 | + * | ||
| 53 | + * Copyright (C) 2005 Nokia Corporation | ||
| 54 | + * Written by Tony Lindgren <tony@atomide.com> | ||
| 55 | + * | ||
| 56 | + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
| 57 | + * | ||
| 58 | + * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
| 59 | + * Updated to support OMAP3 | ||
| 60 | + * Rajendra Nayak <rnayak@ti.com> | ||
| 61 | + * | ||
| 62 | + * This program is free software; you can redistribute it and/or modify | ||
| 63 | + * it under the terms of the GNU General Public License version 2 as | ||
| 64 | + * published by the Free Software Foundation. | ||
| 65 | + */ | ||
| 66 | +#include <linux/types.h> | ||
| 67 | +#include <linux/kernel.h> | ||
| 68 | +#include <linux/sched.h> | ||
| 69 | +#include <linux/cpufreq.h> | ||
| 70 | +#include <linux/delay.h> | ||
| 71 | +#include <linux/init.h> | ||
| 72 | +#include <linux/err.h> | ||
| 73 | +#include <linux/clk.h> | ||
| 74 | +#include <linux/io.h> | ||
| 75 | +#include <linux/opp.h> | ||
| 76 | + | ||
| 77 | +#include <asm/system.h> | ||
| 78 | + | ||
| 79 | +#include <plat/clock.h> | ||
| 80 | +#include <plat/omap-pm.h> | ||
| 81 | + | ||
| 82 | +#include <mach/hardware.h> | ||
| 83 | + | ||
| 84 | +#define VERY_HI_RATE 900000000 | ||
| 85 | + | ||
| 86 | +static struct cpufreq_frequency_table *freq_table; | ||
| 87 | +static struct clk *mpu_clk; | ||
| 88 | + | ||
| 89 | +static int omap_verify_speed(struct cpufreq_policy *policy) | ||
| 90 | +{ | ||
| 91 | + if (freq_table) | ||
| 92 | + return cpufreq_frequency_table_verify(policy, freq_table); | ||
| 93 | + | ||
| 94 | + if (policy->cpu) | ||
| 95 | + return -EINVAL; | ||
| 96 | + | ||
| 97 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
| 98 | + policy->cpuinfo.max_freq); | ||
| 99 | + | ||
| 100 | + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | ||
| 101 | + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | ||
| 102 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
| 103 | + policy->cpuinfo.max_freq); | ||
| 104 | + return 0; | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +static unsigned int omap_getspeed(unsigned int cpu) | ||
| 108 | +{ | ||
| 109 | + unsigned long rate; | ||
| 110 | + | ||
| 111 | + if (cpu) | ||
| 112 | + return 0; | ||
| 113 | + | ||
| 114 | + rate = clk_get_rate(mpu_clk) / 1000; | ||
| 115 | + return rate; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +static int omap_target(struct cpufreq_policy *policy, | ||
| 119 | + unsigned int target_freq, | ||
| 120 | + unsigned int relation) | ||
| 121 | +{ | ||
| 122 | + struct cpufreq_freqs freqs; | ||
| 123 | + int ret = 0; | ||
| 124 | + | ||
| 125 | + /* Ensure desired rate is within allowed range. Some govenors | ||
| 126 | + * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
| 127 | + if (target_freq < policy->min) | ||
| 128 | + target_freq = policy->min; | ||
| 129 | + if (target_freq > policy->max) | ||
| 130 | + target_freq = policy->max; | ||
| 131 | + | ||
| 132 | + freqs.old = omap_getspeed(0); | ||
| 133 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 134 | + freqs.cpu = 0; | ||
| 135 | + | ||
| 136 | + if (freqs.old == freqs.new) | ||
| 137 | + return ret; | ||
| 138 | + | ||
| 139 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 140 | + | ||
| 141 | +#ifdef CONFIG_CPU_FREQ_DEBUG | ||
| 142 | + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
| 143 | +#endif | ||
| 144 | + ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
| 145 | + | ||
| 146 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 147 | + | ||
| 148 | + return ret; | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +static int __init omap_cpu_init(struct cpufreq_policy *policy) | ||
| 152 | +{ | ||
| 153 | + int result = 0; | ||
| 154 | + | ||
| 155 | + mpu_clk = clk_get(NULL, "mpu"); | ||
| 156 | + if (IS_ERR(mpu_clk)) | ||
| 157 | + return PTR_ERR(mpu_clk); | ||
| 158 | + | ||
| 159 | + if (policy->cpu != 0) | ||
| 160 | + return -EINVAL; | ||
| 161 | + | ||
| 162 | + policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
| 163 | + | ||
| 164 | + clk_init_cpufreq_table(&freq_table); | ||
| 165 | + | ||
| 166 | + if (freq_table) { | ||
| 167 | + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 168 | + if (!result) | ||
| 169 | + cpufreq_frequency_table_get_attr(freq_table, | ||
| 170 | + policy->cpu); | ||
| 171 | + } else { | ||
| 172 | + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
| 173 | + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
| 174 | + VERY_HI_RATE) / 1000; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + policy->min = policy->cpuinfo.min_freq; | ||
| 178 | + policy->max = policy->cpuinfo.max_freq; | ||
| 179 | + policy->cur = omap_getspeed(0); | ||
| 180 | + | ||
| 181 | + /* FIXME: what's the actual transition time? */ | ||
| 182 | + policy->cpuinfo.transition_latency = 300 * 1000; | ||
| 183 | + | ||
| 184 | + return 0; | ||
| 185 | +} | ||
| 186 | + | ||
| 187 | +static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
| 188 | +{ | ||
| 189 | + clk_exit_cpufreq_table(&freq_table); | ||
| 190 | + clk_put(mpu_clk); | ||
| 191 | + return 0; | ||
| 192 | +} | ||
| 193 | + | ||
| 194 | +static struct freq_attr *omap_cpufreq_attr[] = { | ||
| 195 | + &cpufreq_freq_attr_scaling_available_freqs, | ||
| 196 | + NULL, | ||
| 197 | +}; | ||
| 198 | + | ||
| 199 | +static struct cpufreq_driver omap_driver = { | ||
| 200 | + .flags = CPUFREQ_STICKY, | ||
| 201 | + .verify = omap_verify_speed, | ||
| 202 | + .target = omap_target, | ||
| 203 | + .get = omap_getspeed, | ||
| 204 | + .init = omap_cpu_init, | ||
| 205 | + .exit = omap_cpu_exit, | ||
| 206 | + .name = "omap1", | ||
| 207 | + .attr = omap_cpufreq_attr, | ||
| 208 | +}; | ||
| 209 | + | ||
| 210 | +static int __init omap_cpufreq_init(void) | ||
| 211 | +{ | ||
| 212 | + return cpufreq_register_driver(&omap_driver); | ||
| 213 | +} | ||
| 214 | + | ||
| 215 | +static void __exit omap_cpufreq_exit(void) | ||
| 216 | +{ | ||
| 217 | + cpufreq_unregister_driver(&omap_driver); | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs"); | ||
| 221 | +MODULE_LICENSE("GPL"); | ||
| 222 | +module_init(omap_cpufreq_init); | ||
| 223 | +module_exit(omap_cpufreq_exit); | ||
| 224 | diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile | ||
| 225 | index 05cd983..e9c2445 100644 | ||
| 226 | --- a/arch/arm/mach-omap2/Makefile | ||
| 227 | +++ b/arch/arm/mach-omap2/Makefile | ||
| 228 | @@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o | ||
| 229 | obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o | ||
| 230 | endif | ||
| 231 | |||
| 232 | +# CPUFREQ driver | ||
| 233 | +obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o | ||
| 234 | + | ||
| 235 | # Power Management | ||
| 236 | ifeq ($(CONFIG_PM),y) | ||
| 237 | obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o | ||
| 238 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 239 | new file mode 100644 | ||
| 240 | index 0000000..14f84cc | ||
| 241 | --- /dev/null | ||
| 242 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 243 | @@ -0,0 +1,201 @@ | ||
| 244 | +/* | ||
| 245 | + * OMAP2PLUS cpufreq driver | ||
| 246 | + * | ||
| 247 | + * CPU frequency scaling for OMAP | ||
| 248 | + * | ||
| 249 | + * Copyright (C) 2005 Nokia Corporation | ||
| 250 | + * Written by Tony Lindgren <tony@atomide.com> | ||
| 251 | + * | ||
| 252 | + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
| 253 | + * | ||
| 254 | + * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
| 255 | + * Updated to support OMAP3 | ||
| 256 | + * Rajendra Nayak <rnayak@ti.com> | ||
| 257 | + * | ||
| 258 | + * This program is free software; you can redistribute it and/or modify | ||
| 259 | + * it under the terms of the GNU General Public License version 2 as | ||
| 260 | + * published by the Free Software Foundation. | ||
| 261 | + */ | ||
| 262 | +#include <linux/types.h> | ||
| 263 | +#include <linux/kernel.h> | ||
| 264 | +#include <linux/sched.h> | ||
| 265 | +#include <linux/cpufreq.h> | ||
| 266 | +#include <linux/delay.h> | ||
| 267 | +#include <linux/init.h> | ||
| 268 | +#include <linux/err.h> | ||
| 269 | +#include <linux/clk.h> | ||
| 270 | +#include <linux/io.h> | ||
| 271 | +#include <linux/opp.h> | ||
| 272 | + | ||
| 273 | +#include <asm/system.h> | ||
| 274 | +#include <asm/smp_plat.h> | ||
| 275 | + | ||
| 276 | +#include <plat/clock.h> | ||
| 277 | +#include <plat/omap-pm.h> | ||
| 278 | +#include <plat/common.h> | ||
| 279 | + | ||
| 280 | +#include <mach/hardware.h> | ||
| 281 | + | ||
| 282 | +#define VERY_HI_RATE 900000000 | ||
| 283 | + | ||
| 284 | +static struct cpufreq_frequency_table *freq_table; | ||
| 285 | +static struct clk *mpu_clk; | ||
| 286 | + | ||
| 287 | +static int omap_verify_speed(struct cpufreq_policy *policy) | ||
| 288 | +{ | ||
| 289 | + if (freq_table) | ||
| 290 | + return cpufreq_frequency_table_verify(policy, freq_table); | ||
| 291 | + | ||
| 292 | + if (policy->cpu) | ||
| 293 | + return -EINVAL; | ||
| 294 | + | ||
| 295 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
| 296 | + policy->cpuinfo.max_freq); | ||
| 297 | + | ||
| 298 | + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | ||
| 299 | + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | ||
| 300 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
| 301 | + policy->cpuinfo.max_freq); | ||
| 302 | + return 0; | ||
| 303 | +} | ||
| 304 | + | ||
| 305 | +static unsigned int omap_getspeed(unsigned int cpu) | ||
| 306 | +{ | ||
| 307 | + unsigned long rate; | ||
| 308 | + | ||
| 309 | + if (cpu) | ||
| 310 | + return 0; | ||
| 311 | + | ||
| 312 | + rate = clk_get_rate(mpu_clk) / 1000; | ||
| 313 | + return rate; | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | +static int omap_target(struct cpufreq_policy *policy, | ||
| 317 | + unsigned int target_freq, | ||
| 318 | + unsigned int relation) | ||
| 319 | +{ | ||
| 320 | + int ret = 0; | ||
| 321 | + struct cpufreq_freqs freqs; | ||
| 322 | + | ||
| 323 | + /* Ensure desired rate is within allowed range. Some govenors | ||
| 324 | + * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
| 325 | + if (target_freq < policy->min) | ||
| 326 | + target_freq = policy->min; | ||
| 327 | + if (target_freq > policy->max) | ||
| 328 | + target_freq = policy->max; | ||
| 329 | + | ||
| 330 | + freqs.old = omap_getspeed(0); | ||
| 331 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 332 | + freqs.cpu = 0; | ||
| 333 | + | ||
| 334 | + if (freqs.old == freqs.new) | ||
| 335 | + return ret; | ||
| 336 | + | ||
| 337 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 338 | + | ||
| 339 | +#ifdef CONFIG_CPU_FREQ_DEBUG | ||
| 340 | + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
| 341 | +#endif | ||
| 342 | + | ||
| 343 | + ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
| 344 | + | ||
| 345 | + /* | ||
| 346 | + * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies | ||
| 347 | + * won't get updated when UP machine cpufreq build with | ||
| 348 | + * CONFIG_SMP enabled. Below code is added only to manage that | ||
| 349 | + * scenario | ||
| 350 | + */ | ||
| 351 | + if (!is_smp()) | ||
| 352 | + loops_per_jiffy = | ||
| 353 | + cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); | ||
| 354 | + | ||
| 355 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 356 | + | ||
| 357 | + return ret; | ||
| 358 | +} | ||
| 359 | + | ||
| 360 | +static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 361 | +{ | ||
| 362 | + int result = 0; | ||
| 363 | + struct device *mpu_dev; | ||
| 364 | + | ||
| 365 | + if (cpu_is_omap24xx()) | ||
| 366 | + mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
| 367 | + else if (cpu_is_omap34xx()) | ||
| 368 | + mpu_clk = clk_get(NULL, "dpll1_ck"); | ||
| 369 | + else if (cpu_is_omap34xx()) | ||
| 370 | + mpu_clk = clk_get(NULL, "dpll_mpu_ck"); | ||
| 371 | + | ||
| 372 | + if (IS_ERR(mpu_clk)) | ||
| 373 | + return PTR_ERR(mpu_clk); | ||
| 374 | + | ||
| 375 | + if (policy->cpu != 0) | ||
| 376 | + return -EINVAL; | ||
| 377 | + | ||
| 378 | + policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
| 379 | + | ||
| 380 | + mpu_dev = omap2_get_mpuss_device(); | ||
| 381 | + if (!mpu_dev) { | ||
| 382 | + pr_warning("%s: unable to get the mpu device\n", __func__); | ||
| 383 | + return -EINVAL; | ||
| 384 | + } | ||
| 385 | + opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
| 386 | + | ||
| 387 | + if (freq_table) { | ||
| 388 | + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 389 | + if (!result) | ||
| 390 | + cpufreq_frequency_table_get_attr(freq_table, | ||
| 391 | + policy->cpu); | ||
| 392 | + } else { | ||
| 393 | + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
| 394 | + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
| 395 | + VERY_HI_RATE) / 1000; | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + policy->min = policy->cpuinfo.min_freq; | ||
| 399 | + policy->max = policy->cpuinfo.max_freq; | ||
| 400 | + policy->cur = omap_getspeed(0); | ||
| 401 | + | ||
| 402 | + /* FIXME: what's the actual transition time? */ | ||
| 403 | + policy->cpuinfo.transition_latency = 300 * 1000; | ||
| 404 | + | ||
| 405 | + return 0; | ||
| 406 | +} | ||
| 407 | + | ||
| 408 | +static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
| 409 | +{ | ||
| 410 | + clk_exit_cpufreq_table(&freq_table); | ||
| 411 | + clk_put(mpu_clk); | ||
| 412 | + return 0; | ||
| 413 | +} | ||
| 414 | + | ||
| 415 | +static struct freq_attr *omap_cpufreq_attr[] = { | ||
| 416 | + &cpufreq_freq_attr_scaling_available_freqs, | ||
| 417 | + NULL, | ||
| 418 | +}; | ||
| 419 | + | ||
| 420 | +static struct cpufreq_driver omap_driver = { | ||
| 421 | + .flags = CPUFREQ_STICKY, | ||
| 422 | + .verify = omap_verify_speed, | ||
| 423 | + .target = omap_target, | ||
| 424 | + .get = omap_getspeed, | ||
| 425 | + .init = omap_cpu_init, | ||
| 426 | + .exit = omap_cpu_exit, | ||
| 427 | + .name = "omap2plus", | ||
| 428 | + .attr = omap_cpufreq_attr, | ||
| 429 | +}; | ||
| 430 | + | ||
| 431 | +static int __init omap_cpufreq_init(void) | ||
| 432 | +{ | ||
| 433 | + return cpufreq_register_driver(&omap_driver); | ||
| 434 | +} | ||
| 435 | + | ||
| 436 | +static void __exit omap_cpufreq_exit(void) | ||
| 437 | +{ | ||
| 438 | + cpufreq_unregister_driver(&omap_driver); | ||
| 439 | +} | ||
| 440 | + | ||
| 441 | +MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs"); | ||
| 442 | +MODULE_LICENSE("GPL"); | ||
| 443 | +module_init(omap_cpufreq_init); | ||
| 444 | +module_exit(omap_cpufreq_exit); | ||
| 445 | diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile | ||
| 446 | index a4a1285..ec7862e 100644 | ||
| 447 | --- a/arch/arm/plat-omap/Makefile | ||
| 448 | +++ b/arch/arm/plat-omap/Makefile | ||
| 449 | @@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o | ||
| 450 | obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o | ||
| 451 | obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o | ||
| 452 | |||
| 453 | -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | ||
| 454 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o | ||
| 455 | obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o | ||
| 456 | obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o | ||
| 457 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
| 458 | deleted file mode 100644 | ||
| 459 | index 9cd2709..0000000 | ||
| 460 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
| 461 | +++ /dev/null | ||
| 462 | @@ -1,204 +0,0 @@ | ||
| 463 | -/* | ||
| 464 | - * linux/arch/arm/plat-omap/cpu-omap.c | ||
| 465 | - * | ||
| 466 | - * CPU frequency scaling for OMAP | ||
| 467 | - * | ||
| 468 | - * Copyright (C) 2005 Nokia Corporation | ||
| 469 | - * Written by Tony Lindgren <tony@atomide.com> | ||
| 470 | - * | ||
| 471 | - * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
| 472 | - * | ||
| 473 | - * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
| 474 | - * Updated to support OMAP3 | ||
| 475 | - * Rajendra Nayak <rnayak@ti.com> | ||
| 476 | - * | ||
| 477 | - * This program is free software; you can redistribute it and/or modify | ||
| 478 | - * it under the terms of the GNU General Public License version 2 as | ||
| 479 | - * published by the Free Software Foundation. | ||
| 480 | - */ | ||
| 481 | -#include <linux/types.h> | ||
| 482 | -#include <linux/kernel.h> | ||
| 483 | -#include <linux/sched.h> | ||
| 484 | -#include <linux/cpufreq.h> | ||
| 485 | -#include <linux/delay.h> | ||
| 486 | -#include <linux/init.h> | ||
| 487 | -#include <linux/err.h> | ||
| 488 | -#include <linux/clk.h> | ||
| 489 | -#include <linux/io.h> | ||
| 490 | -#include <linux/opp.h> | ||
| 491 | - | ||
| 492 | -#include <mach/hardware.h> | ||
| 493 | -#include <plat/clock.h> | ||
| 494 | -#include <asm/system.h> | ||
| 495 | - | ||
| 496 | -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 497 | -#include <plat/omap-pm.h> | ||
| 498 | -#include <plat/common.h> | ||
| 499 | -#endif | ||
| 500 | - | ||
| 501 | -#define VERY_HI_RATE 900000000 | ||
| 502 | - | ||
| 503 | -static struct cpufreq_frequency_table *freq_table; | ||
| 504 | - | ||
| 505 | -#ifdef CONFIG_ARCH_OMAP1 | ||
| 506 | -#define MPU_CLK "mpu" | ||
| 507 | -#elif defined(CONFIG_ARCH_OMAP3) | ||
| 508 | -#define MPU_CLK "arm_fck" | ||
| 509 | -#else | ||
| 510 | -#define MPU_CLK "virt_prcm_set" | ||
| 511 | -#endif | ||
| 512 | - | ||
| 513 | -static struct clk *mpu_clk; | ||
| 514 | - | ||
| 515 | -/* TODO: Add support for SDRAM timing changes */ | ||
| 516 | - | ||
| 517 | -static int omap_verify_speed(struct cpufreq_policy *policy) | ||
| 518 | -{ | ||
| 519 | - if (freq_table) | ||
| 520 | - return cpufreq_frequency_table_verify(policy, freq_table); | ||
| 521 | - | ||
| 522 | - if (policy->cpu) | ||
| 523 | - return -EINVAL; | ||
| 524 | - | ||
| 525 | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
| 526 | - policy->cpuinfo.max_freq); | ||
| 527 | - | ||
| 528 | - policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | ||
| 529 | - policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | ||
| 530 | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
| 531 | - policy->cpuinfo.max_freq); | ||
| 532 | - return 0; | ||
| 533 | -} | ||
| 534 | - | ||
| 535 | -static unsigned int omap_getspeed(unsigned int cpu) | ||
| 536 | -{ | ||
| 537 | - unsigned long rate; | ||
| 538 | - | ||
| 539 | - if (cpu) | ||
| 540 | - return 0; | ||
| 541 | - | ||
| 542 | - rate = clk_get_rate(mpu_clk) / 1000; | ||
| 543 | - return rate; | ||
| 544 | -} | ||
| 545 | - | ||
| 546 | -static int omap_target(struct cpufreq_policy *policy, | ||
| 547 | - unsigned int target_freq, | ||
| 548 | - unsigned int relation) | ||
| 549 | -{ | ||
| 550 | -#ifdef CONFIG_ARCH_OMAP1 | ||
| 551 | - struct cpufreq_freqs freqs; | ||
| 552 | -#endif | ||
| 553 | -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 554 | - unsigned long freq; | ||
| 555 | - struct device *mpu_dev = omap2_get_mpuss_device(); | ||
| 556 | -#endif | ||
| 557 | - int ret = 0; | ||
| 558 | - | ||
| 559 | - /* Ensure desired rate is within allowed range. Some govenors | ||
| 560 | - * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
| 561 | - if (target_freq < policy->min) | ||
| 562 | - target_freq = policy->min; | ||
| 563 | - if (target_freq > policy->max) | ||
| 564 | - target_freq = policy->max; | ||
| 565 | - | ||
| 566 | -#ifdef CONFIG_ARCH_OMAP1 | ||
| 567 | - freqs.old = omap_getspeed(0); | ||
| 568 | - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 569 | - freqs.cpu = 0; | ||
| 570 | - | ||
| 571 | - if (freqs.old == freqs.new) | ||
| 572 | - return ret; | ||
| 573 | - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 574 | -#ifdef CONFIG_CPU_FREQ_DEBUG | ||
| 575 | - printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", | ||
| 576 | - freqs.old, freqs.new); | ||
| 577 | -#endif | ||
| 578 | - ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
| 579 | - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 580 | -#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
| 581 | - freq = target_freq * 1000; | ||
| 582 | - if (opp_find_freq_ceil(mpu_dev, &freq)) | ||
| 583 | - omap_pm_cpu_set_freq(freq); | ||
| 584 | -#endif | ||
| 585 | - return ret; | ||
| 586 | -} | ||
| 587 | - | ||
| 588 | -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 589 | -{ | ||
| 590 | - int result = 0; | ||
| 591 | - | ||
| 592 | - mpu_clk = clk_get(NULL, MPU_CLK); | ||
| 593 | - if (IS_ERR(mpu_clk)) | ||
| 594 | - return PTR_ERR(mpu_clk); | ||
| 595 | - | ||
| 596 | - if (policy->cpu != 0) | ||
| 597 | - return -EINVAL; | ||
| 598 | - | ||
| 599 | - policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
| 600 | - | ||
| 601 | - if (!cpu_is_omap34xx()) { | ||
| 602 | - clk_init_cpufreq_table(&freq_table); | ||
| 603 | - } else { | ||
| 604 | - struct device *mpu_dev = omap2_get_mpuss_device(); | ||
| 605 | - | ||
| 606 | - opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
| 607 | - } | ||
| 608 | - | ||
| 609 | - if (freq_table) { | ||
| 610 | - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 611 | - if (!result) | ||
| 612 | - cpufreq_frequency_table_get_attr(freq_table, | ||
| 613 | - policy->cpu); | ||
| 614 | - } else { | ||
| 615 | - policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
| 616 | - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
| 617 | - VERY_HI_RATE) / 1000; | ||
| 618 | - } | ||
| 619 | - | ||
| 620 | - policy->min = policy->cpuinfo.min_freq; | ||
| 621 | - policy->max = policy->cpuinfo.max_freq; | ||
| 622 | - policy->cur = omap_getspeed(0); | ||
| 623 | - | ||
| 624 | - /* FIXME: what's the actual transition time? */ | ||
| 625 | - policy->cpuinfo.transition_latency = 300 * 1000; | ||
| 626 | - | ||
| 627 | - return 0; | ||
| 628 | -} | ||
| 629 | - | ||
| 630 | -static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
| 631 | -{ | ||
| 632 | - clk_exit_cpufreq_table(&freq_table); | ||
| 633 | - clk_put(mpu_clk); | ||
| 634 | - return 0; | ||
| 635 | -} | ||
| 636 | - | ||
| 637 | -static struct freq_attr *omap_cpufreq_attr[] = { | ||
| 638 | - &cpufreq_freq_attr_scaling_available_freqs, | ||
| 639 | - NULL, | ||
| 640 | -}; | ||
| 641 | - | ||
| 642 | -static struct cpufreq_driver omap_driver = { | ||
| 643 | - .flags = CPUFREQ_STICKY, | ||
| 644 | - .verify = omap_verify_speed, | ||
| 645 | - .target = omap_target, | ||
| 646 | - .get = omap_getspeed, | ||
| 647 | - .init = omap_cpu_init, | ||
| 648 | - .exit = omap_cpu_exit, | ||
| 649 | - .name = "omap", | ||
| 650 | - .attr = omap_cpufreq_attr, | ||
| 651 | -}; | ||
| 652 | - | ||
| 653 | -static int __init omap_cpufreq_init(void) | ||
| 654 | -{ | ||
| 655 | - return cpufreq_register_driver(&omap_driver); | ||
| 656 | -} | ||
| 657 | - | ||
| 658 | -late_initcall(omap_cpufreq_init); | ||
| 659 | - | ||
| 660 | -/* | ||
| 661 | - * if ever we want to remove this, upon cleanup call: | ||
| 662 | - * | ||
| 663 | - * cpufreq_unregister_driver() | ||
| 664 | - * cpufreq_frequency_table_put_attr() | ||
| 665 | - */ | ||
| 666 | - | ||
| 667 | -- | ||
| 668 | 1.6.6.1 | ||
| 669 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch new file mode 100644 index 00000000..6624d1ec --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | From f375d3c39d2835929d34c2a046b8c43cea6d1467 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 3 | Date: Mon, 14 Mar 2011 17:08:49 +0530 | ||
| 4 | Subject: [PATCH 7/8] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430 | ||
| 5 | |||
| 6 | On OMAP SMP configuartion, both processors share the voltage | ||
| 7 | and clock. So both CPUs needs to be scaled together and hence | ||
| 8 | needs software co-ordination. | ||
| 9 | |||
| 10 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 11 | Cc: Kevin Hilman <khilman@ti.com> | ||
| 12 | cc: Vishwanath BS <vishwanath.bs@ti.com> | ||
| 13 | --- | ||
| 14 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++----- | ||
| 15 | 1 files changed, 62 insertions(+), 11 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 18 | index 14f84cc..8d472f6 100644 | ||
| 19 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 20 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 21 | @@ -26,9 +26,11 @@ | ||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/opp.h> | ||
| 25 | +#include <linux/cpu.h> | ||
| 26 | |||
| 27 | #include <asm/system.h> | ||
| 28 | #include <asm/smp_plat.h> | ||
| 29 | +#include <asm/cpu.h> | ||
| 30 | |||
| 31 | #include <plat/clock.h> | ||
| 32 | #include <plat/omap-pm.h> | ||
| 33 | @@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu) | ||
| 34 | { | ||
| 35 | unsigned long rate; | ||
| 36 | |||
| 37 | - if (cpu) | ||
| 38 | + if (cpu >= NR_CPUS) | ||
| 39 | return 0; | ||
| 40 | |||
| 41 | rate = clk_get_rate(mpu_clk) / 1000; | ||
| 42 | @@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 43 | unsigned int target_freq, | ||
| 44 | unsigned int relation) | ||
| 45 | { | ||
| 46 | - int ret = 0; | ||
| 47 | + int i, ret = 0; | ||
| 48 | struct cpufreq_freqs freqs; | ||
| 49 | |||
| 50 | + /* Changes not allowed until all CPUs are online */ | ||
| 51 | + if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
| 52 | + return ret; | ||
| 53 | + | ||
| 54 | /* Ensure desired rate is within allowed range. Some govenors | ||
| 55 | * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
| 56 | if (target_freq < policy->min) | ||
| 57 | @@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 58 | if (target_freq > policy->max) | ||
| 59 | target_freq = policy->max; | ||
| 60 | |||
| 61 | - freqs.old = omap_getspeed(0); | ||
| 62 | + freqs.old = omap_getspeed(policy->cpu); | ||
| 63 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
| 64 | - freqs.cpu = 0; | ||
| 65 | + freqs.cpu = policy->cpu; | ||
| 66 | |||
| 67 | if (freqs.old == freqs.new) | ||
| 68 | return ret; | ||
| 69 | |||
| 70 | - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 71 | + if (!is_smp()) { | ||
| 72 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 73 | + goto set_freq; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /* notifiers */ | ||
| 77 | + for_each_cpu(i, policy->cpus) { | ||
| 78 | + freqs.cpu = i; | ||
| 79 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 80 | + } | ||
| 81 | |||
| 82 | +set_freq: | ||
| 83 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
| 84 | pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
| 85 | #endif | ||
| 86 | @@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy, | ||
| 87 | * CONFIG_SMP enabled. Below code is added only to manage that | ||
| 88 | * scenario | ||
| 89 | */ | ||
| 90 | - if (!is_smp()) | ||
| 91 | + freqs.new = omap_getspeed(policy->cpu); | ||
| 92 | + if (!is_smp()) { | ||
| 93 | loops_per_jiffy = | ||
| 94 | cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); | ||
| 95 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 96 | + goto skip_lpj; | ||
| 97 | + } | ||
| 98 | |||
| 99 | - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 100 | +#ifdef CONFIG_SMP | ||
| 101 | + /* | ||
| 102 | + * Note that loops_per_jiffy is not updated on SMP systems in | ||
| 103 | + * cpufreq driver. So, update the per-CPU loops_per_jiffy value | ||
| 104 | + * on frequency transition. We need to update all dependent CPUs. | ||
| 105 | + */ | ||
| 106 | + for_each_cpu(i, policy->cpus) | ||
| 107 | + per_cpu(cpu_data, i).loops_per_jiffy = | ||
| 108 | + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, | ||
| 109 | + freqs.old, freqs.new); | ||
| 110 | +#endif | ||
| 111 | |||
| 112 | + /* notifiers */ | ||
| 113 | + for_each_cpu(i, policy->cpus) { | ||
| 114 | + freqs.cpu = i; | ||
| 115 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | +skip_lpj: | ||
| 119 | return ret; | ||
| 120 | } | ||
| 121 | |||
| 122 | @@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 123 | { | ||
| 124 | int result = 0; | ||
| 125 | struct device *mpu_dev; | ||
| 126 | + static cpumask_var_t cpumask; | ||
| 127 | |||
| 128 | if (cpu_is_omap24xx()) | ||
| 129 | mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
| 130 | @@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 131 | if (IS_ERR(mpu_clk)) | ||
| 132 | return PTR_ERR(mpu_clk); | ||
| 133 | |||
| 134 | - if (policy->cpu != 0) | ||
| 135 | + if (policy->cpu >= NR_CPUS) | ||
| 136 | return -EINVAL; | ||
| 137 | |||
| 138 | - policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
| 139 | - | ||
| 140 | + policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); | ||
| 141 | mpu_dev = omap2_get_mpuss_device(); | ||
| 142 | + | ||
| 143 | if (!mpu_dev) { | ||
| 144 | pr_warning("%s: unable to get the mpu device\n", __func__); | ||
| 145 | return -EINVAL; | ||
| 146 | @@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 147 | |||
| 148 | policy->min = policy->cpuinfo.min_freq; | ||
| 149 | policy->max = policy->cpuinfo.max_freq; | ||
| 150 | - policy->cur = omap_getspeed(0); | ||
| 151 | + policy->cur = omap_getspeed(policy->cpu); | ||
| 152 | + | ||
| 153 | + /* | ||
| 154 | + * On OMAP SMP configuartion, both processors share the voltage | ||
| 155 | + * and clock. So both CPUs needs to be scaled together and hence | ||
| 156 | + * needs software co-ordination. Use cpufreq affected_cpus | ||
| 157 | + * interface to handle this scenario. Additional is_smp() check | ||
| 158 | + * is to keep SMP_ON_UP build working. | ||
| 159 | + */ | ||
| 160 | + if (is_smp()) { | ||
| 161 | + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; | ||
| 162 | + cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask); | ||
| 163 | + cpumask_copy(policy->cpus, cpumask); | ||
| 164 | + } | ||
| 165 | |||
| 166 | /* FIXME: what's the actual transition time? */ | ||
| 167 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
| 168 | -- | ||
| 169 | 1.6.6.1 | ||
| 170 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch new file mode 100644 index 00000000..3797443c --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | From 6e101764a47cb6975a555e2237843ad391a542a4 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jarkko Nikula <jhnikula@gmail.com> | ||
| 3 | Date: Thu, 14 Apr 2011 16:21:58 +0300 | ||
| 4 | Subject: [PATCH 8/8] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4 | ||
| 5 | |||
| 6 | Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly | ||
| 7 | trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available. | ||
| 8 | |||
| 9 | Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> | ||
| 10 | --- | ||
| 11 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +- | ||
| 12 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 15 | index 8d472f6..d53ce23 100644 | ||
| 16 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 17 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
| 18 | @@ -161,7 +161,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
| 19 | mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
| 20 | else if (cpu_is_omap34xx()) | ||
| 21 | mpu_clk = clk_get(NULL, "dpll1_ck"); | ||
| 22 | - else if (cpu_is_omap34xx()) | ||
| 23 | + else if (cpu_is_omap44xx()) | ||
| 24 | mpu_clk = clk_get(NULL, "dpll_mpu_ck"); | ||
| 25 | |||
| 26 | if (IS_ERR(mpu_clk)) | ||
| 27 | -- | ||
| 28 | 1.6.6.1 | ||
| 29 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch new file mode 100644 index 00000000..d9b05173 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | From 988f50cb51d18e81ed2f7673a09694d28c9d086a Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Tue, 5 Apr 2011 15:22:31 +0530 | ||
| 4 | Subject: [PATCH 1/6] OMAP2+: clockdomain: Add an api to read idle mode | ||
| 5 | |||
| 6 | Add a clockdomain api to check if hardware supervised | ||
| 7 | idle transitions are enabled on a clockdomain. | ||
| 8 | |||
| 9 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 10 | --- | ||
| 11 | arch/arm/mach-omap2/clockdomain.c | 21 +++++++++++++++++++++ | ||
| 12 | arch/arm/mach-omap2/clockdomain.h | 3 +++ | ||
| 13 | 2 files changed, 24 insertions(+), 0 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c | ||
| 16 | index 6cb6c03..2ab3686 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/clockdomain.c | ||
| 18 | +++ b/arch/arm/mach-omap2/clockdomain.c | ||
| 19 | @@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm) | ||
| 20 | arch_clkdm->clkdm_deny_idle(clkdm); | ||
| 21 | } | ||
| 22 | |||
| 23 | +/** | ||
| 24 | + * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled | ||
| 25 | + * @clkdm: struct clockdomain * | ||
| 26 | + * | ||
| 27 | + * Returns true if the clockdomain is in hardware-supervised | ||
| 28 | + * idle mode, or 0 otherwise. | ||
| 29 | + * | ||
| 30 | + */ | ||
| 31 | +int clkdm_is_idle(struct clockdomain *clkdm) | ||
| 32 | +{ | ||
| 33 | + if (!clkdm) | ||
| 34 | + return -EINVAL; | ||
| 35 | + | ||
| 36 | + if (!arch_clkdm || !arch_clkdm->clkdm_is_idle) | ||
| 37 | + return -EINVAL; | ||
| 38 | + | ||
| 39 | + pr_debug("clockdomain: reading idle state for %s\n", clkdm->name); | ||
| 40 | + | ||
| 41 | + return arch_clkdm->clkdm_is_idle(clkdm); | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | |||
| 45 | /* Clockdomain-to-clock framework interface code */ | ||
| 46 | |||
| 47 | diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h | ||
| 48 | index 5823584..085ed82 100644 | ||
| 49 | --- a/arch/arm/mach-omap2/clockdomain.h | ||
| 50 | +++ b/arch/arm/mach-omap2/clockdomain.h | ||
| 51 | @@ -138,6 +138,7 @@ struct clockdomain { | ||
| 52 | * @clkdm_wakeup: Force a clockdomain to wakeup | ||
| 53 | * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain | ||
| 54 | * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain | ||
| 55 | + * @clkdm_is_idle: Check if hw supervised idle transitions are enabled | ||
| 56 | * @clkdm_clk_enable: Put the clkdm in right state for a clock enable | ||
| 57 | * @clkdm_clk_disable: Put the clkdm in right state for a clock disable | ||
| 58 | */ | ||
| 59 | @@ -154,6 +155,7 @@ struct clkdm_ops { | ||
| 60 | int (*clkdm_wakeup)(struct clockdomain *clkdm); | ||
| 61 | void (*clkdm_allow_idle)(struct clockdomain *clkdm); | ||
| 62 | void (*clkdm_deny_idle)(struct clockdomain *clkdm); | ||
| 63 | + int (*clkdm_is_idle)(struct clockdomain *clkdm); | ||
| 64 | int (*clkdm_clk_enable)(struct clockdomain *clkdm); | ||
| 65 | int (*clkdm_clk_disable)(struct clockdomain *clkdm); | ||
| 66 | }; | ||
| 67 | @@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); | ||
| 68 | |||
| 69 | void clkdm_allow_idle(struct clockdomain *clkdm); | ||
| 70 | void clkdm_deny_idle(struct clockdomain *clkdm); | ||
| 71 | +int clkdm_is_idle(struct clockdomain *clkdm); | ||
| 72 | |||
| 73 | int clkdm_wakeup(struct clockdomain *clkdm); | ||
| 74 | int clkdm_sleep(struct clockdomain *clkdm); | ||
| 75 | -- | ||
| 76 | 1.6.6.1 | ||
| 77 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch new file mode 100644 index 00000000..c7c1ea0b --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | From e3ba8d41bfafd782f3ee7f8930d9bf393986c662 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Tue, 5 Apr 2011 15:22:36 +0530 | ||
| 4 | Subject: [PATCH 2/6] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle | ||
| 5 | |||
| 6 | Add the SoC specific implemenation for clkdm_is_idle | ||
| 7 | for OMAP2/3 and OMAP4. | ||
| 8 | |||
| 9 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 10 | --- | ||
| 11 | arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 12 ++++++++++++ | ||
| 12 | arch/arm/mach-omap2/clockdomain44xx.c | 7 +++++++ | ||
| 13 | 2 files changed, 19 insertions(+), 0 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | ||
| 16 | index 48d0db7..db49baa 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | ||
| 18 | +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | ||
| 19 | @@ -13,6 +13,7 @@ | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/types.h> | ||
| 23 | +#include <linux/errno.h> | ||
| 24 | #include <plat/prcm.h> | ||
| 25 | #include "prm.h" | ||
| 26 | #include "prm2xxx_3xxx.h" | ||
| 27 | @@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) | ||
| 28 | _clkdm_del_autodeps(clkdm); | ||
| 29 | } | ||
| 30 | |||
| 31 | +static int omap2_clkdm_is_idle(struct clockdomain *clkdm) | ||
| 32 | +{ | ||
| 33 | + if (!clkdm->clktrctrl_mask) | ||
| 34 | + return -1; | ||
| 35 | + | ||
| 36 | + return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
| 37 | + clkdm->clktrctrl_mask); | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | static void _enable_hwsup(struct clockdomain *clkdm) | ||
| 41 | { | ||
| 42 | if (cpu_is_omap24xx()) | ||
| 43 | @@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = { | ||
| 44 | .clkdm_wakeup = omap2_clkdm_wakeup, | ||
| 45 | .clkdm_allow_idle = omap2_clkdm_allow_idle, | ||
| 46 | .clkdm_deny_idle = omap2_clkdm_deny_idle, | ||
| 47 | + .clkdm_is_idle = omap2_clkdm_is_idle, | ||
| 48 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | ||
| 49 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | ||
| 50 | }; | ||
| 51 | @@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = { | ||
| 52 | .clkdm_wakeup = omap3_clkdm_wakeup, | ||
| 53 | .clkdm_allow_idle = omap3_clkdm_allow_idle, | ||
| 54 | .clkdm_deny_idle = omap3_clkdm_deny_idle, | ||
| 55 | + .clkdm_is_idle = omap2_clkdm_is_idle, | ||
| 56 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | ||
| 57 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | ||
| 58 | }; | ||
| 59 | diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c | ||
| 60 | index a1a4ecd..4b10727 100644 | ||
| 61 | --- a/arch/arm/mach-omap2/clockdomain44xx.c | ||
| 62 | +++ b/arch/arm/mach-omap2/clockdomain44xx.c | ||
| 63 | @@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) | ||
| 64 | clkdm->cm_inst, clkdm->clkdm_offs); | ||
| 65 | } | ||
| 66 | |||
| 67 | +static int omap4_clkdm_is_idle(struct clockdomain *clkdm) | ||
| 68 | +{ | ||
| 69 | + return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, | ||
| 70 | + clkdm->cm_inst, clkdm->clkdm_offs); | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) | ||
| 74 | { | ||
| 75 | bool hwsup = false; | ||
| 76 | @@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = { | ||
| 77 | .clkdm_wakeup = omap4_clkdm_wakeup, | ||
| 78 | .clkdm_allow_idle = omap4_clkdm_allow_idle, | ||
| 79 | .clkdm_deny_idle = omap4_clkdm_deny_idle, | ||
| 80 | + .clkdm_is_idle = omap4_clkdm_is_idle, | ||
| 81 | .clkdm_clk_enable = omap4_clkdm_clk_enable, | ||
| 82 | .clkdm_clk_disable = omap4_clkdm_clk_disable, | ||
| 83 | }; | ||
| 84 | -- | ||
| 85 | 1.6.6.1 | ||
| 86 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch new file mode 100644 index 00000000..cbe5ca20 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | From 7cdc87071a4bb390ad5d7ddea210bd2b4d662114 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Tue, 5 Apr 2011 15:22:41 +0530 | ||
| 4 | Subject: [PATCH 3/6] OMAP2+: PM: Initialise sleep_switch to a non-valid value | ||
| 5 | |||
| 6 | sleep_switch which is initialised to 0 in omap_set_pwrdm_state | ||
| 7 | happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH) | ||
| 8 | which are defined as | ||
| 9 | #define FORCEWAKEUP_SWITCH 0 | ||
| 10 | #define LOWPOWERSTATE_SWITCH 1 | ||
| 11 | |||
| 12 | This causes the function to wrongly program some clock domains | ||
| 13 | even when the Powerdomain is in ON state. | ||
| 14 | |||
| 15 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 16 | --- | ||
| 17 | arch/arm/mach-omap2/pm.c | 2 +- | ||
| 18 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
| 19 | |||
| 20 | diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c | ||
| 21 | index 49486f5..d48813f 100644 | ||
| 22 | --- a/arch/arm/mach-omap2/pm.c | ||
| 23 | +++ b/arch/arm/mach-omap2/pm.c | ||
| 24 | @@ -106,7 +106,7 @@ static void omap2_init_processor_devices(void) | ||
| 25 | int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
| 26 | { | ||
| 27 | u32 cur_state; | ||
| 28 | - int sleep_switch = 0; | ||
| 29 | + int sleep_switch = -1; | ||
| 30 | int ret = 0; | ||
| 31 | |||
| 32 | if (pwrdm == NULL || IS_ERR(pwrdm)) | ||
| 33 | -- | ||
| 34 | 1.6.6.1 | ||
| 35 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch new file mode 100644 index 00000000..16eedf9a --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | From cec133850aa42c03d912c764aaa441677e782eca Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Tue, 5 Apr 2011 15:22:48 +0530 | ||
| 4 | Subject: [PATCH 4/6] OMAP2+: PM: idle clkdms only if already in idle | ||
| 5 | |||
| 6 | The omap_set_pwrdm_state function forces clockdomains | ||
| 7 | to idle, without checking the existing idle state | ||
| 8 | programmed, instead based solely on the HW capability | ||
| 9 | of the clockdomain to support idle. | ||
| 10 | This is wrong and the clockdomains should be idled | ||
| 11 | post a state_switch *only* if idle transitions on the | ||
| 12 | clockdomain were already enabled. | ||
| 13 | |||
| 14 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 15 | --- | ||
| 16 | arch/arm/mach-omap2/pm.c | 4 +++- | ||
| 17 | 1 files changed, 3 insertions(+), 1 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c | ||
| 20 | index d48813f..840b0e1 100644 | ||
| 21 | --- a/arch/arm/mach-omap2/pm.c | ||
| 22 | +++ b/arch/arm/mach-omap2/pm.c | ||
| 23 | @@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
| 24 | u32 cur_state; | ||
| 25 | int sleep_switch = -1; | ||
| 26 | int ret = 0; | ||
| 27 | + int hwsup = 0; | ||
| 28 | |||
| 29 | if (pwrdm == NULL || IS_ERR(pwrdm)) | ||
| 30 | return -EINVAL; | ||
| 31 | @@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
| 32 | (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { | ||
| 33 | sleep_switch = LOWPOWERSTATE_SWITCH; | ||
| 34 | } else { | ||
| 35 | + hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]); | ||
| 36 | clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); | ||
| 37 | pwrdm_wait_transition(pwrdm); | ||
| 38 | sleep_switch = FORCEWAKEUP_SWITCH; | ||
| 39 | @@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
| 40 | |||
| 41 | switch (sleep_switch) { | ||
| 42 | case FORCEWAKEUP_SWITCH: | ||
| 43 | - if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) | ||
| 44 | + if (hwsup) | ||
| 45 | clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); | ||
| 46 | else | ||
| 47 | clkdm_sleep(pwrdm->pwrdm_clkdms[0]); | ||
| 48 | -- | ||
| 49 | 1.6.6.1 | ||
| 50 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch new file mode 100644 index 00000000..b0af9e7f --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | From 8fb6b7c488b31fbff5b81bdeea5dbb236342458b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Tue, 29 Mar 2011 22:37:43 +0530 | ||
| 4 | Subject: [PATCH 5/6] OMAP2+: hwmod: Follow the recomended PRCM sequence | ||
| 5 | |||
| 6 | Follow the recomended PRCM sequence. | ||
| 7 | This still does not take care of Optional clocks. | ||
| 8 | |||
| 9 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 10 | --- | ||
| 11 | arch/arm/mach-omap2/omap_hwmod.c | 9 ++++++++- | ||
| 12 | 1 files changed, 8 insertions(+), 1 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c | ||
| 15 | index e034294..fc0db0c 100644 | ||
| 16 | --- a/arch/arm/mach-omap2/omap_hwmod.c | ||
| 17 | +++ b/arch/arm/mach-omap2/omap_hwmod.c | ||
| 18 | @@ -1223,6 +1223,7 @@ static int _reset(struct omap_hwmod *oh) | ||
| 19 | static int _enable(struct omap_hwmod *oh) | ||
| 20 | { | ||
| 21 | int r; | ||
| 22 | + int hwsup = 0; | ||
| 23 | |||
| 24 | if (oh->_state != _HWMOD_STATE_INITIALIZED && | ||
| 25 | oh->_state != _HWMOD_STATE_IDLE && | ||
| 26 | @@ -1250,10 +1251,16 @@ static int _enable(struct omap_hwmod *oh) | ||
| 27 | omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); | ||
| 28 | |||
| 29 | _add_initiator_dep(oh, mpu_oh); | ||
| 30 | + if (oh->_clk && oh->_clk->clkdm) { | ||
| 31 | + hwsup = clkdm_is_idle(oh->_clk->clkdm); | ||
| 32 | + clkdm_wakeup(oh->_clk->clkdm); | ||
| 33 | + } | ||
| 34 | _enable_clocks(oh); | ||
| 35 | - | ||
| 36 | r = _wait_target_ready(oh); | ||
| 37 | if (!r) { | ||
| 38 | + if (oh->_clk && oh->_clk->clkdm && hwsup) | ||
| 39 | + clkdm_allow_idle(oh->_clk->clkdm); | ||
| 40 | + | ||
| 41 | oh->_state = _HWMOD_STATE_ENABLED; | ||
| 42 | |||
| 43 | /* Access the sysconfig only if the target is ready */ | ||
| 44 | -- | ||
| 45 | 1.6.6.1 | ||
| 46 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch new file mode 100644 index 00000000..a8fc0c07 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | From 7b74888d198c260992349fab214cad3adf853ef9 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rajendra Nayak <rnayak@ti.com> | ||
| 3 | Date: Tue, 2 Mar 2010 17:25:30 +0530 | ||
| 4 | Subject: [PATCH 6/6] OMAP: Serial: Check wk_st only if present | ||
| 5 | |||
| 6 | Uart on the resume path tries to read wk_st registers, even | ||
| 7 | on architectures were its not present/populated. | ||
| 8 | This patch fixes the issue. | ||
| 9 | |||
| 10 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/serial.c | 5 +++-- | ||
| 13 | 1 files changed, 3 insertions(+), 2 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c | ||
| 16 | index 1ac361b..a0046ce 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/serial.c | ||
| 18 | +++ b/arch/arm/mach-omap2/serial.c | ||
| 19 | @@ -418,8 +418,9 @@ void omap_uart_resume_idle(int num) | ||
| 20 | } | ||
| 21 | |||
| 22 | /* Check for normal UART wakeup */ | ||
| 23 | - if (__raw_readl(uart->wk_st) & uart->wk_mask) | ||
| 24 | - omap_uart_block_sleep(uart); | ||
| 25 | + if (uart->wk_st && uart->wk_mask) | ||
| 26 | + if (__raw_readl(uart->wk_st) & uart->wk_mask) | ||
| 27 | + omap_uart_block_sleep(uart); | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | -- | ||
| 32 | 1.6.6.1 | ||
| 33 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch new file mode 100644 index 00000000..0d1cbce6 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | From 4af697edf9d1d85d2735e86e86e1203c3509dcba Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Sat, 12 Feb 2011 17:27:14 +0530 | ||
| 4 | Subject: [PATCH 01/12] OMAP3+: voltage: remove spurious pr_notice for debugfs | ||
| 5 | |||
| 6 | cat of debugfs entry for vp_volt provides voltage. The additional pr_notice | ||
| 7 | is just spam on console and provides no additional information. | ||
| 8 | |||
| 9 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 10 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 11 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 12 | --- | ||
| 13 | arch/arm/mach-omap2/voltage.c | 1 - | ||
| 14 | 1 files changed, 0 insertions(+), 1 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c | ||
| 17 | index 0c1552d..9ef3789 100644 | ||
| 18 | --- a/arch/arm/mach-omap2/voltage.c | ||
| 19 | +++ b/arch/arm/mach-omap2/voltage.c | ||
| 20 | @@ -148,7 +148,6 @@ static int vp_volt_debug_get(void *data, u64 *val) | ||
| 21 | } | ||
| 22 | |||
| 23 | vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); | ||
| 24 | - pr_notice("curr_vsel = %x\n", vsel); | ||
| 25 | |||
| 26 | if (!vdd->pmic_info->vsel_to_uv) { | ||
| 27 | pr_warning("PMIC function to convert vsel to voltage" | ||
| 28 | -- | ||
| 29 | 1.6.6.1 | ||
| 30 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch new file mode 100644 index 00000000..7b137925 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | From 37fb1c8eeecd39542716d3d0c7c5e3ca0eb198f8 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Sun, 13 Mar 2011 09:07:23 +0530 | ||
| 4 | Subject: [PATCH 02/12] OMAP4: PM: remove redundant #ifdef CONFIG_PM | ||
| 5 | |||
| 6 | pm44xx.c is built only when CONFIG_PM is setup, | ||
| 7 | remove redundant CONFIG_PM check. | ||
| 8 | |||
| 9 | This also fixes: | ||
| 10 | https://bugzilla.kernel.org/show_bug.cgi?id=25022 | ||
| 11 | |||
| 12 | Reported-by: Martin Etti <ettl.martin@gmx.de> | ||
| 13 | |||
| 14 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 15 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 16 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 17 | --- | ||
| 18 | arch/arm/mach-omap2/pm44xx.c | 2 -- | ||
| 19 | 1 files changed, 0 insertions(+), 2 deletions(-) | ||
| 20 | |||
| 21 | diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c | ||
| 22 | index 76cfff2..59a870b 100644 | ||
| 23 | --- a/arch/arm/mach-omap2/pm44xx.c | ||
| 24 | +++ b/arch/arm/mach-omap2/pm44xx.c | ||
| 25 | @@ -105,13 +105,11 @@ static int __init omap4_pm_init(void) | ||
| 26 | |||
| 27 | pr_err("Power Management for TI OMAP4.\n"); | ||
| 28 | |||
| 29 | -#ifdef CONFIG_PM | ||
| 30 | ret = pwrdm_for_each(pwrdms_setup, NULL); | ||
| 31 | if (ret) { | ||
| 32 | pr_err("Failed to setup powerdomains\n"); | ||
| 33 | goto err2; | ||
| 34 | } | ||
| 35 | -#endif | ||
| 36 | |||
| 37 | #ifdef CONFIG_SUSPEND | ||
| 38 | suspend_set_ops(&omap_pm_ops); | ||
| 39 | -- | ||
| 40 | 1.6.6.1 | ||
| 41 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch new file mode 100644 index 00000000..6c37b622 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | From a22a0dcefe99c8ee260e0c489bc44e6e14bb1ccb Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 3 | Date: Thu, 24 Mar 2011 18:35:31 +0200 | ||
| 4 | Subject: [PATCH 03/12] OMAP3+: smartreflex: fix sr_late_init() error path in probe | ||
| 5 | |||
| 6 | sr_late_init() will take care of freeing the resources. | ||
| 7 | |||
| 8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/smartreflex.c | 2 +- | ||
| 13 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 16 | index 13e24f9..dbc4b6f 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 19 | @@ -883,7 +883,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 20 | ret = sr_late_init(sr_info); | ||
| 21 | if (ret) { | ||
| 22 | pr_warning("%s: Error in SR late init\n", __func__); | ||
| 23 | - goto err_release_region; | ||
| 24 | + return ret; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | -- | ||
| 29 | 1.6.6.1 | ||
| 30 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch new file mode 100644 index 00000000..263094d5 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | From db9c7da6a78be8584c96c83a3a2d1c8aeb623da8 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 3 | Date: Thu, 24 Mar 2011 18:35:32 +0200 | ||
| 4 | Subject: [PATCH 04/12] OMAP3+: smartreflex: request the memory region | ||
| 5 | |||
| 6 | We are releasing the memory region, but never actually request it. | ||
| 7 | |||
| 8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/smartreflex.c | 8 ++++++++ | ||
| 13 | 1 files changed, 8 insertions(+), 0 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 16 | index dbc4b6f..703143a 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 19 | @@ -847,6 +847,14 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 20 | goto err_free_devinfo; | ||
| 21 | } | ||
| 22 | |||
| 23 | + mem = request_mem_region(mem->start, resource_size(mem), | ||
| 24 | + dev_name(&pdev->dev)); | ||
| 25 | + if (!mem) { | ||
| 26 | + dev_err(&pdev->dev, "%s: no mem region\n", __func__); | ||
| 27 | + ret = -EBUSY; | ||
| 28 | + goto err_free_devinfo; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 32 | |||
| 33 | pm_runtime_enable(&pdev->dev); | ||
| 34 | -- | ||
| 35 | 1.6.6.1 | ||
| 36 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch new file mode 100644 index 00000000..ea1e5673 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | From b3ca51ac09da7c260c28df396d4c830814697ff0 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 3 | Date: Thu, 24 Mar 2011 18:35:33 +0200 | ||
| 4 | Subject: [PATCH 05/12] OMAP3+: smartreflex: fix ioremap leak on probe error | ||
| 5 | |||
| 6 | Add missing iounmap() to error paths. | ||
| 7 | |||
| 8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/smartreflex.c | 10 ++++++---- | ||
| 13 | 1 files changed, 6 insertions(+), 4 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 16 | index 703143a..156807e 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 19 | @@ -904,7 +904,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 20 | vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm); | ||
| 21 | if (!vdd_dbg_dir) { | ||
| 22 | ret = -EINVAL; | ||
| 23 | - goto err_release_region; | ||
| 24 | + goto err_iounmap; | ||
| 25 | } | ||
| 26 | |||
| 27 | sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir); | ||
| 28 | @@ -912,7 +912,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 29 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", | ||
| 30 | __func__); | ||
| 31 | ret = PTR_ERR(sr_info->dbg_dir); | ||
| 32 | - goto err_release_region; | ||
| 33 | + goto err_iounmap; | ||
| 34 | } | ||
| 35 | |||
| 36 | (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, | ||
| 37 | @@ -929,7 +929,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 38 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory" | ||
| 39 | "for n-values\n", __func__); | ||
| 40 | ret = PTR_ERR(nvalue_dir); | ||
| 41 | - goto err_release_region; | ||
| 42 | + goto err_iounmap; | ||
| 43 | } | ||
| 44 | |||
| 45 | omap_voltage_get_volttable(sr_info->voltdm, &volt_data); | ||
| 46 | @@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 47 | "entries for n-values\n", | ||
| 48 | __func__, sr_info->voltdm->name); | ||
| 49 | ret = -ENODATA; | ||
| 50 | - goto err_release_region; | ||
| 51 | + goto err_iounmap; | ||
| 52 | } | ||
| 53 | |||
| 54 | for (i = 0; i < sr_info->nvalue_count; i++) { | ||
| 55 | @@ -953,6 +953,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 56 | |||
| 57 | return ret; | ||
| 58 | |||
| 59 | +err_iounmap: | ||
| 60 | + iounmap(sr_info->base); | ||
| 61 | err_release_region: | ||
| 62 | release_mem_region(mem->start, resource_size(mem)); | ||
| 63 | err_free_devinfo: | ||
| 64 | -- | ||
| 65 | 1.6.6.1 | ||
| 66 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch new file mode 100644 index 00000000..cda6da63 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | From 92e63a2f098ce344cfc51ec9a7420e1a5cf85c3e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 3 | Date: Thu, 24 Mar 2011 18:35:34 +0200 | ||
| 4 | Subject: [PATCH 06/12] OMAP3+: smartreflex: delete instance from sr_list on probe error | ||
| 5 | |||
| 6 | If the probe fails, the node should be deleted from sr_list. | ||
| 7 | |||
| 8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/smartreflex.c | 1 + | ||
| 13 | 1 files changed, 1 insertions(+), 0 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 16 | index 156807e..f0a488a 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 19 | @@ -954,6 +954,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 20 | return ret; | ||
| 21 | |||
| 22 | err_iounmap: | ||
| 23 | + list_del(&sr_info->node); | ||
| 24 | iounmap(sr_info->base); | ||
| 25 | err_release_region: | ||
| 26 | release_mem_region(mem->start, resource_size(mem)); | ||
| 27 | -- | ||
| 28 | 1.6.6.1 | ||
| 29 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch new file mode 100644 index 00000000..d4543a46 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | From c194377152df812bcb29fff8f217ffbde59089be Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 3 | Date: Thu, 24 Mar 2011 18:35:35 +0200 | ||
| 4 | Subject: [PATCH 07/12] OMAP3+: smartreflex: delete debugfs entries on probe error | ||
| 5 | |||
| 6 | Delete created debugfs entries if probe fails. | ||
| 7 | |||
| 8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
| 9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 11 | --- | ||
| 12 | arch/arm/mach-omap2/smartreflex.c | 6 ++++-- | ||
| 13 | 1 files changed, 4 insertions(+), 2 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 16 | index f0a488a..fb7dc52 100644 | ||
| 17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 19 | @@ -929,7 +929,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 20 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory" | ||
| 21 | "for n-values\n", __func__); | ||
| 22 | ret = PTR_ERR(nvalue_dir); | ||
| 23 | - goto err_iounmap; | ||
| 24 | + goto err_debugfs; | ||
| 25 | } | ||
| 26 | |||
| 27 | omap_voltage_get_volttable(sr_info->voltdm, &volt_data); | ||
| 28 | @@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 29 | "entries for n-values\n", | ||
| 30 | __func__, sr_info->voltdm->name); | ||
| 31 | ret = -ENODATA; | ||
| 32 | - goto err_iounmap; | ||
| 33 | + goto err_debugfs; | ||
| 34 | } | ||
| 35 | |||
| 36 | for (i = 0; i < sr_info->nvalue_count; i++) { | ||
| 37 | @@ -953,6 +953,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
| 38 | |||
| 39 | return ret; | ||
| 40 | |||
| 41 | +err_debugfs: | ||
| 42 | + debugfs_remove_recursive(sr_info->dbg_dir); | ||
| 43 | err_iounmap: | ||
| 44 | list_del(&sr_info->node); | ||
| 45 | iounmap(sr_info->base); | ||
| 46 | -- | ||
| 47 | 1.6.6.1 | ||
| 48 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch new file mode 100644 index 00000000..e3ee0412 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | From 2b9e07516cc3853340b5e06e9ae7244ca5681466 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jean Pihet <j-pihet@ti.com> | ||
| 3 | Date: Fri, 29 Apr 2011 11:26:22 +0200 | ||
| 4 | Subject: [PATCH 08/12] OMAP3 cpuidle: remove useless SDP specific timings | ||
| 5 | |||
| 6 | The cpuidle states settings can be overriden by some board- | ||
| 7 | specific settings, by calling omap3_pm_init_cpuidle. | ||
| 8 | Remove the 3430SDP specific states settings registration | ||
| 9 | since the figures are identical to the default ones (in cpuidle34xx.c). | ||
| 10 | |||
| 11 | Signed-off-by: Jean Pihet <j-pihet@ti.com> | ||
| 12 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 13 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 14 | --- | ||
| 15 | arch/arm/mach-omap2/board-3430sdp.c | 19 ------------------- | ||
| 16 | 1 files changed, 0 insertions(+), 19 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c | ||
| 19 | index 9afd087..7ffad7b 100644 | ||
| 20 | --- a/arch/arm/mach-omap2/board-3430sdp.c | ||
| 21 | +++ b/arch/arm/mach-omap2/board-3430sdp.c | ||
| 22 | @@ -59,24 +59,6 @@ | ||
| 23 | |||
| 24 | #define TWL4030_MSECURE_GPIO 22 | ||
| 25 | |||
| 26 | -/* FIXME: These values need to be updated based on more profiling on 3430sdp*/ | ||
| 27 | -static struct cpuidle_params omap3_cpuidle_params_table[] = { | ||
| 28 | - /* C1 */ | ||
| 29 | - {1, 2, 2, 5}, | ||
| 30 | - /* C2 */ | ||
| 31 | - {1, 10, 10, 30}, | ||
| 32 | - /* C3 */ | ||
| 33 | - {1, 50, 50, 300}, | ||
| 34 | - /* C4 */ | ||
| 35 | - {1, 1500, 1800, 4000}, | ||
| 36 | - /* C5 */ | ||
| 37 | - {1, 2500, 7500, 12000}, | ||
| 38 | - /* C6 */ | ||
| 39 | - {1, 3000, 8500, 15000}, | ||
| 40 | - /* C7 */ | ||
| 41 | - {1, 10000, 30000, 300000}, | ||
| 42 | -}; | ||
| 43 | - | ||
| 44 | static uint32_t board_keymap[] = { | ||
| 45 | KEY(0, 0, KEY_LEFT), | ||
| 46 | KEY(0, 1, KEY_RIGHT), | ||
| 47 | @@ -883,7 +865,6 @@ static void __init omap_3430sdp_init(void) | ||
| 48 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | ||
| 49 | omap_board_config = sdp3430_config; | ||
| 50 | omap_board_config_size = ARRAY_SIZE(sdp3430_config); | ||
| 51 | - omap3_pm_init_cpuidle(omap3_cpuidle_params_table); | ||
| 52 | omap3430_i2c_init(); | ||
| 53 | omap_display_init(&sdp3430_dss_data); | ||
| 54 | if (omap_rev() > OMAP3430_REV_ES1_0) | ||
| 55 | -- | ||
| 56 | 1.6.6.1 | ||
| 57 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch new file mode 100644 index 00000000..c44371df --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | From a0f28097b944930e479998780863b9e5a39e30b3 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Mon, 14 Feb 2011 12:16:36 +0530 | ||
| 4 | Subject: [PATCH 09/12] OMAP3+: SR: make notify independent of class | ||
| 5 | |||
| 6 | Interrupt notification mechanism of SmartReflex can be used by the | ||
| 7 | choice of implementation of the class driver. For example, Class 2 and | ||
| 8 | Class 1.5 of SmartReflex can both use the interrupt notification to | ||
| 9 | identify the transition of voltage or other events. | ||
| 10 | |||
| 11 | Hence, the actual class does not matter for notifier. Let the class | ||
| 12 | driver's handling decide how it should be used. SmartReflex driver | ||
| 13 | should provide just the primitives. | ||
| 14 | |||
| 15 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 16 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 17 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 18 | --- | ||
| 19 | arch/arm/mach-omap2/smartreflex.c | 6 ++---- | ||
| 20 | 1 files changed, 2 insertions(+), 4 deletions(-) | ||
| 21 | |||
| 22 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 23 | index fb7dc52..3ee7261 100644 | ||
| 24 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 25 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 26 | @@ -143,7 +143,7 @@ static irqreturn_t sr_interrupt(int irq, void *data) | ||
| 27 | sr_write_reg(sr_info, IRQSTATUS, status); | ||
| 28 | } | ||
| 29 | |||
| 30 | - if (sr_class->class_type == SR_CLASS2 && sr_class->notify) | ||
| 31 | + if (sr_class->notify) | ||
| 32 | sr_class->notify(sr_info->voltdm, status); | ||
| 33 | |||
| 34 | return IRQ_HANDLED; | ||
| 35 | @@ -258,9 +258,7 @@ static int sr_late_init(struct omap_sr *sr_info) | ||
| 36 | struct resource *mem; | ||
| 37 | int ret = 0; | ||
| 38 | |||
| 39 | - if (sr_class->class_type == SR_CLASS2 && | ||
| 40 | - sr_class->notify_flags && sr_info->irq) { | ||
| 41 | - | ||
| 42 | + if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { | ||
| 43 | name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name); | ||
| 44 | if (name == NULL) { | ||
| 45 | ret = -ENOMEM; | ||
| 46 | -- | ||
| 47 | 1.6.6.1 | ||
| 48 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch new file mode 100644 index 00000000..e25c3e86 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | From ca5dc57538a566681731102e09a9d1865a4a7020 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Mon, 14 Feb 2011 12:41:10 +0530 | ||
| 4 | Subject: [PATCH 10/12] OMAP3+: SR: disable interrupt by default | ||
| 5 | |||
| 6 | We will enable and disable interrupt on a need basis in the class | ||
| 7 | driver. We need to keep the IRQ disabled by default else the | ||
| 8 | forceupdate or vcbypass events could trigger events that we don't | ||
| 9 | need/expect to handle. | ||
| 10 | |||
| 11 | This is a preparation for SmartReflex AVS class drivers such as | ||
| 12 | class 2 and class 1.5 which would need to use interrupts. Existing | ||
| 13 | SmartReflex AVS class 3 driver does not require to use interrupts | ||
| 14 | and is not impacted by this change. | ||
| 15 | |||
| 16 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 17 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 18 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 19 | --- | ||
| 20 | arch/arm/mach-omap2/smartreflex.c | 1 + | ||
| 21 | 1 files changed, 1 insertions(+), 0 deletions(-) | ||
| 22 | |||
| 23 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 24 | index 3ee7261..616ef62 100644 | ||
| 25 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 26 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 27 | @@ -268,6 +268,7 @@ static int sr_late_init(struct omap_sr *sr_info) | ||
| 28 | 0, name, (void *)sr_info); | ||
| 29 | if (ret) | ||
| 30 | goto error; | ||
| 31 | + disable_irq(sr_info->irq); | ||
| 32 | } | ||
| 33 | |||
| 34 | if (pdata && pdata->enable_on_init) | ||
| 35 | -- | ||
| 36 | 1.6.6.1 | ||
| 37 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch new file mode 100644 index 00000000..b96682ea --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | From 4aa67e94d6b13905abcf3e95cb66ea7be9c2e8dd Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Mon, 14 Feb 2011 21:14:17 +0530 | ||
| 4 | Subject: [PATCH 11/12] OMAP3+: SR: enable/disable SR only on need | ||
| 5 | |||
| 6 | Since we already know the state of the autocomp enablement, we can | ||
| 7 | see if the requested state is different from the current state and | ||
| 8 | enable/disable SR only on the need basis. | ||
| 9 | |||
| 10 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 11 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 12 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 13 | --- | ||
| 14 | arch/arm/mach-omap2/smartreflex.c | 11 +++++++---- | ||
| 15 | 1 files changed, 7 insertions(+), 4 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 18 | index 616ef62..3bd9fac 100644 | ||
| 19 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 20 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 21 | @@ -807,10 +807,13 @@ static int omap_sr_autocomp_store(void *data, u64 val) | ||
| 22 | return -EINVAL; | ||
| 23 | } | ||
| 24 | |||
| 25 | - if (!val) | ||
| 26 | - sr_stop_vddautocomp(sr_info); | ||
| 27 | - else | ||
| 28 | - sr_start_vddautocomp(sr_info); | ||
| 29 | + /* control enable/disable only if there is a delta in value */ | ||
| 30 | + if (sr_info->autocomp_active != val) { | ||
| 31 | + if (!val) | ||
| 32 | + sr_stop_vddautocomp(sr_info); | ||
| 33 | + else | ||
| 34 | + sr_start_vddautocomp(sr_info); | ||
| 35 | + } | ||
| 36 | |||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | -- | ||
| 40 | 1.6.6.1 | ||
| 41 | |||
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch new file mode 100644 index 00000000..eda76a0d --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | From 0c2089eecdfc3a85a376eddf9c77857f3d575be6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nishanth Menon <nm@ti.com> | ||
| 3 | Date: Mon, 14 Feb 2011 12:33:13 +0530 | ||
| 4 | Subject: [PATCH 12/12] OMAP3+: SR: fix cosmetic indentation | ||
| 5 | |||
| 6 | Error label case seems to have a 2 tab indentation when just 1 is | ||
| 7 | necessary. | ||
| 8 | |||
| 9 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
| 10 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
| 11 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
| 12 | --- | ||
| 13 | arch/arm/mach-omap2/smartreflex.c | 20 ++++++++++---------- | ||
| 14 | 1 files changed, 10 insertions(+), 10 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
| 17 | index 3bd9fac..2ce2fb7 100644 | ||
| 18 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
| 19 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
| 20 | @@ -277,16 +277,16 @@ static int sr_late_init(struct omap_sr *sr_info) | ||
| 21 | return ret; | ||
| 22 | |||
| 23 | error: | ||
| 24 | - iounmap(sr_info->base); | ||
| 25 | - mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); | ||
| 26 | - release_mem_region(mem->start, resource_size(mem)); | ||
| 27 | - list_del(&sr_info->node); | ||
| 28 | - dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" | ||
| 29 | - "interrupt handler. Smartreflex will" | ||
| 30 | - "not function as desired\n", __func__); | ||
| 31 | - kfree(name); | ||
| 32 | - kfree(sr_info); | ||
| 33 | - return ret; | ||
| 34 | + iounmap(sr_info->base); | ||
| 35 | + mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); | ||
| 36 | + release_mem_region(mem->start, resource_size(mem)); | ||
| 37 | + list_del(&sr_info->node); | ||
| 38 | + dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" | ||
| 39 | + "interrupt handler. Smartreflex will" | ||
| 40 | + "not function as desired\n", __func__); | ||
| 41 | + kfree(name); | ||
| 42 | + kfree(sr_info); | ||
| 43 | + return ret; | ||
| 44 | } | ||
| 45 | |||
| 46 | static void sr_v1_disable(struct omap_sr *sr) | ||
| 47 | -- | ||
| 48 | 1.6.6.1 | ||
| 49 | |||
