1 /** @file 2 Provide constructor and GetTick for Base instance of ACPI Timer Library 3 4 Copyright (C) 2014, Gabriel L. Somlo <somlo (at) cmu.edu> 5 6 This program and the accompanying materials are licensed and made 7 available under the terms and conditions of the BSD License which 8 accompanies this distribution. The full text of the license may 9 be found at http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 **/ 14 15 #include <Library/DebugLib.h> 16 #include <Library/IoLib.h> 17 #include <Library/PciLib.h> 18 #include <OvmfPlatforms.h> 19 20 // 21 // Cached ACPI Timer IO Address 22 // 23 STATIC UINT32 mAcpiTimerIoAddr; 24 25 /** 26 The constructor function caches the ACPI tick counter address, and, 27 if necessary, enables ACPI IO space. 28 29 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. 30 31 **/ 32 RETURN_STATUS 33 EFIAPI 34 AcpiTimerLibConstructor ( 35 VOID 36 ) 37 { 38 UINT16 HostBridgeDevId; 39 UINTN Pmba; 40 UINT32 PmbaAndVal; 41 UINT32 PmbaOrVal; 42 UINTN AcpiCtlReg; 43 UINT8 AcpiEnBit; 44 45 // 46 // Query Host Bridge DID to determine platform type 47 // 48 HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID); 49 switch (HostBridgeDevId) { 50 case INTEL_82441_DEVICE_ID: 51 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA); 52 PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK; 53 PmbaOrVal = PIIX4_PMBA_VALUE; 54 AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC); 55 AcpiEnBit = PIIX4_PMREGMISC_PMIOSE; 56 break; 57 case INTEL_Q35_MCH_DEVICE_ID: 58 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE); 59 PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK; 60 PmbaOrVal = ICH9_PMBASE_VALUE; 61 AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL); 62 AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN; 63 break; 64 default: 65 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n", 66 __FUNCTION__, HostBridgeDevId)); 67 ASSERT (FALSE); 68 return RETURN_UNSUPPORTED; 69 } 70 71 // 72 // Check to see if the Power Management Base Address is already enabled 73 // 74 if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) { 75 // 76 // If the Power Management Base Address is not programmed, 77 // then program it now. 78 // 79 PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal); 80 81 // 82 // Enable PMBA I/O port decodes 83 // 84 PciOr8 (AcpiCtlReg, AcpiEnBit); 85 } 86 87 mAcpiTimerIoAddr = (PciRead32 (Pmba) & ~PMBA_RTE) + ACPI_TIMER_OFFSET; 88 return RETURN_SUCCESS; 89 } 90 91 /** 92 Internal function to read the current tick counter of ACPI. 93 94 Read the current ACPI tick counter using the counter address cached 95 by this instance's constructor. 96 97 @return The tick counter read. 98 99 **/ 100 UINT32 101 InternalAcpiGetTimerTick ( 102 VOID 103 ) 104 { 105 // 106 // Return the current ACPI timer value. 107 // 108 return IoRead32 (mAcpiTimerIoAddr); 109 } 110