]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/Library/DuetTimerLib/X86TimerLib.c
Update the copyright notice format
[mirror_edk2.git] / DuetPkg / Library / DuetTimerLib / X86TimerLib.c
CommitLineData
f5752cb2 1/** @file\r
9be2c306 2 Timer Library functions built upon ACPI on IA32/x64.\r
3 \r
4 ACPI power management timer is a 24-bit or 32-bit fixed rate free running count-up\r
5 timer that runs off a 3.579545 MHz clock. \r
6 When startup, Duet will check the FADT to determine whether the PM timer is a \r
7 32-bit or 25-bit timer.\r
f5752cb2 8\r
b1f700a8
HT
9 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r
10 This program and the accompanying materials\r
f5752cb2 11 are licensed and made available under the terms and conditions of the BSD License\r
12 which accompanies this distribution. The full text of the license may be found at\r
13 http://opensource.org/licenses/bsd-license.php\r
14\r
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17\r
18**/\r
19\r
20#include <Base.h>\r
21#include <Library/TimerLib.h>\r
22#include <Library/BaseLib.h>\r
f5752cb2 23#include <Library/DebugLib.h>\r
9be2c306 24#include <Library/HobLib.h>\r
25#include <Guid/AcpiDescription.h>\r
26#include <Library/IoLib.h>\r
27#include <Library/PciLib.h>\r
f5752cb2 28\r
9be2c306 29EFI_ACPI_DESCRIPTION *gAcpiDesc = NULL;\r
f5752cb2 30\r
31/**\r
9be2c306 32 Internal function to get Acpi information from HOB.\r
33 \r
34 @return Pointer to ACPI description structure.\r
35**/\r
36EFI_ACPI_DESCRIPTION*\r
37InternalGetApciDescrptionTable (\r
38 VOID\r
39 )\r
f5752cb2 40{\r
9be2c306 41 EFI_PEI_HOB_POINTERS GuidHob;\r
42 \r
43 if (gAcpiDesc != NULL) {\r
44 return gAcpiDesc;\r
dc4dc1de 45 }\r
46 \r
9be2c306 47 GuidHob.Raw = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);\r
48 if (GuidHob.Raw != NULL) {\r
49 gAcpiDesc = GET_GUID_HOB_DATA (GuidHob.Guid);\r
50 DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.RegisterBitWidth = 0x%X\n", gAcpiDesc->PM_TMR_BLK.RegisterBitWidth));\r
51 DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.Address = 0x%X\n", gAcpiDesc->PM_TMR_BLK.Address));\r
52 return gAcpiDesc;\r
53 } else {\r
54 DEBUG ((EFI_D_ERROR, "Fail to get Acpi description table from hob\n"));\r
55 return NULL;\r
56 }\r
57}\r
58\r
59/**\r
60 Internal function to read the current tick counter of ACPI.\r
61\r
62 @return The tick counter read.\r
63\r
f5752cb2 64**/\r
9be2c306 65STATIC\r
66UINT32\r
67InternalAcpiGetTimerTick (\r
68 VOID\r
69 )\r
70{\r
71 return IoRead32 ((UINTN)gAcpiDesc->PM_TMR_BLK.Address);\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
83STATIC\r
84VOID\r
85InternalAcpiDelay (\r
86 IN UINT32 Delay\r
87 )\r
88{\r
89 UINT32 Ticks;\r
90 UINT32 Times;\r
91\r
92 Times = Delay >> (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);\r
93 Delay &= (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2)) - 1;\r
94 do {\r
95 //\r
96 // The target timer count is calculated here\r
97 //\r
98 Ticks = InternalAcpiGetTimerTick () + Delay;\r
99 Delay = 1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);\r
100 //\r
101 // Wait until time out\r
102 // Delay >= 2^23 (if ACPI provide 24-bit timer) or Delay >= 2^31 (if ACPI\r
103 // provide 32-bit timer) could not be handled by this function\r
104 // Timer wrap-arounds are handled correctly by this function\r
105 //\r
106 while (((Ticks - InternalAcpiGetTimerTick ()) & (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 1))) == 0) {\r
107 CpuPause ();\r
108 }\r
109 } while (Times-- > 0);\r
110}\r
f5752cb2 111\r
112/**\r
113 Stalls the CPU for at least the given number of microseconds.\r
114\r
115 Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
116\r
117 @param MicroSeconds The minimum number of microseconds to delay.\r
118\r
119 @return MicroSeconds\r
120\r
121**/\r
122UINTN\r
123EFIAPI\r
124MicroSecondDelay (\r
125 IN UINTN MicroSeconds\r
126 )\r
127{\r
9be2c306 128\r
129 if (InternalGetApciDescrptionTable() == NULL) {\r
dc4dc1de 130 return MicroSeconds;\r
131 }\r
9be2c306 132 \r
133 InternalAcpiDelay (\r
134 (UINT32)DivU64x32 (\r
135 MultU64x32 (\r
136 MicroSeconds,\r
137 3579545\r
138 ),\r
139 1000000u\r
140 )\r
141 );\r
f5752cb2 142 return MicroSeconds;\r
143}\r
144\r
145/**\r
146 Stalls the CPU for at least the given number of nanoseconds.\r
147\r
148 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.\r
149\r
150 @param NanoSeconds The minimum number of nanoseconds to delay.\r
151\r
152 @return NanoSeconds\r
153\r
154**/\r
155UINTN\r
156EFIAPI\r
157NanoSecondDelay (\r
158 IN UINTN NanoSeconds\r
159 )\r
160{\r
9be2c306 161 if (InternalGetApciDescrptionTable() == NULL) {\r
162 return NanoSeconds;\r
163 }\r
164 \r
165 InternalAcpiDelay (\r
166 (UINT32)DivU64x32 (\r
167 MultU64x32 (\r
168 NanoSeconds,\r
169 3579545\r
170 ),\r
171 1000000000u\r
172 )\r
173 );\r
174 return NanoSeconds;\r
f5752cb2 175}\r
176\r
177/**\r
178 Retrieves the current value of a 64-bit free running performance counter.\r
179\r
180 Retrieves the current value of a 64-bit free running performance counter. The\r
181 counter can either count up by 1 or count down by 1. If the physical\r
182 performance counter counts by a larger increment, then the counter values\r
183 must be translated. The properties of the counter can be retrieved from\r
184 GetPerformanceCounterProperties().\r
185\r
186 @return The current value of the free running performance counter.\r
187\r
188**/\r
189UINT64\r
190EFIAPI\r
191GetPerformanceCounter (\r
192 VOID\r
193 )\r
194{\r
9be2c306 195 if (InternalGetApciDescrptionTable() == NULL) {\r
196 return 0;\r
197 }\r
198 \r
199 return (UINT64)InternalAcpiGetTimerTick ();\r
f5752cb2 200}\r
201\r
202/**\r
203 Retrieves the 64-bit frequency in Hz and the range of performance counter\r
204 values.\r
205\r
206 If StartValue is not NULL, then the value that the performance counter starts\r
207 with immediately after is it rolls over is returned in StartValue. If\r
208 EndValue is not NULL, then the value that the performance counter end with\r
209 immediately before it rolls over is returned in EndValue. The 64-bit\r
210 frequency of the performance counter in Hz is always returned. If StartValue\r
211 is less than EndValue, then the performance counter counts up. If StartValue\r
212 is greater than EndValue, then the performance counter counts down. For\r
213 example, a 64-bit free running counter that counts up would have a StartValue\r
214 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter\r
215 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.\r
216\r
217 @param StartValue The value the performance counter starts with when it\r
218 rolls over.\r
219 @param EndValue The value that the performance counter ends with before\r
220 it rolls over.\r
221\r
222 @return The frequency in Hz.\r
223\r
224**/\r
225UINT64\r
226EFIAPI\r
227GetPerformanceCounterProperties (\r
228 OUT UINT64 *StartValue, OPTIONAL\r
229 OUT UINT64 *EndValue OPTIONAL\r
230 )\r
231{\r
9be2c306 232 if (InternalGetApciDescrptionTable() == NULL) {\r
233 return 0;\r
234 }\r
235 \r
236 if (StartValue != NULL) {\r
237 *StartValue = 0;\r
238 }\r
239\r
240 if (EndValue != NULL) {\r
241 *EndValue = (1 << gAcpiDesc->PM_TMR_BLK.RegisterBitWidth) - 1;\r
242 }\r
243\r
244 return 3579545;\r
f5752cb2 245}\r