evevent.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: evevent - Fixed Event handling and dispatch
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #include "acevents.h"
  12. #define _COMPONENT ACPI_EVENTS
  13. ACPI_MODULE_NAME("evevent")
  14. #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
  15. /* Local prototypes */
  16. static acpi_status acpi_ev_fixed_event_initialize(void);
  17. static u32 acpi_ev_fixed_event_dispatch(u32 event);
  18. /*******************************************************************************
  19. *
  20. * FUNCTION: acpi_ev_initialize_events
  21. *
  22. * PARAMETERS: None
  23. *
  24. * RETURN: Status
  25. *
  26. * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
  27. *
  28. ******************************************************************************/
  29. acpi_status acpi_ev_initialize_events(void)
  30. {
  31. acpi_status status;
  32. ACPI_FUNCTION_TRACE(ev_initialize_events);
  33. /* If Hardware Reduced flag is set, there are no fixed events */
  34. if (acpi_gbl_reduced_hardware) {
  35. return_ACPI_STATUS(AE_OK);
  36. }
  37. /*
  38. * Initialize the Fixed and General Purpose Events. This is done prior to
  39. * enabling SCIs to prevent interrupts from occurring before the handlers
  40. * are installed.
  41. */
  42. status = acpi_ev_fixed_event_initialize();
  43. if (ACPI_FAILURE(status)) {
  44. ACPI_EXCEPTION((AE_INFO, status,
  45. "Unable to initialize fixed events"));
  46. return_ACPI_STATUS(status);
  47. }
  48. status = acpi_ev_gpe_initialize();
  49. if (ACPI_FAILURE(status)) {
  50. ACPI_EXCEPTION((AE_INFO, status,
  51. "Unable to initialize general purpose events"));
  52. return_ACPI_STATUS(status);
  53. }
  54. return_ACPI_STATUS(status);
  55. }
  56. /*******************************************************************************
  57. *
  58. * FUNCTION: acpi_ev_install_xrupt_handlers
  59. *
  60. * PARAMETERS: None
  61. *
  62. * RETURN: Status
  63. *
  64. * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
  65. *
  66. ******************************************************************************/
  67. acpi_status acpi_ev_install_xrupt_handlers(void)
  68. {
  69. acpi_status status;
  70. ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
  71. /* If Hardware Reduced flag is set, there is no ACPI h/w */
  72. if (acpi_gbl_reduced_hardware) {
  73. return_ACPI_STATUS(AE_OK);
  74. }
  75. /* Install the SCI handler */
  76. status = acpi_ev_install_sci_handler();
  77. if (ACPI_FAILURE(status)) {
  78. ACPI_EXCEPTION((AE_INFO, status,
  79. "Unable to install System Control Interrupt handler"));
  80. return_ACPI_STATUS(status);
  81. }
  82. /* Install the handler for the Global Lock */
  83. status = acpi_ev_init_global_lock_handler();
  84. if (ACPI_FAILURE(status)) {
  85. ACPI_EXCEPTION((AE_INFO, status,
  86. "Unable to initialize Global Lock handler"));
  87. return_ACPI_STATUS(status);
  88. }
  89. acpi_gbl_events_initialized = TRUE;
  90. return_ACPI_STATUS(status);
  91. }
  92. /*******************************************************************************
  93. *
  94. * FUNCTION: acpi_ev_fixed_event_initialize
  95. *
  96. * PARAMETERS: None
  97. *
  98. * RETURN: Status
  99. *
  100. * DESCRIPTION: Install the fixed event handlers and disable all fixed events.
  101. *
  102. ******************************************************************************/
  103. static acpi_status acpi_ev_fixed_event_initialize(void)
  104. {
  105. u32 i;
  106. acpi_status status;
  107. /*
  108. * Initialize the structure that keeps track of fixed event handlers and
  109. * disable all of the fixed events.
  110. */
  111. for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
  112. acpi_gbl_fixed_event_handlers[i].handler = NULL;
  113. acpi_gbl_fixed_event_handlers[i].context = NULL;
  114. /* Disable the fixed event */
  115. if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
  116. status =
  117. acpi_write_bit_register(acpi_gbl_fixed_event_info
  118. [i].enable_register_id,
  119. ACPI_DISABLE_EVENT);
  120. if (ACPI_FAILURE(status)) {
  121. return (status);
  122. }
  123. }
  124. }
  125. return (AE_OK);
  126. }
  127. /*******************************************************************************
  128. *
  129. * FUNCTION: acpi_ev_fixed_event_detect
  130. *
  131. * PARAMETERS: None
  132. *
  133. * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  134. *
  135. * DESCRIPTION: Checks the PM status register for active fixed events
  136. *
  137. ******************************************************************************/
  138. u32 acpi_ev_fixed_event_detect(void)
  139. {
  140. u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
  141. u32 fixed_status;
  142. u32 fixed_enable;
  143. u32 i;
  144. acpi_status status;
  145. ACPI_FUNCTION_NAME(ev_fixed_event_detect);
  146. /*
  147. * Read the fixed feature status and enable registers, as all the cases
  148. * depend on their values. Ignore errors here.
  149. */
  150. status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
  151. status |=
  152. acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
  153. if (ACPI_FAILURE(status)) {
  154. return (int_status);
  155. }
  156. ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
  157. "Fixed Event Block: Enable %08X Status %08X\n",
  158. fixed_enable, fixed_status));
  159. /*
  160. * Check for all possible Fixed Events and dispatch those that are active
  161. */
  162. for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
  163. /* Both the status and enable bits must be on for this event */
  164. if ((fixed_status & acpi_gbl_fixed_event_info[i].
  165. status_bit_mask)
  166. && (fixed_enable & acpi_gbl_fixed_event_info[i].
  167. enable_bit_mask)) {
  168. /*
  169. * Found an active (signalled) event. Invoke global event
  170. * handler if present.
  171. */
  172. acpi_fixed_event_count[i]++;
  173. if (acpi_gbl_global_event_handler) {
  174. acpi_gbl_global_event_handler
  175. (ACPI_EVENT_TYPE_FIXED, NULL, i,
  176. acpi_gbl_global_event_handler_context);
  177. }
  178. int_status |= acpi_ev_fixed_event_dispatch(i);
  179. }
  180. }
  181. return (int_status);
  182. }
  183. /*******************************************************************************
  184. *
  185. * FUNCTION: acpi_ev_fixed_event_dispatch
  186. *
  187. * PARAMETERS: event - Event type
  188. *
  189. * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  190. *
  191. * DESCRIPTION: Clears the status bit for the requested event, calls the
  192. * handler that previously registered for the event.
  193. * NOTE: If there is no handler for the event, the event is
  194. * disabled to prevent further interrupts.
  195. *
  196. ******************************************************************************/
  197. static u32 acpi_ev_fixed_event_dispatch(u32 event)
  198. {
  199. ACPI_FUNCTION_ENTRY();
  200. /* Clear the status bit */
  201. (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
  202. status_register_id, ACPI_CLEAR_STATUS);
  203. /*
  204. * Make sure that a handler exists. If not, report an error
  205. * and disable the event to prevent further interrupts.
  206. */
  207. if (!acpi_gbl_fixed_event_handlers[event].handler) {
  208. (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
  209. enable_register_id,
  210. ACPI_DISABLE_EVENT);
  211. ACPI_ERROR((AE_INFO,
  212. "No installed handler for fixed event - %s (%u), disabling",
  213. acpi_ut_get_event_name(event), event));
  214. return (ACPI_INTERRUPT_NOT_HANDLED);
  215. }
  216. /* Invoke the Fixed Event handler */
  217. return ((acpi_gbl_fixed_event_handlers[event].
  218. handler) (acpi_gbl_fixed_event_handlers[event].context));
  219. }
  220. /*******************************************************************************
  221. *
  222. * FUNCTION: acpi_any_fixed_event_status_set
  223. *
  224. * PARAMETERS: None
  225. *
  226. * RETURN: TRUE or FALSE
  227. *
  228. * DESCRIPTION: Checks the PM status register for active fixed events
  229. *
  230. ******************************************************************************/
  231. u32 acpi_any_fixed_event_status_set(void)
  232. {
  233. acpi_status status;
  234. u32 in_status;
  235. u32 in_enable;
  236. u32 i;
  237. status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable);
  238. if (ACPI_FAILURE(status)) {
  239. return (FALSE);
  240. }
  241. status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status);
  242. if (ACPI_FAILURE(status)) {
  243. return (FALSE);
  244. }
  245. /*
  246. * Check for all possible Fixed Events and dispatch those that are active
  247. */
  248. for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
  249. /* Both the status and enable bits must be on for this event */
  250. if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
  251. (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
  252. return (TRUE);
  253. }
  254. }
  255. return (FALSE);
  256. }
  257. #endif /* !ACPI_REDUCED_HARDWARE */