1 | /****************************************************************************** |
2 | * |
3 | * Module Name: hwgpe - Low level GPE enable/disable/clear functions |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, 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.h" |
45 | #include "accommon.h" |
46 | #include "acevents.h" |
47 | |
48 | #define _COMPONENT ACPI_HARDWARE |
49 | ACPI_MODULE_NAME ("hwgpe" ) |
50 | |
51 | #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ |
52 | |
53 | /* Local prototypes */ |
54 | |
55 | static ACPI_STATUS |
56 | AcpiHwEnableWakeupGpeBlock ( |
57 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
58 | ACPI_GPE_BLOCK_INFO *GpeBlock, |
59 | void *Context); |
60 | |
61 | static ACPI_STATUS |
62 | AcpiHwGpeEnableWrite ( |
63 | UINT8 EnableMask, |
64 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo); |
65 | |
66 | |
67 | /****************************************************************************** |
68 | * |
69 | * FUNCTION: AcpiHwGetGpeRegisterBit |
70 | * |
71 | * PARAMETERS: GpeEventInfo - Info block for the GPE |
72 | * |
73 | * RETURN: Register mask with a one in the GPE bit position |
74 | * |
75 | * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the |
76 | * correct position for the input GPE. |
77 | * |
78 | ******************************************************************************/ |
79 | |
80 | UINT32 |
81 | AcpiHwGetGpeRegisterBit ( |
82 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
83 | { |
84 | |
85 | return ((UINT32) 1 << |
86 | (GpeEventInfo->GpeNumber - GpeEventInfo->RegisterInfo->BaseGpeNumber)); |
87 | } |
88 | |
89 | |
90 | /****************************************************************************** |
91 | * |
92 | * FUNCTION: AcpiHwLowSetGpe |
93 | * |
94 | * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled |
95 | * Action - Enable or disable |
96 | * |
97 | * RETURN: Status |
98 | * |
99 | * DESCRIPTION: Enable or disable a single GPE in the parent enable register. |
100 | * The EnableMask field of the involved GPE register must be |
101 | * updated by the caller if necessary. |
102 | * |
103 | ******************************************************************************/ |
104 | |
105 | ACPI_STATUS |
106 | AcpiHwLowSetGpe ( |
107 | ACPI_GPE_EVENT_INFO *GpeEventInfo, |
108 | UINT32 Action) |
109 | { |
110 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
111 | ACPI_STATUS Status = AE_OK; |
112 | UINT32 EnableMask; |
113 | UINT32 RegisterBit; |
114 | |
115 | |
116 | ACPI_FUNCTION_ENTRY (); |
117 | |
118 | |
119 | /* Get the info block for the entire GPE register */ |
120 | |
121 | GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
122 | if (!GpeRegisterInfo) |
123 | { |
124 | return (AE_NOT_EXIST); |
125 | } |
126 | |
127 | /* Get current value of the enable register that contains this GPE */ |
128 | |
129 | Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); |
130 | if (ACPI_FAILURE (Status)) |
131 | { |
132 | return (Status); |
133 | } |
134 | |
135 | /* Set or clear just the bit that corresponds to this GPE */ |
136 | |
137 | RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); |
138 | switch (Action) |
139 | { |
140 | case ACPI_GPE_CONDITIONAL_ENABLE: |
141 | |
142 | /* Only enable if the corresponding EnableMask bit is set */ |
143 | |
144 | if (!(RegisterBit & GpeRegisterInfo->EnableMask)) |
145 | { |
146 | return (AE_BAD_PARAMETER); |
147 | } |
148 | |
149 | /*lint -fallthrough */ |
150 | |
151 | case ACPI_GPE_ENABLE: |
152 | |
153 | ACPI_SET_BIT (EnableMask, RegisterBit); |
154 | break; |
155 | |
156 | case ACPI_GPE_DISABLE: |
157 | |
158 | ACPI_CLEAR_BIT (EnableMask, RegisterBit); |
159 | break; |
160 | |
161 | default: |
162 | |
163 | ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u" , Action)); |
164 | return (AE_BAD_PARAMETER); |
165 | } |
166 | |
167 | if (!(RegisterBit & GpeRegisterInfo->MaskForRun)) |
168 | { |
169 | /* Write the updated enable mask */ |
170 | |
171 | Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); |
172 | } |
173 | return (Status); |
174 | } |
175 | |
176 | |
177 | /****************************************************************************** |
178 | * |
179 | * FUNCTION: AcpiHwClearGpe |
180 | * |
181 | * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared |
182 | * |
183 | * RETURN: Status |
184 | * |
185 | * DESCRIPTION: Clear the status bit for a single GPE. |
186 | * |
187 | ******************************************************************************/ |
188 | |
189 | ACPI_STATUS |
190 | AcpiHwClearGpe ( |
191 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
192 | { |
193 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
194 | ACPI_STATUS Status; |
195 | UINT32 RegisterBit; |
196 | |
197 | |
198 | ACPI_FUNCTION_ENTRY (); |
199 | |
200 | /* Get the info block for the entire GPE register */ |
201 | |
202 | GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
203 | if (!GpeRegisterInfo) |
204 | { |
205 | return (AE_NOT_EXIST); |
206 | } |
207 | |
208 | /* |
209 | * Write a one to the appropriate bit in the status register to |
210 | * clear this GPE. |
211 | */ |
212 | RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); |
213 | |
214 | Status = AcpiHwWrite (RegisterBit, &GpeRegisterInfo->StatusAddress); |
215 | return (Status); |
216 | } |
217 | |
218 | |
219 | /****************************************************************************** |
220 | * |
221 | * FUNCTION: AcpiHwGetGpeStatus |
222 | * |
223 | * PARAMETERS: GpeEventInfo - Info block for the GPE to queried |
224 | * EventStatus - Where the GPE status is returned |
225 | * |
226 | * RETURN: Status |
227 | * |
228 | * DESCRIPTION: Return the status of a single GPE. |
229 | * |
230 | ******************************************************************************/ |
231 | |
232 | ACPI_STATUS |
233 | AcpiHwGetGpeStatus ( |
234 | ACPI_GPE_EVENT_INFO *GpeEventInfo, |
235 | ACPI_EVENT_STATUS *EventStatus) |
236 | { |
237 | UINT32 InByte; |
238 | UINT32 RegisterBit; |
239 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
240 | ACPI_EVENT_STATUS LocalEventStatus = 0; |
241 | ACPI_STATUS Status; |
242 | |
243 | |
244 | ACPI_FUNCTION_ENTRY (); |
245 | |
246 | |
247 | if (!EventStatus) |
248 | { |
249 | return (AE_BAD_PARAMETER); |
250 | } |
251 | |
252 | /* GPE currently handled? */ |
253 | |
254 | if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != |
255 | ACPI_GPE_DISPATCH_NONE) |
256 | { |
257 | LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER; |
258 | } |
259 | |
260 | /* Get the info block for the entire GPE register */ |
261 | |
262 | GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
263 | |
264 | /* Get the register bitmask for this GPE */ |
265 | |
266 | RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); |
267 | |
268 | /* GPE currently enabled? (enabled for runtime?) */ |
269 | |
270 | if (RegisterBit & GpeRegisterInfo->EnableForRun) |
271 | { |
272 | LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; |
273 | } |
274 | |
275 | /* GPE currently masked? (masked for runtime?) */ |
276 | |
277 | if (RegisterBit & GpeRegisterInfo->MaskForRun) |
278 | { |
279 | LocalEventStatus |= ACPI_EVENT_FLAG_MASKED; |
280 | } |
281 | |
282 | /* GPE enabled for wake? */ |
283 | |
284 | if (RegisterBit & GpeRegisterInfo->EnableForWake) |
285 | { |
286 | LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; |
287 | } |
288 | |
289 | /* GPE currently enabled (enable bit == 1)? */ |
290 | |
291 | Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress); |
292 | if (ACPI_FAILURE (Status)) |
293 | { |
294 | return (Status); |
295 | } |
296 | |
297 | if (RegisterBit & InByte) |
298 | { |
299 | LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET; |
300 | } |
301 | |
302 | /* GPE currently active (status bit == 1)? */ |
303 | |
304 | Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); |
305 | if (ACPI_FAILURE (Status)) |
306 | { |
307 | return (Status); |
308 | } |
309 | |
310 | if (RegisterBit & InByte) |
311 | { |
312 | LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET; |
313 | } |
314 | |
315 | /* Set return value */ |
316 | |
317 | (*EventStatus) = LocalEventStatus; |
318 | return (AE_OK); |
319 | } |
320 | |
321 | |
322 | /****************************************************************************** |
323 | * |
324 | * FUNCTION: AcpiHwGpeEnableWrite |
325 | * |
326 | * PARAMETERS: EnableMask - Bit mask to write to the GPE register |
327 | * GpeRegisterInfo - Gpe Register info |
328 | * |
329 | * RETURN: Status |
330 | * |
331 | * DESCRIPTION: Write the enable mask byte to the given GPE register. |
332 | * |
333 | ******************************************************************************/ |
334 | |
335 | static ACPI_STATUS |
336 | AcpiHwGpeEnableWrite ( |
337 | UINT8 EnableMask, |
338 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) |
339 | { |
340 | ACPI_STATUS Status; |
341 | |
342 | |
343 | GpeRegisterInfo->EnableMask = EnableMask; |
344 | |
345 | Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); |
346 | return (Status); |
347 | } |
348 | |
349 | |
350 | /****************************************************************************** |
351 | * |
352 | * FUNCTION: AcpiHwDisableGpeBlock |
353 | * |
354 | * PARAMETERS: GpeXruptInfo - GPE Interrupt info |
355 | * GpeBlock - Gpe Block info |
356 | * |
357 | * RETURN: Status |
358 | * |
359 | * DESCRIPTION: Disable all GPEs within a single GPE block |
360 | * |
361 | ******************************************************************************/ |
362 | |
363 | ACPI_STATUS |
364 | AcpiHwDisableGpeBlock ( |
365 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
366 | ACPI_GPE_BLOCK_INFO *GpeBlock, |
367 | void *Context) |
368 | { |
369 | UINT32 i; |
370 | ACPI_STATUS Status; |
371 | |
372 | |
373 | /* Examine each GPE Register within the block */ |
374 | |
375 | for (i = 0; i < GpeBlock->RegisterCount; i++) |
376 | { |
377 | /* Disable all GPEs in this register */ |
378 | |
379 | Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]); |
380 | if (ACPI_FAILURE (Status)) |
381 | { |
382 | return (Status); |
383 | } |
384 | } |
385 | |
386 | return (AE_OK); |
387 | } |
388 | |
389 | |
390 | /****************************************************************************** |
391 | * |
392 | * FUNCTION: AcpiHwClearGpeBlock |
393 | * |
394 | * PARAMETERS: GpeXruptInfo - GPE Interrupt info |
395 | * GpeBlock - Gpe Block info |
396 | * |
397 | * RETURN: Status |
398 | * |
399 | * DESCRIPTION: Clear status bits for all GPEs within a single GPE block |
400 | * |
401 | ******************************************************************************/ |
402 | |
403 | ACPI_STATUS |
404 | AcpiHwClearGpeBlock ( |
405 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
406 | ACPI_GPE_BLOCK_INFO *GpeBlock, |
407 | void *Context) |
408 | { |
409 | UINT32 i; |
410 | ACPI_STATUS Status; |
411 | |
412 | |
413 | /* Examine each GPE Register within the block */ |
414 | |
415 | for (i = 0; i < GpeBlock->RegisterCount; i++) |
416 | { |
417 | /* Clear status on all GPEs in this register */ |
418 | |
419 | Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); |
420 | if (ACPI_FAILURE (Status)) |
421 | { |
422 | return (Status); |
423 | } |
424 | } |
425 | |
426 | return (AE_OK); |
427 | } |
428 | |
429 | |
430 | /****************************************************************************** |
431 | * |
432 | * FUNCTION: AcpiHwEnableRuntimeGpeBlock |
433 | * |
434 | * PARAMETERS: GpeXruptInfo - GPE Interrupt info |
435 | * GpeBlock - Gpe Block info |
436 | * |
437 | * RETURN: Status |
438 | * |
439 | * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes |
440 | * combination wake/run GPEs. |
441 | * |
442 | ******************************************************************************/ |
443 | |
444 | ACPI_STATUS |
445 | AcpiHwEnableRuntimeGpeBlock ( |
446 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
447 | ACPI_GPE_BLOCK_INFO *GpeBlock, |
448 | void *Context) |
449 | { |
450 | UINT32 i; |
451 | ACPI_STATUS Status; |
452 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
453 | UINT8 EnableMask; |
454 | |
455 | |
456 | /* NOTE: assumes that all GPEs are currently disabled */ |
457 | |
458 | /* Examine each GPE Register within the block */ |
459 | |
460 | for (i = 0; i < GpeBlock->RegisterCount; i++) |
461 | { |
462 | GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; |
463 | if (!GpeRegisterInfo->EnableForRun) |
464 | { |
465 | continue; |
466 | } |
467 | |
468 | /* Enable all "runtime" GPEs in this register */ |
469 | |
470 | EnableMask = GpeRegisterInfo->EnableForRun & |
471 | ~GpeRegisterInfo->MaskForRun; |
472 | Status = AcpiHwGpeEnableWrite (EnableMask, GpeRegisterInfo); |
473 | if (ACPI_FAILURE (Status)) |
474 | { |
475 | return (Status); |
476 | } |
477 | } |
478 | |
479 | return (AE_OK); |
480 | } |
481 | |
482 | |
483 | /****************************************************************************** |
484 | * |
485 | * FUNCTION: AcpiHwEnableWakeupGpeBlock |
486 | * |
487 | * PARAMETERS: GpeXruptInfo - GPE Interrupt info |
488 | * GpeBlock - Gpe Block info |
489 | * |
490 | * RETURN: Status |
491 | * |
492 | * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes |
493 | * combination wake/run GPEs. |
494 | * |
495 | ******************************************************************************/ |
496 | |
497 | static ACPI_STATUS |
498 | AcpiHwEnableWakeupGpeBlock ( |
499 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
500 | ACPI_GPE_BLOCK_INFO *GpeBlock, |
501 | void *Context) |
502 | { |
503 | UINT32 i; |
504 | ACPI_STATUS Status; |
505 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
506 | |
507 | |
508 | /* Examine each GPE Register within the block */ |
509 | |
510 | for (i = 0; i < GpeBlock->RegisterCount; i++) |
511 | { |
512 | GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; |
513 | |
514 | /* |
515 | * Enable all "wake" GPEs in this register and disable the |
516 | * remaining ones. |
517 | */ |
518 | Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake, |
519 | GpeRegisterInfo); |
520 | if (ACPI_FAILURE (Status)) |
521 | { |
522 | return (Status); |
523 | } |
524 | } |
525 | |
526 | return (AE_OK); |
527 | } |
528 | |
529 | |
530 | /****************************************************************************** |
531 | * |
532 | * FUNCTION: AcpiHwDisableAllGpes |
533 | * |
534 | * PARAMETERS: None |
535 | * |
536 | * RETURN: Status |
537 | * |
538 | * DESCRIPTION: Disable and clear all GPEs in all GPE blocks |
539 | * |
540 | ******************************************************************************/ |
541 | |
542 | ACPI_STATUS |
543 | AcpiHwDisableAllGpes ( |
544 | void) |
545 | { |
546 | ACPI_STATUS Status; |
547 | |
548 | |
549 | ACPI_FUNCTION_TRACE (HwDisableAllGpes); |
550 | |
551 | |
552 | Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); |
553 | Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); |
554 | return_ACPI_STATUS (Status); |
555 | } |
556 | |
557 | |
558 | /****************************************************************************** |
559 | * |
560 | * FUNCTION: AcpiHwEnableAllRuntimeGpes |
561 | * |
562 | * PARAMETERS: None |
563 | * |
564 | * RETURN: Status |
565 | * |
566 | * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks |
567 | * |
568 | ******************************************************************************/ |
569 | |
570 | ACPI_STATUS |
571 | AcpiHwEnableAllRuntimeGpes ( |
572 | void) |
573 | { |
574 | ACPI_STATUS Status; |
575 | |
576 | |
577 | ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); |
578 | |
579 | |
580 | Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); |
581 | return_ACPI_STATUS (Status); |
582 | } |
583 | |
584 | |
585 | /****************************************************************************** |
586 | * |
587 | * FUNCTION: AcpiHwEnableAllWakeupGpes |
588 | * |
589 | * PARAMETERS: None |
590 | * |
591 | * RETURN: Status |
592 | * |
593 | * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks |
594 | * |
595 | ******************************************************************************/ |
596 | |
597 | ACPI_STATUS |
598 | AcpiHwEnableAllWakeupGpes ( |
599 | void) |
600 | { |
601 | ACPI_STATUS Status; |
602 | |
603 | |
604 | ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); |
605 | |
606 | |
607 | Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); |
608 | return_ACPI_STATUS (Status); |
609 | } |
610 | |
611 | #endif /* !ACPI_REDUCED_HARDWARE */ |
612 | |