^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Name: hwtimer.c - ACPI Power Management Timer Interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2000 - 2020, Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define EXPORT_ACPI_INTERFACES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <acpi/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "accommon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define _COMPONENT ACPI_HARDWARE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) ACPI_MODULE_NAME("hwtimer")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * FUNCTION: acpi_get_timer_resolution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * PARAMETERS: resolution - Where the resolution is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * RETURN: Status and timer resolution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) acpi_status acpi_get_timer_resolution(u32 * resolution)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!resolution) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return_ACPI_STATUS(AE_BAD_PARAMETER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *resolution = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *resolution = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return_ACPI_STATUS(AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * FUNCTION: acpi_get_timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * PARAMETERS: ticks - Where the timer value is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * RETURN: Status and current timer value (ticks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) acpi_status acpi_get_timer(u32 * ticks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u64 timer_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ACPI_FUNCTION_TRACE(acpi_get_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!ticks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return_ACPI_STATUS(AE_BAD_PARAMETER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* ACPI 5.0A: PM Timer is optional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!acpi_gbl_FADT.xpm_timer_block.address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return_ACPI_STATUS(AE_SUPPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) status = acpi_hw_read(&timer_value, &acpi_gbl_FADT.xpm_timer_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (ACPI_SUCCESS(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* ACPI PM Timer is defined to be 32 bits (PM_TMR_LEN) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *ticks = (u32)timer_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return_ACPI_STATUS(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ACPI_EXPORT_SYMBOL(acpi_get_timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * FUNCTION: acpi_get_timer_duration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * PARAMETERS: start_ticks - Starting timestamp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * end_ticks - End timestamp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * time_elapsed - Where the elapsed time is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * RETURN: Status and time_elapsed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * DESCRIPTION: Computes the time elapsed (in microseconds) between two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * PM Timer time stamps, taking into account the possibility of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * rollovers, the timer resolution, and timer frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * The PM Timer's clock ticks at roughly 3.6 times per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * _microsecond_, and its clock continues through Cx state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * transitions (unlike many CPU timestamp counters) -- making it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * a versatile and accurate timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Note that this function accommodates only a single timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * rollover. Thus for 24-bit timers, this function should only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * be used for calculating durations less than ~4.6 seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * (~20 minutes for 32-bit timers) -- calculations below:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 *time_elapsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u64 delta_ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u64 quotient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!time_elapsed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return_ACPI_STATUS(AE_BAD_PARAMETER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* ACPI 5.0A: PM Timer is optional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!acpi_gbl_FADT.xpm_timer_block.address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return_ACPI_STATUS(AE_SUPPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (start_ticks == end_ticks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *time_elapsed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return_ACPI_STATUS(AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Compute Tick Delta:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) delta_ticks = end_ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (start_ticks > end_ticks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* 24-bit Timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) delta_ticks |= (u64)1 << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* 32-bit Timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) delta_ticks |= (u64)1 << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) delta_ticks -= start_ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Compute Duration (Requires a 64-bit multiply and divide):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * time_elapsed (microseconds) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) status = acpi_ut_short_divide(delta_ticks * ACPI_USEC_PER_SEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ACPI_PM_TIMER_FREQUENCY, "ient, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *time_elapsed = (u32)quotient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return_ACPI_STATUS(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #endif /* !ACPI_REDUCED_HARDWARE */