xref: /openbmc/linux/drivers/acpi/acpica/hwtimer.c (revision ba494bee)
195b482a8SLen Brown 
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Name: hwtimer.c - ACPI Power Management Timer Interface
595b482a8SLen Brown  *
695b482a8SLen Brown  *****************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown /*
977848130SBob Moore  * Copyright (C) 2000 - 2012, 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 
45214f2c90SPaul Gortmaker #include <linux/export.h>
4695b482a8SLen Brown #include <acpi/acpi.h>
47e2f7a777SLen Brown #include "accommon.h"
4895b482a8SLen Brown 
4995b482a8SLen Brown #define _COMPONENT          ACPI_HARDWARE
5095b482a8SLen Brown ACPI_MODULE_NAME("hwtimer")
5195b482a8SLen Brown 
5233620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
5395b482a8SLen Brown /******************************************************************************
5495b482a8SLen Brown  *
5595b482a8SLen Brown  * FUNCTION:    acpi_get_timer_resolution
5695b482a8SLen Brown  *
57ba494beeSBob Moore  * PARAMETERS:  resolution          - Where the resolution is returned
5895b482a8SLen Brown  *
5995b482a8SLen Brown  * RETURN:      Status and timer resolution
6095b482a8SLen Brown  *
6195b482a8SLen Brown  * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6295b482a8SLen Brown  *
6395b482a8SLen Brown  ******************************************************************************/
6495b482a8SLen Brown acpi_status acpi_get_timer_resolution(u32 * resolution)
6595b482a8SLen Brown {
6695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
6795b482a8SLen Brown 
6895b482a8SLen Brown 	if (!resolution) {
6995b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
7095b482a8SLen Brown 	}
7195b482a8SLen Brown 
7295b482a8SLen Brown 	if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
7395b482a8SLen Brown 		*resolution = 24;
7495b482a8SLen Brown 	} else {
7595b482a8SLen Brown 		*resolution = 32;
7695b482a8SLen Brown 	}
7795b482a8SLen Brown 
7895b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
7995b482a8SLen Brown }
8095b482a8SLen Brown 
8195b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
8295b482a8SLen Brown 
8395b482a8SLen Brown /******************************************************************************
8495b482a8SLen Brown  *
8595b482a8SLen Brown  * FUNCTION:    acpi_get_timer
8695b482a8SLen Brown  *
87ba494beeSBob Moore  * PARAMETERS:  ticks               - Where the timer value is returned
8895b482a8SLen Brown  *
8995b482a8SLen Brown  * RETURN:      Status and current timer value (ticks)
9095b482a8SLen Brown  *
9195b482a8SLen Brown  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
9295b482a8SLen Brown  *
9395b482a8SLen Brown  ******************************************************************************/
9495b482a8SLen Brown acpi_status acpi_get_timer(u32 * ticks)
9595b482a8SLen Brown {
9695b482a8SLen Brown 	acpi_status status;
9795b482a8SLen Brown 
9895b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer);
9995b482a8SLen Brown 
10095b482a8SLen Brown 	if (!ticks) {
10195b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
10295b482a8SLen Brown 	}
10395b482a8SLen Brown 
10495b482a8SLen Brown 	status =
105c6b5774cSBob Moore 	    acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
10695b482a8SLen Brown 
10795b482a8SLen Brown 	return_ACPI_STATUS(status);
10895b482a8SLen Brown }
10995b482a8SLen Brown 
11095b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer)
11195b482a8SLen Brown 
11295b482a8SLen Brown /******************************************************************************
11395b482a8SLen Brown  *
11495b482a8SLen Brown  * FUNCTION:    acpi_get_timer_duration
11595b482a8SLen Brown  *
11695b482a8SLen Brown  * PARAMETERS:  start_ticks         - Starting timestamp
11795b482a8SLen Brown  *              end_ticks           - End timestamp
11895b482a8SLen Brown  *              time_elapsed        - Where the elapsed time is returned
11995b482a8SLen Brown  *
12095b482a8SLen Brown  * RETURN:      Status and time_elapsed
12195b482a8SLen Brown  *
12295b482a8SLen Brown  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
12395b482a8SLen Brown  *              PM Timer time stamps, taking into account the possibility of
12495b482a8SLen Brown  *              rollovers, the timer resolution, and timer frequency.
12595b482a8SLen Brown  *
12695b482a8SLen Brown  *              The PM Timer's clock ticks at roughly 3.6 times per
12795b482a8SLen Brown  *              _microsecond_, and its clock continues through Cx state
12895b482a8SLen Brown  *              transitions (unlike many CPU timestamp counters) -- making it
12995b482a8SLen Brown  *              a versatile and accurate timer.
13095b482a8SLen Brown  *
13195b482a8SLen Brown  *              Note that this function accommodates only a single timer
13295b482a8SLen Brown  *              rollover.  Thus for 24-bit timers, this function should only
13395b482a8SLen Brown  *              be used for calculating durations less than ~4.6 seconds
13495b482a8SLen Brown  *              (~20 minutes for 32-bit timers) -- calculations below:
13595b482a8SLen Brown  *
13695b482a8SLen Brown  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
13795b482a8SLen Brown  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
13895b482a8SLen Brown  *
13995b482a8SLen Brown  ******************************************************************************/
14095b482a8SLen Brown acpi_status
14195b482a8SLen Brown acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
14295b482a8SLen Brown {
14395b482a8SLen Brown 	acpi_status status;
14495b482a8SLen Brown 	u32 delta_ticks;
1455df7e6cbSBob Moore 	u64 quotient;
14695b482a8SLen Brown 
14795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
14895b482a8SLen Brown 
14995b482a8SLen Brown 	if (!time_elapsed) {
15095b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
15195b482a8SLen Brown 	}
15295b482a8SLen Brown 
15395b482a8SLen Brown 	/*
15495b482a8SLen Brown 	 * Compute Tick Delta:
15595b482a8SLen Brown 	 * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
15695b482a8SLen Brown 	 */
15795b482a8SLen Brown 	if (start_ticks < end_ticks) {
15895b482a8SLen Brown 		delta_ticks = end_ticks - start_ticks;
15995b482a8SLen Brown 	} else if (start_ticks > end_ticks) {
16095b482a8SLen Brown 		if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
16195b482a8SLen Brown 
16295b482a8SLen Brown 			/* 24-bit Timer */
16395b482a8SLen Brown 
16495b482a8SLen Brown 			delta_ticks =
16595b482a8SLen Brown 			    (((0x00FFFFFF - start_ticks) +
16695b482a8SLen Brown 			      end_ticks) & 0x00FFFFFF);
16795b482a8SLen Brown 		} else {
16895b482a8SLen Brown 			/* 32-bit Timer */
16995b482a8SLen Brown 
17095b482a8SLen Brown 			delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
17195b482a8SLen Brown 		}
17295b482a8SLen Brown 	} else {		/* start_ticks == end_ticks */
17395b482a8SLen Brown 
17495b482a8SLen Brown 		*time_elapsed = 0;
17595b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
17695b482a8SLen Brown 	}
17795b482a8SLen Brown 
17895b482a8SLen Brown 	/*
17995b482a8SLen Brown 	 * Compute Duration (Requires a 64-bit multiply and divide):
18095b482a8SLen Brown 	 *
18195b482a8SLen Brown 	 * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
18295b482a8SLen Brown 	 */
18395b482a8SLen Brown 	status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000,
18495b482a8SLen Brown 				      PM_TIMER_FREQUENCY, &quotient, NULL);
18595b482a8SLen Brown 
18695b482a8SLen Brown 	*time_elapsed = (u32) quotient;
18795b482a8SLen Brown 	return_ACPI_STATUS(status);
18895b482a8SLen Brown }
18995b482a8SLen Brown 
19095b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
19133620c54SBob Moore #endif				/* !ACPI_REDUCED_HARDWARE */
192