Import 2.3.18pre1
[davej-history.git] / arch / sparc64 / kernel / power.c
blob83101112859093709178e13aa31d4dc786a45059
1 /* $Id: power.c,v 1.4 1999/08/31 18:22:05 davem Exp $
2 * power.c: Power management driver.
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
5 */
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/sched.h>
11 #include <linux/signal.h>
12 #include <linux/delay.h>
14 #include <asm/ebus.h>
16 #define __KERNEL_SYSCALLS__
17 #include <linux/unistd.h>
19 #ifdef CONFIG_PCI
20 static unsigned long power_reg = 0UL;
21 #define POWER_SYSTEM_OFF (1 << 0)
22 #define POWER_COURTESY_OFF (1 << 1)
24 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
25 static int button_pressed = 0;
27 static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
29 if (button_pressed == 0) {
30 wake_up(&powerd_wait);
31 button_pressed = 1;
34 #endif /* CONFIG_PCI */
36 extern void machine_halt(void);
38 void machine_power_off(void)
40 #ifdef CONFIG_PCI
41 if (power_reg != 0UL) {
42 /* Both register bits seem to have the
43 * same effect, so until I figure out
44 * what the difference is...
46 writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
48 #endif /* CONFIG_PCI */
49 machine_halt();
52 #ifdef CONFIG_PCI
53 static int powerd(void *__unused)
55 static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
56 char *argv[] = { "/usr/bin/shutdown", "-h", "now", NULL };
58 current->session = 1;
59 current->pgrp = 1;
60 sprintf(current->comm, "powerd");
62 again:
63 while(button_pressed == 0) {
64 spin_lock_irq(&current->sigmask_lock);
65 flush_signals(current);
66 spin_unlock_irq(&current->sigmask_lock);
67 interruptible_sleep_on(&powerd_wait);
70 /* Ok, down we go... */
71 if (execve("/usr/bin/shutdown", argv, envp) < 0) {
72 printk("powerd: shutdown execution failed\n");
73 button_pressed = 0;
74 goto again;
76 return 0;
79 void __init power_init(void)
81 struct linux_ebus *ebus;
82 struct linux_ebus_device *edev;
84 for_each_ebus(ebus) {
85 for_each_ebusdev(edev, ebus) {
86 if (!strcmp(edev->prom_name, "power"))
87 goto found;
90 return;
92 found:
93 power_reg = edev->resource[0].start;
94 printk("power: Control reg at %016lx ... ", power_reg);
95 if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
96 printk("Failed to start power daemon.\n");
97 return;
99 printk("powerd running.\n");
100 if (request_irq(edev->irqs[0],
101 power_handler, SA_SHIRQ, "power",
102 (void *) power_reg) < 0)
103 printk("power: Error, cannot register IRQ handler.\n");
105 #endif /* CONFIG_PCI */