poweroff.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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.
  6. *
  7. * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
  8. *
  9. * This file is released under the GPLv2.
  10. */
  11. #include <linux/pm.h>
  12. #include <linux/init.h>
  13. #include <acpi/acpi_bus.h>
  14. #include <linux/sysdev.h>
  15. #include <asm/io.h>
  16. #include "sleep.h"
  17. int acpi_sleep_prepare(u32 acpi_state)
  18. {
  19. /* do we have a wakeup address for S2 and S3? */
  20. if (acpi_state == ACPI_STATE_S3) {
  21. if (!acpi_wakeup_address) {
  22. return -EFAULT;
  23. }
  24. acpi_set_firmware_waking_vector((acpi_physical_address)
  25. virt_to_phys((void *)
  26. acpi_wakeup_address));
  27. }
  28. ACPI_FLUSH_CPU_CACHE();
  29. acpi_enable_wakeup_device_prep(acpi_state);
  30. acpi_gpe_sleep_prepare(acpi_state);
  31. acpi_enter_sleep_state_prep(acpi_state);
  32. return 0;
  33. }
  34. #ifdef CONFIG_PM
  35. static void acpi_power_off_prepare(void)
  36. {
  37. /* Prepare to power off the system */
  38. acpi_sleep_prepare(ACPI_STATE_S5);
  39. }
  40. static void acpi_power_off(void)
  41. {
  42. /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
  43. printk("%s called\n", __FUNCTION__);
  44. local_irq_disable();
  45. /* Some SMP machines only can poweroff in boot CPU */
  46. acpi_enter_sleep_state(ACPI_STATE_S5);
  47. }
  48. static int acpi_poweroff_init(void)
  49. {
  50. if (!acpi_disabled) {
  51. u8 type_a, type_b;
  52. acpi_status status;
  53. status =
  54. acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
  55. if (ACPI_SUCCESS(status)) {
  56. pm_power_off_prepare = acpi_power_off_prepare;
  57. pm_power_off = acpi_power_off;
  58. }
  59. }
  60. return 0;
  61. }
  62. late_initcall(acpi_poweroff_init);
  63. #endif /* CONFIG_PM */