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)
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>
16 #define __KERNEL_SYSCALLS__
17 #include <linux/unistd.h>
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
);
34 #endif /* CONFIG_PCI */
36 extern void machine_halt(void);
38 void machine_power_off(void)
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 */
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
};
60 sprintf(current
->comm
, "powerd");
63 while(button_pressed
== 0) {
64 spin_lock_irq(¤t
->sigmask_lock
);
65 flush_signals(current
);
66 spin_unlock_irq(¤t
->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");
79 void __init
power_init(void)
81 struct linux_ebus
*ebus
;
82 struct linux_ebus_device
*edev
;
85 for_each_ebusdev(edev
, ebus
) {
86 if (!strcmp(edev
->prom_name
, "power"))
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");
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 */