version 1.1.1.1, 2008/06/03 10:38:42 |
version 1.1.1.1.2.1, 2008/08/13 17:12:25 |
|
|
#include <machdep.h> |
#include <machdep.h> |
#include <event.h> |
#include <event.h> |
#include <pm.h> |
#include <pm.h> |
#include "dvs.h" |
#include <cpufreq.h> |
|
|
/* #define DEBUG_PM 1 */ |
/* #define DEBUG_PM 1 */ |
|
|
#ifdef DEBUG_PM |
#ifdef DEBUG_PM |
#define pm_printf(fmt, args...) printk("pm: " fmt, ## args) |
#define DPRINTF(a) printf a |
#else |
#else |
#define pm_printf(fmt...) do {} while (0) |
#define DPRINTF(a) |
#endif |
#endif |
|
|
|
|
#ifdef CONFIG_PM_POWERSAVE |
#ifdef CONFIG_PM_POWERSAVE |
#define DEFAULT_POWER_POLICY PM_POWERSAVE |
#define DEFAULT_POWER_POLICY PM_POWERSAVE |
#else |
#else |
|
|
#endif |
#endif |
|
|
static int pm_open(device_t dev, int mode); |
static int pm_open(device_t dev, int mode); |
static int pm_ioctl(device_t dev, int cmd, u_long arg); |
static int pm_ioctl(device_t dev, u_long cmd, void *arg); |
static int pm_close(device_t dev); |
static int pm_close(device_t dev); |
static int pm_init(void); |
static int pm_init(void); |
|
|
|
|
/* init */ pm_init, |
/* init */ pm_init, |
}; |
}; |
|
|
|
/* |
|
* Device I/O table |
|
*/ |
static struct devio pm_io = { |
static struct devio pm_io = { |
/* open */ pm_open, |
/* open */ pm_open, |
/* close */ pm_close, |
/* close */ pm_close, |
|
|
{ |
{ |
int err; |
int err; |
|
|
pm_printf("Suspend system\n"); |
DPRINTF(("Suspend system\n")); |
err = device_broadcast(EVT_SUSPEND, 1); |
err = device_broadcast(EVT_SUSPEND, 1); |
if (err) |
if (err) |
return err; |
return err; |
|
|
int |
int |
pm_resume(void) |
pm_resume(void) |
{ |
{ |
pm_printf("Resume system\n"); |
|
|
DPRINTF(("Resume system\n")); |
device_broadcast(EVT_RESUME, 1); |
device_broadcast(EVT_RESUME, 1); |
return 0; |
return 0; |
} |
} |
|
|
{ |
{ |
int err; |
int err; |
|
|
pm_printf("Power off...\n"); |
#ifdef DEBUG |
|
printf("power off...\n"); |
|
#endif |
err = device_broadcast(EVT_SHUTDOWN, 1); |
err = device_broadcast(EVT_SHUTDOWN, 1); |
if (err) |
if (err) |
return err; |
return err; |
|
|
{ |
{ |
int err; |
int err; |
|
|
pm_printf("rebooting...\n"); |
#ifdef DEBUG |
|
printf("rebooting...\n"); |
|
#endif |
err = device_broadcast(EVT_SHUTDOWN, 1); |
err = device_broadcast(EVT_SHUTDOWN, 1); |
if (err) |
if (err) |
return err; |
return err; |
|
|
} |
} |
|
|
/* |
/* |
* Idle timer handler |
* Idle timer handler. |
*/ |
*/ |
static void |
static void |
idle_timeout(u_long dummy) |
idle_timeout(void *arg) |
{ |
{ |
|
|
irq_lock(); |
irq_lock(); |
|
|
if (idle_count >= suspend_timeout) |
if (idle_count >= suspend_timeout) |
pm_suspend(); |
pm_suspend(); |
else |
else |
timer_callout(&idle_timer, idle_timeout, 0, 1000); |
timer_callout(&idle_timer, 1000, &idle_timeout, NULL); |
} |
} |
|
|
|
#if 0 |
/* |
/* |
* Set suspend timer |
* Set suspend timer. |
*/ |
*/ |
int |
static int |
pm_settimer(u_long sec) |
pm_settimer(u_long sec) |
{ |
{ |
|
|
sched_lock(); |
sched_lock(); |
if (sec) |
if (sec) |
timer_callout(&idle_timer, idle_timeout, 0, 1000); |
timer_callout(&idle_timer, 1000, &idle_timeout, NULL); |
else |
else |
timer_stop(&idle_timer); |
timer_stop(&idle_timer); |
idle_count = 0; |
idle_count = 0; |
|
|
} |
} |
|
|
/* |
/* |
* Get power management timer |
* Get power management timer. |
*/ |
*/ |
int |
static int |
pm_gettimer(u_long *sec) |
pm_gettimer(u_long *sec) |
{ |
{ |
|
|
*sec = suspend_timeout; |
*sec = suspend_timeout; |
return 0; |
return 0; |
} |
} |
|
#endif |
|
|
/* |
/* |
* Reload idle timer |
* Reload idle timer. |
|
* |
|
* A keyboard or mouse driver will call this routine when |
|
* it detect the user activity like key press or mouse move. |
*/ |
*/ |
void |
void |
pm_active(void) |
pm_active(void) |
|
|
} |
} |
|
|
/* |
/* |
* Set power policy |
* Set power policy. |
*/ |
*/ |
static int |
static int |
pm_setpolicy(int policy) |
pm_setpolicy(int policy) |
|
|
} |
} |
|
|
/* |
/* |
* Get current power policy |
* Get current power policy. |
*/ |
*/ |
int |
int |
pm_getpolicy(void) |
pm_getpolicy(void) |
|
|
} |
} |
|
|
static int |
static int |
pm_ioctl(device_t dev, int cmd, u_long arg) |
pm_ioctl(device_t dev, u_long cmd, void *arg) |
{ |
{ |
int err = 0; |
int err = 0; |
int policy; |
int policy, subcmd; |
|
|
switch (cmd) { |
switch (cmd) { |
case PMIOC_SET_POWER: |
case PMIOC_SET_POWER: |
switch (arg) { |
if (umem_copyin(arg, &subcmd, sizeof(int))) |
|
return EFAULT; |
|
|
|
switch (subcmd) { |
case POWER_SUSPEND: |
case POWER_SUSPEND: |
pm_suspend(); |
pm_suspend(); |
break; |
break; |
|
|
return EINVAL; |
return EINVAL; |
} |
} |
break; |
break; |
|
|
case PMIOC_SET_POLICY: |
case PMIOC_SET_POLICY: |
err = pm_setpolicy((int)arg); |
if (umem_copyin(arg, &policy, sizeof(int))) |
|
return EFAULT; |
|
err = pm_setpolicy(policy); |
break; |
break; |
|
|
case PMIOC_GET_POLICY: |
case PMIOC_GET_POLICY: |
policy = pm_getpolicy(); |
policy = pm_getpolicy(); |
if (umem_copyout(&policy, (int *)arg, sizeof(int))) |
if (umem_copyout(&policy, arg, sizeof(int))) |
return EFAULT; |
return EFAULT; |
break; |
break; |
default: |
default: |
|
|
suspend_timeout = 0; |
suspend_timeout = 0; |
power_policy = DEFAULT_POWER_POLICY; |
power_policy = DEFAULT_POWER_POLICY; |
timer_init(&idle_timer); |
timer_init(&idle_timer); |
printk("pm: Default power policy is %s mode\n", |
#ifdef DEBUG |
|
printf("pm: Default power policy is %s mode\n", |
(power_policy == PM_POWERSAVE) ? "power save" : "performance"); |
(power_policy == PM_POWERSAVE) ? "power save" : "performance"); |
|
#endif |
return 0; |
return 0; |
} |
} |