1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <m0_param.h> 8*91f16700Schasinglulu #include "rk3399_mcu.h" 9*91f16700Schasinglulu 10*91f16700Schasinglulu /* use 24MHz SysTick */ 11*91f16700Schasinglulu #define US_TO_CYCLE(US) (US * 24) 12*91f16700Schasinglulu 13*91f16700Schasinglulu #define SYST_CST 0xe000e010 14*91f16700Schasinglulu /* enable counter */ 15*91f16700Schasinglulu #define ENABLE (1 << 0) 16*91f16700Schasinglulu /* count down to 0 does not cause SysTick exception to pend */ 17*91f16700Schasinglulu #define TICKINT (1 << 1) 18*91f16700Schasinglulu /* core clock used for SysTick */ 19*91f16700Schasinglulu #define CLKSOURCE (1 << 2) 20*91f16700Schasinglulu 21*91f16700Schasinglulu #define COUNTFLAG (1 << 16) 22*91f16700Schasinglulu #define SYST_RVR 0xe000e014 23*91f16700Schasinglulu #define MAX_VALUE 0xffffff 24*91f16700Schasinglulu #define MAX_USECS (MAX_VALUE / US_TO_CYCLE(1)) 25*91f16700Schasinglulu #define SYST_CVR 0xe000e018 26*91f16700Schasinglulu #define SYST_CALIB 0xe000e01c 27*91f16700Schasinglulu 28*91f16700Schasinglulu unsigned int remaining_usecs; 29*91f16700Schasinglulu 30*91f16700Schasinglulu static inline void stopwatch_set_usecs(void) 31*91f16700Schasinglulu { 32*91f16700Schasinglulu unsigned int cycle; 33*91f16700Schasinglulu unsigned int usecs = MIN(MAX_USECS, remaining_usecs); 34*91f16700Schasinglulu 35*91f16700Schasinglulu remaining_usecs -= usecs; 36*91f16700Schasinglulu cycle = US_TO_CYCLE(usecs); 37*91f16700Schasinglulu mmio_write_32(SYST_RVR, cycle); 38*91f16700Schasinglulu mmio_write_32(SYST_CVR, 0); 39*91f16700Schasinglulu 40*91f16700Schasinglulu mmio_write_32(SYST_CST, ENABLE | TICKINT | CLKSOURCE); 41*91f16700Schasinglulu } 42*91f16700Schasinglulu 43*91f16700Schasinglulu void stopwatch_init_usecs_expire(unsigned int usecs) 44*91f16700Schasinglulu { 45*91f16700Schasinglulu /* 46*91f16700Schasinglulu * Enter an inifite loop if the stopwatch is in use. This will allow the 47*91f16700Schasinglulu * state to be analyzed with a debugger. 48*91f16700Schasinglulu */ 49*91f16700Schasinglulu if (mmio_read_32(SYST_CST) & ENABLE) 50*91f16700Schasinglulu while (1) 51*91f16700Schasinglulu ; 52*91f16700Schasinglulu 53*91f16700Schasinglulu remaining_usecs = usecs; 54*91f16700Schasinglulu stopwatch_set_usecs(); 55*91f16700Schasinglulu } 56*91f16700Schasinglulu 57*91f16700Schasinglulu int stopwatch_expired(void) 58*91f16700Schasinglulu { 59*91f16700Schasinglulu int val = mmio_read_32(SYST_CST); 60*91f16700Schasinglulu if ((val & COUNTFLAG) || !(val & ENABLE)) { 61*91f16700Schasinglulu if (!remaining_usecs) 62*91f16700Schasinglulu return 1; 63*91f16700Schasinglulu 64*91f16700Schasinglulu stopwatch_set_usecs(); 65*91f16700Schasinglulu } 66*91f16700Schasinglulu 67*91f16700Schasinglulu return 0; 68*91f16700Schasinglulu } 69*91f16700Schasinglulu 70*91f16700Schasinglulu void stopwatch_reset(void) 71*91f16700Schasinglulu { 72*91f16700Schasinglulu mmio_clrbits_32(SYST_CST, ENABLE); 73*91f16700Schasinglulu remaining_usecs = 0; 74*91f16700Schasinglulu } 75