[POWERPC] PS3: Save power in busy loops on halt

PS3 save power on halt:
  - Replace infinite busy loops by smarter loops calling
    lv1_pause() to save power.
  - Add ps3_halt() and ps3_sys_manager_halt().
  - Add __noreturn annotations.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Geert Uytterhoeven 2008-03-27 11:38:31 +11:00 committed by Paul Mackerras
parent 5761eaa3a5
commit ca052f7924
4 changed files with 44 additions and 19 deletions

View file

@ -95,6 +95,14 @@ static void ps3_power_off(void)
ps3_sys_manager_power_off(); /* never returns */ ps3_sys_manager_power_off(); /* never returns */
} }
static void ps3_halt(void)
{
DBG("%s:%d\n", __func__, __LINE__);
smp_send_stop();
ps3_sys_manager_halt(); /* never returns */
}
static void ps3_panic(char *str) static void ps3_panic(char *str)
{ {
DBG("%s:%d %s\n", __func__, __LINE__, str); DBG("%s:%d %s\n", __func__, __LINE__, str);
@ -105,7 +113,8 @@ static void ps3_panic(char *str)
printk(" Please press POWER button.\n"); printk(" Please press POWER button.\n");
printk("\n"); printk("\n");
while(1); while(1)
lv1_pause(1);
} }
#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
@ -266,6 +275,7 @@ define_machine(ps3) {
.progress = ps3_progress, .progress = ps3_progress,
.restart = ps3_restart, .restart = ps3_restart,
.power_off = ps3_power_off, .power_off = ps3_power_off,
.halt = ps3_halt,
#if defined(CONFIG_KEXEC) #if defined(CONFIG_KEXEC)
.kexec_cpu_down = ps3_kexec_cpu_down, .kexec_cpu_down = ps3_kexec_cpu_down,
.machine_kexec = default_machine_kexec, .machine_kexec = default_machine_kexec,

View file

@ -24,6 +24,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/lv1call.h>
#include <asm/ps3.h> #include <asm/ps3.h>
#include "vuart.h" #include "vuart.h"
@ -581,6 +582,23 @@ fail_id:
return -EIO; return -EIO;
} }
static void ps3_sys_manager_fin(struct ps3_system_bus_device *dev)
{
ps3_sys_manager_send_request_shutdown(dev);
pr_emerg("System Halted, OK to turn off power\n");
while (ps3_sys_manager_handle_msg(dev)) {
/* pause until next DEC interrupt */
lv1_pause(0);
}
while (1) {
/* pause, ignoring DEC interrupt */
lv1_pause(1);
}
}
/** /**
* ps3_sys_manager_final_power_off - The final platform machine_power_off routine. * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
* *
@ -602,12 +620,8 @@ static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
PS3_SM_WAKE_DEFAULT); PS3_SM_WAKE_DEFAULT);
ps3_sys_manager_send_request_shutdown(dev);
pr_emerg("System Halted, OK to turn off power\n"); ps3_sys_manager_fin(dev);
while (1)
ps3_sys_manager_handle_msg(dev);
} }
/** /**
@ -639,12 +653,8 @@ static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
ps3_sys_manager_send_attr(dev, 0); ps3_sys_manager_send_attr(dev, 0);
ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT, ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT,
PS3_SM_WAKE_DEFAULT); PS3_SM_WAKE_DEFAULT);
ps3_sys_manager_send_request_shutdown(dev);
pr_emerg("System Halted, OK to turn off power\n"); ps3_sys_manager_fin(dev);
while (1)
ps3_sys_manager_handle_msg(dev);
} }
/** /**

View file

@ -19,6 +19,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/lv1call.h>
#include <asm/ps3.h> #include <asm/ps3.h>
/** /**
@ -50,10 +51,7 @@ void ps3_sys_manager_power_off(void)
if (ps3_sys_manager_ops.power_off) if (ps3_sys_manager_ops.power_off)
ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev); ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
printk(KERN_EMERG "System Halted, OK to turn off power\n"); ps3_sys_manager_halt();
local_irq_disable();
while (1)
(void)0;
} }
void ps3_sys_manager_restart(void) void ps3_sys_manager_restart(void)
@ -61,8 +59,14 @@ void ps3_sys_manager_restart(void)
if (ps3_sys_manager_ops.restart) if (ps3_sys_manager_ops.restart)
ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev); ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
printk(KERN_EMERG "System Halted, OK to turn off power\n"); ps3_sys_manager_halt();
}
void ps3_sys_manager_halt(void)
{
pr_emerg("System Halted, OK to turn off power\n");
local_irq_disable(); local_irq_disable();
while (1) while (1)
(void)0; lv1_pause(1);
} }

View file

@ -434,8 +434,9 @@ struct ps3_sys_manager_ops {
}; };
void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops); void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
void ps3_sys_manager_power_off(void); void __noreturn ps3_sys_manager_power_off(void);
void ps3_sys_manager_restart(void); void __noreturn ps3_sys_manager_restart(void);
void __noreturn ps3_sys_manager_halt(void);
struct ps3_prealloc { struct ps3_prealloc {
const char *name; const char *name;