ARM: EXYNOS4: Add support Core1 Power On/Off with hotplug in/out

To insert the code for power on/off with pmu control to support hotplug in/out core1
As for hotplug.c, the codes for core1 to be hotplug in/out is inserted.
As for regs-pmu.h, S5P_CORE_LOCAL_PWR_EN is defined.
As for platsmp.c, the codes for core1 to be powered on is inserted.

Signed-off-by: JungHi Min <junghi.min@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
This commit is contained in:
JungHi Min 2011-07-16 13:39:09 +09:00 committed by Kukjin Kim
parent 55981f7b3c
commit 911c29b0e5
3 changed files with 38 additions and 6 deletions

View File

@ -13,9 +13,12 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/io.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <mach/regs-pmu.h>
extern volatile int pen_release; extern volatile int pen_release;
static inline void cpu_enter_lowpower(void) static inline void cpu_enter_lowpower(void)
@ -58,12 +61,12 @@ static inline void cpu_leave_lowpower(void)
static inline void platform_do_lowpower(unsigned int cpu, int *spurious) static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{ {
/*
* there is no power-control hardware on this platform, so all
* we can do is put the core into WFI; this is safe as the calling
* code will have already disabled interrupts
*/
for (;;) { for (;;) {
/* make cpu1 to be turned off at next WFI command */
if (cpu == 1)
__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
/* /*
* here's the WFI * here's the WFI
*/ */

View File

@ -158,6 +158,7 @@
#define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0) #define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0)
#define S5P_PMU_SATA_PHY_CONTROL_EN 0x1 #define S5P_PMU_SATA_PHY_CONTROL_EN 0x1
#define S5P_CORE_LOCAL_PWR_EN 0x3
#define S5P_INT_LOCAL_PWR_EN 0x7 #define S5P_INT_LOCAL_PWR_EN 0x7
#define S5P_CHECK_SLEEP 0x00000BAD #define S5P_CHECK_SLEEP 0x00000BAD

View File

@ -28,9 +28,12 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
#include <mach/regs-pmu.h>
extern void exynos4_secondary_startup(void); extern void exynos4_secondary_startup(void);
#define CPU1_BOOT_REG S5P_VA_SYSRAM
/* /*
* control for which core is the next to come out of the secondary * control for which core is the next to come out of the secondary
* boot "holding pen" * boot "holding pen"
@ -125,16 +128,41 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
*/ */
write_pen_release(cpu); write_pen_release(cpu);
if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
__raw_writel(S5P_CORE_LOCAL_PWR_EN,
S5P_ARM_CORE1_CONFIGURATION);
timeout = 10;
/* wait max 10 ms until cpu1 is on */
while ((__raw_readl(S5P_ARM_CORE1_STATUS)
& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
if (timeout-- == 0)
break;
mdelay(1);
}
if (timeout == 0) {
printk(KERN_ERR "cpu1 power enable failed");
spin_unlock(&boot_lock);
return -ETIMEDOUT;
}
}
/* /*
* Send the secondary CPU a soft interrupt, thereby causing * Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register, * the boot monitor to read the system wide flags register,
* and branch to the address found there. * and branch to the address found there.
*/ */
gic_raise_softirq(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ); timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
smp_rmb(); smp_rmb();
__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
CPU1_BOOT_REG);
gic_raise_softirq(cpumask_of(cpu), 1);
if (pen_release == -1) if (pen_release == -1)
break; break;