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