diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-07-07 13:39:47 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-09-19 15:15:43 +0200 |
commit | 31470a483d96caf4d439fe41e8144bde728cf286 (patch) | |
tree | 05d860463de00efee669d4630c2bf0d7150f8303 /drivers/cpufreq | |
parent | f39ddd4052704c60a950c055b6f18f5aeed0c40e (diff) |
ux500: align u5500 PRCMU & CPUFREQ management with u8500 (multiple commits in one)
Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org>
Merge of following commits too:
u5500: add support for sysclk
basic sysclk support added in PRCMU driver and
clock framework driver updated.
Signed-off-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
U5500: Support for ESRAM12 EPOD in PRCMU driver
Signed-off-by: Vijaya Kumar Kilari <vijay.kilari@stericsson.com>
ux500: regulator: handle different base offset of ePOD ID
5500 ePOD ids are offseted for some reason in the PRCMU driver. Adjust the ids
to index the local arrays to avoid memory corruption.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
ux500: pm: support PRCMU status check on 5500
This also removes unused 8500v1 code.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
arm: ux500: prcmu_ac_wake_req workaround
This patch adds a check in prcmu_ac_wake_req that the modem is
awake (in terms of the value in the PRCM_MOD_AWAKE_STATUS
register) after the AC_WAKE_ACK has been received from the PRCMU
FW. If the check fails, a retry is made.
This seems to be necessary, since the modem can generate an
AC_WAKE_ACK, and then still go to sleep.
Signed-off-by: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
U5500: Add support for PRCMU Mailbox0
Add PRCMU mailbox 0 support for irq wakeup
enable and disable
Signed-off-by: Vijaya Kumar K <vijay.kilari@stericsson.com>
U5500: Add support for power state transition
PRCMU driver is updated to provide API for
system power state transition
Signed-off-by: Vijaya Kumar K <vijay.kilari@stericsson.com>
ARM: ux500: prcmu: Add A9 watchdog interface
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
U5500 : ab5500 core interrupt hander update
AB5500 interrupts will be now handled by PRCMU and then
routed to AB5500 core driver.AB5500 irq handler will
no more read the latch registers to find the interrupt
reason.Instead PRCMU will read the latch registers and
provide the values to core driver.
Signed-off-by: Bibek Basu <bibek.basu@stericsson.com>
ARM: ux500: prcmu-dbg: Tiny code clean-up
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
u5500: add mailbox1 and related function support
Add cpufreq-db5500.c file for db5500 CPUfreq support.
PRCMU mailbox1 and related functions' support is added.
List of functions implemented:
- prcmu_get/set_arm_opp
- read_mailbox_1
Signed-off-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
Fix for PRCMU
u5500: PRCMU IRQ should be NO_SUSPEND
As on 8500.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
ARM: u5500: PRCMU reset API
Added API for rebooting the board and for getting the last reboot code.
Signed-off-by: Pawel Szyszuk <pawel.szyszuk@stericsson.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/Makefile | 1 | ||||
-rw-r--r-- | drivers/cpufreq/db5500-cpufreq.c | 172 | ||||
-rw-r--r-- | drivers/cpufreq/db8500-cpufreq.c | 6 |
3 files changed, 178 insertions, 1 deletions
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index e2fc2d21fa6..a01791e7566 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o # ARM SoC drivers obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o +obj-$(CONFIG_UX500_SOC_DB5500) += db5500-cpufreq.o diff --git a/drivers/cpufreq/db5500-cpufreq.c b/drivers/cpufreq/db5500-cpufreq.c new file mode 100644 index 00000000000..7c78bcb4761 --- /dev/null +++ b/drivers/cpufreq/db5500-cpufreq.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Sundar Iyer <sundar.iyer@stericsson.com> + * Author: Martin Persson <martin.persson@stericsson.com> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * + */ +#include <linux/kernel.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <mach/prcmu.h> +#include <mach/id.h> + +static struct cpufreq_frequency_table freq_table[] = { + [0] = { + .index = 0, + .frequency = 200000, + }, + [1] = { + .index = 1, + .frequency = 300000, + }, + [2] = { + .index = 2, + .frequency = 600000, + }, + [3] = { + .index = 3, + .frequency = CPUFREQ_TABLE_END, + }, +}; + +static enum arm_opp idx2opp[] = { + ARM_EXTCLK, + ARM_50_OPP, + ARM_100_OPP +}; + +/* + * Below is a temporary workaround for wlan performance issues + */ + +#include <linux/kernel_stat.h> +#include <linux/workqueue.h> +#include <linux/cpu.h> + +#include <mach/irqs.h> + +static struct freq_attr *db5500_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static int db5500_cpufreq_verify_speed(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, freq_table); +} + +static int db5500_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + unsigned int idx; + + /* scale the target frequency to one of the extremes supported */ + if (target_freq < policy->cpuinfo.min_freq) + target_freq = policy->cpuinfo.min_freq; + if (target_freq > policy->cpuinfo.max_freq) + target_freq = policy->cpuinfo.max_freq; + + /* Lookup the next frequency */ + if (cpufreq_frequency_table_target + (policy, freq_table, target_freq, relation, &idx)) { + return -EINVAL; + } + + freqs.old = policy->cur; + freqs.new = freq_table[idx].frequency; + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new) + return 0; + + /* pre-change notification */ + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* request the PRCM unit for opp change */ + if (prcmu_set_arm_opp(idx2opp[idx])) { + pr_err("db5500-cpufreq: Failed to set OPP level\n"); + return -EINVAL; + } + + /* post change notification */ + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; +} + +static unsigned int db5500_cpufreq_getspeed(unsigned int cpu) +{ + int i; + /* request the prcm to get the current ARM opp */ + for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++) + ; + return freq_table[i].frequency; +} + +static int __cpuinit db5500_cpufreq_init(struct cpufreq_policy *policy) +{ + int res; + int i = 0; + + BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); + + pr_info("db5500-cpufreq : Available frequencies:\n"); + while (freq_table[i].frequency != CPUFREQ_TABLE_END) + pr_info(" %d Mhz\n", freq_table[i++].frequency/1000); + + /* get policy fields based on the table */ + res = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!res) + cpufreq_frequency_table_get_attr(freq_table, policy->cpu); + else { + pr_err("db5500-cpufreq : Failed to read policy table\n"); + return res; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = db5500_cpufreq_getspeed(policy->cpu); + + for (i = 0; freq_table[i].frequency != policy->cur; i++) + ; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + /* + * FIXME : Need to take time measurement across the target() + * function with no/some/all drivers in the notification + * list. + */ + policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ + + /* policy sharing between dual CPUs */ + cpumask_copy(policy->cpus, &cpu_present_map); + + policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; + + return 0; +} + +static struct cpufreq_driver db5500_cpufreq_driver = { + .flags = CPUFREQ_STICKY, + .verify = db5500_cpufreq_verify_speed, + .target = db5500_cpufreq_target, + .get = db5500_cpufreq_getspeed, + .init = db5500_cpufreq_init, + .name = "DB5500", + .attr = db5500_cpufreq_attr, +}; + +static int __init db5500_cpufreq_register(void) +{ + pr_info("cpufreq for DB5500 started\n"); + return cpufreq_register_driver(&db5500_cpufreq_driver); +} +device_initcall(db5500_cpufreq_register); diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 4943578f452..4b863110bd8 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -151,7 +151,7 @@ static unsigned int db8500_cpufreq_getspeed(unsigned int cpu) static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) { int res; - int i; + int i = 0; BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); @@ -169,6 +169,10 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) &work_wlan_workaround, msecs_to_jiffies(WLAN_PROBE_DELAY)); + pr_info("db8500-cpufreq : Available frequencies:\n"); + while (freq_table[i].frequency != CPUFREQ_TABLE_END) + pr_info(" %d Mhz\n", freq_table[i++].frequency/1000); + /* get policy fields based on the table */ res = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (!res) |