• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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