1 /******************************************************************************
2  *
3  * Name: hwtimer.c - ACPI Power Management Timer Interface
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #define EXPORT_ACPI_INTERFACES
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 
49 #define _COMPONENT          ACPI_HARDWARE
50         ACPI_MODULE_NAME    ("hwtimer")
51 
52 
53 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
54 /******************************************************************************
55  *
56  * FUNCTION:    AcpiGetTimerResolution
57  *
58  * PARAMETERS:  Resolution          - Where the resolution is returned
59  *
60  * RETURN:      Status and timer resolution
61  *
62  * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
63  *
64  ******************************************************************************/
65 
66 ACPI_STATUS
67 AcpiGetTimerResolution (
68     UINT32                  *Resolution)
69 {
70     ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
71 
72 
73     if (!Resolution)
74     {
75         return_ACPI_STATUS (AE_BAD_PARAMETER);
76     }
77 
78     if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
79     {
80         *Resolution = 24;
81     }
82     else
83     {
84         *Resolution = 32;
85     }
86 
87     return_ACPI_STATUS (AE_OK);
88 }
89 
90 ACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
91 
92 
93 /******************************************************************************
94  *
95  * FUNCTION:    AcpiGetTimer
96  *
97  * PARAMETERS:  Ticks               - Where the timer value is returned
98  *
99  * RETURN:      Status and current timer value (ticks)
100  *
101  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
102  *
103  ******************************************************************************/
104 
105 ACPI_STATUS
106 AcpiGetTimer (
107     UINT32                  *Ticks)
108 {
109     ACPI_STATUS             Status;
110 
111 
112     ACPI_FUNCTION_TRACE (AcpiGetTimer);
113 
114 
115     if (!Ticks)
116     {
117         return_ACPI_STATUS (AE_BAD_PARAMETER);
118     }
119 
120     /* ACPI 5.0A: PM Timer is optional */
121 
122     if (!AcpiGbl_FADT.XPmTimerBlock.Address)
123     {
124         return_ACPI_STATUS (AE_SUPPORT);
125     }
126 
127     Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock);
128     return_ACPI_STATUS (Status);
129 }
130 
131 ACPI_EXPORT_SYMBOL (AcpiGetTimer)
132 
133 
134 /******************************************************************************
135  *
136  * FUNCTION:    AcpiGetTimerDuration
137  *
138  * PARAMETERS:  StartTicks          - Starting timestamp
139  *              EndTicks            - End timestamp
140  *              TimeElapsed         - Where the elapsed time is returned
141  *
142  * RETURN:      Status and TimeElapsed
143  *
144  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
145  *              PM Timer time stamps, taking into account the possibility of
146  *              rollovers, the timer resolution, and timer frequency.
147  *
148  *              The PM Timer's clock ticks at roughly 3.6 times per
149  *              _microsecond_, and its clock continues through Cx state
150  *              transitions (unlike many CPU timestamp counters) -- making it
151  *              a versatile and accurate timer.
152  *
153  *              Note that this function accommodates only a single timer
154  *              rollover. Thus for 24-bit timers, this function should only
155  *              be used for calculating durations less than ~4.6 seconds
156  *              (~20 minutes for 32-bit timers) -- calculations below:
157  *
158  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
159  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
160  *
161  ******************************************************************************/
162 
163 ACPI_STATUS
164 AcpiGetTimerDuration (
165     UINT32                  StartTicks,
166     UINT32                  EndTicks,
167     UINT32                  *TimeElapsed)
168 {
169     ACPI_STATUS             Status;
170     UINT32                  DeltaTicks;
171     UINT64                  Quotient;
172 
173 
174     ACPI_FUNCTION_TRACE (AcpiGetTimerDuration);
175 
176 
177     if (!TimeElapsed)
178     {
179         return_ACPI_STATUS (AE_BAD_PARAMETER);
180     }
181 
182     /* ACPI 5.0A: PM Timer is optional */
183 
184     if (!AcpiGbl_FADT.XPmTimerBlock.Address)
185     {
186         return_ACPI_STATUS (AE_SUPPORT);
187     }
188 
189     /*
190      * Compute Tick Delta:
191      * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
192      */
193     if (StartTicks < EndTicks)
194     {
195         DeltaTicks = EndTicks - StartTicks;
196     }
197     else if (StartTicks > EndTicks)
198     {
199         if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
200         {
201             /* 24-bit Timer */
202 
203             DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF);
204         }
205         else
206         {
207             /* 32-bit Timer */
208 
209             DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks;
210         }
211     }
212     else /* StartTicks == EndTicks */
213     {
214         *TimeElapsed = 0;
215         return_ACPI_STATUS (AE_OK);
216     }
217 
218     /*
219      * Compute Duration (Requires a 64-bit multiply and divide):
220      *
221      * TimeElapsed (microseconds) =
222      *  (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
223      */
224     Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC,
225                 ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL);
226 
227     *TimeElapsed = (UINT32) Quotient;
228     return_ACPI_STATUS (Status);
229 }
230 
231 ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
232 
233 #endif /* !ACPI_REDUCED_HARDWARE */
234