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 - 2019, 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 
acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info * gpe_event_info)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
acpi_hw_low_set_gpe(struct acpi_gpe_event_info * gpe_event_info,u32 action)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 
acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)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
acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,acpi_event_status * event_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
acpi_hw_gpe_enable_write(u8 enable_mask,struct acpi_gpe_register_info * gpe_register_info)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
acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,struct acpi_gpe_block_info * gpe_block,void * context)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
acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,struct acpi_gpe_block_info * gpe_block,void * context)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
acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,struct acpi_gpe_block_info * gpe_block,void * context)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
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,struct acpi_gpe_block_info * gpe_block,void * context)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 /******************************************************************************
448  *
449  * FUNCTION:    acpi_hw_disable_all_gpes
450  *
451  * PARAMETERS:  None
452  *
453  * RETURN:      Status
454  *
455  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
456  *
457  ******************************************************************************/
458 
acpi_hw_disable_all_gpes(void)459 acpi_status acpi_hw_disable_all_gpes(void)
460 {
461 	acpi_status status;
462 
463 	ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
464 
465 	status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
466 	return_ACPI_STATUS(status);
467 }
468 
469 /******************************************************************************
470  *
471  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
472  *
473  * PARAMETERS:  None
474  *
475  * RETURN:      Status
476  *
477  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
478  *
479  ******************************************************************************/
480 
acpi_hw_enable_all_runtime_gpes(void)481 acpi_status acpi_hw_enable_all_runtime_gpes(void)
482 {
483 	acpi_status status;
484 
485 	ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
486 
487 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
488 	return_ACPI_STATUS(status);
489 }
490 
491 /******************************************************************************
492  *
493  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
494  *
495  * PARAMETERS:  None
496  *
497  * RETURN:      Status
498  *
499  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
500  *
501  ******************************************************************************/
502 
acpi_hw_enable_all_wakeup_gpes(void)503 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
504 {
505 	acpi_status status;
506 
507 	ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
508 
509 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
510 	return_ACPI_STATUS(status);
511 }
512 
513 #endif				/* !ACPI_REDUCED_HARDWARE */
514