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