diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:55:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:55:47 -0700 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/platforms/celleb/beat.c | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'arch/powerpc/platforms/celleb/beat.c')
-rw-r--r-- | arch/powerpc/platforms/celleb/beat.c | 106 |
1 files changed, 105 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/celleb/beat.c index 99341ce8a697..93ebb7d85120 100644 --- a/arch/powerpc/platforms/celleb/beat.c +++ b/arch/powerpc/platforms/celleb/beat.c @@ -22,16 +22,24 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/rtc.h> +#include <linux/interrupt.h> +#include <linux/irqreturn.h> +#include <linux/reboot.h> #include <asm/hvconsole.h> #include <asm/time.h> +#include <asm/machdep.h> +#include <asm/firmware.h> #include "beat_wrapper.h" #include "beat.h" +#include "interrupt.h" + +static int beat_pm_poweroff_flag; void beat_restart(char *cmd) { - beat_shutdown_logical_partition(1); + beat_shutdown_logical_partition(!beat_pm_poweroff_flag); } void beat_power_off(void) @@ -158,6 +166,102 @@ int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2) return beat_put_characters_to_console(vterm, len, (u8*)db); } +void beat_power_save(void) +{ + beat_pause(0); +} + +#ifdef CONFIG_KEXEC +void beat_kexec_cpu_down(int crash, int secondary) +{ + beatic_deinit_IRQ(); +} +#endif + +static irqreturn_t beat_power_event(int virq, void *arg) +{ + printk(KERN_DEBUG "Beat: power button pressed\n"); + beat_pm_poweroff_flag = 1; + ctrl_alt_del(); + return IRQ_HANDLED; +} + +static irqreturn_t beat_reset_event(int virq, void *arg) +{ + printk(KERN_DEBUG "Beat: reset button pressed\n"); + beat_pm_poweroff_flag = 0; + ctrl_alt_del(); + return IRQ_HANDLED; +} + +static struct beat_event_list { + const char *typecode; + irq_handler_t handler; + unsigned int virq; +} beat_event_list[] = { + { "power", beat_power_event, 0 }, + { "reset", beat_reset_event, 0 }, +}; + +static int __init beat_register_event(void) +{ + u64 path[4], data[2]; + int rc, i; + unsigned int virq; + + for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) { + struct beat_event_list *ev = &beat_event_list[i]; + + if (beat_construct_event_receive_port(data) != 0) { + printk(KERN_ERR "Beat: " + "cannot construct event receive port for %s\n", + ev->typecode); + return -EINVAL; + } + + virq = irq_create_mapping(NULL, data[0]); + if (virq == NO_IRQ) { + printk(KERN_ERR "Beat: failed to get virtual IRQ" + " for event receive port for %s\n", + ev->typecode); + beat_destruct_event_receive_port(data[0]); + return -EIO; + } + ev->virq = virq; + + rc = request_irq(virq, ev->handler, IRQF_DISABLED, + ev->typecode, NULL); + if (rc != 0) { + printk(KERN_ERR "Beat: failed to request virtual IRQ" + " for event receive port for %s\n", + ev->typecode); + beat_destruct_event_receive_port(data[0]); + return rc; + } + + path[0] = 0x1000000065780000ul; /* 1,ex */ + path[1] = 0x627574746f6e0000ul; /* button */ + path[2] = 0; + strncpy((char *)&path[2], ev->typecode, 8); + path[3] = 0; + data[1] = 0; + + beat_create_repository_node(path, data); + } + return 0; +} + +static int __init beat_event_init(void) +{ + if (!firmware_has_feature(FW_FEATURE_BEAT)) + return -EINVAL; + + beat_pm_poweroff_flag = 0; + return beat_register_event(); +} + +device_initcall(beat_event_init); + EXPORT_SYMBOL(beat_get_term_char); EXPORT_SYMBOL(beat_put_term_char); EXPORT_SYMBOL(beat_halt_code); |