X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Facpi%2Fsleep%2Fmain.c;h=048295ec370786aae9b04b900402103e29c72df8;hb=fe2520094d88018423dfc42b3cd0015f74e8adea;hp=e8cff5dd4cbc8ba20cda8260825bff32122f4cbe;hpb=a6ce22a5f61ba838b43763bf1e5be399f9dee4d0;p=linux-2.6-omap-h63xx.git diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index e8cff5dd4cb..048295ec370 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -15,16 +15,42 @@ #include #include #include + +#include + #include #include #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; +#ifdef CONFIG_PM_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; +#endif + +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; +} #ifdef CONFIG_SUSPEND -static struct pm_ops acpi_pm_ops; +static struct platform_suspend_ops acpi_pm_ops; extern void do_suspend_lowlevel(void); @@ -59,13 +85,12 @@ static int acpi_pm_set_target(suspend_state_t pm_state) /** * acpi_pm_prepare - Do preliminary suspend work. - * @pm_state: ignored * * If necessary, set the firmware waking vector and do arch-specific * nastiness to get the wakeup code to the waking vector. */ -static int acpi_pm_prepare(suspend_state_t pm_state) +static int acpi_pm_prepare(void) { int error = acpi_sleep_prepare(acpi_target_sleep_state); @@ -134,13 +159,12 @@ static int acpi_pm_enter(suspend_state_t pm_state) /** * acpi_pm_finish - Finish up suspend sequence. - * @pm_state: ignored * * This is called after we wake back up (or if entering the sleep state * failed). */ -static int acpi_pm_finish(suspend_state_t pm_state) +static void acpi_pm_finish(void) { u32 acpi_state = acpi_target_sleep_state; @@ -158,7 +182,6 @@ static int acpi_pm_finish(suspend_state_t pm_state) init_8259A(0); } #endif - return 0; } static int acpi_pm_state_valid(suspend_state_t pm_state) @@ -177,7 +200,7 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) } } -static struct pm_ops acpi_pm_ops = { +static struct platform_suspend_ops acpi_pm_ops = { .valid = acpi_pm_state_valid, .set_target = acpi_pm_set_target, .prepare = acpi_pm_prepare, @@ -189,7 +212,7 @@ static struct pm_ops acpi_pm_ops = { * Toshiba fails to preserve interrupts over S1, reinitialization * of 8259 is needed after S1 resume. */ -static int __init init_ints_after_s1(struct dmi_system_id *d) +static int __init init_ints_after_s1(const struct dmi_system_id *d) { printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); init_8259A_after_S1 = 1; @@ -207,6 +230,12 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { #endif /* CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION +static int acpi_hibernation_start(void) +{ + acpi_target_sleep_state = ACPI_STATE_S4; + return 0; +} + static int acpi_hibernation_prepare(void) { return acpi_sleep_prepare(ACPI_STATE_S4); @@ -228,6 +257,15 @@ static int acpi_hibernation_enter(void) return ACPI_SUCCESS(status) ? 0 : -EFAULT; } +static void acpi_hibernation_leave(void) +{ + /* + * If ACPI is not enabled by the BIOS and the boot kernel, we need to + * enable it here. + */ + acpi_enable(); +} + static void acpi_hibernation_finish(void) { acpi_leave_sleep_state(ACPI_STATE_S4); @@ -235,6 +273,8 @@ static void acpi_hibernation_finish(void) /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); + + acpi_target_sleep_state = ACPI_STATE_S0; } static int acpi_hibernation_pre_restore(void) @@ -251,10 +291,13 @@ static void acpi_hibernation_restore_cleanup(void) acpi_hw_enable_all_runtime_gpes(); } -static struct hibernation_ops acpi_hibernation_ops = { +static struct platform_hibernation_ops acpi_hibernation_ops = { + .start = acpi_hibernation_start, + .pre_snapshot = acpi_hibernation_prepare, + .finish = acpi_hibernation_finish, .prepare = acpi_hibernation_prepare, .enter = acpi_hibernation_enter, - .finish = acpi_hibernation_finish, + .leave = acpi_hibernation_leave, .pre_restore = acpi_hibernation_pre_restore, .restore_cleanup = acpi_hibernation_restore_cleanup, }; @@ -275,6 +318,7 @@ int acpi_suspend(u32 acpi_state) return -EINVAL; } +#ifdef CONFIG_PM_SLEEP /** * acpi_pm_device_sleep_state - return preferred power state of ACPI device * in the system sleep state given by %acpi_target_sleep_state @@ -305,7 +349,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) unsigned long d_min, d_max; if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { - printk(KERN_ERR "ACPI handle has no context!\n"); + printk(KERN_DEBUG "ACPI handle has no context!\n"); return -ENODEV; } @@ -349,6 +393,21 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) *d_min_p = d_min; return d_max; } +#endif + +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) { @@ -363,18 +422,19 @@ 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); + suspend_set_ops(&acpi_pm_ops); #endif #ifdef CONFIG_HIBERNATION @@ -382,10 +442,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; }