|
@@ -15,6 +15,9 @@
|
|
|
#include <linux/dmi.h>
|
|
|
#include <linux/device.h>
|
|
|
#include <linux/suspend.h>
|
|
|
+
|
|
|
+#include <asm/io.h>
|
|
|
+
|
|
|
#include <acpi/acpi_bus.h>
|
|
|
#include <acpi/acpi_drivers.h>
|
|
|
#include "sleep.h"
|
|
@@ -57,6 +60,27 @@ static int acpi_pm_set_target(suspend_state_t pm_state)
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+int acpi_sleep_prepare(u32 acpi_state)
|
|
|
+{
|
|
|
+#ifdef CONFIG_ACPI_SLEEP
|
|
|
+ /* do we have a wakeup address for S2 and S3? */
|
|
|
+ if (acpi_state == ACPI_STATE_S3) {
|
|
|
+ if (!acpi_wakeup_address) {
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+ acpi_set_firmware_waking_vector((acpi_physical_address)
|
|
|
+ virt_to_phys((void *)
|
|
|
+ acpi_wakeup_address));
|
|
|
+
|
|
|
+ }
|
|
|
+ ACPI_FLUSH_CPU_CACHE();
|
|
|
+ acpi_enable_wakeup_device_prep(acpi_state);
|
|
|
+#endif
|
|
|
+ acpi_gpe_sleep_prepare(acpi_state);
|
|
|
+ acpi_enter_sleep_state_prep(acpi_state);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* acpi_pm_prepare - Do preliminary suspend work.
|
|
|
* @pm_state: ignored
|
|
@@ -350,6 +374,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
|
|
|
return d_max;
|
|
|
}
|
|
|
|
|
|
+static void acpi_power_off_prepare(void)
|
|
|
+{
|
|
|
+ /* Prepare to power off the system */
|
|
|
+ acpi_sleep_prepare(ACPI_STATE_S5);
|
|
|
+}
|
|
|
+
|
|
|
+static void acpi_power_off(void)
|
|
|
+{
|
|
|
+ /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
|
|
|
+ printk("%s called\n", __FUNCTION__);
|
|
|
+ local_irq_disable();
|
|
|
+ acpi_enter_sleep_state(ACPI_STATE_S5);
|
|
|
+}
|
|
|
+
|
|
|
int __init acpi_sleep_init(void)
|
|
|
{
|
|
|
acpi_status status;
|
|
@@ -363,16 +401,17 @@ int __init acpi_sleep_init(void)
|
|
|
if (acpi_disabled)
|
|
|
return 0;
|
|
|
|
|
|
+ sleep_states[ACPI_STATE_S0] = 1;
|
|
|
+ printk(KERN_INFO PREFIX "(supports S0");
|
|
|
+
|
|
|
#ifdef CONFIG_SUSPEND
|
|
|
- printk(KERN_INFO PREFIX "(supports");
|
|
|
- for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) {
|
|
|
+ for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) {
|
|
|
status = acpi_get_sleep_type_data(i, &type_a, &type_b);
|
|
|
if (ACPI_SUCCESS(status)) {
|
|
|
sleep_states[i] = 1;
|
|
|
printk(" S%d", i);
|
|
|
}
|
|
|
}
|
|
|
- printk(")\n");
|
|
|
|
|
|
pm_set_ops(&acpi_pm_ops);
|
|
|
#endif
|
|
@@ -382,10 +421,16 @@ int __init acpi_sleep_init(void)
|
|
|
if (ACPI_SUCCESS(status)) {
|
|
|
hibernation_set_ops(&acpi_hibernation_ops);
|
|
|
sleep_states[ACPI_STATE_S4] = 1;
|
|
|
+ printk(" S4");
|
|
|
}
|
|
|
-#else
|
|
|
- sleep_states[ACPI_STATE_S4] = 0;
|
|
|
#endif
|
|
|
-
|
|
|
+ status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
|
|
|
+ if (ACPI_SUCCESS(status)) {
|
|
|
+ sleep_states[ACPI_STATE_S5] = 1;
|
|
|
+ printk(" S5");
|
|
|
+ pm_power_off_prepare = acpi_power_off_prepare;
|
|
|
+ pm_power_off = acpi_power_off;
|
|
|
+ }
|
|
|
+ printk(")\n");
|
|
|
return 0;
|
|
|
}
|