Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * poweroff.c - ACPI handler for powering off the system. | |
3 | * | |
4 | * AKA S5, but it is independent of whether or not the kernel supports | |
5 | * any other sleep support in the system. | |
e2a5b420 AS |
6 | * |
7 | * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> | |
8 | * | |
9 | * This file is released under the GPLv2. | |
1da177e4 LT |
10 | */ |
11 | ||
12 | #include <linux/pm.h> | |
13 | #include <linux/init.h> | |
14 | #include <acpi/acpi_bus.h> | |
e2a5b420 AS |
15 | #include <linux/sysdev.h> |
16 | #include <asm/io.h> | |
1da177e4 LT |
17 | #include "sleep.h" |
18 | ||
e2a5b420 AS |
19 | int acpi_sleep_prepare(u32 acpi_state) |
20 | { | |
e2a5b420 AS |
21 | #ifdef CONFIG_ACPI_SLEEP |
22 | /* do we have a wakeup address for S2 and S3? */ | |
b01d8684 | 23 | if (acpi_state == ACPI_STATE_S3) { |
e2a5b420 AS |
24 | if (!acpi_wakeup_address) { |
25 | return -EFAULT; | |
26 | } | |
27 | acpi_set_firmware_waking_vector((acpi_physical_address) | |
28 | virt_to_phys((void *) | |
29 | acpi_wakeup_address)); | |
30 | ||
31 | } | |
32 | ACPI_FLUSH_CPU_CACHE(); | |
33 | acpi_enable_wakeup_device_prep(acpi_state); | |
34 | #endif | |
729b4d4c | 35 | acpi_gpe_sleep_prepare(acpi_state); |
e2a5b420 AS |
36 | acpi_enter_sleep_state_prep(acpi_state); |
37 | return 0; | |
38 | } | |
39 | ||
b35c67a4 EB |
40 | #ifdef CONFIG_PM |
41 | ||
bd804eba RW |
42 | static void acpi_power_off_prepare(void) |
43 | { | |
44 | /* Prepare to power off the system */ | |
45 | acpi_sleep_prepare(ACPI_STATE_S5); | |
46 | } | |
47 | ||
48 | static void acpi_power_off(void) | |
1da177e4 | 49 | { |
b35c67a4 | 50 | /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ |
e2a5b420 | 51 | printk("%s called\n", __FUNCTION__); |
e2a5b420 | 52 | local_irq_disable(); |
1da177e4 | 53 | /* Some SMP machines only can poweroff in boot CPU */ |
1da177e4 LT |
54 | acpi_enter_sleep_state(ACPI_STATE_S5); |
55 | } | |
56 | ||
57 | static int acpi_poweroff_init(void) | |
58 | { | |
59 | if (!acpi_disabled) { | |
60 | u8 type_a, type_b; | |
61 | acpi_status status; | |
62 | ||
e2a5b420 AS |
63 | status = |
64 | acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | |
65 | if (ACPI_SUCCESS(status)) { | |
bd804eba RW |
66 | pm_power_off_prepare = acpi_power_off_prepare; |
67 | pm_power_off = acpi_power_off; | |
e2a5b420 | 68 | } |
1da177e4 LT |
69 | } |
70 | return 0; | |
71 | } | |
72 | ||
73 | late_initcall(acpi_poweroff_init); | |
b35c67a4 | 74 | |
4be44fcd | 75 | #endif /* CONFIG_PM */ |