xref: /openbmc/linux/drivers/acpi/acpica/evgpeblk.c (revision d6e0cbb1)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: evgpeblk - GPE block creation and initialization.
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 #include "acnamesp.h"
14 
15 #define _COMPONENT          ACPI_EVENTS
16 ACPI_MODULE_NAME("evgpeblk")
17 #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
18 /* Local prototypes */
19 static acpi_status
20 acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
21 			  u32 interrupt_number);
22 
23 static acpi_status
24 acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
25 
26 /*******************************************************************************
27  *
28  * FUNCTION:    acpi_ev_install_gpe_block
29  *
30  * PARAMETERS:  gpe_block               - New GPE block
31  *              interrupt_number        - Xrupt to be associated with this
32  *                                        GPE block
33  *
34  * RETURN:      Status
35  *
36  * DESCRIPTION: Install new GPE block with mutex support
37  *
38  ******************************************************************************/
39 
40 static acpi_status
41 acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
42 			  u32 interrupt_number)
43 {
44 	struct acpi_gpe_block_info *next_gpe_block;
45 	struct acpi_gpe_xrupt_info *gpe_xrupt_block;
46 	acpi_status status;
47 	acpi_cpu_flags flags;
48 
49 	ACPI_FUNCTION_TRACE(ev_install_gpe_block);
50 
51 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
52 	if (ACPI_FAILURE(status)) {
53 		return_ACPI_STATUS(status);
54 	}
55 
56 	status =
57 	    acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block);
58 	if (ACPI_FAILURE(status)) {
59 		goto unlock_and_exit;
60 	}
61 
62 	/* Install the new block at the end of the list with lock */
63 
64 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
65 	if (gpe_xrupt_block->gpe_block_list_head) {
66 		next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
67 		while (next_gpe_block->next) {
68 			next_gpe_block = next_gpe_block->next;
69 		}
70 
71 		next_gpe_block->next = gpe_block;
72 		gpe_block->previous = next_gpe_block;
73 	} else {
74 		gpe_xrupt_block->gpe_block_list_head = gpe_block;
75 	}
76 
77 	gpe_block->xrupt_block = gpe_xrupt_block;
78 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
79 
80 unlock_and_exit:
81 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
82 	return_ACPI_STATUS(status);
83 }
84 
85 /*******************************************************************************
86  *
87  * FUNCTION:    acpi_ev_delete_gpe_block
88  *
89  * PARAMETERS:  gpe_block           - Existing GPE block
90  *
91  * RETURN:      Status
92  *
93  * DESCRIPTION: Remove a GPE block
94  *
95  ******************************************************************************/
96 
97 acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
98 {
99 	acpi_status status;
100 	acpi_cpu_flags flags;
101 
102 	ACPI_FUNCTION_TRACE(ev_install_gpe_block);
103 
104 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
105 	if (ACPI_FAILURE(status)) {
106 		return_ACPI_STATUS(status);
107 	}
108 
109 	/* Disable all GPEs in this block */
110 
111 	status =
112 	    acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL);
113 
114 	if (!gpe_block->previous && !gpe_block->next) {
115 
116 		/* This is the last gpe_block on this interrupt */
117 
118 		status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
119 		if (ACPI_FAILURE(status)) {
120 			goto unlock_and_exit;
121 		}
122 	} else {
123 		/* Remove the block on this interrupt with lock */
124 
125 		flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
126 		if (gpe_block->previous) {
127 			gpe_block->previous->next = gpe_block->next;
128 		} else {
129 			gpe_block->xrupt_block->gpe_block_list_head =
130 			    gpe_block->next;
131 		}
132 
133 		if (gpe_block->next) {
134 			gpe_block->next->previous = gpe_block->previous;
135 		}
136 
137 		acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
138 	}
139 
140 	acpi_current_gpe_count -= gpe_block->gpe_count;
141 
142 	/* Free the gpe_block */
143 
144 	ACPI_FREE(gpe_block->register_info);
145 	ACPI_FREE(gpe_block->event_info);
146 	ACPI_FREE(gpe_block);
147 
148 unlock_and_exit:
149 	status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
150 	return_ACPI_STATUS(status);
151 }
152 
153 /*******************************************************************************
154  *
155  * FUNCTION:    acpi_ev_create_gpe_info_blocks
156  *
157  * PARAMETERS:  gpe_block   - New GPE block
158  *
159  * RETURN:      Status
160  *
161  * DESCRIPTION: Create the register_info and event_info blocks for this GPE block
162  *
163  ******************************************************************************/
164 
165 static acpi_status
166 acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
167 {
168 	struct acpi_gpe_register_info *gpe_register_info = NULL;
169 	struct acpi_gpe_event_info *gpe_event_info = NULL;
170 	struct acpi_gpe_event_info *this_event;
171 	struct acpi_gpe_register_info *this_register;
172 	u32 i;
173 	u32 j;
174 	acpi_status status;
175 
176 	ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
177 
178 	/* Allocate the GPE register information block */
179 
180 	gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->
181 						 register_count *
182 						 sizeof(struct
183 							acpi_gpe_register_info));
184 	if (!gpe_register_info) {
185 		ACPI_ERROR((AE_INFO,
186 			    "Could not allocate the GpeRegisterInfo table"));
187 		return_ACPI_STATUS(AE_NO_MEMORY);
188 	}
189 
190 	/*
191 	 * Allocate the GPE event_info block. There are eight distinct GPEs
192 	 * per register. Initialization to zeros is sufficient.
193 	 */
194 	gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->gpe_count *
195 					      sizeof(struct
196 						     acpi_gpe_event_info));
197 	if (!gpe_event_info) {
198 		ACPI_ERROR((AE_INFO,
199 			    "Could not allocate the GpeEventInfo table"));
200 		status = AE_NO_MEMORY;
201 		goto error_exit;
202 	}
203 
204 	/* Save the new Info arrays in the GPE block */
205 
206 	gpe_block->register_info = gpe_register_info;
207 	gpe_block->event_info = gpe_event_info;
208 
209 	/*
210 	 * Initialize the GPE Register and Event structures. A goal of these
211 	 * tables is to hide the fact that there are two separate GPE register
212 	 * sets in a given GPE hardware block, the status registers occupy the
213 	 * first half, and the enable registers occupy the second half.
214 	 */
215 	this_register = gpe_register_info;
216 	this_event = gpe_event_info;
217 
218 	for (i = 0; i < gpe_block->register_count; i++) {
219 
220 		/* Init the register_info for this GPE register (8 GPEs) */
221 
222 		this_register->base_gpe_number = (u16)
223 		    (gpe_block->block_base_number +
224 		     (i * ACPI_GPE_REGISTER_WIDTH));
225 
226 		this_register->status_address.address = gpe_block->address + i;
227 
228 		this_register->enable_address.address =
229 		    gpe_block->address + i + gpe_block->register_count;
230 
231 		this_register->status_address.space_id = gpe_block->space_id;
232 		this_register->enable_address.space_id = gpe_block->space_id;
233 		this_register->status_address.bit_width =
234 		    ACPI_GPE_REGISTER_WIDTH;
235 		this_register->enable_address.bit_width =
236 		    ACPI_GPE_REGISTER_WIDTH;
237 		this_register->status_address.bit_offset = 0;
238 		this_register->enable_address.bit_offset = 0;
239 
240 		/* Init the event_info for each GPE within this register */
241 
242 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
243 			this_event->gpe_number =
244 			    (u8) (this_register->base_gpe_number + j);
245 			this_event->register_info = this_register;
246 			this_event++;
247 		}
248 
249 		/* Disable all GPEs within this register */
250 
251 		status = acpi_hw_write(0x00, &this_register->enable_address);
252 		if (ACPI_FAILURE(status)) {
253 			goto error_exit;
254 		}
255 
256 		/* Clear any pending GPE events within this register */
257 
258 		status = acpi_hw_write(0xFF, &this_register->status_address);
259 		if (ACPI_FAILURE(status)) {
260 			goto error_exit;
261 		}
262 
263 		this_register++;
264 	}
265 
266 	return_ACPI_STATUS(AE_OK);
267 
268 error_exit:
269 	if (gpe_register_info) {
270 		ACPI_FREE(gpe_register_info);
271 	}
272 	if (gpe_event_info) {
273 		ACPI_FREE(gpe_event_info);
274 	}
275 
276 	return_ACPI_STATUS(status);
277 }
278 
279 /*******************************************************************************
280  *
281  * FUNCTION:    acpi_ev_create_gpe_block
282  *
283  * PARAMETERS:  gpe_device          - Handle to the parent GPE block
284  *              gpe_block_address   - Address and space_ID
285  *              register_count      - Number of GPE register pairs in the block
286  *              gpe_block_base_number - Starting GPE number for the block
287  *              interrupt_number    - H/W interrupt for the block
288  *              return_gpe_block    - Where the new block descriptor is returned
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
293  *              the block are disabled at exit.
294  *              Note: Assumes namespace is locked.
295  *
296  ******************************************************************************/
297 
298 acpi_status
299 acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
300 			 u64 address,
301 			 u8 space_id,
302 			 u32 register_count,
303 			 u16 gpe_block_base_number,
304 			 u32 interrupt_number,
305 			 struct acpi_gpe_block_info **return_gpe_block)
306 {
307 	acpi_status status;
308 	struct acpi_gpe_block_info *gpe_block;
309 	struct acpi_gpe_walk_info walk_info;
310 
311 	ACPI_FUNCTION_TRACE(ev_create_gpe_block);
312 
313 	if (!register_count) {
314 		return_ACPI_STATUS(AE_OK);
315 	}
316 
317 	/* Allocate a new GPE block */
318 
319 	gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
320 	if (!gpe_block) {
321 		return_ACPI_STATUS(AE_NO_MEMORY);
322 	}
323 
324 	/* Initialize the new GPE block */
325 
326 	gpe_block->address = address;
327 	gpe_block->space_id = space_id;
328 	gpe_block->node = gpe_device;
329 	gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
330 	gpe_block->initialized = FALSE;
331 	gpe_block->register_count = register_count;
332 	gpe_block->block_base_number = gpe_block_base_number;
333 
334 	/*
335 	 * Create the register_info and event_info sub-structures
336 	 * Note: disables and clears all GPEs in the block
337 	 */
338 	status = acpi_ev_create_gpe_info_blocks(gpe_block);
339 	if (ACPI_FAILURE(status)) {
340 		ACPI_FREE(gpe_block);
341 		return_ACPI_STATUS(status);
342 	}
343 
344 	/* Install the new block in the global lists */
345 
346 	status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
347 	if (ACPI_FAILURE(status)) {
348 		ACPI_FREE(gpe_block->register_info);
349 		ACPI_FREE(gpe_block->event_info);
350 		ACPI_FREE(gpe_block);
351 		return_ACPI_STATUS(status);
352 	}
353 
354 	acpi_gbl_all_gpes_initialized = FALSE;
355 
356 	/* Find all GPE methods (_Lxx or_Exx) for this block */
357 
358 	walk_info.gpe_block = gpe_block;
359 	walk_info.gpe_device = gpe_device;
360 	walk_info.execute_by_owner_id = FALSE;
361 
362 	status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
363 					ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
364 					acpi_ev_match_gpe_method, NULL,
365 					&walk_info, NULL);
366 
367 	/* Return the new block */
368 
369 	if (return_gpe_block) {
370 		(*return_gpe_block) = gpe_block;
371 	}
372 
373 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
374 			      "    Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
375 			      (u32)gpe_block->block_base_number,
376 			      (u32)(gpe_block->block_base_number +
377 				    (gpe_block->gpe_count - 1)),
378 			      gpe_device->name.ascii, gpe_block->register_count,
379 			      interrupt_number,
380 			      interrupt_number ==
381 			      acpi_gbl_FADT.sci_interrupt ? " (SCI)" : ""));
382 
383 	/* Update global count of currently available GPEs */
384 
385 	acpi_current_gpe_count += gpe_block->gpe_count;
386 	return_ACPI_STATUS(AE_OK);
387 }
388 
389 /*******************************************************************************
390  *
391  * FUNCTION:    acpi_ev_initialize_gpe_block
392  *
393  * PARAMETERS:  acpi_gpe_callback
394  *
395  * RETURN:      Status
396  *
397  * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
398  *              associated methods.
399  *              Note: Assumes namespace is locked.
400  *
401  ******************************************************************************/
402 
403 acpi_status
404 acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
405 			     struct acpi_gpe_block_info *gpe_block,
406 			     void *context)
407 {
408 	acpi_status status;
409 	struct acpi_gpe_event_info *gpe_event_info;
410 	u32 gpe_enabled_count;
411 	u32 gpe_index;
412 	u32 i;
413 	u32 j;
414 	u8 *is_polling_needed = context;
415 	ACPI_ERROR_ONLY(u32 gpe_number);
416 
417 	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
418 
419 	/*
420 	 * Ignore a null GPE block (e.g., if no GPE block 1 exists), and
421 	 * any GPE blocks that have been initialized already.
422 	 */
423 	if (!gpe_block || gpe_block->initialized) {
424 		return_ACPI_STATUS(AE_OK);
425 	}
426 
427 	/*
428 	 * Enable all GPEs that have a corresponding method and have the
429 	 * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
430 	 * must be enabled via the acpi_enable_gpe() interface.
431 	 */
432 	gpe_enabled_count = 0;
433 
434 	for (i = 0; i < gpe_block->register_count; i++) {
435 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
436 
437 			/* Get the info block for this particular GPE */
438 
439 			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
440 			gpe_event_info = &gpe_block->event_info[gpe_index];
441 			ACPI_ERROR_ONLY(gpe_number =
442 					gpe_block->block_base_number +
443 					gpe_index);
444 			gpe_event_info->flags |= ACPI_GPE_INITIALIZED;
445 
446 			/*
447 			 * Ignore GPEs that have no corresponding _Lxx/_Exx method
448 			 * and GPEs that are used for wakeup
449 			 */
450 			if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
451 			     ACPI_GPE_DISPATCH_METHOD)
452 			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
453 				continue;
454 			}
455 
456 			status = acpi_ev_add_gpe_reference(gpe_event_info, FALSE);
457 			if (ACPI_FAILURE(status)) {
458 				ACPI_EXCEPTION((AE_INFO, status,
459 					"Could not enable GPE 0x%02X",
460 					gpe_number));
461 				continue;
462 			}
463 
464 			gpe_event_info->flags |= ACPI_GPE_AUTO_ENABLED;
465 
466 			if (is_polling_needed &&
467 			    ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
468 				*is_polling_needed = TRUE;
469 			}
470 
471 			gpe_enabled_count++;
472 		}
473 	}
474 
475 	if (gpe_enabled_count) {
476 		ACPI_INFO(("Enabled %u GPEs in block %02X to %02X",
477 			   gpe_enabled_count, (u32)gpe_block->block_base_number,
478 			   (u32)(gpe_block->block_base_number +
479 				 (gpe_block->gpe_count - 1))));
480 	}
481 
482 	gpe_block->initialized = TRUE;
483 
484 	return_ACPI_STATUS(AE_OK);
485 }
486 
487 #endif				/* !ACPI_REDUCED_HARDWARE */
488