xref: /rk3399_ARM-atf/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c (revision f132b4a05b23916c1101add4bd6d973a99983719)
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 Huang static 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 Huang void 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 Huang int 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 Huang void stopwatch_reset(void)
7195c3f422SLin Huang {
7295c3f422SLin Huang 	mmio_clrbits_32(SYST_CST, ENABLE);
7395c3f422SLin Huang 	remaining_usecs = 0;
7495c3f422SLin Huang }
75