Home | History | Annotate | Download | only in delay_timer
      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 % 10 == 0) && (div % 10 == 0)) {
     53 		mult /= 10;
     54 		div /= 10;
     55 	}
     56 
     57 	generic_delay_timer_init_args(mult, div);
     58 }
     59 
     60