hwsleep.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
  5. * original/legacy sleep/PM registers.
  6. *
  7. * Copyright (C) 2000 - 2018, Intel Corp.
  8. *
  9. *****************************************************************************/
  10. #include <acpi/acpi.h>
  11. #include "accommon.h"
  12. #define _COMPONENT ACPI_HARDWARE
  13. ACPI_MODULE_NAME("hwsleep")
  14. #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
  15. /*******************************************************************************
  16. *
  17. * FUNCTION: acpi_hw_legacy_sleep
  18. *
  19. * PARAMETERS: sleep_state - Which sleep state to enter
  20. *
  21. * RETURN: Status
  22. *
  23. * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
  24. * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  25. *
  26. ******************************************************************************/
  27. acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
  28. {
  29. struct acpi_bit_register_info *sleep_type_reg_info;
  30. struct acpi_bit_register_info *sleep_enable_reg_info;
  31. u32 pm1a_control;
  32. u32 pm1b_control;
  33. u32 in_value;
  34. acpi_status status;
  35. ACPI_FUNCTION_TRACE(hw_legacy_sleep);
  36. sleep_type_reg_info =
  37. acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
  38. sleep_enable_reg_info =
  39. acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
  40. /* Clear wake status */
  41. status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
  42. ACPI_CLEAR_STATUS);
  43. if (ACPI_FAILURE(status)) {
  44. return_ACPI_STATUS(status);
  45. }
  46. /* Disable all GPEs */
  47. status = acpi_hw_disable_all_gpes();
  48. if (ACPI_FAILURE(status)) {
  49. return_ACPI_STATUS(status);
  50. }
  51. status = acpi_hw_clear_acpi_status();
  52. if (ACPI_FAILURE(status)) {
  53. return_ACPI_STATUS(status);
  54. }
  55. acpi_gbl_system_awake_and_running = FALSE;
  56. /* Enable all wakeup GPEs */
  57. status = acpi_hw_enable_all_wakeup_gpes();
  58. if (ACPI_FAILURE(status)) {
  59. return_ACPI_STATUS(status);
  60. }
  61. /* Get current value of PM1A control */
  62. status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
  63. &pm1a_control);
  64. if (ACPI_FAILURE(status)) {
  65. return_ACPI_STATUS(status);
  66. }
  67. ACPI_DEBUG_PRINT((ACPI_DB_INIT,
  68. "Entering sleep state [S%u]\n", sleep_state));
  69. /* Clear the SLP_EN and SLP_TYP fields */
  70. pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
  71. sleep_enable_reg_info->access_bit_mask);
  72. pm1b_control = pm1a_control;
  73. /* Insert the SLP_TYP bits */
  74. pm1a_control |=
  75. (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
  76. pm1b_control |=
  77. (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
  78. /*
  79. * We split the writes of SLP_TYP and SLP_EN to workaround
  80. * poorly implemented hardware.
  81. */
  82. /* Write #1: write the SLP_TYP data to the PM1 Control registers */
  83. status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
  84. if (ACPI_FAILURE(status)) {
  85. return_ACPI_STATUS(status);
  86. }
  87. /* Insert the sleep enable (SLP_EN) bit */
  88. pm1a_control |= sleep_enable_reg_info->access_bit_mask;
  89. pm1b_control |= sleep_enable_reg_info->access_bit_mask;
  90. /* Flush caches, as per ACPI specification */
  91. ACPI_FLUSH_CPU_CACHE();
  92. status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control);
  93. if (status == AE_CTRL_TERMINATE) {
  94. return_ACPI_STATUS(AE_OK);
  95. }
  96. if (ACPI_FAILURE(status)) {
  97. return_ACPI_STATUS(status);
  98. }
  99. /* Write #2: Write both SLP_TYP + SLP_EN */
  100. status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
  101. if (ACPI_FAILURE(status)) {
  102. return_ACPI_STATUS(status);
  103. }
  104. if (sleep_state > ACPI_STATE_S3) {
  105. /*
  106. * We wanted to sleep > S3, but it didn't happen (by virtue of the
  107. * fact that we are still executing!)
  108. *
  109. * Wait ten seconds, then try again. This is to get S4/S5 to work on
  110. * all machines.
  111. *
  112. * We wait so long to allow chipsets that poll this reg very slowly
  113. * to still read the right value. Ideally, this block would go
  114. * away entirely.
  115. */
  116. acpi_os_stall(10 * ACPI_USEC_PER_SEC);
  117. status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
  118. sleep_enable_reg_info->
  119. access_bit_mask);
  120. if (ACPI_FAILURE(status)) {
  121. return_ACPI_STATUS(status);
  122. }
  123. }
  124. /* Wait for transition back to Working State */
  125. do {
  126. status =
  127. acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
  128. if (ACPI_FAILURE(status)) {
  129. return_ACPI_STATUS(status);
  130. }
  131. } while (!in_value);
  132. return_ACPI_STATUS(AE_OK);
  133. }
  134. /*******************************************************************************
  135. *
  136. * FUNCTION: acpi_hw_legacy_wake_prep
  137. *
  138. * PARAMETERS: sleep_state - Which sleep state we just exited
  139. *
  140. * RETURN: Status
  141. *
  142. * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
  143. * sleep.
  144. * Called with interrupts ENABLED.
  145. *
  146. ******************************************************************************/
  147. acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
  148. {
  149. acpi_status status;
  150. struct acpi_bit_register_info *sleep_type_reg_info;
  151. struct acpi_bit_register_info *sleep_enable_reg_info;
  152. u32 pm1a_control;
  153. u32 pm1b_control;
  154. ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
  155. /*
  156. * Set SLP_TYPE and SLP_EN to state S0.
  157. * This is unclear from the ACPI Spec, but it is required
  158. * by some machines.
  159. */
  160. status = acpi_get_sleep_type_data(ACPI_STATE_S0,
  161. &acpi_gbl_sleep_type_a,
  162. &acpi_gbl_sleep_type_b);
  163. if (ACPI_SUCCESS(status)) {
  164. sleep_type_reg_info =
  165. acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
  166. sleep_enable_reg_info =
  167. acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
  168. /* Get current value of PM1A control */
  169. status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
  170. &pm1a_control);
  171. if (ACPI_SUCCESS(status)) {
  172. /* Clear the SLP_EN and SLP_TYP fields */
  173. pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
  174. sleep_enable_reg_info->
  175. access_bit_mask);
  176. pm1b_control = pm1a_control;
  177. /* Insert the SLP_TYP bits */
  178. pm1a_control |= (acpi_gbl_sleep_type_a <<
  179. sleep_type_reg_info->bit_position);
  180. pm1b_control |= (acpi_gbl_sleep_type_b <<
  181. sleep_type_reg_info->bit_position);
  182. /* Write the control registers and ignore any errors */
  183. (void)acpi_hw_write_pm1_control(pm1a_control,
  184. pm1b_control);
  185. }
  186. }
  187. return_ACPI_STATUS(status);
  188. }
  189. /*******************************************************************************
  190. *
  191. * FUNCTION: acpi_hw_legacy_wake
  192. *
  193. * PARAMETERS: sleep_state - Which sleep state we just exited
  194. *
  195. * RETURN: Status
  196. *
  197. * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
  198. * Called with interrupts ENABLED.
  199. *
  200. ******************************************************************************/
  201. acpi_status acpi_hw_legacy_wake(u8 sleep_state)
  202. {
  203. acpi_status status;
  204. ACPI_FUNCTION_TRACE(hw_legacy_wake);
  205. /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
  206. acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
  207. acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
  208. /*
  209. * GPEs must be enabled before _WAK is called as GPEs
  210. * might get fired there
  211. *
  212. * Restore the GPEs:
  213. * 1) Disable all GPEs
  214. * 2) Enable all runtime GPEs
  215. */
  216. status = acpi_hw_disable_all_gpes();
  217. if (ACPI_FAILURE(status)) {
  218. return_ACPI_STATUS(status);
  219. }
  220. status = acpi_hw_enable_all_runtime_gpes();
  221. if (ACPI_FAILURE(status)) {
  222. return_ACPI_STATUS(status);
  223. }
  224. /*
  225. * Now we can execute _WAK, etc. Some machines require that the GPEs
  226. * are enabled before the wake methods are executed.
  227. */
  228. acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
  229. /*
  230. * Some BIOS code assumes that WAK_STS will be cleared on resume
  231. * and use it to determine whether the system is rebooting or
  232. * resuming. Clear WAK_STS for compatibility.
  233. */
  234. (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
  235. ACPI_CLEAR_STATUS);
  236. acpi_gbl_system_awake_and_running = TRUE;
  237. /* Enable power button */
  238. (void)
  239. acpi_write_bit_register(acpi_gbl_fixed_event_info
  240. [ACPI_EVENT_POWER_BUTTON].
  241. enable_register_id, ACPI_ENABLE_EVENT);
  242. (void)
  243. acpi_write_bit_register(acpi_gbl_fixed_event_info
  244. [ACPI_EVENT_POWER_BUTTON].
  245. status_register_id, ACPI_CLEAR_STATUS);
  246. acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
  247. return_ACPI_STATUS(status);
  248. }
  249. #endif /* !ACPI_REDUCED_HARDWARE */