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