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