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