aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/kernel/time.c4
-rw-r--r--drivers/cpuidle/cpuidle-powernv.c34
3 files changed, 39 insertions, 1 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 957bf344c0f5..b84142000a4d 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -130,6 +130,8 @@ config PPC
130 select GENERIC_CMOS_UPDATE 130 select GENERIC_CMOS_UPDATE
131 select GENERIC_TIME_VSYSCALL_OLD 131 select GENERIC_TIME_VSYSCALL_OLD
132 select GENERIC_CLOCKEVENTS 132 select GENERIC_CLOCKEVENTS
133 select GENERIC_CLOCKEVENTS_BROADCAST if SMP
134 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
133 select GENERIC_STRNCPY_FROM_USER 135 select GENERIC_STRNCPY_FROM_USER
134 select GENERIC_STRNLEN_USER 136 select GENERIC_STRNLEN_USER
135 select HAVE_MOD_ARCH_SPECIFIC 137 select HAVE_MOD_ARCH_SPECIFIC
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index df2989b0d4c0..122a580f7322 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -42,6 +42,7 @@
42#include <linux/timex.h> 42#include <linux/timex.h>
43#include <linux/kernel_stat.h> 43#include <linux/kernel_stat.h>
44#include <linux/time.h> 44#include <linux/time.h>
45#include <linux/clockchips.h>
45#include <linux/init.h> 46#include <linux/init.h>
46#include <linux/profile.h> 47#include <linux/profile.h>
47#include <linux/cpu.h> 48#include <linux/cpu.h>
@@ -106,7 +107,7 @@ struct clock_event_device decrementer_clockevent = {
106 .irq = 0, 107 .irq = 0,
107 .set_next_event = decrementer_set_next_event, 108 .set_next_event = decrementer_set_next_event,
108 .set_mode = decrementer_set_mode, 109 .set_mode = decrementer_set_mode,
109 .features = CLOCK_EVT_FEAT_ONESHOT, 110 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP,
110}; 111};
111EXPORT_SYMBOL(decrementer_clockevent); 112EXPORT_SYMBOL(decrementer_clockevent);
112 113
@@ -944,6 +945,7 @@ void __init time_init(void)
944 clocksource_init(); 945 clocksource_init();
945 946
946 init_decrementer_clockevent(); 947 init_decrementer_clockevent();
948 tick_setup_hrtimer_broadcast();
947} 949}
948 950
949 951
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 78fd174c57e8..4fb97cef82fd 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -11,6 +11,7 @@
11#include <linux/cpuidle.h> 11#include <linux/cpuidle.h>
12#include <linux/cpu.h> 12#include <linux/cpu.h>
13#include <linux/notifier.h> 13#include <linux/notifier.h>
14#include <linux/clockchips.h>
14 15
15#include <asm/machdep.h> 16#include <asm/machdep.h>
16#include <asm/firmware.h> 17#include <asm/firmware.h>
@@ -49,6 +50,32 @@ static int nap_loop(struct cpuidle_device *dev,
49 return index; 50 return index;
50} 51}
51 52
53static int fastsleep_loop(struct cpuidle_device *dev,
54 struct cpuidle_driver *drv,
55 int index)
56{
57 unsigned long old_lpcr = mfspr(SPRN_LPCR);
58 unsigned long new_lpcr;
59
60 if (unlikely(system_state < SYSTEM_RUNNING))
61 return index;
62
63 new_lpcr = old_lpcr;
64 new_lpcr &= ~(LPCR_MER | LPCR_PECE); /* lpcr[mer] must be 0 */
65
66 /* exit powersave upon external interrupt, but not decrementer
67 * interrupt.
68 */
69 new_lpcr |= LPCR_PECE0;
70
71 mtspr(SPRN_LPCR, new_lpcr);
72 power7_sleep();
73
74 mtspr(SPRN_LPCR, old_lpcr);
75
76 return index;
77}
78
52/* 79/*
53 * States for dedicated partition case. 80 * States for dedicated partition case.
54 */ 81 */
@@ -67,6 +94,13 @@ static struct cpuidle_state powernv_states[] = {
67 .exit_latency = 10, 94 .exit_latency = 10,
68 .target_residency = 100, 95 .target_residency = 100,
69 .enter = &nap_loop }, 96 .enter = &nap_loop },
97 { /* Fastsleep */
98 .name = "fastsleep",
99 .desc = "fastsleep",
100 .flags = CPUIDLE_FLAG_TIME_VALID,
101 .exit_latency = 10,
102 .target_residency = 100,
103 .enter = &fastsleep_loop },
70}; 104};
71 105
72static int powernv_cpuidle_add_cpu_notifier(struct notifier_block *n, 106static int powernv_cpuidle_add_cpu_notifier(struct notifier_block *n,