195c3f422SLin Huang /* 295c3f422SLin Huang * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 395c3f422SLin Huang * 4*82cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 595c3f422SLin Huang */ 695c3f422SLin Huang 795c3f422SLin Huang #include <m0_param.h> 895c3f422SLin Huang #include "rk3399_mcu.h" 995c3f422SLin Huang 1095c3f422SLin Huang /* use 24MHz SysTick */ 1195c3f422SLin Huang #define US_TO_CYCLE(US) (US * 24) 1295c3f422SLin Huang 1395c3f422SLin Huang #define SYST_CST 0xe000e010 1495c3f422SLin Huang /* enable counter */ 1595c3f422SLin Huang #define ENABLE (1 << 0) 1695c3f422SLin Huang /* count down to 0 does not cause SysTick exception to pend */ 1795c3f422SLin Huang #define TICKINT (1 << 1) 1895c3f422SLin Huang /* core clock used for SysTick */ 1995c3f422SLin Huang #define CLKSOURCE (1 << 2) 2095c3f422SLin Huang 2195c3f422SLin Huang #define COUNTFLAG (1 << 16) 2295c3f422SLin Huang #define SYST_RVR 0xe000e014 2395c3f422SLin Huang #define MAX_VALUE 0xffffff 2495c3f422SLin Huang #define MAX_USECS (MAX_VALUE / US_TO_CYCLE(1)) 2595c3f422SLin Huang #define SYST_CVR 0xe000e018 2695c3f422SLin Huang #define SYST_CALIB 0xe000e01c 2795c3f422SLin Huang 2895c3f422SLin Huang unsigned int remaining_usecs; 2995c3f422SLin Huang stopwatch_set_usecs(void)3095c3f422SLin Huangstatic inline void stopwatch_set_usecs(void) 3195c3f422SLin Huang { 3295c3f422SLin Huang unsigned int cycle; 3395c3f422SLin Huang unsigned int usecs = MIN(MAX_USECS, remaining_usecs); 3495c3f422SLin Huang 3595c3f422SLin Huang remaining_usecs -= usecs; 3695c3f422SLin Huang cycle = US_TO_CYCLE(usecs); 3795c3f422SLin Huang mmio_write_32(SYST_RVR, cycle); 3895c3f422SLin Huang mmio_write_32(SYST_CVR, 0); 3995c3f422SLin Huang 4095c3f422SLin Huang mmio_write_32(SYST_CST, ENABLE | TICKINT | CLKSOURCE); 4195c3f422SLin Huang } 4295c3f422SLin Huang stopwatch_init_usecs_expire(unsigned int usecs)4395c3f422SLin Huangvoid stopwatch_init_usecs_expire(unsigned int usecs) 4495c3f422SLin Huang { 4595c3f422SLin Huang /* 4695c3f422SLin Huang * Enter an inifite loop if the stopwatch is in use. This will allow the 4795c3f422SLin Huang * state to be analyzed with a debugger. 4895c3f422SLin Huang */ 4995c3f422SLin Huang if (mmio_read_32(SYST_CST) & ENABLE) 5095c3f422SLin Huang while (1) 5195c3f422SLin Huang ; 5295c3f422SLin Huang 5395c3f422SLin Huang remaining_usecs = usecs; 5495c3f422SLin Huang stopwatch_set_usecs(); 5595c3f422SLin Huang } 5695c3f422SLin Huang stopwatch_expired(void)5795c3f422SLin Huangint stopwatch_expired(void) 5895c3f422SLin Huang { 5995c3f422SLin Huang int val = mmio_read_32(SYST_CST); 6095c3f422SLin Huang if ((val & COUNTFLAG) || !(val & ENABLE)) { 6195c3f422SLin Huang if (!remaining_usecs) 6295c3f422SLin Huang return 1; 6395c3f422SLin Huang 6495c3f422SLin Huang stopwatch_set_usecs(); 6595c3f422SLin Huang } 6695c3f422SLin Huang 6795c3f422SLin Huang return 0; 6895c3f422SLin Huang } 6995c3f422SLin Huang stopwatch_reset(void)7095c3f422SLin Huangvoid stopwatch_reset(void) 7195c3f422SLin Huang { 7295c3f422SLin Huang mmio_clrbits_32(SYST_CST, ENABLE); 7395c3f422SLin Huang remaining_usecs = 0; 7495c3f422SLin Huang } 75