hwgpe.c revision 217365
167754Smsmith 267754Smsmith/****************************************************************************** 367754Smsmith * 470243Smsmith * Module Name: hwgpe - Low level GPE enable/disable/clear functions 567754Smsmith * 667754Smsmith *****************************************************************************/ 767754Smsmith 867754Smsmith/* 967754Smsmith * Copyright (C) 2000 - 2011, Intel Corp. 1067754Smsmith * All rights reserved. 1167754Smsmith * 1271867Smsmith * Redistribution and use in source and binary forms, with or without 1370243Smsmith * modification, are permitted provided that the following conditions 1467754Smsmith * are met: 1567754Smsmith * 1. Redistributions of source code must retain the above copyright 1667754Smsmith * notice, this list of conditions, and the following disclaimer, 1767754Smsmith * without modification. 1867754Smsmith * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1967754Smsmith * substantially similar to the "NO WARRANTY" disclaimer below 2067754Smsmith * ("Disclaimer") and any redistribution must be conditioned upon 2167754Smsmith * including a substantially similar Disclaimer requirement for further 2267754Smsmith * binary redistribution. 2367754Smsmith * 3. Neither the names of the above-listed copyright holders nor the names 2467754Smsmith * of any contributors may be used to endorse or promote products derived 2567754Smsmith * from this software without specific prior written permission. 2667754Smsmith * 2767754Smsmith * Alternatively, this software may be distributed under the terms of the 2867754Smsmith * GNU General Public License ("GPL") version 2 as published by the Free 2967754Smsmith * Software Foundation. 3067754Smsmith * 3167754Smsmith * NO WARRANTY 3267754Smsmith * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3367754Smsmith * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3467754Smsmith * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3567754Smsmith * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3667754Smsmith * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3767754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3867754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3967754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4067754Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4167754Smsmith * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4267754Smsmith * POSSIBILITY OF SUCH DAMAGES. 4367754Smsmith */ 4467754Smsmith 4567754Smsmith#include <contrib/dev/acpica/include/acpi.h> 4667754Smsmith#include <contrib/dev/acpica/include/accommon.h> 4767754Smsmith#include <contrib/dev/acpica/include/acevents.h> 4867754Smsmith 4967754Smsmith#define _COMPONENT ACPI_HARDWARE 5067754Smsmith ACPI_MODULE_NAME ("hwgpe") 5167754Smsmith 5267754Smsmith/* Local prototypes */ 5367754Smsmith 5467754Smsmithstatic ACPI_STATUS 5567754SmsmithAcpiHwEnableWakeupGpeBlock ( 5667754Smsmith ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 5767754Smsmith ACPI_GPE_BLOCK_INFO *GpeBlock, 5867754Smsmith void *Context); 5967754Smsmith 6067754Smsmith 6167754Smsmith/****************************************************************************** 6267754Smsmith * 6367754Smsmith * FUNCTION: AcpiHwGetGpeRegisterBit 6467754Smsmith * 6567754Smsmith * PARAMETERS: GpeEventInfo - Info block for the GPE 6667754Smsmith * GpeRegisterInfo - Info block for the GPE register 6767754Smsmith * 6867754Smsmith * RETURN: Register mask with a one in the GPE bit position 6967754Smsmith * 7067754Smsmith * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the 7167754Smsmith * correct position for the input GPE. 7267754Smsmith * 7367754Smsmith ******************************************************************************/ 7467754Smsmith 7567754SmsmithUINT32 7667754SmsmithAcpiHwGetGpeRegisterBit ( 7767754Smsmith ACPI_GPE_EVENT_INFO *GpeEventInfo, 7867754Smsmith ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) 7967754Smsmith{ 8067754Smsmith 8167754Smsmith return ((UINT32) 1 << 8267754Smsmith (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); 8367754Smsmith} 8467754Smsmith 8567754Smsmith 8667754Smsmith/****************************************************************************** 8767754Smsmith * 8867754Smsmith * FUNCTION: AcpiHwLowSetGpe 8967754Smsmith * 9067754Smsmith * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled 9167754Smsmith * Action - Enable or disable 9267754Smsmith * 9367754Smsmith * RETURN: Status 9467754Smsmith * 9567754Smsmith * DESCRIPTION: Enable or disable a single GPE in the parent enable register. 9667754Smsmith * 9767754Smsmith ******************************************************************************/ 9867754Smsmith 9967754SmsmithACPI_STATUS 10067754SmsmithAcpiHwLowSetGpe ( 10167754Smsmith ACPI_GPE_EVENT_INFO *GpeEventInfo, 10267754Smsmith UINT32 Action) 10367754Smsmith{ 10467754Smsmith ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 10567754Smsmith ACPI_STATUS Status; 10667754Smsmith UINT32 EnableMask; 10767754Smsmith UINT32 RegisterBit; 10867754Smsmith 10967754Smsmith 11067754Smsmith ACPI_FUNCTION_ENTRY (); 11167754Smsmith 11267754Smsmith 11367754Smsmith /* Get the info block for the entire GPE register */ 11467754Smsmith 11567754Smsmith GpeRegisterInfo = GpeEventInfo->RegisterInfo; 11667754Smsmith if (!GpeRegisterInfo) 11767754Smsmith { 11867754Smsmith return (AE_NOT_EXIST); 11967754Smsmith } 12067754Smsmith 12167754Smsmith /* Get current value of the enable register that contains this GPE */ 12267754Smsmith 12367754Smsmith Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); 12477424Smsmith if (ACPI_FAILURE (Status)) 12580062Smsmith { 12667754Smsmith return (Status); 12767754Smsmith } 12867754Smsmith 12967754Smsmith /* Set or clear just the bit that corresponds to this GPE */ 13067754Smsmith 13167754Smsmith RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 13267754Smsmith switch (Action) 13367754Smsmith { 13467754Smsmith case ACPI_GPE_CONDITIONAL_ENABLE: 13567754Smsmith 13667754Smsmith /* Only enable if the EnableForRun bit is set */ 13767754Smsmith 13867754Smsmith if (!(RegisterBit & GpeRegisterInfo->EnableForRun)) 13967754Smsmith { 14067754Smsmith return (AE_BAD_PARAMETER); 14167754Smsmith } 14280062Smsmith 14380062Smsmith /*lint -fallthrough */ 14480062Smsmith 14580062Smsmith case ACPI_GPE_ENABLE: 14667754Smsmith ACPI_SET_BIT (EnableMask, RegisterBit); 14767754Smsmith break; 14867754Smsmith 14967754Smsmith case ACPI_GPE_DISABLE: 15067754Smsmith ACPI_CLEAR_BIT (EnableMask, RegisterBit); 15167754Smsmith break; 15267754Smsmith 15367754Smsmith default: 15480062Smsmith ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action)); 15567754Smsmith return (AE_BAD_PARAMETER); 15667754Smsmith } 15780062Smsmith 15867754Smsmith /* Write the updated enable mask */ 15980062Smsmith 16067754Smsmith Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); 16167754Smsmith return (Status); 16267754Smsmith} 16377424Smsmith 16477424Smsmith 16577424Smsmith/****************************************************************************** 16677424Smsmith * 16777424Smsmith * FUNCTION: AcpiHwClearGpe 16877424Smsmith * 16977424Smsmith * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared 17077424Smsmith * 17177424Smsmith * RETURN: Status 17277424Smsmith * 17377424Smsmith * DESCRIPTION: Clear the status bit for a single GPE. 17477424Smsmith * 17577424Smsmith ******************************************************************************/ 17677424Smsmith 17777424SmsmithACPI_STATUS 17877424SmsmithAcpiHwClearGpe ( 17977424Smsmith ACPI_GPE_EVENT_INFO *GpeEventInfo) 18067754Smsmith{ 18167754Smsmith ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 18267754Smsmith ACPI_STATUS Status; 18367754Smsmith UINT32 RegisterBit; 18467754Smsmith 18580062Smsmith 18669450Smsmith ACPI_FUNCTION_ENTRY (); 18767754Smsmith 18867754Smsmith /* Get the info block for the entire GPE register */ 18967754Smsmith 19080062Smsmith GpeRegisterInfo = GpeEventInfo->RegisterInfo; 19167754Smsmith if (!GpeRegisterInfo) 19267754Smsmith { 19367754Smsmith return (AE_NOT_EXIST); 19467754Smsmith } 19567754Smsmith 19667754Smsmith /* 19767754Smsmith * Write a one to the appropriate bit in the status register to 19867754Smsmith * clear this GPE. 19967754Smsmith */ 20067754Smsmith RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 20167754Smsmith 20267754Smsmith Status = AcpiHwWrite (RegisterBit, 20367754Smsmith &GpeRegisterInfo->StatusAddress); 20467754Smsmith 20567754Smsmith return (Status); 20667754Smsmith} 20767754Smsmith 20867754Smsmith 20967754Smsmith/****************************************************************************** 21067754Smsmith * 21167754Smsmith * FUNCTION: AcpiHwGetGpeStatus 21278986Smsmith * 21378986Smsmith * PARAMETERS: GpeEventInfo - Info block for the GPE to queried 21478986Smsmith * EventStatus - Where the GPE status is returned 21578986Smsmith * 21678986Smsmith * RETURN: Status 21778986Smsmith * 21867754Smsmith * DESCRIPTION: Return the status of a single GPE. 21978986Smsmith * 22067754Smsmith ******************************************************************************/ 22167754Smsmith 22267754SmsmithACPI_STATUS 22367754SmsmithAcpiHwGetGpeStatus ( 22467754Smsmith ACPI_GPE_EVENT_INFO *GpeEventInfo, 22567754Smsmith ACPI_EVENT_STATUS *EventStatus) 22667754Smsmith{ 22767754Smsmith UINT32 InByte; 22867754Smsmith UINT32 RegisterBit; 22977424Smsmith ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 23067754Smsmith ACPI_EVENT_STATUS LocalEventStatus = 0; 23167754Smsmith ACPI_STATUS Status; 23267754Smsmith 23367754Smsmith 23467754Smsmith ACPI_FUNCTION_ENTRY (); 23567754Smsmith 23677424Smsmith 23767754Smsmith if (!EventStatus) 23867754Smsmith { 23967754Smsmith return (AE_BAD_PARAMETER); 24067754Smsmith } 24167754Smsmith 24267754Smsmith /* Get the info block for the entire GPE register */ 24367754Smsmith 24467754Smsmith GpeRegisterInfo = GpeEventInfo->RegisterInfo; 24567754Smsmith 24667754Smsmith /* Get the register bitmask for this GPE */ 24767754Smsmith 24867754Smsmith RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 24967754Smsmith 25067754Smsmith /* GPE currently enabled? (enabled for runtime?) */ 25167754Smsmith 25267754Smsmith if (RegisterBit & GpeRegisterInfo->EnableForRun) 25367754Smsmith { 25467754Smsmith LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; 25567754Smsmith } 25667754Smsmith 25767754Smsmith /* GPE enabled for wake? */ 25867754Smsmith 25967754Smsmith if (RegisterBit & GpeRegisterInfo->EnableForWake) 26067754Smsmith { 26167754Smsmith LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; 26267754Smsmith } 26367754Smsmith 26467754Smsmith /* GPE currently active (status bit == 1)? */ 26567754Smsmith 26667754Smsmith Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); 26767754Smsmith if (ACPI_FAILURE (Status)) 26867754Smsmith { 26967754Smsmith return (Status); 27067754Smsmith } 27167754Smsmith 27267754Smsmith if (RegisterBit & InByte) 27367754Smsmith { 27467754Smsmith LocalEventStatus |= ACPI_EVENT_FLAG_SET; 27567754Smsmith } 27667754Smsmith 27767754Smsmith /* Set return value */ 27867754Smsmith 27967754Smsmith (*EventStatus) = LocalEventStatus; 28067754Smsmith return (AE_OK); 28167754Smsmith} 28267754Smsmith 28367754Smsmith 28467754Smsmith/****************************************************************************** 28567754Smsmith * 28667754Smsmith * FUNCTION: AcpiHwDisableGpeBlock 28767754Smsmith * 28877424Smsmith * PARAMETERS: GpeXruptInfo - GPE Interrupt info 28967754Smsmith * GpeBlock - Gpe Block info 29067754Smsmith * 29167754Smsmith * RETURN: Status 29267754Smsmith * 29367754Smsmith * DESCRIPTION: Disable all GPEs within a single GPE block 29477424Smsmith * 29567754Smsmith ******************************************************************************/ 29667754Smsmith 29767754SmsmithACPI_STATUS 29867754SmsmithAcpiHwDisableGpeBlock ( 29967754Smsmith ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 30077424Smsmith ACPI_GPE_BLOCK_INFO *GpeBlock, 30167754Smsmith void *Context) 30267754Smsmith{ 30367754Smsmith UINT32 i; 30467754Smsmith ACPI_STATUS Status; 30567754Smsmith 30677424Smsmith 30767754Smsmith /* Examine each GPE Register within the block */ 30867754Smsmith 30967754Smsmith for (i = 0; i < GpeBlock->RegisterCount; i++) 31067754Smsmith { 31167754Smsmith /* Disable all GPEs in this register */ 31267754Smsmith 31377424Smsmith Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress); 31467754Smsmith if (ACPI_FAILURE (Status)) 31567754Smsmith { 31667754Smsmith return (Status); 31767754Smsmith } 31877424Smsmith } 31977424Smsmith 32077424Smsmith return (AE_OK); 32167754Smsmith} 32267754Smsmith 32367754Smsmith 32467754Smsmith/****************************************************************************** 32567754Smsmith * 32677424Smsmith * FUNCTION: AcpiHwClearGpeBlock 32777424Smsmith * 32867754Smsmith * PARAMETERS: GpeXruptInfo - GPE Interrupt info 32967754Smsmith * GpeBlock - Gpe Block info 33067754Smsmith * 33167754Smsmith * RETURN: Status 33267754Smsmith * 33377424Smsmith * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 33467754Smsmith * 33567754Smsmith ******************************************************************************/ 33667754Smsmith 33767754SmsmithACPI_STATUS 33867754SmsmithAcpiHwClearGpeBlock ( 33967754Smsmith ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 34067754Smsmith ACPI_GPE_BLOCK_INFO *GpeBlock, 34167754Smsmith void *Context) 34267754Smsmith{ 34367754Smsmith UINT32 i; 34467754Smsmith ACPI_STATUS Status; 34567754Smsmith 34667754Smsmith 34777424Smsmith /* Examine each GPE Register within the block */ 34867754Smsmith 34967754Smsmith for (i = 0; i < GpeBlock->RegisterCount; i++) 35067754Smsmith { 35167754Smsmith /* Clear status on all GPEs in this register */ 35267754Smsmith 35367754Smsmith Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); 35467754Smsmith if (ACPI_FAILURE (Status)) 35567754Smsmith { 35667754Smsmith return (Status); 35767754Smsmith } 35867754Smsmith } 35967754Smsmith 36067754Smsmith return (AE_OK); 36167754Smsmith} 36267754Smsmith 36367754Smsmith 36467754Smsmith/****************************************************************************** 36567754Smsmith * 36667754Smsmith * FUNCTION: AcpiHwEnableRuntimeGpeBlock 36767754Smsmith * 36867754Smsmith * PARAMETERS: GpeXruptInfo - GPE Interrupt info 36967754Smsmith * GpeBlock - Gpe Block info 37067754Smsmith * 37167754Smsmith * RETURN: Status 37267754Smsmith * 37367754Smsmith * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 37467754Smsmith * combination wake/run GPEs. 37567754Smsmith * 37667754Smsmith ******************************************************************************/ 37767754Smsmith 37867754SmsmithACPI_STATUS 37967754SmsmithAcpiHwEnableRuntimeGpeBlock ( 38067754Smsmith ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 38167754Smsmith ACPI_GPE_BLOCK_INFO *GpeBlock, 38267754Smsmith void *Context) 38367754Smsmith{ 38467754Smsmith UINT32 i; 38567754Smsmith ACPI_STATUS Status; 38667754Smsmith 38767754Smsmith 38867754Smsmith /* NOTE: assumes that all GPEs are currently disabled */ 38967754Smsmith 39067754Smsmith /* Examine each GPE Register within the block */ 39167754Smsmith 39267754Smsmith for (i = 0; i < GpeBlock->RegisterCount; i++) 39367754Smsmith { 39467754Smsmith if (!GpeBlock->RegisterInfo[i].EnableForRun) 39567754Smsmith { 39667754Smsmith continue; 39767754Smsmith } 39867754Smsmith 39967754Smsmith /* Enable all "runtime" GPEs in this register */ 40067754Smsmith 40169450Smsmith Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun, 40267754Smsmith &GpeBlock->RegisterInfo[i].EnableAddress); 40367754Smsmith if (ACPI_FAILURE (Status)) 40467754Smsmith { 40569450Smsmith return (Status); 40667754Smsmith } 40767754Smsmith } 40871867Smsmith 40971867Smsmith return (AE_OK); 41071867Smsmith} 41171867Smsmith 41267754Smsmith 41367754Smsmith/****************************************************************************** 41467754Smsmith * 41567754Smsmith * FUNCTION: AcpiHwEnableWakeupGpeBlock 41667754Smsmith * 41767754Smsmith * PARAMETERS: GpeXruptInfo - GPE Interrupt info 41867754Smsmith * GpeBlock - Gpe Block info 41967754Smsmith * 42067754Smsmith * RETURN: Status 42167754Smsmith * 42267754Smsmith * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 42367754Smsmith * combination wake/run GPEs. 42467754Smsmith * 42567754Smsmith ******************************************************************************/ 42667754Smsmith 42767754Smsmithstatic ACPI_STATUS 42867754SmsmithAcpiHwEnableWakeupGpeBlock ( 42967754Smsmith ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 43067754Smsmith ACPI_GPE_BLOCK_INFO *GpeBlock, 43167754Smsmith void *Context) 43267754Smsmith{ 43367754Smsmith UINT32 i; 43467754Smsmith ACPI_STATUS Status; 43567754Smsmith 43667754Smsmith 43767754Smsmith /* Examine each GPE Register within the block */ 43867754Smsmith 43967754Smsmith for (i = 0; i < GpeBlock->RegisterCount; i++) 44067754Smsmith { 44167754Smsmith if (!GpeBlock->RegisterInfo[i].EnableForWake) 44267754Smsmith { 443 continue; 444 } 445 446 /* Enable all "wake" GPEs in this register */ 447 448 Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake, 449 &GpeBlock->RegisterInfo[i].EnableAddress); 450 if (ACPI_FAILURE (Status)) 451 { 452 return (Status); 453 } 454 } 455 456 return (AE_OK); 457} 458 459 460/****************************************************************************** 461 * 462 * FUNCTION: AcpiHwDisableAllGpes 463 * 464 * PARAMETERS: None 465 * 466 * RETURN: Status 467 * 468 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 469 * 470 ******************************************************************************/ 471 472ACPI_STATUS 473AcpiHwDisableAllGpes ( 474 void) 475{ 476 ACPI_STATUS Status; 477 478 479 ACPI_FUNCTION_TRACE (HwDisableAllGpes); 480 481 482 Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); 483 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 484 return_ACPI_STATUS (Status); 485} 486 487 488/****************************************************************************** 489 * 490 * FUNCTION: AcpiHwEnableAllRuntimeGpes 491 * 492 * PARAMETERS: None 493 * 494 * RETURN: Status 495 * 496 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 497 * 498 ******************************************************************************/ 499 500ACPI_STATUS 501AcpiHwEnableAllRuntimeGpes ( 502 void) 503{ 504 ACPI_STATUS Status; 505 506 507 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); 508 509 510 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); 511 return_ACPI_STATUS (Status); 512} 513 514 515/****************************************************************************** 516 * 517 * FUNCTION: AcpiHwEnableAllWakeupGpes 518 * 519 * PARAMETERS: None 520 * 521 * RETURN: Status 522 * 523 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 524 * 525 ******************************************************************************/ 526 527ACPI_STATUS 528AcpiHwEnableAllWakeupGpes ( 529 void) 530{ 531 ACPI_STATUS Status; 532 533 534 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); 535 536 537 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); 538 return_ACPI_STATUS (Status); 539} 540 541