1 /** @file
2   ACPI Timer implements one instance of Timer Library.
3 
4 
5   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8 
9 #include <Base.h>
10 #include <Library/TimerLib.h>
11 #include <Library/BaseLib.h>
12 #include <Library/PcdLib.h>
13 #include <Library/PciLib.h>
14 #include <Library/IoLib.h>
15 #include <Library/DebugLib.h>
16 #include <IndustryStandard/Acpi.h>
17 //
18 // OVERRIDE: OverrideBegin
19 //
20 #include <Register/Cpuid.h>
21 //
22 // OVERRIDE: OverrideEnd
23 //
24 
25 
26 /**
27   Internal function to retrieves the 64-bit frequency in Hz.
28 
29   Internal function to retrieves the 64-bit frequency in Hz.
30 
31   @return The frequency in Hz.
32 
33 **/
34 UINT64
35 InternalGetPerformanceCounterFrequency (
36   VOID
37   );
38 
39 /**
40   The constructor function enables ACPI IO space.
41 
42   If ACPI I/O space not enabled, this function will enable it.
43   It will always return RETURN_SUCCESS.
44 
45   @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.
46 
47 **/
48 RETURN_STATUS
49 EFIAPI
50 AcpiTimerLibConstructor (
51   VOID
52   )
53 {
54   UINTN   Bus;
55   UINTN   Device;
56   UINTN   Function;
57   UINTN   EnableRegister;
58   UINT8   EnableMask;
59 
60   //
61   // ASSERT for the invalid PCD values. They must be configured to the real value.
62   //
63   ASSERT (PcdGet16 (PcdAcpiIoPciBarRegisterOffset) != 0xFFFF);
64   ASSERT (PcdGet16 (PcdAcpiIoPortBaseAddress)      != 0xFFFF);
65 
66   //
67   // If the register offset to the BAR for the ACPI I/O Port Base Address is 0x0000, then
68   // no PCI register programming is required to enable access to the the ACPI registers
69   // specified by PcdAcpiIoPortBaseAddress
70   //
71   if (PcdGet16 (PcdAcpiIoPciBarRegisterOffset) == 0x0000) {
72     return RETURN_SUCCESS;
73   }
74 
75   //
76   // ASSERT for the invalid PCD values. They must be configured to the real value.
77   //
78   ASSERT (PcdGet8  (PcdAcpiIoPciDeviceNumber)   != 0xFF);
79   ASSERT (PcdGet8  (PcdAcpiIoPciFunctionNumber) != 0xFF);
80   ASSERT (PcdGet16 (PcdAcpiIoPciEnableRegisterOffset) != 0xFFFF);
81 
82   //
83   // Retrieve the PCD values for the PCI configuration space required to program the ACPI I/O Port Base Address
84   //
85   Bus            = PcdGet8  (PcdAcpiIoPciBusNumber);
86   Device         = PcdGet8  (PcdAcpiIoPciDeviceNumber);
87   Function       = PcdGet8  (PcdAcpiIoPciFunctionNumber);
88   EnableRegister = PcdGet16 (PcdAcpiIoPciEnableRegisterOffset);
89   EnableMask     = PcdGet8  (PcdAcpiIoBarEnableMask);
90 
91   //
92   // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it.
93   //
94   if ((PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, EnableRegister)) & EnableMask) != EnableMask) {
95     PciWrite16 (
96       PCI_LIB_ADDRESS (Bus, Device, Function, PcdGet16 (PcdAcpiIoPciBarRegisterOffset)),
97       PcdGet16 (PcdAcpiIoPortBaseAddress)
98       );
99     PciOr8 (
100       PCI_LIB_ADDRESS (Bus, Device, Function, EnableRegister),
101       EnableMask
102       );
103   }
104 
105   return RETURN_SUCCESS;
106 }
107 
108 /**
109   Internal function to retrieve the ACPI I/O Port Base Address.
110 
111   Internal function to retrieve the ACPI I/O Port Base Address.
112 
113   @return The 16-bit ACPI I/O Port Base Address.
114 
115 **/
116 UINT16
117 InternalAcpiGetAcpiTimerIoPort (
118   VOID
119   )
120 {
121   UINT16  Port;
122 
123   Port = PcdGet16 (PcdAcpiIoPortBaseAddress);
124 
125   //
126   // If the register offset to the BAR for the ACPI I/O Port Base Address is not 0x0000, then
127   // read the PCI register for the ACPI BAR value in case the BAR has been programmed to a
128   // value other than PcdAcpiIoPortBaseAddress
129   //
130   if (PcdGet16 (PcdAcpiIoPciBarRegisterOffset) != 0x0000) {
131     Port = PciRead16 (PCI_LIB_ADDRESS (
132                         PcdGet8  (PcdAcpiIoPciBusNumber),
133                         PcdGet8  (PcdAcpiIoPciDeviceNumber),
134                         PcdGet8  (PcdAcpiIoPciFunctionNumber),
135                         PcdGet16 (PcdAcpiIoPciBarRegisterOffset)
136                         ));
137   }
138 
139   return (Port & PcdGet16 (PcdAcpiIoPortBaseAddressMask)) + PcdGet16 (PcdAcpiPm1TmrOffset);
140 }
141 
142 /**
143   Stalls the CPU for at least the given number of ticks.
144 
145   Stalls the CPU for at least the given number of ticks. It's invoked by
146   MicroSecondDelay() and NanoSecondDelay().
147 
148   @param  Delay     A period of time to delay in ticks.
149 
150 **/
151 VOID
152 InternalAcpiDelay (
153   IN UINT32  Delay
154   )
155 {
156   UINT16   Port;
157   UINT32   Ticks;
158   UINT32   Times;
159 
160   Port   = InternalAcpiGetAcpiTimerIoPort ();
161   Times  = Delay >> 22;
162   Delay &= BIT22 - 1;
163   do {
164     //
165     // The target timer count is calculated here
166     //
167     Ticks = IoBitFieldRead32 (Port, 0, 23) + Delay;
168     Delay = BIT22;
169     //
170     // Wait until time out
171     // Delay >= 2^23 could not be handled by this function
172     // Timer wrap-arounds are handled correctly by this function
173     //
174     while (((Ticks - IoBitFieldRead32 (Port, 0, 23)) & BIT23) == 0) {
175       CpuPause ();
176     }
177   } while (Times-- > 0);
178 }
179 
180 /**
181   Stalls the CPU for at least the given number of microseconds.
182 
183   Stalls the CPU for the number of microseconds specified by MicroSeconds.
184 
185   @param  MicroSeconds  The minimum number of microseconds to delay.
186 
187   @return MicroSeconds
188 
189 **/
190 UINTN
191 EFIAPI
192 MicroSecondDelay (
193   IN UINTN  MicroSeconds
194   )
195 {
196   InternalAcpiDelay (
197     (UINT32)DivU64x32 (
198               MultU64x32 (
199                 MicroSeconds,
200                 ACPI_TIMER_FREQUENCY
201                 ),
202               1000000u
203               )
204     );
205   return MicroSeconds;
206 }
207 
208 /**
209   Stalls the CPU for at least the given number of nanoseconds.
210 
211   Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
212 
213   @param  NanoSeconds The minimum number of nanoseconds to delay.
214 
215   @return NanoSeconds
216 
217 **/
218 UINTN
219 EFIAPI
220 NanoSecondDelay (
221   IN UINTN  NanoSeconds
222   )
223 {
224   InternalAcpiDelay (
225     (UINT32)DivU64x32 (
226               MultU64x32 (
227                 NanoSeconds,
228                 ACPI_TIMER_FREQUENCY
229                 ),
230               1000000000u
231               )
232     );
233   return NanoSeconds;
234 }
235 
236 /**
237   Retrieves the current value of a 64-bit free running performance counter.
238 
239   Retrieves the current value of a 64-bit free running performance counter. The
240   counter can either count up by 1 or count down by 1. If the physical
241   performance counter counts by a larger increment, then the counter values
242   must be translated. The properties of the counter can be retrieved from
243   GetPerformanceCounterProperties().
244 
245   @return The current value of the free running performance counter.
246 
247 **/
248 UINT64
249 EFIAPI
250 GetPerformanceCounter (
251   VOID
252   )
253 {
254   return AsmReadTsc ();
255 }
256 
257 /**
258   Retrieves the 64-bit frequency in Hz and the range of performance counter
259   values.
260 
261   If StartValue is not NULL, then the value that the performance counter starts
262   with immediately after is it rolls over is returned in StartValue. If
263   EndValue is not NULL, then the value that the performance counter end with
264   immediately before it rolls over is returned in EndValue. The 64-bit
265   frequency of the performance counter in Hz is always returned. If StartValue
266   is less than EndValue, then the performance counter counts up. If StartValue
267   is greater than EndValue, then the performance counter counts down. For
268   example, a 64-bit free running counter that counts up would have a StartValue
269   of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
270   that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
271 
272   @param  StartValue  The value the performance counter starts with when it
273                       rolls over.
274   @param  EndValue    The value that the performance counter ends with before
275                       it rolls over.
276 
277   @return The frequency in Hz.
278 
279 **/
280 UINT64
281 EFIAPI
282 GetPerformanceCounterProperties (
283   OUT UINT64  *StartValue,  OPTIONAL
284   OUT UINT64  *EndValue     OPTIONAL
285   )
286 {
287   if (StartValue != NULL) {
288     *StartValue = 0;
289   }
290 
291   if (EndValue != NULL) {
292     *EndValue = 0xffffffffffffffffULL;
293   }
294   return InternalGetPerformanceCounterFrequency ();
295 }
296 
297 /**
298   Converts elapsed ticks of performance counter to time in nanoseconds.
299 
300   This function converts the elapsed ticks of running performance counter to
301   time value in unit of nanoseconds.
302 
303   @param  Ticks     The number of elapsed ticks of running performance counter.
304 
305   @return The elapsed time in nanoseconds.
306 
307 **/
308 UINT64
309 EFIAPI
310 GetTimeInNanoSecond (
311   IN UINT64  Ticks
312   )
313 {
314   UINT64  Frequency;
315   UINT64  NanoSeconds;
316   UINT64  Remainder;
317   INTN    Shift;
318   Frequency = GetPerformanceCounterProperties (NULL, NULL);
319 
320   //
321   //          Ticks
322   // Time = --------- x 1,000,000,000
323   //        Frequency
324   //
325   NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
326 
327   //
328   // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
329   // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
330   // i.e. highest bit set in Remainder should <= 33.
331   //
332   Shift = MAX (0, HighBitSet64 (Remainder) - 33);
333   Remainder = RShiftU64 (Remainder, (UINTN) Shift);
334   Frequency = RShiftU64 (Frequency, (UINTN) Shift);
335   NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
336 
337   return NanoSeconds;
338 }
339 
340 //
341 // OVERRIDE: OverrideBegin
342 //
343 /**
344   Calculate TSC frequency.
345 
346   The TSC counting frequency is determined by using CPUID leaf 0x15 that is the preferred
347   method for Skylake and beyond.  Frequency in MHz = Core XTAL frequency * EBX/EAX.
348   In newer flavors of the CPU, core xtal frequency is returned in ECX (or 0 if not
349   supported).  If ECX is 0, 24MHz is assumed.
350   @return The number of TSC counts per second.
351 
352 **/
353 UINT64
354 InternalCalculateTscFrequency (
355   VOID
356   )
357 {
358   UINT64      TscFrequency;
359   UINT64      CoreXtalFrequency;
360   UINT32      RegEax;
361   UINT32      RegEbx;
362   UINT32      RegEcx;
363 
364   //
365   // Use CPUID leaf 0x15.
366   // TSC frequency = (Core Xtal Frequency) * EBX/EAX.  EBX returns 0 if not
367   // supported. ECX, if non zero, provides Core Xtal Frequency in hertz
368   // (SDM Dec 2016).
369   //
370   AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
371   ASSERT (RegEbx != 0);
372 
373   //
374   // If core xtal frequency (ECX) returns 0, it is safe to use 24MHz for post
375   // Skylake client CPU's.
376   //
377   if (RegEcx == 0) {
378     CoreXtalFrequency = 24000000ul;
379   } else {
380     CoreXtalFrequency = (UINT64)RegEcx;
381   }
382 
383   //
384   // Calculate frequency.  For integer division, round up/down result
385   // correctly by adding denominator/2 to the numerator prior to division.
386   //
387   TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
388 
389   return TscFrequency;
390 }
391 //
392 // OVERRIDE: OverrideEnd
393 //
394 
395