linux/drivers/acpi/acpica/hwtimer.c
<<
>>
Prefs
   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 - 2021, 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
  16ACPI_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 ******************************************************************************/
  30acpi_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
  47ACPI_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 ******************************************************************************/
  60acpi_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
  88ACPI_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 ******************************************************************************/
 118acpi_status
 119acpi_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, &quotient, NULL);
 169
 170        *time_elapsed = (u32)quotient;
 171        return_ACPI_STATUS(status);
 172}
 173
 174ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
 175#endif                          /* !ACPI_REDUCED_HARDWARE */
 176