1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2021 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <arch_helpers.h> 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <drivers/delay_timer.h> 11*91f16700Schasinglulu #include <lib/mmio.h> 12*91f16700Schasinglulu #include <lib/utils_def.h> 13*91f16700Schasinglulu #include <nxp_timer.h> 14*91f16700Schasinglulu #include <plat/common/platform.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu static uintptr_t g_nxp_timer_addr; 17*91f16700Schasinglulu static timer_ops_t ops; 18*91f16700Schasinglulu 19*91f16700Schasinglulu uint64_t get_timer_val(uint64_t start) 20*91f16700Schasinglulu { 21*91f16700Schasinglulu uint64_t cntpct; 22*91f16700Schasinglulu 23*91f16700Schasinglulu isb(); 24*91f16700Schasinglulu cntpct = read_cntpct_el0(); 25*91f16700Schasinglulu return (cntpct * 1000ULL / read_cntfrq_el0() - start); 26*91f16700Schasinglulu } 27*91f16700Schasinglulu 28*91f16700Schasinglulu static uint32_t timer_get_value(void) 29*91f16700Schasinglulu { 30*91f16700Schasinglulu uint64_t cntpct; 31*91f16700Schasinglulu 32*91f16700Schasinglulu isb(); 33*91f16700Schasinglulu cntpct = read_cntpct_el0(); 34*91f16700Schasinglulu #ifdef ERRATA_SOC_A008585 35*91f16700Schasinglulu uint8_t max_fetch_count = 10U; 36*91f16700Schasinglulu /* This erratum number needs to be confirmed to match ARM document */ 37*91f16700Schasinglulu uint64_t temp; 38*91f16700Schasinglulu 39*91f16700Schasinglulu isb(); 40*91f16700Schasinglulu temp = read_cntpct_el0(); 41*91f16700Schasinglulu 42*91f16700Schasinglulu while (temp != cntpct && max_fetch_count) { 43*91f16700Schasinglulu isb(); 44*91f16700Schasinglulu cntpct = read_cntpct_el0(); 45*91f16700Schasinglulu isb(); 46*91f16700Schasinglulu temp = read_cntpct_el0(); 47*91f16700Schasinglulu max_fetch_count--; 48*91f16700Schasinglulu } 49*91f16700Schasinglulu #endif 50*91f16700Schasinglulu 51*91f16700Schasinglulu /* 52*91f16700Schasinglulu * Generic delay timer implementation expects the timer to be a down 53*91f16700Schasinglulu * counter. We apply bitwise NOT operator to the tick values returned 54*91f16700Schasinglulu * by read_cntpct_el0() to simulate the down counter. The value is 55*91f16700Schasinglulu * clipped from 64 to 32 bits. 56*91f16700Schasinglulu */ 57*91f16700Schasinglulu return (uint32_t)(~cntpct); 58*91f16700Schasinglulu } 59*91f16700Schasinglulu 60*91f16700Schasinglulu static void delay_timer_init_args(uint32_t mult, uint32_t div) 61*91f16700Schasinglulu { 62*91f16700Schasinglulu ops.get_timer_value = timer_get_value; 63*91f16700Schasinglulu ops.clk_mult = mult; 64*91f16700Schasinglulu ops.clk_div = div; 65*91f16700Schasinglulu 66*91f16700Schasinglulu timer_init(&ops); 67*91f16700Schasinglulu 68*91f16700Schasinglulu VERBOSE("Generic delay timer configured with mult=%u and div=%u\n", 69*91f16700Schasinglulu mult, div); 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* 73*91f16700Schasinglulu * Initialise the nxp on-chip free rolling usec counter as the delay 74*91f16700Schasinglulu * timer. 75*91f16700Schasinglulu */ 76*91f16700Schasinglulu void delay_timer_init(uintptr_t nxp_timer_addr) 77*91f16700Schasinglulu { 78*91f16700Schasinglulu /* Value in ticks */ 79*91f16700Schasinglulu unsigned int mult = MHZ_TICKS_PER_SEC; 80*91f16700Schasinglulu 81*91f16700Schasinglulu unsigned int div; 82*91f16700Schasinglulu 83*91f16700Schasinglulu unsigned int counter_base_frequency = plat_get_syscnt_freq2(); 84*91f16700Schasinglulu 85*91f16700Schasinglulu g_nxp_timer_addr = nxp_timer_addr; 86*91f16700Schasinglulu /* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */ 87*91f16700Schasinglulu if (counter_base_frequency > MHZ_TICKS_PER_SEC) { 88*91f16700Schasinglulu counter_base_frequency = (counter_base_frequency 89*91f16700Schasinglulu / MHZ_TICKS_PER_SEC) 90*91f16700Schasinglulu * MHZ_TICKS_PER_SEC; 91*91f16700Schasinglulu } else { 92*91f16700Schasinglulu counter_base_frequency = (counter_base_frequency 93*91f16700Schasinglulu / KHZ_TICKS_PER_SEC) 94*91f16700Schasinglulu * KHZ_TICKS_PER_SEC; 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu /* Value in ticks per second (Hz) */ 98*91f16700Schasinglulu div = counter_base_frequency; 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* Reduce multiplier and divider by dividing them repeatedly by 10 */ 101*91f16700Schasinglulu while ((mult % 10U == 0U) && (div % 10U == 0U)) { 102*91f16700Schasinglulu mult /= 10U; 103*91f16700Schasinglulu div /= 10U; 104*91f16700Schasinglulu } 105*91f16700Schasinglulu 106*91f16700Schasinglulu /* Enable and initialize the System level generic timer */ 107*91f16700Schasinglulu mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, 108*91f16700Schasinglulu CNTCR_FCREQ(0) | CNTCR_EN); 109*91f16700Schasinglulu 110*91f16700Schasinglulu delay_timer_init_args(mult, div); 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu 114*91f16700Schasinglulu #ifdef IMAGE_BL31 115*91f16700Schasinglulu /******************************************************************************* 116*91f16700Schasinglulu * TBD: Configures access to the system counter timer module. 117*91f16700Schasinglulu ******************************************************************************/ 118*91f16700Schasinglulu void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base, 119*91f16700Schasinglulu uint8_t ls_config_cntacr, 120*91f16700Schasinglulu uint8_t plat_ls_ns_timer_frame_id) 121*91f16700Schasinglulu { 122*91f16700Schasinglulu unsigned int reg_val; 123*91f16700Schasinglulu 124*91f16700Schasinglulu if (ls_config_cntacr == 1U) { 125*91f16700Schasinglulu reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT); 126*91f16700Schasinglulu reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT); 127*91f16700Schasinglulu reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT); 128*91f16700Schasinglulu mmio_write_32(ls_sys_timctl_base + 129*91f16700Schasinglulu CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val); 130*91f16700Schasinglulu mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2()); 131*91f16700Schasinglulu } 132*91f16700Schasinglulu 133*91f16700Schasinglulu reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id)); 134*91f16700Schasinglulu mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val); 135*91f16700Schasinglulu } 136*91f16700Schasinglulu 137*91f16700Schasinglulu void enable_init_timer(void) 138*91f16700Schasinglulu { 139*91f16700Schasinglulu /* Enable and initialize the System level generic timer */ 140*91f16700Schasinglulu mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, 141*91f16700Schasinglulu CNTCR_FCREQ(0) | CNTCR_EN); 142*91f16700Schasinglulu } 143*91f16700Schasinglulu #endif 144