Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Name: hwtimer.c - ACPI Power Management Timer Interface
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #define EXPORT_ACPI_INTERFACES
0011 
0012 #include <acpi/acpi.h>
0013 #include "accommon.h"
0014 
0015 #define _COMPONENT          ACPI_HARDWARE
0016 ACPI_MODULE_NAME("hwtimer")
0017 
0018 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
0019 /******************************************************************************
0020  *
0021  * FUNCTION:    acpi_get_timer_resolution
0022  *
0023  * PARAMETERS:  resolution          - Where the resolution is returned
0024  *
0025  * RETURN:      Status and timer resolution
0026  *
0027  * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
0028  *
0029  ******************************************************************************/
0030 acpi_status acpi_get_timer_resolution(u32 * resolution)
0031 {
0032     ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
0033 
0034     if (!resolution) {
0035         return_ACPI_STATUS(AE_BAD_PARAMETER);
0036     }
0037 
0038     if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
0039         *resolution = 24;
0040     } else {
0041         *resolution = 32;
0042     }
0043 
0044     return_ACPI_STATUS(AE_OK);
0045 }
0046 
0047 ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
0048 
0049 /******************************************************************************
0050  *
0051  * FUNCTION:    acpi_get_timer
0052  *
0053  * PARAMETERS:  ticks               - Where the timer value is returned
0054  *
0055  * RETURN:      Status and current timer value (ticks)
0056  *
0057  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
0058  *
0059  ******************************************************************************/
0060 acpi_status acpi_get_timer(u32 * ticks)
0061 {
0062     acpi_status status;
0063     u64 timer_value;
0064 
0065     ACPI_FUNCTION_TRACE(acpi_get_timer);
0066 
0067     if (!ticks) {
0068         return_ACPI_STATUS(AE_BAD_PARAMETER);
0069     }
0070 
0071     /* ACPI 5.0A: PM Timer is optional */
0072 
0073     if (!acpi_gbl_FADT.xpm_timer_block.address) {
0074         return_ACPI_STATUS(AE_SUPPORT);
0075     }
0076 
0077     status = acpi_hw_read(&timer_value, &acpi_gbl_FADT.xpm_timer_block);
0078     if (ACPI_SUCCESS(status)) {
0079 
0080         /* ACPI PM Timer is defined to be 32 bits (PM_TMR_LEN) */
0081 
0082         *ticks = (u32)timer_value;
0083     }
0084 
0085     return_ACPI_STATUS(status);
0086 }
0087 
0088 ACPI_EXPORT_SYMBOL(acpi_get_timer)
0089 
0090 /******************************************************************************
0091  *
0092  * FUNCTION:    acpi_get_timer_duration
0093  *
0094  * PARAMETERS:  start_ticks         - Starting timestamp
0095  *              end_ticks           - End timestamp
0096  *              time_elapsed        - Where the elapsed time is returned
0097  *
0098  * RETURN:      Status and time_elapsed
0099  *
0100  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
0101  *              PM Timer time stamps, taking into account the possibility of
0102  *              rollovers, the timer resolution, and timer frequency.
0103  *
0104  *              The PM Timer's clock ticks at roughly 3.6 times per
0105  *              _microsecond_, and its clock continues through Cx state
0106  *              transitions (unlike many CPU timestamp counters) -- making it
0107  *              a versatile and accurate timer.
0108  *
0109  *              Note that this function accommodates only a single timer
0110  *              rollover. Thus for 24-bit timers, this function should only
0111  *              be used for calculating durations less than ~4.6 seconds
0112  *              (~20 minutes for 32-bit timers) -- calculations below:
0113  *
0114  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
0115  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
0116  *
0117  ******************************************************************************/
0118 acpi_status
0119 acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 *time_elapsed)
0120 {
0121     acpi_status status;
0122     u64 delta_ticks;
0123     u64 quotient;
0124 
0125     ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
0126 
0127     if (!time_elapsed) {
0128         return_ACPI_STATUS(AE_BAD_PARAMETER);
0129     }
0130 
0131     /* ACPI 5.0A: PM Timer is optional */
0132 
0133     if (!acpi_gbl_FADT.xpm_timer_block.address) {
0134         return_ACPI_STATUS(AE_SUPPORT);
0135     }
0136 
0137     if (start_ticks == end_ticks) {
0138         *time_elapsed = 0;
0139         return_ACPI_STATUS(AE_OK);
0140     }
0141 
0142     /*
0143      * Compute Tick Delta:
0144      * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
0145      */
0146     delta_ticks = end_ticks;
0147     if (start_ticks > end_ticks) {
0148         if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
0149 
0150             /* 24-bit Timer */
0151 
0152             delta_ticks |= (u64)1 << 24;
0153         } else {
0154             /* 32-bit Timer */
0155 
0156             delta_ticks |= (u64)1 << 32;
0157         }
0158     }
0159     delta_ticks -= start_ticks;
0160 
0161     /*
0162      * Compute Duration (Requires a 64-bit multiply and divide):
0163      *
0164      * time_elapsed (microseconds) =
0165      *  (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
0166      */
0167     status = acpi_ut_short_divide(delta_ticks * ACPI_USEC_PER_SEC,
0168                       ACPI_PM_TIMER_FREQUENCY, &quotient, NULL);
0169 
0170     *time_elapsed = (u32)quotient;
0171     return_ACPI_STATUS(status);
0172 }
0173 
0174 ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
0175 #endif              /* !ACPI_REDUCED_HARDWARE */