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