diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-04 11:36:39 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-11 13:29:18 +0100 |
commit | 292ec42af7c6361435fe9df50cd59ec76f6741c6 (patch) | |
tree | 376c6bdc9f615988c19f9597020a8cde99005543 | |
parent | Merge branch 'next' of git://git.monstr.eu/linux-2.6-microblaze (diff) | |
download | linux-292ec42af7c6361435fe9df50cd59ec76f6741c6.tar.xz linux-292ec42af7c6361435fe9df50cd59ec76f6741c6.zip |
ARM: pm: add function to set WFI low-power mode for SMP CPUs
Add a function to set the SCU low-power mode for SMP CPUs. This
centralizes this functionality rather than having to expose the
SCU register definitions to each platform.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/include/asm/smp_scu.h | 7 | ||||
-rw-r--r-- | arch/arm/kernel/smp_scu.c | 23 |
2 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h index 2376835015d6..4eb6d005ffaa 100644 --- a/arch/arm/include/asm/smp_scu.h +++ b/arch/arm/include/asm/smp_scu.h @@ -1,7 +1,14 @@ #ifndef __ASMARM_ARCH_SCU_H #define __ASMARM_ARCH_SCU_H +#define SCU_PM_NORMAL 0 +#define SCU_PM_DORMANT 2 +#define SCU_PM_POWEROFF 3 + +#ifndef __ASSEMBLER__ unsigned int scu_get_core_count(void __iomem *); void scu_enable(void __iomem *); +int scu_power_mode(void __iomem *, unsigned int); +#endif #endif diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 9ab4149bd983..a1e757c3439b 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c @@ -50,3 +50,26 @@ void __init scu_enable(void __iomem *scu_base) */ flush_cache_all(); } + +/* + * Set the executing CPUs power mode as defined. This will be in + * preparation for it executing a WFI instruction. + * + * This function must be called with preemption disabled, and as it + * has the side effect of disabling coherency, caches must have been + * flushed. Interrupts must also have been disabled. + */ +int scu_power_mode(void __iomem *scu_base, unsigned int mode) +{ + unsigned int val; + int cpu = smp_processor_id(); + + if (mode > 3 || mode == 1 || cpu > 3) + return -EINVAL; + + val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; + val |= mode; + __raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu); + + return 0; +} |