]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c
c20f29930420e2265cf6986f44865cd93cfc6a91
[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 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 <Library/PcdLib.h>
19 #include <OvmfPlatforms.h>
20
21 //
22 // Power Management PCI Configuration Register fields
23 //
24 #define PMBA_RTE BIT0
25 #define PIIX4_PMIOSE BIT0
26
27 //
28 // Offset in the Power Management Base Address to the ACPI Timer
29 //
30 #define ACPI_TIMER_OFFSET 0x8
31
32 //
33 // Cached ACPI Timer IO Address
34 //
35 STATIC UINT32 mAcpiTimerIoAddr;
36
37 /**
38 The constructor function caches the ACPI tick counter address, and,
39 if necessary, enables ACPI IO space.
40
41 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
42
43 **/
44 RETURN_STATUS
45 EFIAPI
46 AcpiTimerLibConstructor (
47 VOID
48 )
49 {
50 UINT16 HostBridgeDevId;
51 UINTN Pmba;
52 UINTN AcpiCtlReg;
53 UINT8 AcpiEnBit;
54
55 //
56 // Query Host Bridge DID to determine platform type
57 //
58 HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
59 switch (HostBridgeDevId) {
60 case INTEL_82441_DEVICE_ID:
61 Pmba = POWER_MGMT_REGISTER_PIIX4 (0x40);
62 AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (0x80); // PMREGMISC
63 AcpiEnBit = PIIX4_PMIOSE;
64 break;
65 case INTEL_Q35_MCH_DEVICE_ID:
66 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
67 AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
68 AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN;
69 break;
70 default:
71 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
72 __FUNCTION__, HostBridgeDevId));
73 ASSERT (FALSE);
74 return RETURN_UNSUPPORTED;
75 }
76
77 mAcpiTimerIoAddr = (PciRead32 (Pmba) & ~PMBA_RTE) + ACPI_TIMER_OFFSET;
78
79 //
80 // Check to see if the Power Management Base Address is already enabled
81 //
82 if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
83 //
84 // If the Power Management Base Address is not programmed,
85 // then program the Power Management Base Address from a PCD.
86 //
87 PciAndThenOr32 (Pmba, (UINT32) ~0xFFC0, PcdGet16 (PcdAcpiPmBaseAddress));
88
89 //
90 // Enable PMBA I/O port decodes
91 //
92 PciOr8 (AcpiCtlReg, AcpiEnBit);
93 }
94
95 return RETURN_SUCCESS;
96 }
97
98 /**
99 Internal function to read the current tick counter of ACPI.
100
101 Read the current ACPI tick counter using the counter address cached
102 by this instance's constructor.
103
104 @return The tick counter read.
105
106 **/
107 UINT32
108 InternalAcpiGetTimerTick (
109 VOID
110 )
111 {
112 //
113 // Return the current ACPI timer value.
114 //
115 return IoRead32 (mAcpiTimerIoAddr);
116 }