788fc56e5f610aa6a37fb4f6f129c36720761111
[reactos.git] / drivers / bus / acpi / acpica / hardware / hwgpe.c
1 /******************************************************************************
2 *
3 * Module Name: hwgpe - Low level GPE enable/disable/clear functions
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2018, 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 UINT64 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 UINT64 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 return_ACPI_STATUS (Status);
554 }
555
556
557 /******************************************************************************
558 *
559 * FUNCTION: AcpiHwEnableAllRuntimeGpes
560 *
561 * PARAMETERS: None
562 *
563 * RETURN: Status
564 *
565 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
566 *
567 ******************************************************************************/
568
569 ACPI_STATUS
570 AcpiHwEnableAllRuntimeGpes (
571 void)
572 {
573 ACPI_STATUS Status;
574
575
576 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
577
578
579 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
580 return_ACPI_STATUS (Status);
581 }
582
583
584 /******************************************************************************
585 *
586 * FUNCTION: AcpiHwEnableAllWakeupGpes
587 *
588 * PARAMETERS: None
589 *
590 * RETURN: Status
591 *
592 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
593 *
594 ******************************************************************************/
595
596 ACPI_STATUS
597 AcpiHwEnableAllWakeupGpes (
598 void)
599 {
600 ACPI_STATUS Status;
601
602
603 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
604
605
606 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
607 return_ACPI_STATUS (Status);
608 }
609
610 #endif /* !ACPI_REDUCED_HARDWARE */