]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c
UefiPayloadPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiPayloadPkg / Library / AcpiTimerLib / AcpiTimerLib.c
CommitLineData
04af8bf2
DG
1/** @file\r
2 ACPI Timer implements one instance of Timer Library.\r
3\r
4 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include <PiPei.h>\r
10#include <Library/TimerLib.h>\r
11#include <Library/BaseLib.h>\r
12#include <Library/IoLib.h>\r
13#include <Library/HobLib.h>\r
14#include <Library/DebugLib.h>\r
15\r
16#include <Guid/AcpiBoardInfoGuid.h>\r
17#include <IndustryStandard/Acpi.h>\r
18\r
19#define ACPI_TIMER_COUNT_SIZE BIT24\r
20\r
e5efcf8b 21UINTN mPmTimerReg = 0;\r
04af8bf2
DG
22\r
23/**\r
24 The constructor function enables ACPI IO space.\r
25\r
26 If ACPI I/O space not enabled, this function will enable it.\r
27 It will always return RETURN_SUCCESS.\r
28\r
29 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.\r
30\r
31**/\r
32RETURN_STATUS\r
33EFIAPI\r
34AcpiTimerLibConstructor (\r
35 VOID\r
36 )\r
37{\r
38 EFI_HOB_GUID_TYPE *GuidHob;\r
39 ACPI_BOARD_INFO *pAcpiBoardInfo;\r
40\r
41 //\r
42 // Find the acpi board information guid hob\r
43 //\r
44 GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);\r
45 ASSERT (GuidHob != NULL);\r
46\r
47 pAcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);\r
48\r
49 mPmTimerReg = (UINTN)pAcpiBoardInfo->PmTimerRegBase;\r
50\r
51 return EFI_SUCCESS;\r
52}\r
53\r
54/**\r
55 Internal function to read the current tick counter of ACPI.\r
56\r
57 Internal function to read the current tick counter of ACPI.\r
58\r
59 @return The tick counter read.\r
60\r
61**/\r
62UINT32\r
63InternalAcpiGetTimerTick (\r
64 VOID\r
65 )\r
66{\r
67 if (mPmTimerReg == 0) {\r
68 AcpiTimerLibConstructor ();\r
69 }\r
e5efcf8b 70\r
04af8bf2
DG
71 return IoRead32 (mPmTimerReg);\r
72}\r
73\r
74/**\r
75 Stalls the CPU for at least the given number of ticks.\r
76\r
77 Stalls the CPU for at least the given number of ticks. It's invoked by\r
78 MicroSecondDelay() and NanoSecondDelay().\r
79\r
80 @param Delay A period of time to delay in ticks.\r
81\r
82**/\r
83VOID\r
84InternalAcpiDelay (\r
e5efcf8b 85 IN UINT32 Delay\r
04af8bf2
DG
86 )\r
87{\r
e5efcf8b
MK
88 UINT32 Ticks;\r
89 UINT32 Times;\r
04af8bf2 90\r
e5efcf8b
MK
91 Times = Delay >> 22;\r
92 Delay &= BIT22 - 1;\r
04af8bf2
DG
93 do {\r
94 //\r
95 // The target timer count is calculated here\r
96 //\r
e5efcf8b
MK
97 Ticks = InternalAcpiGetTimerTick () + Delay;\r
98 Delay = BIT22;\r
04af8bf2
DG
99 //\r
100 // Wait until time out\r
101 // Delay >= 2^23 could not be handled by this function\r
102 // Timer wrap-arounds are handled correctly by this function\r
103 //\r
104 while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) {\r
105 CpuPause ();\r
106 }\r
107 } while (Times-- > 0);\r
108}\r
109\r
110/**\r
111 Stalls the CPU for at least the given number of microseconds.\r
112\r
113 Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
114\r
115 @param MicroSeconds The minimum number of microseconds to delay.\r
116\r
117 @return MicroSeconds\r
118\r
119**/\r
120UINTN\r
121EFIAPI\r
122MicroSecondDelay (\r
e5efcf8b 123 IN UINTN MicroSeconds\r
04af8bf2
DG
124 )\r
125{\r
126 InternalAcpiDelay (\r
127 (UINT32)DivU64x32 (\r
128 MultU64x32 (\r
129 MicroSeconds,\r
130 ACPI_TIMER_FREQUENCY\r
131 ),\r
132 1000000u\r
133 )\r
134 );\r
135 return MicroSeconds;\r
136}\r
137\r
138/**\r
139 Stalls the CPU for at least the given number of nanoseconds.\r
140\r
141 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.\r
142\r
143 @param NanoSeconds The minimum number of nanoseconds to delay.\r
144\r
145 @return NanoSeconds\r
146\r
147**/\r
148UINTN\r
149EFIAPI\r
150NanoSecondDelay (\r
e5efcf8b 151 IN UINTN NanoSeconds\r
04af8bf2
DG
152 )\r
153{\r
154 InternalAcpiDelay (\r
155 (UINT32)DivU64x32 (\r
156 MultU64x32 (\r
157 NanoSeconds,\r
158 ACPI_TIMER_FREQUENCY\r
159 ),\r
160 1000000000u\r
161 )\r
162 );\r
163 return NanoSeconds;\r
164}\r
165\r
166/**\r
167 Retrieves the current value of a 64-bit free running performance counter.\r
168\r
169 Retrieves the current value of a 64-bit free running performance counter. The\r
170 counter can either count up by 1 or count down by 1. If the physical\r
171 performance counter counts by a larger increment, then the counter values\r
172 must be translated. The properties of the counter can be retrieved from\r
173 GetPerformanceCounterProperties().\r
174\r
175 @return The current value of the free running performance counter.\r
176\r
177**/\r
178UINT64\r
179EFIAPI\r
180GetPerformanceCounter (\r
181 VOID\r
182 )\r
183{\r
184 return (UINT64)InternalAcpiGetTimerTick ();\r
185}\r
186\r
187/**\r
188 Retrieves the 64-bit frequency in Hz and the range of performance counter\r
189 values.\r
190\r
191 If StartValue is not NULL, then the value that the performance counter starts\r
192 with immediately after is it rolls over is returned in StartValue. If\r
193 EndValue is not NULL, then the value that the performance counter end with\r
194 immediately before it rolls over is returned in EndValue. The 64-bit\r
195 frequency of the performance counter in Hz is always returned. If StartValue\r
196 is less than EndValue, then the performance counter counts up. If StartValue\r
197 is greater than EndValue, then the performance counter counts down. For\r
198 example, a 64-bit free running counter that counts up would have a StartValue\r
199 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter\r
200 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.\r
201\r
202 @param StartValue The value the performance counter starts with when it\r
203 rolls over.\r
204 @param EndValue The value that the performance counter ends with before\r
205 it rolls over.\r
206\r
207 @return The frequency in Hz.\r
208\r
209**/\r
210UINT64\r
211EFIAPI\r
212GetPerformanceCounterProperties (\r
e5efcf8b
MK
213 OUT UINT64 *StartValue OPTIONAL,\r
214 OUT UINT64 *EndValue OPTIONAL\r
04af8bf2
DG
215 )\r
216{\r
217 if (StartValue != NULL) {\r
218 *StartValue = 0;\r
219 }\r
220\r
221 if (EndValue != NULL) {\r
222 *EndValue = ACPI_TIMER_COUNT_SIZE - 1;\r
223 }\r
224\r
225 return ACPI_TIMER_FREQUENCY;\r
226}\r
227\r
228/**\r
229 Converts elapsed ticks of performance counter to time in nanoseconds.\r
230\r
231 This function converts the elapsed ticks of running performance counter to\r
232 time value in unit of nanoseconds.\r
233\r
234 @param Ticks The number of elapsed ticks of running performance counter.\r
235\r
236 @return The elapsed time in nanoseconds.\r
237\r
238**/\r
239UINT64\r
240EFIAPI\r
241GetTimeInNanoSecond (\r
e5efcf8b 242 IN UINT64 Ticks\r
04af8bf2
DG
243 )\r
244{\r
245 UINT64 Frequency;\r
246 UINT64 NanoSeconds;\r
247 UINT64 Remainder;\r
248 INTN Shift;\r
249\r
250 Frequency = GetPerformanceCounterProperties (NULL, NULL);\r
251\r
252 //\r
253 // Ticks\r
254 // Time = --------- x 1,000,000,000\r
255 // Frequency\r
256 //\r
257 NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);\r
258\r
259 //\r
260 // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.\r
261 // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,\r
262 // i.e. highest bit set in Remainder should <= 33.\r
263 //\r
e5efcf8b
MK
264 Shift = MAX (0, HighBitSet64 (Remainder) - 33);\r
265 Remainder = RShiftU64 (Remainder, (UINTN)Shift);\r
266 Frequency = RShiftU64 (Frequency, (UINTN)Shift);\r
04af8bf2
DG
267 NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);\r
268\r
269 return NanoSeconds;\r
270}\r