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