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