1 /** @file
2 ACPI Timer implements one instance of Timer Library.
3
4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
6
7 This program and the accompanying materials are
8 licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include <Base.h>
18 #include <Library/TimerLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/PciLib.h>
22 #include <Library/DebugLib.h>
23 #include <Library/PcdLib.h>
24 #include <IndustryStandard/Pci22.h>
25 #include <IndustryStandard/Acpi.h>
26
27 //
28 // PCI Location of PIIX4 Power Management PCI Configuration Registers
29 //
30 #define PIIX4_POWER_MANAGEMENT_BUS 0x00
31 #define PIIX4_POWER_MANAGEMENT_DEVICE 0x01
32 #define PIIX4_POWER_MANAGEMENT_FUNCTION 0x03
33
34 //
35 // Macro to access PIIX4 Power Management PCI Configuration Registers
36 //
37 #define PIIX4_PCI_POWER_MANAGEMENT_REGISTER(Register) \
38 PCI_LIB_ADDRESS ( \
39 PIIX4_POWER_MANAGEMENT_BUS, \
40 PIIX4_POWER_MANAGEMENT_DEVICE, \
41 PIIX4_POWER_MANAGEMENT_FUNCTION, \
42 Register \
43 )
44
45 //
46 // PCI Location of Q35 Power Management PCI Configuration Registers
47 //
48 #define Q35_POWER_MANAGEMENT_BUS 0x00
49 #define Q35_POWER_MANAGEMENT_DEVICE 0x1f
50 #define Q35_POWER_MANAGEMENT_FUNCTION 0x00
51
52 //
53 // Macro to access Q35 Power Management PCI Configuration Registers
54 //
55 #define Q35_PCI_POWER_MANAGEMENT_REGISTER(Register) \
56 PCI_LIB_ADDRESS ( \
57 Q35_POWER_MANAGEMENT_BUS, \
58 Q35_POWER_MANAGEMENT_DEVICE, \
59 Q35_POWER_MANAGEMENT_FUNCTION, \
60 Register \
61 )
62
63 //
64 // PCI Location of Host Bridge PCI Configuration Registers
65 //
66 #define HOST_BRIDGE_BUS 0x00
67 #define HOST_BRIDGE_DEVICE 0x00
68 #define HOST_BRIDGE_FUNCTION 0x00
69
70 //
71 // Macro to access Host Bridge Configuration Registers
72 //
73 #define HOST_BRIDGE_REGISTER(Register) \
74 PCI_LIB_ADDRESS ( \
75 HOST_BRIDGE_BUS, \
76 HOST_BRIDGE_DEVICE, \
77 HOST_BRIDGE_FUNCTION, \
78 Register \
79 )
80
81 //
82 // Host Bridge Device ID (DID) Register
83 //
84 #define HOST_BRIDGE_DID HOST_BRIDGE_REGISTER (0x02)
85
86 //
87 // Host Bridge DID Register values
88 //
89 #define PCI_DEVICE_ID_INTEL_82441 0x1237 // DID value for PIIX4
90 #define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29C0 // DID value for Q35
91
92 //
93 // Access Power Management PCI Config Regs based on Host Bridge type
94 //
95 #define PCI_POWER_MANAGEMENT_REGISTER(Register) \
96 ((PciRead16 (HOST_BRIDGE_DID) == PCI_DEVICE_ID_INTEL_Q35_MCH) ? \
97 Q35_PCI_POWER_MANAGEMENT_REGISTER (Register) : \
98 PIIX4_PCI_POWER_MANAGEMENT_REGISTER (Register))
99
100 //
101 // Power Management PCI Configuration Registers
102 //
103 #define PMBA PCI_POWER_MANAGEMENT_REGISTER (0x40)
104 #define PMBA_RTE BIT0
105 #define PMREGMISC PCI_POWER_MANAGEMENT_REGISTER (0x80)
106 #define PMIOSE BIT0
107
108 //
109 // The ACPI Time is a 24-bit counter
110 //
111 #define ACPI_TIMER_COUNT_SIZE BIT24
112
113 //
114 // Offset in the Power Management Base Address to the ACPI Timer
115 //
116 #define ACPI_TIMER_OFFSET 0x8
117
118 /**
119 The constructor function enables ACPI IO space.
120
121 If ACPI I/O space not enabled, this function will enable it.
122 It will always return RETURN_SUCCESS.
123
124 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
125
126 **/
127 RETURN_STATUS
128 EFIAPI
AcpiTimerLibConstructor(VOID)129 AcpiTimerLibConstructor (
130 VOID
131 )
132 {
133 //
134 // Check to see if the Power Management Base Address is already enabled
135 //
136 if ((PciRead8 (PMREGMISC) & PMIOSE) == 0) {
137 //
138 // If the Power Management Base Address is not programmed,
139 // then program the Power Management Base Address from a PCD.
140 //
141 PciAndThenOr32 (PMBA, (UINT32)(~0x0000FFC0), PcdGet16 (PcdAcpiPmBaseAddress));
142
143 //
144 // Enable PMBA I/O port decodes in PMREGMISC
145 //
146 PciOr8 (PMREGMISC, PMIOSE);
147 }
148
149 return RETURN_SUCCESS;
150 }
151
152 /**
153 Internal function to read the current tick counter of ACPI.
154
155 Internal function to read the current tick counter of ACPI.
156
157 @return The tick counter read.
158
159 **/
160 UINT32
InternalAcpiGetTimerTick(VOID)161 InternalAcpiGetTimerTick (
162 VOID
163 )
164 {
165 //
166 // Read PMBA to read and return the current ACPI timer value.
167 //
168 return IoRead32 ((PciRead32 (PMBA) & ~PMBA_RTE) + ACPI_TIMER_OFFSET);
169 }
170
171 /**
172 Stalls the CPU for at least the given number of ticks.
173
174 Stalls the CPU for at least the given number of ticks. It's invoked by
175 MicroSecondDelay() and NanoSecondDelay().
176
177 @param Delay A period of time to delay in ticks.
178
179 **/
180 VOID
InternalAcpiDelay(IN UINT32 Delay)181 InternalAcpiDelay (
182 IN UINT32 Delay
183 )
184 {
185 UINT32 Ticks;
186 UINT32 Times;
187
188 Times = Delay >> 22;
189 Delay &= BIT22 - 1;
190 do {
191 //
192 // The target timer count is calculated here
193 //
194 Ticks = InternalAcpiGetTimerTick () + Delay;
195 Delay = BIT22;
196 //
197 // Wait until time out
198 // Delay >= 2^23 could not be handled by this function
199 // Timer wrap-arounds are handled correctly by this function
200 //
201 while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) {
202 CpuPause ();
203 }
204 } while (Times-- > 0);
205 }
206
207 /**
208 Stalls the CPU for at least the given number of microseconds.
209
210 Stalls the CPU for the number of microseconds specified by MicroSeconds.
211
212 @param MicroSeconds The minimum number of microseconds to delay.
213
214 @return MicroSeconds
215
216 **/
217 UINTN
218 EFIAPI
MicroSecondDelay(IN UINTN MicroSeconds)219 MicroSecondDelay (
220 IN UINTN MicroSeconds
221 )
222 {
223 InternalAcpiDelay (
224 (UINT32)DivU64x32 (
225 MultU64x32 (
226 MicroSeconds,
227 ACPI_TIMER_FREQUENCY
228 ),
229 1000000u
230 )
231 );
232 return MicroSeconds;
233 }
234
235 /**
236 Stalls the CPU for at least the given number of nanoseconds.
237
238 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
239
240 @param NanoSeconds The minimum number of nanoseconds to delay.
241
242 @return NanoSeconds
243
244 **/
245 UINTN
246 EFIAPI
NanoSecondDelay(IN UINTN NanoSeconds)247 NanoSecondDelay (
248 IN UINTN NanoSeconds
249 )
250 {
251 InternalAcpiDelay (
252 (UINT32)DivU64x32 (
253 MultU64x32 (
254 NanoSeconds,
255 ACPI_TIMER_FREQUENCY
256 ),
257 1000000000u
258 )
259 );
260 return NanoSeconds;
261 }
262
263 /**
264 Retrieves the current value of a 64-bit free running performance counter.
265
266 Retrieves the current value of a 64-bit free running performance counter. The
267 counter can either count up by 1 or count down by 1. If the physical
268 performance counter counts by a larger increment, then the counter values
269 must be translated. The properties of the counter can be retrieved from
270 GetPerformanceCounterProperties().
271
272 @return The current value of the free running performance counter.
273
274 **/
275 UINT64
276 EFIAPI
GetPerformanceCounter(VOID)277 GetPerformanceCounter (
278 VOID
279 )
280 {
281 return (UINT64)InternalAcpiGetTimerTick ();
282 }
283
284 /**
285 Retrieves the 64-bit frequency in Hz and the range of performance counter
286 values.
287
288 If StartValue is not NULL, then the value that the performance counter starts
289 with immediately after is it rolls over is returned in StartValue. If
290 EndValue is not NULL, then the value that the performance counter end with
291 immediately before it rolls over is returned in EndValue. The 64-bit
292 frequency of the performance counter in Hz is always returned. If StartValue
293 is less than EndValue, then the performance counter counts up. If StartValue
294 is greater than EndValue, then the performance counter counts down. For
295 example, a 64-bit free running counter that counts up would have a StartValue
296 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
297 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
298
299 @param StartValue The value the performance counter starts with when it
300 rolls over.
301 @param EndValue The value that the performance counter ends with before
302 it rolls over.
303
304 @return The frequency in Hz.
305
306 **/
307 UINT64
308 EFIAPI
GetPerformanceCounterProperties(OUT UINT64 * StartValue,OPTIONAL OUT UINT64 * EndValue OPTIONAL)309 GetPerformanceCounterProperties (
310 OUT UINT64 *StartValue, OPTIONAL
311 OUT UINT64 *EndValue OPTIONAL
312 )
313 {
314 if (StartValue != NULL) {
315 *StartValue = 0;
316 }
317
318 if (EndValue != NULL) {
319 *EndValue = ACPI_TIMER_COUNT_SIZE - 1;
320 }
321
322 return ACPI_TIMER_FREQUENCY;
323 }
324
325 /**
326 Converts elapsed ticks of performance counter to time in nanoseconds.
327
328 This function converts the elapsed ticks of running performance counter to
329 time value in unit of nanoseconds.
330
331 @param Ticks The number of elapsed ticks of running performance counter.
332
333 @return The elapsed time in nanoseconds.
334
335 **/
336 UINT64
337 EFIAPI
GetTimeInNanoSecond(IN UINT64 Ticks)338 GetTimeInNanoSecond (
339 IN UINT64 Ticks
340 )
341 {
342 UINT64 NanoSeconds;
343 UINT32 Remainder;
344
345 //
346 // Ticks
347 // Time = --------- x 1,000,000,000
348 // Frequency
349 //
350 NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, ACPI_TIMER_FREQUENCY, &Remainder), 1000000000u);
351
352 //
353 // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)
354 // will not overflow 64-bit.
355 //
356 NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), ACPI_TIMER_FREQUENCY);
357
358 return NanoSeconds;
359 }
360