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 <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
AcpiTimerLibConstructor(VOID)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
InternalAcpiGetTimerTick(VOID)101 InternalAcpiGetTimerTick (
102 VOID
103 )
104 {
105 //
106 // Return the current ACPI timer value.
107 //
108 return IoRead32 (mAcpiTimerIoAddr);
109 }
110