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