hwxfsleep.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #define EXPORT_ACPI_INTERFACES
  10. #include <acpi/acpi.h>
  11. #include "accommon.h"
  12. #define _COMPONENT ACPI_HARDWARE
  13. ACPI_MODULE_NAME("hwxfsleep")
  14. /* Local prototypes */
  15. #if (!ACPI_REDUCED_HARDWARE)
  16. static acpi_status
  17. acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
  18. acpi_physical_address physical_address,
  19. acpi_physical_address physical_address64);
  20. #endif
  21. /*
  22. * These functions are removed for the ACPI_REDUCED_HARDWARE case:
  23. * acpi_set_firmware_waking_vector
  24. * acpi_enter_sleep_state_s4bios
  25. */
  26. #if (!ACPI_REDUCED_HARDWARE)
  27. /*******************************************************************************
  28. *
  29. * FUNCTION: acpi_hw_set_firmware_waking_vector
  30. *
  31. * PARAMETERS: facs - Pointer to FACS table
  32. * physical_address - 32-bit physical address of ACPI real mode
  33. * entry point
  34. * physical_address64 - 64-bit physical address of ACPI protected
  35. * mode entry point
  36. *
  37. * RETURN: Status
  38. *
  39. * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
  40. *
  41. ******************************************************************************/
  42. static acpi_status
  43. acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
  44. acpi_physical_address physical_address,
  45. acpi_physical_address physical_address64)
  46. {
  47. ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector);
  48. /*
  49. * According to the ACPI specification 2.0c and later, the 64-bit
  50. * waking vector should be cleared and the 32-bit waking vector should
  51. * be used, unless we want the wake-up code to be called by the BIOS in
  52. * Protected Mode. Some systems (for example HP dv5-1004nr) are known
  53. * to fail to resume if the 64-bit vector is used.
  54. */
  55. /* Set the 32-bit vector */
  56. facs->firmware_waking_vector = (u32)physical_address;
  57. if (facs->length > 32) {
  58. if (facs->version >= 1) {
  59. /* Set the 64-bit vector */
  60. facs->xfirmware_waking_vector = physical_address64;
  61. } else {
  62. /* Clear the 64-bit vector if it exists */
  63. facs->xfirmware_waking_vector = 0;
  64. }
  65. }
  66. return_ACPI_STATUS(AE_OK);
  67. }
  68. /*******************************************************************************
  69. *
  70. * FUNCTION: acpi_set_firmware_waking_vector
  71. *
  72. * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
  73. * entry point
  74. * physical_address64 - 64-bit physical address of ACPI protected
  75. * mode entry point
  76. *
  77. * RETURN: Status
  78. *
  79. * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
  80. *
  81. ******************************************************************************/
  82. acpi_status
  83. acpi_set_firmware_waking_vector(acpi_physical_address physical_address,
  84. acpi_physical_address physical_address64)
  85. {
  86. ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
  87. if (acpi_gbl_FACS) {
  88. (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS,
  89. physical_address,
  90. physical_address64);
  91. }
  92. return_ACPI_STATUS(AE_OK);
  93. }
  94. ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
  95. /*******************************************************************************
  96. *
  97. * FUNCTION: acpi_enter_sleep_state_s4bios
  98. *
  99. * PARAMETERS: None
  100. *
  101. * RETURN: Status
  102. *
  103. * DESCRIPTION: Perform a S4 bios request.
  104. * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  105. *
  106. ******************************************************************************/
  107. acpi_status acpi_enter_sleep_state_s4bios(void)
  108. {
  109. u32 in_value;
  110. acpi_status status;
  111. ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);
  112. /* Clear the wake status bit (PM1) */
  113. status =
  114. acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
  115. if (ACPI_FAILURE(status)) {
  116. return_ACPI_STATUS(status);
  117. }
  118. status = acpi_hw_clear_acpi_status();
  119. if (ACPI_FAILURE(status)) {
  120. return_ACPI_STATUS(status);
  121. }
  122. /*
  123. * 1) Disable all GPEs
  124. * 2) Enable all wakeup GPEs
  125. */
  126. status = acpi_hw_disable_all_gpes();
  127. if (ACPI_FAILURE(status)) {
  128. return_ACPI_STATUS(status);
  129. }
  130. acpi_gbl_system_awake_and_running = FALSE;
  131. status = acpi_hw_enable_all_wakeup_gpes();
  132. if (ACPI_FAILURE(status)) {
  133. return_ACPI_STATUS(status);
  134. }
  135. status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
  136. (u32)acpi_gbl_FADT.s4_bios_request, 8);
  137. if (ACPI_FAILURE(status)) {
  138. return_ACPI_STATUS(status);
  139. }
  140. do {
  141. acpi_os_stall(ACPI_USEC_PER_MSEC);
  142. status =
  143. acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
  144. if (ACPI_FAILURE(status)) {
  145. return_ACPI_STATUS(status);
  146. }
  147. } while (!in_value);
  148. return_ACPI_STATUS(AE_OK);
  149. }
  150. ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
  151. #endif /* !ACPI_REDUCED_HARDWARE */
  152. /*******************************************************************************
  153. *
  154. * FUNCTION: acpi_enter_sleep_state_prep
  155. *
  156. * PARAMETERS: sleep_state - Which sleep state to enter
  157. *
  158. * RETURN: Status
  159. *
  160. * DESCRIPTION: Prepare to enter a system sleep state.
  161. * This function must execute with interrupts enabled.
  162. * We break sleeping into 2 stages so that OSPM can handle
  163. * various OS-specific tasks between the two steps.
  164. *
  165. ******************************************************************************/
  166. acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
  167. {
  168. acpi_status status;
  169. struct acpi_object_list arg_list;
  170. union acpi_object arg;
  171. u32 sst_value;
  172. ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
  173. status = acpi_get_sleep_type_data(sleep_state,
  174. &acpi_gbl_sleep_type_a,
  175. &acpi_gbl_sleep_type_b);
  176. if (ACPI_FAILURE(status)) {
  177. return_ACPI_STATUS(status);
  178. }
  179. status = acpi_get_sleep_type_data(ACPI_STATE_S0,
  180. &acpi_gbl_sleep_type_a_s0,
  181. &acpi_gbl_sleep_type_b_s0);
  182. if (ACPI_FAILURE(status)) {
  183. acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID;
  184. }
  185. /* Execute the _PTS method (Prepare To Sleep) */
  186. arg_list.count = 1;
  187. arg_list.pointer = &arg;
  188. arg.type = ACPI_TYPE_INTEGER;
  189. arg.integer.value = sleep_state;
  190. status =
  191. acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL);
  192. if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
  193. return_ACPI_STATUS(status);
  194. }
  195. /* Setup the argument to the _SST method (System STatus) */
  196. switch (sleep_state) {
  197. case ACPI_STATE_S0:
  198. sst_value = ACPI_SST_WORKING;
  199. break;
  200. case ACPI_STATE_S1:
  201. case ACPI_STATE_S2:
  202. case ACPI_STATE_S3:
  203. sst_value = ACPI_SST_SLEEPING;
  204. break;
  205. case ACPI_STATE_S4:
  206. sst_value = ACPI_SST_SLEEP_CONTEXT;
  207. break;
  208. default:
  209. sst_value = ACPI_SST_INDICATOR_OFF; /* Default is off */
  210. break;
  211. }
  212. /*
  213. * Set the system indicators to show the desired sleep state.
  214. * _SST is an optional method (return no error if not found)
  215. */
  216. acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value);
  217. return_ACPI_STATUS(AE_OK);
  218. }
  219. ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
  220. /*******************************************************************************
  221. *
  222. * FUNCTION: acpi_enter_sleep_state
  223. *
  224. * PARAMETERS: sleep_state - Which sleep state to enter
  225. *
  226. * RETURN: Status
  227. *
  228. * DESCRIPTION: Enter a system sleep state
  229. * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  230. *
  231. ******************************************************************************/
  232. acpi_status acpi_enter_sleep_state(u8 sleep_state)
  233. {
  234. acpi_status status;
  235. ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
  236. if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
  237. (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
  238. ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",
  239. acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
  240. return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
  241. }
  242. #if !ACPI_REDUCED_HARDWARE
  243. if (!acpi_gbl_reduced_hardware)
  244. status = acpi_hw_legacy_sleep(sleep_state);
  245. else
  246. #endif
  247. status = acpi_hw_extended_sleep(sleep_state);
  248. return_ACPI_STATUS(status);
  249. }
  250. ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
  251. /*******************************************************************************
  252. *
  253. * FUNCTION: acpi_leave_sleep_state_prep
  254. *
  255. * PARAMETERS: sleep_state - Which sleep state we are exiting
  256. *
  257. * RETURN: Status
  258. *
  259. * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
  260. * sleep. Called with interrupts DISABLED.
  261. * We break wake/resume into 2 stages so that OSPM can handle
  262. * various OS-specific tasks between the two steps.
  263. *
  264. ******************************************************************************/
  265. acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
  266. {
  267. acpi_status status;
  268. ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
  269. #if !ACPI_REDUCED_HARDWARE
  270. if (!acpi_gbl_reduced_hardware)
  271. status = acpi_hw_legacy_wake_prep(sleep_state);
  272. else
  273. #endif
  274. status = acpi_hw_extended_wake_prep(sleep_state);
  275. return_ACPI_STATUS(status);
  276. }
  277. ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep)
  278. /*******************************************************************************
  279. *
  280. * FUNCTION: acpi_leave_sleep_state
  281. *
  282. * PARAMETERS: sleep_state - Which sleep state we are exiting
  283. *
  284. * RETURN: Status
  285. *
  286. * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
  287. * Called with interrupts ENABLED.
  288. *
  289. ******************************************************************************/
  290. acpi_status acpi_leave_sleep_state(u8 sleep_state)
  291. {
  292. acpi_status status;
  293. ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
  294. #if !ACPI_REDUCED_HARDWARE
  295. if (!acpi_gbl_reduced_hardware)
  296. status = acpi_hw_legacy_wake(sleep_state);
  297. else
  298. #endif
  299. status = acpi_hw_extended_wake(sleep_state);
  300. return_ACPI_STATUS(status);
  301. }
  302. ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)