xref: /openbmc/linux/drivers/acpi/acpica/hwgpe.c (revision 165f2d28)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
5  *
6  * Copyright (C) 2000 - 2020, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acevents.h"
13 
14 #define _COMPONENT          ACPI_HARDWARE
15 ACPI_MODULE_NAME("hwgpe")
16 #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
17 /* Local prototypes */
18 static acpi_status
19 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
20 				struct acpi_gpe_block_info *gpe_block,
21 				void *context);
22 
23 static acpi_status
24 acpi_hw_gpe_enable_write(u8 enable_mask,
25 			 struct acpi_gpe_register_info *gpe_register_info);
26 
27 /******************************************************************************
28  *
29  * FUNCTION:	acpi_hw_get_gpe_register_bit
30  *
31  * PARAMETERS:	gpe_event_info	    - Info block for the GPE
32  *
33  * RETURN:	Register mask with a one in the GPE bit position
34  *
35  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
36  *              correct position for the input GPE.
37  *
38  ******************************************************************************/
39 
40 u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
41 {
42 
43 	return ((u32)1 <<
44 		(gpe_event_info->gpe_number -
45 		 gpe_event_info->register_info->base_gpe_number));
46 }
47 
48 /******************************************************************************
49  *
50  * FUNCTION:	acpi_hw_low_set_gpe
51  *
52  * PARAMETERS:	gpe_event_info	    - Info block for the GPE to be disabled
53  *		action		    - Enable or disable
54  *
55  * RETURN:	Status
56  *
57  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
58  *              The enable_mask field of the involved GPE register must be
59  *              updated by the caller if necessary.
60  *
61  ******************************************************************************/
62 
63 acpi_status
64 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
65 {
66 	struct acpi_gpe_register_info *gpe_register_info;
67 	acpi_status status = AE_OK;
68 	u64 enable_mask;
69 	u32 register_bit;
70 
71 	ACPI_FUNCTION_ENTRY();
72 
73 	/* Get the info block for the entire GPE register */
74 
75 	gpe_register_info = gpe_event_info->register_info;
76 	if (!gpe_register_info) {
77 		return (AE_NOT_EXIST);
78 	}
79 
80 	/* Get current value of the enable register that contains this GPE */
81 
82 	status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
83 	if (ACPI_FAILURE(status)) {
84 		return (status);
85 	}
86 
87 	/* Set or clear just the bit that corresponds to this GPE */
88 
89 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
90 	switch (action) {
91 	case ACPI_GPE_CONDITIONAL_ENABLE:
92 
93 		/* Only enable if the corresponding enable_mask bit is set */
94 
95 		if (!(register_bit & gpe_register_info->enable_mask)) {
96 			return (AE_BAD_PARAMETER);
97 		}
98 
99 		/*lint -fallthrough */
100 
101 	case ACPI_GPE_ENABLE:
102 
103 		ACPI_SET_BIT(enable_mask, register_bit);
104 		break;
105 
106 	case ACPI_GPE_DISABLE:
107 
108 		ACPI_CLEAR_BIT(enable_mask, register_bit);
109 		break;
110 
111 	default:
112 
113 		ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
114 		return (AE_BAD_PARAMETER);
115 	}
116 
117 	if (!(register_bit & gpe_register_info->mask_for_run)) {
118 
119 		/* Write the updated enable mask */
120 
121 		status =
122 		    acpi_hw_write(enable_mask,
123 				  &gpe_register_info->enable_address);
124 	}
125 	return (status);
126 }
127 
128 /******************************************************************************
129  *
130  * FUNCTION:    acpi_hw_clear_gpe
131  *
132  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
133  *
134  * RETURN:      Status
135  *
136  * DESCRIPTION: Clear the status bit for a single GPE.
137  *
138  ******************************************************************************/
139 
140 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info)
141 {
142 	struct acpi_gpe_register_info *gpe_register_info;
143 	acpi_status status;
144 	u32 register_bit;
145 
146 	ACPI_FUNCTION_ENTRY();
147 
148 	/* Get the info block for the entire GPE register */
149 
150 	gpe_register_info = gpe_event_info->register_info;
151 	if (!gpe_register_info) {
152 		return (AE_NOT_EXIST);
153 	}
154 
155 	/*
156 	 * Write a one to the appropriate bit in the status register to
157 	 * clear this GPE.
158 	 */
159 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
160 
161 	status =
162 	    acpi_hw_write(register_bit, &gpe_register_info->status_address);
163 	return (status);
164 }
165 
166 /******************************************************************************
167  *
168  * FUNCTION:    acpi_hw_get_gpe_status
169  *
170  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
171  *              event_status        - Where the GPE status is returned
172  *
173  * RETURN:      Status
174  *
175  * DESCRIPTION: Return the status of a single GPE.
176  *
177  ******************************************************************************/
178 
179 acpi_status
180 acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
181 		       acpi_event_status *event_status)
182 {
183 	u64 in_byte;
184 	u32 register_bit;
185 	struct acpi_gpe_register_info *gpe_register_info;
186 	acpi_event_status local_event_status = 0;
187 	acpi_status status;
188 
189 	ACPI_FUNCTION_ENTRY();
190 
191 	if (!event_status) {
192 		return (AE_BAD_PARAMETER);
193 	}
194 
195 	/* GPE currently handled? */
196 
197 	if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
198 	    ACPI_GPE_DISPATCH_NONE) {
199 		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
200 	}
201 
202 	/* Get the info block for the entire GPE register */
203 
204 	gpe_register_info = gpe_event_info->register_info;
205 
206 	/* Get the register bitmask for this GPE */
207 
208 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
209 
210 	/* GPE currently enabled? (enabled for runtime?) */
211 
212 	if (register_bit & gpe_register_info->enable_for_run) {
213 		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
214 	}
215 
216 	/* GPE currently masked? (masked for runtime?) */
217 
218 	if (register_bit & gpe_register_info->mask_for_run) {
219 		local_event_status |= ACPI_EVENT_FLAG_MASKED;
220 	}
221 
222 	/* GPE enabled for wake? */
223 
224 	if (register_bit & gpe_register_info->enable_for_wake) {
225 		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
226 	}
227 
228 	/* GPE currently enabled (enable bit == 1)? */
229 
230 	status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address);
231 	if (ACPI_FAILURE(status)) {
232 		return (status);
233 	}
234 
235 	if (register_bit & in_byte) {
236 		local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
237 	}
238 
239 	/* GPE currently active (status bit == 1)? */
240 
241 	status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
242 	if (ACPI_FAILURE(status)) {
243 		return (status);
244 	}
245 
246 	if (register_bit & in_byte) {
247 		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
248 	}
249 
250 	/* Set return value */
251 
252 	(*event_status) = local_event_status;
253 	return (AE_OK);
254 }
255 
256 /******************************************************************************
257  *
258  * FUNCTION:    acpi_hw_gpe_enable_write
259  *
260  * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
261  *              gpe_register_info   - Gpe Register info
262  *
263  * RETURN:      Status
264  *
265  * DESCRIPTION: Write the enable mask byte to the given GPE register.
266  *
267  ******************************************************************************/
268 
269 static acpi_status
270 acpi_hw_gpe_enable_write(u8 enable_mask,
271 			 struct acpi_gpe_register_info *gpe_register_info)
272 {
273 	acpi_status status;
274 
275 	gpe_register_info->enable_mask = enable_mask;
276 
277 	status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
278 	return (status);
279 }
280 
281 /******************************************************************************
282  *
283  * FUNCTION:    acpi_hw_disable_gpe_block
284  *
285  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
286  *              gpe_block           - Gpe Block info
287  *
288  * RETURN:      Status
289  *
290  * DESCRIPTION: Disable all GPEs within a single GPE block
291  *
292  ******************************************************************************/
293 
294 acpi_status
295 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
296 			  struct acpi_gpe_block_info *gpe_block, void *context)
297 {
298 	u32 i;
299 	acpi_status status;
300 
301 	/* Examine each GPE Register within the block */
302 
303 	for (i = 0; i < gpe_block->register_count; i++) {
304 
305 		/* Disable all GPEs in this register */
306 
307 		status =
308 		    acpi_hw_gpe_enable_write(0x00,
309 					     &gpe_block->register_info[i]);
310 		if (ACPI_FAILURE(status)) {
311 			return (status);
312 		}
313 	}
314 
315 	return (AE_OK);
316 }
317 
318 /******************************************************************************
319  *
320  * FUNCTION:    acpi_hw_clear_gpe_block
321  *
322  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
323  *              gpe_block           - Gpe Block info
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
328  *
329  ******************************************************************************/
330 
331 acpi_status
332 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
333 			struct acpi_gpe_block_info *gpe_block, void *context)
334 {
335 	u32 i;
336 	acpi_status status;
337 
338 	/* Examine each GPE Register within the block */
339 
340 	for (i = 0; i < gpe_block->register_count; i++) {
341 
342 		/* Clear status on all GPEs in this register */
343 
344 		status =
345 		    acpi_hw_write(0xFF,
346 				  &gpe_block->register_info[i].status_address);
347 		if (ACPI_FAILURE(status)) {
348 			return (status);
349 		}
350 	}
351 
352 	return (AE_OK);
353 }
354 
355 /******************************************************************************
356  *
357  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
358  *
359  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
360  *              gpe_block           - Gpe Block info
361  *
362  * RETURN:      Status
363  *
364  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
365  *              combination wake/run GPEs.
366  *
367  ******************************************************************************/
368 
369 acpi_status
370 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
371 				 struct acpi_gpe_block_info *gpe_block,
372 				 void *context)
373 {
374 	u32 i;
375 	acpi_status status;
376 	struct acpi_gpe_register_info *gpe_register_info;
377 	u8 enable_mask;
378 
379 	/* NOTE: assumes that all GPEs are currently disabled */
380 
381 	/* Examine each GPE Register within the block */
382 
383 	for (i = 0; i < gpe_block->register_count; i++) {
384 		gpe_register_info = &gpe_block->register_info[i];
385 		if (!gpe_register_info->enable_for_run) {
386 			continue;
387 		}
388 
389 		/* Enable all "runtime" GPEs in this register */
390 
391 		enable_mask = gpe_register_info->enable_for_run &
392 		    ~gpe_register_info->mask_for_run;
393 		status =
394 		    acpi_hw_gpe_enable_write(enable_mask, gpe_register_info);
395 		if (ACPI_FAILURE(status)) {
396 			return (status);
397 		}
398 	}
399 
400 	return (AE_OK);
401 }
402 
403 /******************************************************************************
404  *
405  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
406  *
407  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
408  *              gpe_block           - Gpe Block info
409  *
410  * RETURN:      Status
411  *
412  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
413  *              combination wake/run GPEs.
414  *
415  ******************************************************************************/
416 
417 static acpi_status
418 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
419 				struct acpi_gpe_block_info *gpe_block,
420 				void *context)
421 {
422 	u32 i;
423 	acpi_status status;
424 	struct acpi_gpe_register_info *gpe_register_info;
425 
426 	/* Examine each GPE Register within the block */
427 
428 	for (i = 0; i < gpe_block->register_count; i++) {
429 		gpe_register_info = &gpe_block->register_info[i];
430 
431 		/*
432 		 * Enable all "wake" GPEs in this register and disable the
433 		 * remaining ones.
434 		 */
435 
436 		status =
437 		    acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
438 					     gpe_register_info);
439 		if (ACPI_FAILURE(status)) {
440 			return (status);
441 		}
442 	}
443 
444 	return (AE_OK);
445 }
446 
447 struct acpi_gpe_block_status_context {
448 	struct acpi_gpe_register_info *gpe_skip_register_info;
449 	u8 gpe_skip_mask;
450 	u8 retval;
451 };
452 
453 /******************************************************************************
454  *
455  * FUNCTION:    acpi_hw_get_gpe_block_status
456  *
457  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
458  *              gpe_block           - Gpe Block info
459  *              context             - GPE list walk context data
460  *
461  * RETURN:      Success
462  *
463  * DESCRIPTION: Produce a combined GPE status bits mask for the given block.
464  *
465  ******************************************************************************/
466 
467 static acpi_status
468 acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
469 			     struct acpi_gpe_block_info *gpe_block,
470 			     void *context)
471 {
472 	struct acpi_gpe_block_status_context *c = context;
473 	struct acpi_gpe_register_info *gpe_register_info;
474 	u64 in_enable, in_status;
475 	acpi_status status;
476 	u8 ret_mask;
477 	u32 i;
478 
479 	/* Examine each GPE Register within the block */
480 
481 	for (i = 0; i < gpe_block->register_count; i++) {
482 		gpe_register_info = &gpe_block->register_info[i];
483 
484 		status = acpi_hw_read(&in_enable,
485 				      &gpe_register_info->enable_address);
486 		if (ACPI_FAILURE(status)) {
487 			continue;
488 		}
489 
490 		status = acpi_hw_read(&in_status,
491 				      &gpe_register_info->status_address);
492 		if (ACPI_FAILURE(status)) {
493 			continue;
494 		}
495 
496 		ret_mask = in_enable & in_status;
497 		if (ret_mask && c->gpe_skip_register_info == gpe_register_info) {
498 			ret_mask &= ~c->gpe_skip_mask;
499 		}
500 		c->retval |= ret_mask;
501 	}
502 
503 	return (AE_OK);
504 }
505 
506 /******************************************************************************
507  *
508  * FUNCTION:    acpi_hw_disable_all_gpes
509  *
510  * PARAMETERS:  None
511  *
512  * RETURN:      Status
513  *
514  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
515  *
516  ******************************************************************************/
517 
518 acpi_status acpi_hw_disable_all_gpes(void)
519 {
520 	acpi_status status;
521 
522 	ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
523 
524 	status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
525 	return_ACPI_STATUS(status);
526 }
527 
528 /******************************************************************************
529  *
530  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
531  *
532  * PARAMETERS:  None
533  *
534  * RETURN:      Status
535  *
536  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
537  *
538  ******************************************************************************/
539 
540 acpi_status acpi_hw_enable_all_runtime_gpes(void)
541 {
542 	acpi_status status;
543 
544 	ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
545 
546 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
547 	return_ACPI_STATUS(status);
548 }
549 
550 /******************************************************************************
551  *
552  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
553  *
554  * PARAMETERS:  None
555  *
556  * RETURN:      Status
557  *
558  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
559  *
560  ******************************************************************************/
561 
562 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
563 {
564 	acpi_status status;
565 
566 	ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
567 
568 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
569 	return_ACPI_STATUS(status);
570 }
571 
572 /******************************************************************************
573  *
574  * FUNCTION:    acpi_hw_check_all_gpes
575  *
576  * PARAMETERS:  gpe_skip_device      - GPE devoce of the GPE to skip
577  *              gpe_skip_number      - Number of the GPE to skip
578  *
579  * RETURN:      Combined status of all GPEs
580  *
581  * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one
582  *              represented by the "skip" arguments, and return TRUE if the
583  *              status bit is set for at least one of them of FALSE otherwise.
584  *
585  ******************************************************************************/
586 
587 u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number)
588 {
589 	struct acpi_gpe_block_status_context context = {
590 		.gpe_skip_register_info = NULL,
591 		.retval = 0,
592 	};
593 	struct acpi_gpe_event_info *gpe_event_info;
594 	acpi_cpu_flags flags;
595 
596 	ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes);
597 
598 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
599 
600 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device,
601 						    gpe_skip_number);
602 	if (gpe_event_info) {
603 		context.gpe_skip_register_info = gpe_event_info->register_info;
604 		context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info);
605 	}
606 
607 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
608 
609 	(void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context);
610 	return (context.retval != 0);
611 }
612 
613 #endif				/* !ACPI_REDUCED_HARDWARE */
614