diff options
-rw-r--r-- | arch/powerpc/platforms/celleb/beat.c | 94 |
1 files changed, 93 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/celleb/beat.c index ced6f68c7b0b..93ebb7d85120 100644 --- a/arch/powerpc/platforms/celleb/beat.c +++ b/arch/powerpc/platforms/celleb/beat.c | |||
@@ -22,16 +22,24 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/irqreturn.h> | ||
27 | #include <linux/reboot.h> | ||
25 | 28 | ||
26 | #include <asm/hvconsole.h> | 29 | #include <asm/hvconsole.h> |
27 | #include <asm/time.h> | 30 | #include <asm/time.h> |
31 | #include <asm/machdep.h> | ||
32 | #include <asm/firmware.h> | ||
28 | 33 | ||
29 | #include "beat_wrapper.h" | 34 | #include "beat_wrapper.h" |
30 | #include "beat.h" | 35 | #include "beat.h" |
36 | #include "interrupt.h" | ||
37 | |||
38 | static int beat_pm_poweroff_flag; | ||
31 | 39 | ||
32 | void beat_restart(char *cmd) | 40 | void beat_restart(char *cmd) |
33 | { | 41 | { |
34 | beat_shutdown_logical_partition(1); | 42 | beat_shutdown_logical_partition(!beat_pm_poweroff_flag); |
35 | } | 43 | } |
36 | 44 | ||
37 | void beat_power_off(void) | 45 | void beat_power_off(void) |
@@ -170,6 +178,90 @@ void beat_kexec_cpu_down(int crash, int secondary) | |||
170 | } | 178 | } |
171 | #endif | 179 | #endif |
172 | 180 | ||
181 | static irqreturn_t beat_power_event(int virq, void *arg) | ||
182 | { | ||
183 | printk(KERN_DEBUG "Beat: power button pressed\n"); | ||
184 | beat_pm_poweroff_flag = 1; | ||
185 | ctrl_alt_del(); | ||
186 | return IRQ_HANDLED; | ||
187 | } | ||
188 | |||
189 | static irqreturn_t beat_reset_event(int virq, void *arg) | ||
190 | { | ||
191 | printk(KERN_DEBUG "Beat: reset button pressed\n"); | ||
192 | beat_pm_poweroff_flag = 0; | ||
193 | ctrl_alt_del(); | ||
194 | return IRQ_HANDLED; | ||
195 | } | ||
196 | |||
197 | static struct beat_event_list { | ||
198 | const char *typecode; | ||
199 | irq_handler_t handler; | ||
200 | unsigned int virq; | ||
201 | } beat_event_list[] = { | ||
202 | { "power", beat_power_event, 0 }, | ||
203 | { "reset", beat_reset_event, 0 }, | ||
204 | }; | ||
205 | |||
206 | static int __init beat_register_event(void) | ||
207 | { | ||
208 | u64 path[4], data[2]; | ||
209 | int rc, i; | ||
210 | unsigned int virq; | ||
211 | |||
212 | for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) { | ||
213 | struct beat_event_list *ev = &beat_event_list[i]; | ||
214 | |||
215 | if (beat_construct_event_receive_port(data) != 0) { | ||
216 | printk(KERN_ERR "Beat: " | ||
217 | "cannot construct event receive port for %s\n", | ||
218 | ev->typecode); | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | virq = irq_create_mapping(NULL, data[0]); | ||
223 | if (virq == NO_IRQ) { | ||
224 | printk(KERN_ERR "Beat: failed to get virtual IRQ" | ||
225 | " for event receive port for %s\n", | ||
226 | ev->typecode); | ||
227 | beat_destruct_event_receive_port(data[0]); | ||
228 | return -EIO; | ||
229 | } | ||
230 | ev->virq = virq; | ||
231 | |||
232 | rc = request_irq(virq, ev->handler, IRQF_DISABLED, | ||
233 | ev->typecode, NULL); | ||
234 | if (rc != 0) { | ||
235 | printk(KERN_ERR "Beat: failed to request virtual IRQ" | ||
236 | " for event receive port for %s\n", | ||
237 | ev->typecode); | ||
238 | beat_destruct_event_receive_port(data[0]); | ||
239 | return rc; | ||
240 | } | ||
241 | |||
242 | path[0] = 0x1000000065780000ul; /* 1,ex */ | ||
243 | path[1] = 0x627574746f6e0000ul; /* button */ | ||
244 | path[2] = 0; | ||
245 | strncpy((char *)&path[2], ev->typecode, 8); | ||
246 | path[3] = 0; | ||
247 | data[1] = 0; | ||
248 | |||
249 | beat_create_repository_node(path, data); | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int __init beat_event_init(void) | ||
255 | { | ||
256 | if (!firmware_has_feature(FW_FEATURE_BEAT)) | ||
257 | return -EINVAL; | ||
258 | |||
259 | beat_pm_poweroff_flag = 0; | ||
260 | return beat_register_event(); | ||
261 | } | ||
262 | |||
263 | device_initcall(beat_event_init); | ||
264 | |||
173 | EXPORT_SYMBOL(beat_get_term_char); | 265 | EXPORT_SYMBOL(beat_get_term_char); |
174 | EXPORT_SYMBOL(beat_put_term_char); | 266 | EXPORT_SYMBOL(beat_put_term_char); |
175 | EXPORT_SYMBOL(beat_halt_code); | 267 | EXPORT_SYMBOL(beat_halt_code); |