|
|
@@ -11,6 +11,7 @@
|
|
|
#include <linux/cpuidle.h>
|
|
|
#include <linux/cpu.h>
|
|
|
#include <linux/notifier.h>
|
|
|
+#include <linux/clockchips.h>
|
|
|
|
|
|
#include <asm/machdep.h>
|
|
|
#include <asm/firmware.h>
|
|
|
@@ -49,6 +50,32 @@ static int nap_loop(struct cpuidle_device *dev,
|
|
|
return index;
|
|
|
}
|
|
|
|
|
|
+static int fastsleep_loop(struct cpuidle_device *dev,
|
|
|
+ struct cpuidle_driver *drv,
|
|
|
+ int index)
|
|
|
+{
|
|
|
+ unsigned long old_lpcr = mfspr(SPRN_LPCR);
|
|
|
+ unsigned long new_lpcr;
|
|
|
+
|
|
|
+ if (unlikely(system_state < SYSTEM_RUNNING))
|
|
|
+ return index;
|
|
|
+
|
|
|
+ new_lpcr = old_lpcr;
|
|
|
+ new_lpcr &= ~(LPCR_MER | LPCR_PECE); /* lpcr[mer] must be 0 */
|
|
|
+
|
|
|
+ /* exit powersave upon external interrupt, but not decrementer
|
|
|
+ * interrupt.
|
|
|
+ */
|
|
|
+ new_lpcr |= LPCR_PECE0;
|
|
|
+
|
|
|
+ mtspr(SPRN_LPCR, new_lpcr);
|
|
|
+ power7_sleep();
|
|
|
+
|
|
|
+ mtspr(SPRN_LPCR, old_lpcr);
|
|
|
+
|
|
|
+ return index;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* States for dedicated partition case.
|
|
|
*/
|
|
|
@@ -67,6 +94,13 @@ static struct cpuidle_state powernv_states[] = {
|
|
|
.exit_latency = 10,
|
|
|
.target_residency = 100,
|
|
|
.enter = &nap_loop },
|
|
|
+ { /* Fastsleep */
|
|
|
+ .name = "fastsleep",
|
|
|
+ .desc = "fastsleep",
|
|
|
+ .flags = CPUIDLE_FLAG_TIME_VALID,
|
|
|
+ .exit_latency = 10,
|
|
|
+ .target_residency = 100,
|
|
|
+ .enter = &fastsleep_loop },
|
|
|
};
|
|
|
|
|
|
static int powernv_cpuidle_add_cpu_notifier(struct notifier_block *n,
|