hwgpe.c revision 1.1.1.6 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.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;
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 /* Write the updated enable mask */
168
169 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
170 return (Status);
171 }
172
173
174 /******************************************************************************
175 *
176 * FUNCTION: AcpiHwClearGpe
177 *
178 * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared
179 *
180 * RETURN: Status
181 *
182 * DESCRIPTION: Clear the status bit for a single GPE.
183 *
184 ******************************************************************************/
185
186 ACPI_STATUS
187 AcpiHwClearGpe (
188 ACPI_GPE_EVENT_INFO *GpeEventInfo)
189 {
190 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
191 ACPI_STATUS Status;
192 UINT32 RegisterBit;
193
194
195 ACPI_FUNCTION_ENTRY ();
196
197 /* Get the info block for the entire GPE register */
198
199 GpeRegisterInfo = GpeEventInfo->RegisterInfo;
200 if (!GpeRegisterInfo)
201 {
202 return (AE_NOT_EXIST);
203 }
204
205 /*
206 * Write a one to the appropriate bit in the status register to
207 * clear this GPE.
208 */
209 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
210
211 Status = AcpiHwWrite (RegisterBit,
212 &GpeRegisterInfo->StatusAddress);
213
214 return (Status);
215 }
216
217
218 /******************************************************************************
219 *
220 * FUNCTION: AcpiHwGetGpeStatus
221 *
222 * PARAMETERS: GpeEventInfo - Info block for the GPE to queried
223 * EventStatus - Where the GPE status is returned
224 *
225 * RETURN: Status
226 *
227 * DESCRIPTION: Return the status of a single GPE.
228 *
229 ******************************************************************************/
230
231 ACPI_STATUS
232 AcpiHwGetGpeStatus (
233 ACPI_GPE_EVENT_INFO *GpeEventInfo,
234 ACPI_EVENT_STATUS *EventStatus)
235 {
236 UINT32 InByte;
237 UINT32 RegisterBit;
238 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
239 ACPI_EVENT_STATUS LocalEventStatus = 0;
240 ACPI_STATUS Status;
241
242
243 ACPI_FUNCTION_ENTRY ();
244
245
246 if (!EventStatus)
247 {
248 return (AE_BAD_PARAMETER);
249 }
250
251 /* GPE currently handled? */
252
253 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
254 ACPI_GPE_DISPATCH_NONE)
255 {
256 LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER;
257 }
258
259 /* Get the info block for the entire GPE register */
260
261 GpeRegisterInfo = GpeEventInfo->RegisterInfo;
262
263 /* Get the register bitmask for this GPE */
264
265 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
266
267 /* GPE currently enabled? (enabled for runtime?) */
268
269 if (RegisterBit & GpeRegisterInfo->EnableForRun)
270 {
271 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
272 }
273
274 /* GPE enabled for wake? */
275
276 if (RegisterBit & GpeRegisterInfo->EnableForWake)
277 {
278 LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
279 }
280
281 /* GPE currently enabled (enable bit == 1)? */
282
283 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress);
284 if (ACPI_FAILURE (Status))
285 {
286 return (Status);
287 }
288
289 if (RegisterBit & InByte)
290 {
291 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET;
292 }
293
294 /* GPE currently active (status bit == 1)? */
295
296 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
297 if (ACPI_FAILURE (Status))
298 {
299 return (Status);
300 }
301
302 if (RegisterBit & InByte)
303 {
304 LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET;
305 }
306
307 /* Set return value */
308
309 (*EventStatus) = LocalEventStatus;
310 return (AE_OK);
311 }
312
313
314 /******************************************************************************
315 *
316 * FUNCTION: AcpiHwGpeEnableWrite
317 *
318 * PARAMETERS: EnableMask - Bit mask to write to the GPE register
319 * GpeRegisterInfo - Gpe Register info
320 *
321 * RETURN: Status
322 *
323 * DESCRIPTION: Write the enable mask byte to the given GPE register.
324 *
325 ******************************************************************************/
326
327 static ACPI_STATUS
328 AcpiHwGpeEnableWrite (
329 UINT8 EnableMask,
330 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo)
331 {
332 ACPI_STATUS Status;
333
334
335 GpeRegisterInfo->EnableMask = EnableMask;
336 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
337
338 return (Status);
339 }
340
341
342 /******************************************************************************
343 *
344 * FUNCTION: AcpiHwDisableGpeBlock
345 *
346 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
347 * GpeBlock - Gpe Block info
348 *
349 * RETURN: Status
350 *
351 * DESCRIPTION: Disable all GPEs within a single GPE block
352 *
353 ******************************************************************************/
354
355 ACPI_STATUS
356 AcpiHwDisableGpeBlock (
357 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
358 ACPI_GPE_BLOCK_INFO *GpeBlock,
359 void *Context)
360 {
361 UINT32 i;
362 ACPI_STATUS Status;
363
364
365 /* Examine each GPE Register within the block */
366
367 for (i = 0; i < GpeBlock->RegisterCount; i++)
368 {
369 /* Disable all GPEs in this register */
370
371 Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]);
372 if (ACPI_FAILURE (Status))
373 {
374 return (Status);
375 }
376 }
377
378 return (AE_OK);
379 }
380
381
382 /******************************************************************************
383 *
384 * FUNCTION: AcpiHwClearGpeBlock
385 *
386 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
387 * GpeBlock - Gpe Block info
388 *
389 * RETURN: Status
390 *
391 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
392 *
393 ******************************************************************************/
394
395 ACPI_STATUS
396 AcpiHwClearGpeBlock (
397 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
398 ACPI_GPE_BLOCK_INFO *GpeBlock,
399 void *Context)
400 {
401 UINT32 i;
402 ACPI_STATUS Status;
403
404
405 /* Examine each GPE Register within the block */
406
407 for (i = 0; i < GpeBlock->RegisterCount; i++)
408 {
409 /* Clear status on all GPEs in this register */
410
411 Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
412 if (ACPI_FAILURE (Status))
413 {
414 return (Status);
415 }
416 }
417
418 return (AE_OK);
419 }
420
421
422 /******************************************************************************
423 *
424 * FUNCTION: AcpiHwEnableRuntimeGpeBlock
425 *
426 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
427 * GpeBlock - Gpe Block info
428 *
429 * RETURN: Status
430 *
431 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
432 * combination wake/run GPEs.
433 *
434 ******************************************************************************/
435
436 ACPI_STATUS
437 AcpiHwEnableRuntimeGpeBlock (
438 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
439 ACPI_GPE_BLOCK_INFO *GpeBlock,
440 void *Context)
441 {
442 UINT32 i;
443 ACPI_STATUS Status;
444 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
445
446
447 /* NOTE: assumes that all GPEs are currently disabled */
448
449 /* Examine each GPE Register within the block */
450
451 for (i = 0; i < GpeBlock->RegisterCount; i++)
452 {
453 GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
454 if (!GpeRegisterInfo->EnableForRun)
455 {
456 continue;
457 }
458
459 /* Enable all "runtime" GPEs in this register */
460
461 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForRun,
462 GpeRegisterInfo);
463 if (ACPI_FAILURE (Status))
464 {
465 return (Status);
466 }
467 }
468
469 return (AE_OK);
470 }
471
472
473 /******************************************************************************
474 *
475 * FUNCTION: AcpiHwEnableWakeupGpeBlock
476 *
477 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
478 * GpeBlock - Gpe Block info
479 *
480 * RETURN: Status
481 *
482 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
483 * combination wake/run GPEs.
484 *
485 ******************************************************************************/
486
487 static ACPI_STATUS
488 AcpiHwEnableWakeupGpeBlock (
489 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
490 ACPI_GPE_BLOCK_INFO *GpeBlock,
491 void *Context)
492 {
493 UINT32 i;
494 ACPI_STATUS Status;
495 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
496
497
498 /* Examine each GPE Register within the block */
499
500 for (i = 0; i < GpeBlock->RegisterCount; i++)
501 {
502 GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
503
504 /*
505 * Enable all "wake" GPEs in this register and disable the
506 * remaining ones.
507 */
508 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake,
509 GpeRegisterInfo);
510 if (ACPI_FAILURE (Status))
511 {
512 return (Status);
513 }
514 }
515
516 return (AE_OK);
517 }
518
519
520 /******************************************************************************
521 *
522 * FUNCTION: AcpiHwDisableAllGpes
523 *
524 * PARAMETERS: None
525 *
526 * RETURN: Status
527 *
528 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
529 *
530 ******************************************************************************/
531
532 ACPI_STATUS
533 AcpiHwDisableAllGpes (
534 void)
535 {
536 ACPI_STATUS Status;
537
538
539 ACPI_FUNCTION_TRACE (HwDisableAllGpes);
540
541
542 Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
543 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
544 return_ACPI_STATUS (Status);
545 }
546
547
548 /******************************************************************************
549 *
550 * FUNCTION: AcpiHwEnableAllRuntimeGpes
551 *
552 * PARAMETERS: None
553 *
554 * RETURN: Status
555 *
556 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
557 *
558 ******************************************************************************/
559
560 ACPI_STATUS
561 AcpiHwEnableAllRuntimeGpes (
562 void)
563 {
564 ACPI_STATUS Status;
565
566
567 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
568
569
570 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
571 return_ACPI_STATUS (Status);
572 }
573
574
575 /******************************************************************************
576 *
577 * FUNCTION: AcpiHwEnableAllWakeupGpes
578 *
579 * PARAMETERS: None
580 *
581 * RETURN: Status
582 *
583 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
584 *
585 ******************************************************************************/
586
587 ACPI_STATUS
588 AcpiHwEnableAllWakeupGpes (
589 void)
590 {
591 ACPI_STATUS Status;
592
593
594 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
595
596
597 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
598 return_ACPI_STATUS (Status);
599 }
600
601 #endif /* !ACPI_REDUCED_HARDWARE */
602