1447a42e7SPankaj Gupta /* 2447a42e7SPankaj Gupta * Copyright 2021 NXP 3447a42e7SPankaj Gupta * 4447a42e7SPankaj Gupta * SPDX-License-Identifier: BSD-3-Clause 5447a42e7SPankaj Gupta * 6447a42e7SPankaj Gupta */ 7447a42e7SPankaj Gupta 8447a42e7SPankaj Gupta #include <arch_helpers.h> 9447a42e7SPankaj Gupta #include <common/debug.h> 10447a42e7SPankaj Gupta #include <drivers/delay_timer.h> 11447a42e7SPankaj Gupta #include <lib/mmio.h> 12447a42e7SPankaj Gupta #include <lib/utils_def.h> 13447a42e7SPankaj Gupta #include <nxp_timer.h> 14447a42e7SPankaj Gupta #include <plat/common/platform.h> 15447a42e7SPankaj Gupta 16447a42e7SPankaj Gupta static uintptr_t g_nxp_timer_addr; 17447a42e7SPankaj Gupta static timer_ops_t ops; 18447a42e7SPankaj Gupta 19447a42e7SPankaj Gupta uint64_t get_timer_val(uint64_t start) 20447a42e7SPankaj Gupta { 21447a42e7SPankaj Gupta uint64_t cntpct; 22447a42e7SPankaj Gupta 23447a42e7SPankaj Gupta isb(); 24447a42e7SPankaj Gupta cntpct = read_cntpct_el0(); 25447a42e7SPankaj Gupta return (cntpct * 1000ULL / read_cntfrq_el0() - start); 26447a42e7SPankaj Gupta } 27447a42e7SPankaj Gupta 28447a42e7SPankaj Gupta static uint32_t timer_get_value(void) 29447a42e7SPankaj Gupta { 30447a42e7SPankaj Gupta uint64_t cntpct; 31447a42e7SPankaj Gupta 32447a42e7SPankaj Gupta isb(); 33447a42e7SPankaj Gupta cntpct = read_cntpct_el0(); 34447a42e7SPankaj Gupta #ifdef ERRATA_SOC_A008585 35447a42e7SPankaj Gupta uint8_t max_fetch_count = 10U; 36447a42e7SPankaj Gupta /* This erratum number needs to be confirmed to match ARM document */ 37447a42e7SPankaj Gupta uint64_t temp; 38447a42e7SPankaj Gupta 39447a42e7SPankaj Gupta isb(); 40447a42e7SPankaj Gupta temp = read_cntpct_el0(); 41447a42e7SPankaj Gupta 42447a42e7SPankaj Gupta while (temp != cntpct && max_fetch_count) { 43447a42e7SPankaj Gupta isb(); 44447a42e7SPankaj Gupta cntpct = read_cntpct_el0(); 45447a42e7SPankaj Gupta isb(); 46447a42e7SPankaj Gupta temp = read_cntpct_el0(); 47447a42e7SPankaj Gupta max_fetch_count--; 48447a42e7SPankaj Gupta } 49447a42e7SPankaj Gupta #endif 50447a42e7SPankaj Gupta 51447a42e7SPankaj Gupta /* 52447a42e7SPankaj Gupta * Generic delay timer implementation expects the timer to be a down 53447a42e7SPankaj Gupta * counter. We apply bitwise NOT operator to the tick values returned 54447a42e7SPankaj Gupta * by read_cntpct_el0() to simulate the down counter. The value is 55447a42e7SPankaj Gupta * clipped from 64 to 32 bits. 56447a42e7SPankaj Gupta */ 57447a42e7SPankaj Gupta return (uint32_t)(~cntpct); 58447a42e7SPankaj Gupta } 59447a42e7SPankaj Gupta 60447a42e7SPankaj Gupta static void delay_timer_init_args(uint32_t mult, uint32_t div) 61447a42e7SPankaj Gupta { 62*50b8ea11SElyes Haouas ops.get_timer_value = timer_get_value; 63447a42e7SPankaj Gupta ops.clk_mult = mult; 64447a42e7SPankaj Gupta ops.clk_div = div; 65447a42e7SPankaj Gupta 66447a42e7SPankaj Gupta timer_init(&ops); 67447a42e7SPankaj Gupta 68447a42e7SPankaj Gupta VERBOSE("Generic delay timer configured with mult=%u and div=%u\n", 69447a42e7SPankaj Gupta mult, div); 70447a42e7SPankaj Gupta } 71447a42e7SPankaj Gupta 72447a42e7SPankaj Gupta /* 73447a42e7SPankaj Gupta * Initialise the nxp on-chip free rolling usec counter as the delay 74447a42e7SPankaj Gupta * timer. 75447a42e7SPankaj Gupta */ 76447a42e7SPankaj Gupta void delay_timer_init(uintptr_t nxp_timer_addr) 77447a42e7SPankaj Gupta { 78447a42e7SPankaj Gupta /* Value in ticks */ 79447a42e7SPankaj Gupta unsigned int mult = MHZ_TICKS_PER_SEC; 80447a42e7SPankaj Gupta 81447a42e7SPankaj Gupta unsigned int div; 82447a42e7SPankaj Gupta 83447a42e7SPankaj Gupta unsigned int counter_base_frequency = plat_get_syscnt_freq2(); 84447a42e7SPankaj Gupta 85447a42e7SPankaj Gupta g_nxp_timer_addr = nxp_timer_addr; 86447a42e7SPankaj Gupta /* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */ 87447a42e7SPankaj Gupta if (counter_base_frequency > MHZ_TICKS_PER_SEC) { 88447a42e7SPankaj Gupta counter_base_frequency = (counter_base_frequency 89447a42e7SPankaj Gupta / MHZ_TICKS_PER_SEC) 90447a42e7SPankaj Gupta * MHZ_TICKS_PER_SEC; 91447a42e7SPankaj Gupta } else { 92447a42e7SPankaj Gupta counter_base_frequency = (counter_base_frequency 93447a42e7SPankaj Gupta / KHZ_TICKS_PER_SEC) 94447a42e7SPankaj Gupta * KHZ_TICKS_PER_SEC; 95447a42e7SPankaj Gupta } 96447a42e7SPankaj Gupta 97447a42e7SPankaj Gupta /* Value in ticks per second (Hz) */ 98447a42e7SPankaj Gupta div = counter_base_frequency; 99447a42e7SPankaj Gupta 100447a42e7SPankaj Gupta /* Reduce multiplier and divider by dividing them repeatedly by 10 */ 101447a42e7SPankaj Gupta while ((mult % 10U == 0U) && (div % 10U == 0U)) { 102447a42e7SPankaj Gupta mult /= 10U; 103447a42e7SPankaj Gupta div /= 10U; 104447a42e7SPankaj Gupta } 105447a42e7SPankaj Gupta 106447a42e7SPankaj Gupta /* Enable and initialize the System level generic timer */ 107447a42e7SPankaj Gupta mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, 108447a42e7SPankaj Gupta CNTCR_FCREQ(0) | CNTCR_EN); 109447a42e7SPankaj Gupta 110447a42e7SPankaj Gupta delay_timer_init_args(mult, div); 111447a42e7SPankaj Gupta } 112447a42e7SPankaj Gupta 113447a42e7SPankaj Gupta 114447a42e7SPankaj Gupta #ifdef IMAGE_BL31 115447a42e7SPankaj Gupta /******************************************************************************* 116447a42e7SPankaj Gupta * TBD: Configures access to the system counter timer module. 117447a42e7SPankaj Gupta ******************************************************************************/ 118447a42e7SPankaj Gupta void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base, 119447a42e7SPankaj Gupta uint8_t ls_config_cntacr, 120447a42e7SPankaj Gupta uint8_t plat_ls_ns_timer_frame_id) 121447a42e7SPankaj Gupta { 122447a42e7SPankaj Gupta unsigned int reg_val; 123447a42e7SPankaj Gupta 124447a42e7SPankaj Gupta if (ls_config_cntacr == 1U) { 125447a42e7SPankaj Gupta reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT); 126447a42e7SPankaj Gupta reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT); 127447a42e7SPankaj Gupta reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT); 128447a42e7SPankaj Gupta mmio_write_32(ls_sys_timctl_base + 129447a42e7SPankaj Gupta CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val); 130447a42e7SPankaj Gupta mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2()); 131447a42e7SPankaj Gupta } 132447a42e7SPankaj Gupta 133447a42e7SPankaj Gupta reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id)); 134447a42e7SPankaj Gupta mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val); 135447a42e7SPankaj Gupta } 136447a42e7SPankaj Gupta 137447a42e7SPankaj Gupta void enable_init_timer(void) 138447a42e7SPankaj Gupta { 139447a42e7SPankaj Gupta /* Enable and initialize the System level generic timer */ 140447a42e7SPankaj Gupta mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, 141447a42e7SPankaj Gupta CNTCR_FCREQ(0) | CNTCR_EN); 142447a42e7SPankaj Gupta } 143447a42e7SPankaj Gupta #endif 144