xref: /openbmc/linux/drivers/acpi/acpica/hwgpe.c (revision e0bf6c5c)
1 /******************************************************************************
2  *
3  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acevents.h"
47 
48 #define _COMPONENT          ACPI_HARDWARE
49 ACPI_MODULE_NAME("hwgpe")
50 #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
51 /* Local prototypes */
52 static acpi_status
53 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
54 				struct acpi_gpe_block_info *gpe_block,
55 				void *context);
56 
57 static acpi_status
58 acpi_hw_gpe_enable_write(u8 enable_mask,
59 			 struct acpi_gpe_register_info *gpe_register_info);
60 
61 /******************************************************************************
62  *
63  * FUNCTION:	acpi_hw_get_gpe_register_bit
64  *
65  * PARAMETERS:	gpe_event_info	    - Info block for the GPE
66  *
67  * RETURN:	Register mask with a one in the GPE bit position
68  *
69  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
70  *              correct position for the input GPE.
71  *
72  ******************************************************************************/
73 
74 u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
75 {
76 
77 	return ((u32)1 <<
78 		(gpe_event_info->gpe_number -
79 		 gpe_event_info->register_info->base_gpe_number));
80 }
81 
82 /******************************************************************************
83  *
84  * FUNCTION:	acpi_hw_low_set_gpe
85  *
86  * PARAMETERS:	gpe_event_info	    - Info block for the GPE to be disabled
87  *		action		    - Enable or disable
88  *
89  * RETURN:	Status
90  *
91  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
92  *
93  ******************************************************************************/
94 
95 acpi_status
96 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
97 {
98 	struct acpi_gpe_register_info *gpe_register_info;
99 	acpi_status status;
100 	u32 enable_mask;
101 	u32 register_bit;
102 
103 	ACPI_FUNCTION_ENTRY();
104 
105 	/* Get the info block for the entire GPE register */
106 
107 	gpe_register_info = gpe_event_info->register_info;
108 	if (!gpe_register_info) {
109 		return (AE_NOT_EXIST);
110 	}
111 
112 	/* Get current value of the enable register that contains this GPE */
113 
114 	status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
115 	if (ACPI_FAILURE(status)) {
116 		return (status);
117 	}
118 
119 	/* Set or clear just the bit that corresponds to this GPE */
120 
121 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
122 	switch (action & ~ACPI_GPE_SAVE_MASK) {
123 	case ACPI_GPE_CONDITIONAL_ENABLE:
124 
125 		/* Only enable if the corresponding enable_mask bit is set */
126 
127 		if (!(register_bit & gpe_register_info->enable_mask)) {
128 			return (AE_BAD_PARAMETER);
129 		}
130 
131 		/*lint -fallthrough */
132 
133 	case ACPI_GPE_ENABLE:
134 
135 		ACPI_SET_BIT(enable_mask, register_bit);
136 		break;
137 
138 	case ACPI_GPE_DISABLE:
139 
140 		ACPI_CLEAR_BIT(enable_mask, register_bit);
141 		break;
142 
143 	default:
144 
145 		ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
146 		return (AE_BAD_PARAMETER);
147 	}
148 
149 	/* Write the updated enable mask */
150 
151 	status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
152 	if (ACPI_SUCCESS(status) && (action & ACPI_GPE_SAVE_MASK)) {
153 		gpe_register_info->enable_mask = (u8)enable_mask;
154 	}
155 	return (status);
156 }
157 
158 /******************************************************************************
159  *
160  * FUNCTION:    acpi_hw_clear_gpe
161  *
162  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
163  *
164  * RETURN:      Status
165  *
166  * DESCRIPTION: Clear the status bit for a single GPE.
167  *
168  ******************************************************************************/
169 
170 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
171 {
172 	struct acpi_gpe_register_info *gpe_register_info;
173 	acpi_status status;
174 	u32 register_bit;
175 
176 	ACPI_FUNCTION_ENTRY();
177 
178 	/* Get the info block for the entire GPE register */
179 
180 	gpe_register_info = gpe_event_info->register_info;
181 	if (!gpe_register_info) {
182 		return (AE_NOT_EXIST);
183 	}
184 
185 	/*
186 	 * Write a one to the appropriate bit in the status register to
187 	 * clear this GPE.
188 	 */
189 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
190 
191 	status = acpi_hw_write(register_bit,
192 			       &gpe_register_info->status_address);
193 
194 	return (status);
195 }
196 
197 /******************************************************************************
198  *
199  * FUNCTION:    acpi_hw_get_gpe_status
200  *
201  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
202  *              event_status        - Where the GPE status is returned
203  *
204  * RETURN:      Status
205  *
206  * DESCRIPTION: Return the status of a single GPE.
207  *
208  ******************************************************************************/
209 
210 acpi_status
211 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
212 		       acpi_event_status *event_status)
213 {
214 	u32 in_byte;
215 	u32 register_bit;
216 	struct acpi_gpe_register_info *gpe_register_info;
217 	acpi_event_status local_event_status = 0;
218 	acpi_status status;
219 
220 	ACPI_FUNCTION_ENTRY();
221 
222 	if (!event_status) {
223 		return (AE_BAD_PARAMETER);
224 	}
225 
226 	/* GPE currently handled? */
227 
228 	if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
229 	    ACPI_GPE_DISPATCH_NONE) {
230 		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
231 	}
232 
233 	/* Get the info block for the entire GPE register */
234 
235 	gpe_register_info = gpe_event_info->register_info;
236 
237 	/* Get the register bitmask for this GPE */
238 
239 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
240 
241 	/* GPE currently enabled? (enabled for runtime?) */
242 
243 	if (register_bit & gpe_register_info->enable_for_run) {
244 		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
245 	}
246 
247 	/* GPE enabled for wake? */
248 
249 	if (register_bit & gpe_register_info->enable_for_wake) {
250 		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
251 	}
252 
253 	/* GPE currently active (status bit == 1)? */
254 
255 	status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
256 	if (ACPI_FAILURE(status)) {
257 		return (status);
258 	}
259 
260 	if (register_bit & in_byte) {
261 		local_event_status |= ACPI_EVENT_FLAG_SET;
262 	}
263 
264 	/* Set return value */
265 
266 	(*event_status) = local_event_status;
267 	return (AE_OK);
268 }
269 
270 /******************************************************************************
271  *
272  * FUNCTION:    acpi_hw_gpe_enable_write
273  *
274  * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
275  *              gpe_register_info   - Gpe Register info
276  *
277  * RETURN:      Status
278  *
279  * DESCRIPTION: Write the enable mask byte to the given GPE register.
280  *
281  ******************************************************************************/
282 
283 static acpi_status
284 acpi_hw_gpe_enable_write(u8 enable_mask,
285 			 struct acpi_gpe_register_info *gpe_register_info)
286 {
287 	acpi_status status;
288 
289 	status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
290 	if (ACPI_SUCCESS(status)) {
291 		gpe_register_info->enable_mask = enable_mask;
292 	}
293 	return (status);
294 }
295 
296 /******************************************************************************
297  *
298  * FUNCTION:    acpi_hw_disable_gpe_block
299  *
300  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
301  *              gpe_block           - Gpe Block info
302  *
303  * RETURN:      Status
304  *
305  * DESCRIPTION: Disable all GPEs within a single GPE block
306  *
307  ******************************************************************************/
308 
309 acpi_status
310 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
311 			  struct acpi_gpe_block_info *gpe_block, void *context)
312 {
313 	u32 i;
314 	acpi_status status;
315 
316 	/* Examine each GPE Register within the block */
317 
318 	for (i = 0; i < gpe_block->register_count; i++) {
319 
320 		/* Disable all GPEs in this register */
321 
322 		status =
323 		    acpi_hw_gpe_enable_write(0x00,
324 					     &gpe_block->register_info[i]);
325 		if (ACPI_FAILURE(status)) {
326 			return (status);
327 		}
328 	}
329 
330 	return (AE_OK);
331 }
332 
333 /******************************************************************************
334  *
335  * FUNCTION:    acpi_hw_clear_gpe_block
336  *
337  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
338  *              gpe_block           - Gpe Block info
339  *
340  * RETURN:      Status
341  *
342  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
343  *
344  ******************************************************************************/
345 
346 acpi_status
347 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
348 			struct acpi_gpe_block_info *gpe_block, void *context)
349 {
350 	u32 i;
351 	acpi_status status;
352 
353 	/* Examine each GPE Register within the block */
354 
355 	for (i = 0; i < gpe_block->register_count; i++) {
356 
357 		/* Clear status on all GPEs in this register */
358 
359 		status =
360 		    acpi_hw_write(0xFF,
361 				  &gpe_block->register_info[i].status_address);
362 		if (ACPI_FAILURE(status)) {
363 			return (status);
364 		}
365 	}
366 
367 	return (AE_OK);
368 }
369 
370 /******************************************************************************
371  *
372  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
373  *
374  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
375  *              gpe_block           - Gpe Block info
376  *
377  * RETURN:      Status
378  *
379  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
380  *              combination wake/run GPEs.
381  *
382  ******************************************************************************/
383 
384 acpi_status
385 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
386 				 struct acpi_gpe_block_info * gpe_block,
387 				 void *context)
388 {
389 	u32 i;
390 	acpi_status status;
391 	struct acpi_gpe_register_info *gpe_register_info;
392 
393 	/* NOTE: assumes that all GPEs are currently disabled */
394 
395 	/* Examine each GPE Register within the block */
396 
397 	for (i = 0; i < gpe_block->register_count; i++) {
398 		gpe_register_info = &gpe_block->register_info[i];
399 		if (!gpe_register_info->enable_for_run) {
400 			continue;
401 		}
402 
403 		/* Enable all "runtime" GPEs in this register */
404 
405 		status =
406 		    acpi_hw_gpe_enable_write(gpe_register_info->enable_for_run,
407 					     gpe_register_info);
408 		if (ACPI_FAILURE(status)) {
409 			return (status);
410 		}
411 	}
412 
413 	return (AE_OK);
414 }
415 
416 /******************************************************************************
417  *
418  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
419  *
420  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
421  *              gpe_block           - Gpe Block info
422  *
423  * RETURN:      Status
424  *
425  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
426  *              combination wake/run GPEs.
427  *
428  ******************************************************************************/
429 
430 static acpi_status
431 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
432 				struct acpi_gpe_block_info *gpe_block,
433 				void *context)
434 {
435 	u32 i;
436 	acpi_status status;
437 	struct acpi_gpe_register_info *gpe_register_info;
438 
439 	/* Examine each GPE Register within the block */
440 
441 	for (i = 0; i < gpe_block->register_count; i++) {
442 		gpe_register_info = &gpe_block->register_info[i];
443 
444 		/*
445 		 * Enable all "wake" GPEs in this register and disable the
446 		 * remaining ones.
447 		 */
448 
449 		status =
450 		    acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
451 					     gpe_register_info);
452 		if (ACPI_FAILURE(status)) {
453 			return (status);
454 		}
455 	}
456 
457 	return (AE_OK);
458 }
459 
460 /******************************************************************************
461  *
462  * FUNCTION:    acpi_hw_disable_all_gpes
463  *
464  * PARAMETERS:  None
465  *
466  * RETURN:      Status
467  *
468  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
469  *
470  ******************************************************************************/
471 
472 acpi_status acpi_hw_disable_all_gpes(void)
473 {
474 	acpi_status status;
475 
476 	ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
477 
478 	status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
479 	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
480 	return_ACPI_STATUS(status);
481 }
482 
483 /******************************************************************************
484  *
485  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
486  *
487  * PARAMETERS:  None
488  *
489  * RETURN:      Status
490  *
491  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
492  *
493  ******************************************************************************/
494 
495 acpi_status acpi_hw_enable_all_runtime_gpes(void)
496 {
497 	acpi_status status;
498 
499 	ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
500 
501 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
502 	return_ACPI_STATUS(status);
503 }
504 
505 /******************************************************************************
506  *
507  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
508  *
509  * PARAMETERS:  None
510  *
511  * RETURN:      Status
512  *
513  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
514  *
515  ******************************************************************************/
516 
517 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
518 {
519 	acpi_status status;
520 
521 	ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
522 
523 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
524 	return_ACPI_STATUS(status);
525 }
526 
527 #endif				/* !ACPI_REDUCED_HARDWARE */
528