xref: /netbsd-src/sys/external/bsd/acpica/dist/hardware/hwtimer.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Name: hwtimer.c - ACPI Power Management Timer Interface
428c506b8Sjruoho  *
528c506b8Sjruoho  *****************************************************************************/
628c506b8Sjruoho 
7124f4c82Sjruoho /*
8*046a2985Schristos  * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho  * All rights reserved.
1028c506b8Sjruoho  *
11124f4c82Sjruoho  * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho  * modification, are permitted provided that the following conditions
13124f4c82Sjruoho  * are met:
14124f4c82Sjruoho  * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho  *    notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho  *    without modification.
17124f4c82Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho  *    including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho  *    binary redistribution.
22124f4c82Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho  *    of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho  *    from this software without specific prior written permission.
2528c506b8Sjruoho  *
26124f4c82Sjruoho  * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho  * Software Foundation.
2928c506b8Sjruoho  *
30124f4c82Sjruoho  * NO WARRANTY
31124f4c82Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho  */
4328c506b8Sjruoho 
44ff4a156dSchristos #define EXPORT_ACPI_INTERFACES
45ff4a156dSchristos 
4628c506b8Sjruoho #include "acpi.h"
4728c506b8Sjruoho #include "accommon.h"
4828c506b8Sjruoho 
4928c506b8Sjruoho #define _COMPONENT          ACPI_HARDWARE
5028c506b8Sjruoho         ACPI_MODULE_NAME    ("hwtimer")
5128c506b8Sjruoho 
5228c506b8Sjruoho 
53ff4a156dSchristos #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
5428c506b8Sjruoho /******************************************************************************
5528c506b8Sjruoho  *
5628c506b8Sjruoho  * FUNCTION:    AcpiGetTimerResolution
5728c506b8Sjruoho  *
5828c506b8Sjruoho  * PARAMETERS:  Resolution          - Where the resolution is returned
5928c506b8Sjruoho  *
6028c506b8Sjruoho  * RETURN:      Status and timer resolution
6128c506b8Sjruoho  *
6228c506b8Sjruoho  * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6328c506b8Sjruoho  *
6428c506b8Sjruoho  ******************************************************************************/
6528c506b8Sjruoho 
6628c506b8Sjruoho ACPI_STATUS
AcpiGetTimerResolution(UINT32 * Resolution)6728c506b8Sjruoho AcpiGetTimerResolution (
6828c506b8Sjruoho     UINT32                  *Resolution)
6928c506b8Sjruoho {
7028c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
7128c506b8Sjruoho 
7228c506b8Sjruoho 
7328c506b8Sjruoho     if (!Resolution)
7428c506b8Sjruoho     {
7528c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
7628c506b8Sjruoho     }
7728c506b8Sjruoho 
7828c506b8Sjruoho     if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
7928c506b8Sjruoho     {
8028c506b8Sjruoho         *Resolution = 24;
8128c506b8Sjruoho     }
8228c506b8Sjruoho     else
8328c506b8Sjruoho     {
8428c506b8Sjruoho         *Resolution = 32;
8528c506b8Sjruoho     }
8628c506b8Sjruoho 
8728c506b8Sjruoho     return_ACPI_STATUS (AE_OK);
8828c506b8Sjruoho }
8928c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiGetTimerResolution)9028c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
9128c506b8Sjruoho 
9228c506b8Sjruoho 
9328c506b8Sjruoho /******************************************************************************
9428c506b8Sjruoho  *
9528c506b8Sjruoho  * FUNCTION:    AcpiGetTimer
9628c506b8Sjruoho  *
9728c506b8Sjruoho  * PARAMETERS:  Ticks               - Where the timer value is returned
9828c506b8Sjruoho  *
9928c506b8Sjruoho  * RETURN:      Status and current timer value (ticks)
10028c506b8Sjruoho  *
10128c506b8Sjruoho  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
10228c506b8Sjruoho  *
10328c506b8Sjruoho  ******************************************************************************/
10428c506b8Sjruoho 
10528c506b8Sjruoho ACPI_STATUS
10628c506b8Sjruoho AcpiGetTimer (
10728c506b8Sjruoho     UINT32                  *Ticks)
10828c506b8Sjruoho {
10928c506b8Sjruoho     ACPI_STATUS             Status;
11089b8eb6cSchristos     UINT64                  TimerValue;
11128c506b8Sjruoho 
11228c506b8Sjruoho 
11328c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiGetTimer);
11428c506b8Sjruoho 
11528c506b8Sjruoho 
11628c506b8Sjruoho     if (!Ticks)
11728c506b8Sjruoho     {
11828c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
11928c506b8Sjruoho     }
12028c506b8Sjruoho 
121ff4a156dSchristos     /* ACPI 5.0A: PM Timer is optional */
12228c506b8Sjruoho 
123ff4a156dSchristos     if (!AcpiGbl_FADT.XPmTimerBlock.Address)
124ff4a156dSchristos     {
125ff4a156dSchristos         return_ACPI_STATUS (AE_SUPPORT);
126ff4a156dSchristos     }
127ff4a156dSchristos 
12889b8eb6cSchristos     Status = AcpiHwRead (&TimerValue, &AcpiGbl_FADT.XPmTimerBlock);
12989b8eb6cSchristos     if (ACPI_SUCCESS (Status))
13089b8eb6cSchristos     {
13189b8eb6cSchristos         /* ACPI PM Timer is defined to be 32 bits (PM_TMR_LEN) */
13289b8eb6cSchristos 
13389b8eb6cSchristos         *Ticks = (UINT32) TimerValue;
13489b8eb6cSchristos     }
13589b8eb6cSchristos 
13628c506b8Sjruoho     return_ACPI_STATUS (Status);
13728c506b8Sjruoho }
13828c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiGetTimer)13928c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiGetTimer)
14028c506b8Sjruoho 
14128c506b8Sjruoho 
14228c506b8Sjruoho /******************************************************************************
14328c506b8Sjruoho  *
14428c506b8Sjruoho  * FUNCTION:    AcpiGetTimerDuration
14528c506b8Sjruoho  *
14628c506b8Sjruoho  * PARAMETERS:  StartTicks          - Starting timestamp
14728c506b8Sjruoho  *              EndTicks            - End timestamp
14828c506b8Sjruoho  *              TimeElapsed         - Where the elapsed time is returned
14928c506b8Sjruoho  *
15028c506b8Sjruoho  * RETURN:      Status and TimeElapsed
15128c506b8Sjruoho  *
15228c506b8Sjruoho  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
15328c506b8Sjruoho  *              PM Timer time stamps, taking into account the possibility of
15428c506b8Sjruoho  *              rollovers, the timer resolution, and timer frequency.
15528c506b8Sjruoho  *
15628c506b8Sjruoho  *              The PM Timer's clock ticks at roughly 3.6 times per
15728c506b8Sjruoho  *              _microsecond_, and its clock continues through Cx state
15828c506b8Sjruoho  *              transitions (unlike many CPU timestamp counters) -- making it
15928c506b8Sjruoho  *              a versatile and accurate timer.
16028c506b8Sjruoho  *
16128c506b8Sjruoho  *              Note that this function accommodates only a single timer
16228c506b8Sjruoho  *              rollover. Thus for 24-bit timers, this function should only
16328c506b8Sjruoho  *              be used for calculating durations less than ~4.6 seconds
16428c506b8Sjruoho  *              (~20 minutes for 32-bit timers) -- calculations below:
16528c506b8Sjruoho  *
16628c506b8Sjruoho  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
16728c506b8Sjruoho  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
16828c506b8Sjruoho  *
16928c506b8Sjruoho  ******************************************************************************/
17028c506b8Sjruoho 
17128c506b8Sjruoho ACPI_STATUS
17228c506b8Sjruoho AcpiGetTimerDuration (
17328c506b8Sjruoho     UINT32                  StartTicks,
17428c506b8Sjruoho     UINT32                  EndTicks,
17528c506b8Sjruoho     UINT32                  *TimeElapsed)
17628c506b8Sjruoho {
17728c506b8Sjruoho     ACPI_STATUS             Status;
178b406f703Schristos     UINT64                  DeltaTicks;
17928c506b8Sjruoho     UINT64                  Quotient;
18028c506b8Sjruoho 
18128c506b8Sjruoho 
18228c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiGetTimerDuration);
18328c506b8Sjruoho 
18428c506b8Sjruoho 
18528c506b8Sjruoho     if (!TimeElapsed)
18628c506b8Sjruoho     {
18728c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
18828c506b8Sjruoho     }
18928c506b8Sjruoho 
190ff4a156dSchristos     /* ACPI 5.0A: PM Timer is optional */
191ff4a156dSchristos 
192ff4a156dSchristos     if (!AcpiGbl_FADT.XPmTimerBlock.Address)
193ff4a156dSchristos     {
194ff4a156dSchristos         return_ACPI_STATUS (AE_SUPPORT);
195ff4a156dSchristos     }
196ff4a156dSchristos 
197b406f703Schristos     if (StartTicks == EndTicks)
198b406f703Schristos     {
199b406f703Schristos         *TimeElapsed = 0;
200b406f703Schristos         return_ACPI_STATUS (AE_OK);
201b406f703Schristos     }
202b406f703Schristos 
20328c506b8Sjruoho     /*
20428c506b8Sjruoho      * Compute Tick Delta:
20528c506b8Sjruoho      * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
20628c506b8Sjruoho      */
207b406f703Schristos     DeltaTicks = EndTicks;
208b406f703Schristos     if (StartTicks > EndTicks)
20928c506b8Sjruoho     {
21028c506b8Sjruoho         if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
21128c506b8Sjruoho         {
21228c506b8Sjruoho             /* 24-bit Timer */
21328c506b8Sjruoho 
214b406f703Schristos             DeltaTicks |= (UINT64) 1 << 24;
21528c506b8Sjruoho         }
21628c506b8Sjruoho         else
21728c506b8Sjruoho         {
21828c506b8Sjruoho             /* 32-bit Timer */
21928c506b8Sjruoho 
220b406f703Schristos             DeltaTicks |= (UINT64) 1 << 32;
22128c506b8Sjruoho         }
22228c506b8Sjruoho     }
223b406f703Schristos     DeltaTicks -= StartTicks;
22428c506b8Sjruoho 
22528c506b8Sjruoho     /*
22628c506b8Sjruoho      * Compute Duration (Requires a 64-bit multiply and divide):
22728c506b8Sjruoho      *
228ff4a156dSchristos      * TimeElapsed (microseconds) =
229ff4a156dSchristos      *  (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
23028c506b8Sjruoho      */
231b406f703Schristos     Status = AcpiUtShortDivide (DeltaTicks * ACPI_USEC_PER_SEC,
232ff4a156dSchristos                 ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL);
23328c506b8Sjruoho 
23428c506b8Sjruoho     *TimeElapsed = (UINT32) Quotient;
23528c506b8Sjruoho     return_ACPI_STATUS (Status);
23628c506b8Sjruoho }
23728c506b8Sjruoho 
23828c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
23928c506b8Sjruoho 
240ff4a156dSchristos #endif /* !ACPI_REDUCED_HARDWARE */
241