xref: /openbmc/linux/drivers/acpi/acpica/hwtimer.c (revision 5df7e6cb)
195b482a8SLen Brown 
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Name: hwtimer.c - ACPI Power Management Timer Interface
595b482a8SLen Brown  *
695b482a8SLen Brown  *****************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown /*
9a8357b0cSBob Moore  * Copyright (C) 2000 - 2010, Intel Corp.
1095b482a8SLen Brown  * All rights reserved.
1195b482a8SLen Brown  *
1295b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
1395b482a8SLen Brown  * modification, are permitted provided that the following conditions
1495b482a8SLen Brown  * are met:
1595b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
1695b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
1795b482a8SLen Brown  *    without modification.
1895b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1995b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
2095b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
2195b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
2295b482a8SLen Brown  *    binary redistribution.
2395b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
2495b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
2595b482a8SLen Brown  *    from this software without specific prior written permission.
2695b482a8SLen Brown  *
2795b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
2895b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
2995b482a8SLen Brown  * Software Foundation.
3095b482a8SLen Brown  *
3195b482a8SLen Brown  * NO WARRANTY
3295b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3395b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3495b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3595b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3695b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3795b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3895b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3995b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4095b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4195b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4295b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
4395b482a8SLen Brown  */
4495b482a8SLen Brown 
4595b482a8SLen Brown #include <acpi/acpi.h>
46e2f7a777SLen Brown #include "accommon.h"
4795b482a8SLen Brown 
4895b482a8SLen Brown #define _COMPONENT          ACPI_HARDWARE
4995b482a8SLen Brown ACPI_MODULE_NAME("hwtimer")
5095b482a8SLen Brown 
5195b482a8SLen Brown /******************************************************************************
5295b482a8SLen Brown  *
5395b482a8SLen Brown  * FUNCTION:    acpi_get_timer_resolution
5495b482a8SLen Brown  *
5595b482a8SLen Brown  * PARAMETERS:  Resolution          - Where the resolution is returned
5695b482a8SLen Brown  *
5795b482a8SLen Brown  * RETURN:      Status and timer resolution
5895b482a8SLen Brown  *
5995b482a8SLen Brown  * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6095b482a8SLen Brown  *
6195b482a8SLen Brown  ******************************************************************************/
6295b482a8SLen Brown acpi_status acpi_get_timer_resolution(u32 * resolution)
6395b482a8SLen Brown {
6495b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
6595b482a8SLen Brown 
6695b482a8SLen Brown 	if (!resolution) {
6795b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
6895b482a8SLen Brown 	}
6995b482a8SLen Brown 
7095b482a8SLen Brown 	if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
7195b482a8SLen Brown 		*resolution = 24;
7295b482a8SLen Brown 	} else {
7395b482a8SLen Brown 		*resolution = 32;
7495b482a8SLen Brown 	}
7595b482a8SLen Brown 
7695b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
7795b482a8SLen Brown }
7895b482a8SLen Brown 
7995b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
8095b482a8SLen Brown 
8195b482a8SLen Brown /******************************************************************************
8295b482a8SLen Brown  *
8395b482a8SLen Brown  * FUNCTION:    acpi_get_timer
8495b482a8SLen Brown  *
8595b482a8SLen Brown  * PARAMETERS:  Ticks               - Where the timer value is returned
8695b482a8SLen Brown  *
8795b482a8SLen Brown  * RETURN:      Status and current timer value (ticks)
8895b482a8SLen Brown  *
8995b482a8SLen Brown  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
9095b482a8SLen Brown  *
9195b482a8SLen Brown  ******************************************************************************/
9295b482a8SLen Brown acpi_status acpi_get_timer(u32 * ticks)
9395b482a8SLen Brown {
9495b482a8SLen Brown 	acpi_status status;
9595b482a8SLen Brown 
9695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer);
9795b482a8SLen Brown 
9895b482a8SLen Brown 	if (!ticks) {
9995b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
10095b482a8SLen Brown 	}
10195b482a8SLen Brown 
10295b482a8SLen Brown 	status =
103c6b5774cSBob Moore 	    acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
10495b482a8SLen Brown 
10595b482a8SLen Brown 	return_ACPI_STATUS(status);
10695b482a8SLen Brown }
10795b482a8SLen Brown 
10895b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer)
10995b482a8SLen Brown 
11095b482a8SLen Brown /******************************************************************************
11195b482a8SLen Brown  *
11295b482a8SLen Brown  * FUNCTION:    acpi_get_timer_duration
11395b482a8SLen Brown  *
11495b482a8SLen Brown  * PARAMETERS:  start_ticks         - Starting timestamp
11595b482a8SLen Brown  *              end_ticks           - End timestamp
11695b482a8SLen Brown  *              time_elapsed        - Where the elapsed time is returned
11795b482a8SLen Brown  *
11895b482a8SLen Brown  * RETURN:      Status and time_elapsed
11995b482a8SLen Brown  *
12095b482a8SLen Brown  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
12195b482a8SLen Brown  *              PM Timer time stamps, taking into account the possibility of
12295b482a8SLen Brown  *              rollovers, the timer resolution, and timer frequency.
12395b482a8SLen Brown  *
12495b482a8SLen Brown  *              The PM Timer's clock ticks at roughly 3.6 times per
12595b482a8SLen Brown  *              _microsecond_, and its clock continues through Cx state
12695b482a8SLen Brown  *              transitions (unlike many CPU timestamp counters) -- making it
12795b482a8SLen Brown  *              a versatile and accurate timer.
12895b482a8SLen Brown  *
12995b482a8SLen Brown  *              Note that this function accommodates only a single timer
13095b482a8SLen Brown  *              rollover.  Thus for 24-bit timers, this function should only
13195b482a8SLen Brown  *              be used for calculating durations less than ~4.6 seconds
13295b482a8SLen Brown  *              (~20 minutes for 32-bit timers) -- calculations below:
13395b482a8SLen Brown  *
13495b482a8SLen Brown  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
13595b482a8SLen Brown  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
13695b482a8SLen Brown  *
13795b482a8SLen Brown  ******************************************************************************/
13895b482a8SLen Brown acpi_status
13995b482a8SLen Brown acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
14095b482a8SLen Brown {
14195b482a8SLen Brown 	acpi_status status;
14295b482a8SLen Brown 	u32 delta_ticks;
1435df7e6cbSBob Moore 	u64 quotient;
14495b482a8SLen Brown 
14595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
14695b482a8SLen Brown 
14795b482a8SLen Brown 	if (!time_elapsed) {
14895b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
14995b482a8SLen Brown 	}
15095b482a8SLen Brown 
15195b482a8SLen Brown 	/*
15295b482a8SLen Brown 	 * Compute Tick Delta:
15395b482a8SLen Brown 	 * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
15495b482a8SLen Brown 	 */
15595b482a8SLen Brown 	if (start_ticks < end_ticks) {
15695b482a8SLen Brown 		delta_ticks = end_ticks - start_ticks;
15795b482a8SLen Brown 	} else if (start_ticks > end_ticks) {
15895b482a8SLen Brown 		if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
15995b482a8SLen Brown 
16095b482a8SLen Brown 			/* 24-bit Timer */
16195b482a8SLen Brown 
16295b482a8SLen Brown 			delta_ticks =
16395b482a8SLen Brown 			    (((0x00FFFFFF - start_ticks) +
16495b482a8SLen Brown 			      end_ticks) & 0x00FFFFFF);
16595b482a8SLen Brown 		} else {
16695b482a8SLen Brown 			/* 32-bit Timer */
16795b482a8SLen Brown 
16895b482a8SLen Brown 			delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
16995b482a8SLen Brown 		}
17095b482a8SLen Brown 	} else {		/* start_ticks == end_ticks */
17195b482a8SLen Brown 
17295b482a8SLen Brown 		*time_elapsed = 0;
17395b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
17495b482a8SLen Brown 	}
17595b482a8SLen Brown 
17695b482a8SLen Brown 	/*
17795b482a8SLen Brown 	 * Compute Duration (Requires a 64-bit multiply and divide):
17895b482a8SLen Brown 	 *
17995b482a8SLen Brown 	 * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
18095b482a8SLen Brown 	 */
18195b482a8SLen Brown 	status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000,
18295b482a8SLen Brown 				      PM_TIMER_FREQUENCY, &quotient, NULL);
18395b482a8SLen Brown 
18495b482a8SLen Brown 	*time_elapsed = (u32) quotient;
18595b482a8SLen Brown 	return_ACPI_STATUS(status);
18695b482a8SLen Brown }
18795b482a8SLen Brown 
18895b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
189