]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c
949a89d71394e635a8715b27cfb3177b1a6f0839
[mirror_edk2.git] / OvmfPkg / Library / AcpiTimerLib / AcpiTimerLib.c
1 /** @file
2 ACPI Timer implements one instance of Timer Library.
3
4 Copyright (c) 2008, Intel Corporation<BR> All rights
5 reserved. This program and the accompanying materials are
6 licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Base.h>
16 #include <Library/TimerLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/IoLib.h>
19 #include <Library/PciLib.h>
20
21 #define ACPI_TIMER_FREQUENCY 3579545
22 #define ACPI_TIMER_COUNT_SIZE 0x01000000
23
24 /**
25 The constructor function enables ACPI IO space.
26
27 If ACPI I/O space not enabled, this function will enable it.
28 It will always return RETURN_SUCCESS.
29
30 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
31
32 **/
33 RETURN_STATUS
34 EFIAPI
35 AcpiTimerLibConstructor (
36 VOID
37 )
38 {
39 UINT8 Device;
40
41 Device = 1;
42 // Device = 7;
43
44 //
45 // ACPI Timer enable is in Bus 0, Device ?, Function 3
46 //
47 PciOr8 (PCI_LIB_ADDRESS (0,Device,3,0x04), 0x01);
48 PciAndThenOr32 (PCI_LIB_ADDRESS (0,Device,3,0x40), (UINT32) ~0xfc0, 0x400);
49 PciOr8 (PCI_LIB_ADDRESS (0,Device,3,0x80), 0x01); return RETURN_SUCCESS;
50 }
51
52 /**
53 Internal function to read the current tick counter of ACPI.
54
55 Internal function to read the current tick counter of ACPI.
56
57 @return The tick counter read.
58
59 **/
60 STATIC
61 UINT32
62 InternalAcpiGetTimerTick (
63 VOID
64 )
65 {
66 return IoRead32 (0x408);
67 }
68
69 /**
70 Stalls the CPU for at least the given number of ticks.
71
72 Stalls the CPU for at least the given number of ticks. It's invoked by
73 MicroSecondDelay() and NanoSecondDelay().
74
75 @param Delay A period of time to delay in ticks.
76
77 **/
78 STATIC
79 VOID
80 InternalAcpiDelay (
81 IN UINT32 Delay
82 )
83 {
84 UINT32 Ticks;
85 UINT32 Times;
86
87 Times = Delay >> 22;
88 Delay &= BIT22 - 1;
89 do {
90 //
91 // The target timer count is calculated here
92 //
93 Ticks = InternalAcpiGetTimerTick () + Delay;
94 Delay = BIT22;
95 //
96 // Wait until time out
97 // Delay >= 2^23 could not be handled by this function
98 // Timer wrap-arounds are handled correctly by this function
99 //
100 while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) {
101 CpuPause ();
102 }
103 } while (Times-- > 0);
104 }
105
106 /**
107 Stalls the CPU for at least the given number of microseconds.
108
109 Stalls the CPU for the number of microseconds specified by MicroSeconds.
110
111 @param MicroSeconds The minimum number of microseconds to delay.
112
113 @return MicroSeconds
114
115 **/
116 UINTN
117 EFIAPI
118 MicroSecondDelay (
119 IN UINTN MicroSeconds
120 )
121 {
122 InternalAcpiDelay (
123 (UINT32)DivU64x32 (
124 MultU64x32 (
125 MicroSeconds,
126 ACPI_TIMER_FREQUENCY
127 ),
128 1000000u
129 )
130 );
131 return MicroSeconds;
132 }
133
134 /**
135 Stalls the CPU for at least the given number of nanoseconds.
136
137 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
138
139 @param NanoSeconds The minimum number of nanoseconds to delay.
140
141 @return NanoSeconds
142
143 **/
144 UINTN
145 EFIAPI
146 NanoSecondDelay (
147 IN UINTN NanoSeconds
148 )
149 {
150 InternalAcpiDelay (
151 (UINT32)DivU64x32 (
152 MultU64x32 (
153 NanoSeconds,
154 ACPI_TIMER_FREQUENCY
155 ),
156 1000000000u
157 )
158 );
159 return NanoSeconds;
160 }
161
162 /**
163 Retrieves the current value of a 64-bit free running performance counter.
164
165 Retrieves the current value of a 64-bit free running performance counter. The
166 counter can either count up by 1 or count down by 1. If the physical
167 performance counter counts by a larger increment, then the counter values
168 must be translated. The properties of the counter can be retrieved from
169 GetPerformanceCounterProperties().
170
171 @return The current value of the free running performance counter.
172
173 **/
174 UINT64
175 EFIAPI
176 GetPerformanceCounter (
177 VOID
178 )
179 {
180 return (UINT64)InternalAcpiGetTimerTick ();
181 }
182
183 /**
184 Retrieves the 64-bit frequency in Hz and the range of performance counter
185 values.
186
187 If StartValue is not NULL, then the value that the performance counter starts
188 with immediately after is it rolls over is returned in StartValue. If
189 EndValue is not NULL, then the value that the performance counter end with
190 immediately before it rolls over is returned in EndValue. The 64-bit
191 frequency of the performance counter in Hz is always returned. If StartValue
192 is less than EndValue, then the performance counter counts up. If StartValue
193 is greater than EndValue, then the performance counter counts down. For
194 example, a 64-bit free running counter that counts up would have a StartValue
195 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
196 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
197
198 @param StartValue The value the performance counter starts with when it
199 rolls over.
200 @param EndValue The value that the performance counter ends with before
201 it rolls over.
202
203 @return The frequency in Hz.
204
205 **/
206 UINT64
207 EFIAPI
208 GetPerformanceCounterProperties (
209 OUT UINT64 *StartValue, OPTIONAL
210 OUT UINT64 *EndValue OPTIONAL
211 )
212 {
213 if (StartValue != NULL) {
214 *StartValue = 0;
215 }
216
217 if (EndValue != NULL) {
218 *EndValue = ACPI_TIMER_COUNT_SIZE - 1;
219 }
220
221 return ACPI_TIMER_FREQUENCY;
222 }