2 Provide constructor and GetTick for Base instance of ACPI Timer Library
4 Copyright (C) 2014, Gabriel L. Somlo <somlo@cmu.edu>
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
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.
15 #include <Library/DebugLib.h>
16 #include <Library/IoLib.h>
17 #include <Library/PciLib.h>
18 #include <Library/PcdLib.h>
19 #include <OvmfPlatforms.h>
22 // Power Management PCI Configuration Register fields
25 #define PIIX4_PMIOSE BIT0
26 #define Q35_ACPI_EN BIT7
29 // Offset in the Power Management Base Address to the ACPI Timer
31 #define ACPI_TIMER_OFFSET 0x8
34 // Cached ACPI Timer IO Address
36 STATIC UINT32 mAcpiTimerIoAddr
;
39 The constructor function caches the ACPI tick counter address, and,
40 if necessary, enables ACPI IO space.
42 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
47 AcpiTimerLibConstructor (
51 UINT16 HostBridgeDevId
;
57 // Query Host Bridge DID to determine platform type
59 HostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
60 switch (HostBridgeDevId
) {
61 case INTEL_82441_DEVICE_ID
:
62 Pmba
= POWER_MGMT_REGISTER_PIIX4 (0x40);
63 AcpiCtlReg
= POWER_MGMT_REGISTER_PIIX4 (0x80); // PMREGMISC
64 AcpiEnBit
= PIIX4_PMIOSE
;
66 case INTEL_Q35_MCH_DEVICE_ID
:
67 Pmba
= POWER_MGMT_REGISTER_Q35 (0x40);
68 AcpiCtlReg
= POWER_MGMT_REGISTER_Q35 (0x44); // ACPI_CNTL
69 AcpiEnBit
= Q35_ACPI_EN
;
72 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
73 __FUNCTION__
, HostBridgeDevId
));
75 return RETURN_UNSUPPORTED
;
78 mAcpiTimerIoAddr
= (PciRead32 (Pmba
) & ~PMBA_RTE
) + ACPI_TIMER_OFFSET
;
81 // Check to see if the Power Management Base Address is already enabled
83 if ((PciRead8 (AcpiCtlReg
) & AcpiEnBit
) == 0) {
85 // If the Power Management Base Address is not programmed,
86 // then program the Power Management Base Address from a PCD.
88 PciAndThenOr32 (Pmba
, (UINT32
) ~0xFFC0, PcdGet16 (PcdAcpiPmBaseAddress
));
91 // Enable PMBA I/O port decodes
93 PciOr8 (AcpiCtlReg
, AcpiEnBit
);
96 return RETURN_SUCCESS
;
100 Internal function to read the current tick counter of ACPI.
102 Read the current ACPI tick counter using the counter address cached
103 by this instance's constructor.
105 @return The tick counter read.
109 InternalAcpiGetTimerTick (
114 // Return the current ACPI timer value.
116 return IoRead32 (mAcpiTimerIoAddr
);