summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/time.c39
-rw-r--r--drivers/macintosh/via-pmu.c48
-rw-r--r--include/asm-powerpc/machdep.h13
3 files changed, 58 insertions, 42 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 85cf317c906..5cd3db5cae4 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -629,6 +629,45 @@ void wakeup_decrementer(void)
set_dec(ticks);
}
+#ifdef CONFIG_SUSPEND
+void generic_suspend_disable_irqs(void)
+{
+ preempt_disable();
+
+ /* Disable the decrementer, so that it doesn't interfere
+ * with suspending.
+ */
+
+ set_dec(0x7fffffff);
+ local_irq_disable();
+ set_dec(0x7fffffff);
+}
+
+void generic_suspend_enable_irqs(void)
+{
+ wakeup_decrementer();
+
+ local_irq_enable();
+ preempt_enable();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_disable_irqs(void)
+{
+ if (ppc_md.suspend_disable_irqs)
+ ppc_md.suspend_disable_irqs();
+ generic_suspend_disable_irqs();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_enable_irqs(void)
+{
+ generic_suspend_enable_irqs();
+ if (ppc_md.suspend_enable_irqs)
+ ppc_md.suspend_enable_irqs();
+}
+#endif
+
#ifdef CONFIG_SMP
void __init smp_space_timers(unsigned int max_cpus)
{
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 8f98257e6a1..7e77ac7e370 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -197,12 +197,6 @@ static int proc_read_options(char *page, char **start, off_t off,
static int proc_write_options(struct file *file, const char __user *buffer,
unsigned long count, void *data);
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
-static void powerbook_sleep_init_3400(void);
-#else
-#define powerbook_sleep_init_3400() do { } while (0)
-#endif
-
#ifdef CONFIG_ADB
struct adb_driver via_pmu_driver = {
"PMU",
@@ -450,10 +444,6 @@ static int __init via_pmu_start(void)
pmu_poll();
} while (pmu_state != idle);
- /* Do allocations and ioremaps that will be needed for sleep */
- if (pmu_kind == PMU_OHARE_BASED)
- powerbook_sleep_init_3400();
-
return 0;
}
@@ -2168,13 +2158,7 @@ pmu_release(struct inode *inode, struct file *file)
}
#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
-/*
- * overrides the weak arch_suspend_disable_irqs in kernel/power/main.c
- *
- * XXX: Once Scott Wood's patch is merged, this needs to use the ppc_md
- * hooks that patch adds!
- */
-void arch_suspend_disable_irqs(void)
+static void pmac_suspend_disable_irqs(void)
{
#ifdef CONFIG_PMAC_BACKLIGHT
/* Tell backlight code not to muck around with the chip anymore */
@@ -2184,18 +2168,6 @@ void arch_suspend_disable_irqs(void)
/* Call platform functions marked "on sleep" */
pmac_pfunc_i2c_suspend();
pmac_pfunc_base_suspend();
-
- /* Stop preemption */
- preempt_disable();
-
- /* Make sure the decrementer won't interrupt us */
- asm volatile("mtdec %0" : : "r" (0x7fffffff));
- /* Make sure any pending DEC interrupt occurring while we did
- * the above didn't re-enable the DEC */
- mb();
- asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
- local_irq_disable();
}
static int powerbook_sleep(suspend_state_t state)
@@ -2244,25 +2216,13 @@ static int powerbook_sleep(suspend_state_t state)
return 0;
}
-/*
- * overrides the weak arch_suspend_enable_irqs in kernel/power/main.c
- *
- * XXX: Once Scott Wood's patch is merged, this needs to use the ppc_md
- * hooks that patch adds!
- */
-void arch_suspend_enable_irqs(void)
+static void pmac_suspend_enable_irqs(void)
{
/* Force a poll of ADB interrupts */
adb_int_pending = 1;
via_pmu_interrupt(0, NULL);
- /* Restart jiffies & scheduling */
- wakeup_decrementer();
-
- /* Re-enable local CPU interrupts */
- local_irq_enable();
mdelay(10);
- preempt_enable();
/* Call platform functions marked "on wake" */
pmac_pfunc_base_resume();
@@ -2282,6 +2242,10 @@ static struct platform_suspend_ops pmu_pm_ops = {
static int register_pmu_pm_ops(void)
{
+ if (pmu_kind == PMU_OHARE_BASED)
+ powerbook_sleep_init_3400();
+ ppc_md.suspend_disable_irqs = pmac_suspend_disable_irqs;
+ ppc_md.suspend_enable_irqs = pmac_suspend_enable_irqs;
suspend_set_ops(&pmu_pm_ops);
return 0;
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 79c704ed538..0872ec228c1 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -251,6 +251,16 @@ struct machdep_calls {
*/
void (*machine_kexec)(struct kimage *image);
#endif /* CONFIG_KEXEC */
+
+#ifdef CONFIG_SUSPEND
+ /* These are called to disable and enable, respectively, IRQs when
+ * entering a suspend state. If NULL, then the generic versions
+ * will be called. The generic versions disable/enable the
+ * decrementer along with interrupts.
+ */
+ void (*suspend_disable_irqs)(void);
+ void (*suspend_enable_irqs)(void);
+#endif
};
extern void power4_idle(void);
@@ -347,5 +357,8 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
#define machine_late_initcall(mach,fn) __define_machine_initcall(mach,"7",fn,7)
#define machine_late_initcall_sync(mach,fn) __define_machine_initcall(mach,"7s",fn,7s)
+void generic_suspend_disable_irqs(void);
+void generic_suspend_enable_irqs(void);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MACHDEP_H */