xref: /rk3399_ARM-atf/drivers/delay_timer/generic_delay_timer.c (revision fd7b287cbe9147ca9e07dd9f30c49c58bbdd92a8)
1 /*
2  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <arch_features.h>
10 #include <arch_helpers.h>
11 #include <common/bl_common.h>
12 #include <common/debug.h>
13 #include <drivers/delay_timer.h>
14 #include <drivers/generic_delay_timer.h>
15 #include <plat/common/platform.h>
16 
17 /* Ticks elapsed in one second by a signal of 1 MHz */
18 #define MHZ_TICKS_PER_SEC 1000000
19 
20 static timer_ops_t ops;
21 
22 static uint32_t get_timer_value(void)
23 {
24 	/*
25 	 * Generic delay timer implementation expects the timer to be a down
26 	 * counter. We apply bitwise NOT operator to the tick values returned
27 	 * by read_cntpct_el0() to simulate the down counter. The value is
28 	 * clipped from 64 to 32 bits.
29 	 */
30 	return (uint32_t)(~read_cntpct_el0());
31 }
32 
33 void generic_delay_timer_init_args(uint32_t mult, uint32_t div)
34 {
35 	ops.get_timer_value	= get_timer_value;
36 	ops.clk_mult		= mult;
37 	ops.clk_div		= div;
38 
39 	timer_init(&ops);
40 
41 	VERBOSE("Generic delay timer configured with mult=%u and div=%u\n",
42 		mult, div);
43 }
44 
45 void generic_delay_timer_init(void)
46 {
47 	assert(is_armv7_gentimer_present());
48 
49 	/* Value in ticks */
50 	unsigned int mult = MHZ_TICKS_PER_SEC;
51 
52 	/* Value in ticks per second (Hz) */
53 	unsigned int div  = plat_get_syscnt_freq2();
54 
55 	/* Reduce multiplier and divider by dividing them repeatedly by 10 */
56 	while (((mult % 10U) == 0U) && ((div % 10U) == 0U)) {
57 		mult /= 10U;
58 		div /= 10U;
59 	}
60 
61 	generic_delay_timer_init_args(mult, div);
62 }
63 
64