hwtimer.c revision 306536
1251875Speter/******************************************************************************
2251875Speter *
3251875Speter * Name: hwtimer.c - ACPI Power Management Timer Interface
4251875Speter *
5251875Speter *****************************************************************************/
6251875Speter
7251875Speter/*
8251875Speter * Copyright (C) 2000 - 2016, Intel Corp.
9251875Speter * All rights reserved.
10251875Speter *
11251875Speter * Redistribution and use in source and binary forms, with or without
12251875Speter * modification, are permitted provided that the following conditions
13251875Speter * are met:
14251875Speter * 1. Redistributions of source code must retain the above copyright
15251875Speter *    notice, this list of conditions, and the following disclaimer,
16251875Speter *    without modification.
17251875Speter * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18251875Speter *    substantially similar to the "NO WARRANTY" disclaimer below
19251875Speter *    ("Disclaimer") and any redistribution must be conditioned upon
20251875Speter *    including a substantially similar Disclaimer requirement for further
21251875Speter *    binary redistribution.
22251875Speter * 3. Neither the names of the above-listed copyright holders nor the names
23251875Speter *    of any contributors may be used to endorse or promote products derived
24251875Speter *    from this software without specific prior written permission.
25251875Speter *
26251875Speter * Alternatively, this software may be distributed under the terms of the
27251875Speter * GNU General Public License ("GPL") version 2 as published by the Free
28251875Speter * Software Foundation.
29251875Speter *
30251875Speter * NO WARRANTY
31251875Speter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32251875Speter * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33251875Speter * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34251875Speter * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35251875Speter * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36251875Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37251875Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38251875Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39251875Speter * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40251875Speter * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41253734Speter * POSSIBILITY OF SUCH DAMAGES.
42253734Speter */
43253734Speter
44253734Speter#define EXPORT_ACPI_INTERFACES
45251875Speter
46251875Speter#include <contrib/dev/acpica/include/acpi.h>
47251875Speter#include <contrib/dev/acpica/include/accommon.h>
48251875Speter
49251875Speter#define _COMPONENT          ACPI_HARDWARE
50251875Speter        ACPI_MODULE_NAME    ("hwtimer")
51251875Speter
52251875Speter
53251875Speter#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
54251875Speter/******************************************************************************
55251875Speter *
56251875Speter * FUNCTION:    AcpiGetTimerResolution
57251875Speter *
58251875Speter * PARAMETERS:  Resolution          - Where the resolution is returned
59251875Speter *
60251875Speter * RETURN:      Status and timer resolution
61251875Speter *
62251875Speter * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
63251875Speter *
64251875Speter ******************************************************************************/
65251875Speter
66251875SpeterACPI_STATUS
67253734SpeterAcpiGetTimerResolution (
68253734Speter    UINT32                  *Resolution)
69253734Speter{
70253734Speter    ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
71251875Speter
72251875Speter
73251875Speter    if (!Resolution)
74251875Speter    {
75251875Speter        return_ACPI_STATUS (AE_BAD_PARAMETER);
76251875Speter    }
77251875Speter
78251875Speter    if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
79251875Speter    {
80251875Speter        *Resolution = 24;
81251875Speter    }
82251875Speter    else
83251875Speter    {
84251875Speter        *Resolution = 32;
85251875Speter    }
86251875Speter
87251875Speter    return_ACPI_STATUS (AE_OK);
88251875Speter}
89251875Speter
90251875SpeterACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
91253734Speter
92251875Speter
93251875Speter/******************************************************************************
94251875Speter *
95251875Speter * FUNCTION:    AcpiGetTimer
96251875Speter *
97251875Speter * PARAMETERS:  Ticks               - Where the timer value is returned
98251875Speter *
99251875Speter * RETURN:      Status and current timer value (ticks)
100251875Speter *
101251875Speter * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
102251875Speter *
103251875Speter ******************************************************************************/
104253734Speter
105253734SpeterACPI_STATUS
106251875SpeterAcpiGetTimer (
107251875Speter    UINT32                  *Ticks)
108251875Speter{
109251875Speter    ACPI_STATUS             Status;
110251875Speter
111251875Speter
112251875Speter    ACPI_FUNCTION_TRACE (AcpiGetTimer);
113251875Speter
114251875Speter
115251875Speter    if (!Ticks)
116251875Speter    {
117253734Speter        return_ACPI_STATUS (AE_BAD_PARAMETER);
118251875Speter    }
119251875Speter
120251875Speter    /* ACPI 5.0A: PM Timer is optional */
121251875Speter
122253734Speter    if (!AcpiGbl_FADT.XPmTimerBlock.Address)
123251875Speter    {
124251875Speter        return_ACPI_STATUS (AE_SUPPORT);
125251875Speter    }
126251875Speter
127251875Speter    Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock);
128251875Speter    return_ACPI_STATUS (Status);
129251875Speter}
130251875Speter
131251875SpeterACPI_EXPORT_SYMBOL (AcpiGetTimer)
132251875Speter
133251875Speter
134251875Speter/******************************************************************************
135251875Speter *
136251875Speter * FUNCTION:    AcpiGetTimerDuration
137253734Speter *
138253734Speter * PARAMETERS:  StartTicks          - Starting timestamp
139251875Speter *              EndTicks            - End timestamp
140251875Speter *              TimeElapsed         - Where the elapsed time is returned
141251875Speter *
142251875Speter * RETURN:      Status and TimeElapsed
143251875Speter *
144253734Speter * DESCRIPTION: Computes the time elapsed (in microseconds) between two
145253734Speter *              PM Timer time stamps, taking into account the possibility of
146251875Speter *              rollovers, the timer resolution, and timer frequency.
147251875Speter *
148251875Speter *              The PM Timer's clock ticks at roughly 3.6 times per
149251875Speter *              _microsecond_, and its clock continues through Cx state
150251875Speter *              transitions (unlike many CPU timestamp counters) -- making it
151251875Speter *              a versatile and accurate timer.
152251875Speter *
153251875Speter *              Note that this function accommodates only a single timer
154251875Speter *              rollover. Thus for 24-bit timers, this function should only
155251875Speter *              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
163ACPI_STATUS
164AcpiGetTimerDuration (
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
231ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
232
233#endif /* !ACPI_REDUCED_HARDWARE */
234