xref: /openbmc/u-boot/arch/arm/cpu/armv7/stv0991/timer.c (revision 6180ea7e663893cb7330219367252cba471bf225)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
29fa32b12SVikas Manocha /*
31537d386SPatrice Chotard  * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
41537d386SPatrice Chotard  * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
59fa32b12SVikas Manocha  */
69fa32b12SVikas Manocha 
79fa32b12SVikas Manocha #include <common.h>
89fa32b12SVikas Manocha #include <asm/io.h>
99fa32b12SVikas Manocha #include <asm/arch-stv0991/hardware.h>
109fa32b12SVikas Manocha #include <asm/arch-stv0991/stv0991_cgu.h>
119fa32b12SVikas Manocha #include <asm/arch-stv0991/stv0991_gpt.h>
129fa32b12SVikas Manocha 
139fa32b12SVikas Manocha static struct stv0991_cgu_regs *const stv0991_cgu_regs = \
149fa32b12SVikas Manocha 				(struct stv0991_cgu_regs *) (CGU_BASE_ADDR);
159fa32b12SVikas Manocha 
169fa32b12SVikas Manocha #define READ_TIMER()	(readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING)
179fa32b12SVikas Manocha #define GPT_RESOLUTION	(CONFIG_STV0991_HZ_CLOCK / CONFIG_STV0991_HZ)
189fa32b12SVikas Manocha 
199fa32b12SVikas Manocha DECLARE_GLOBAL_DATA_PTR;
209fa32b12SVikas Manocha 
219fa32b12SVikas Manocha #define timestamp gd->arch.tbl
229fa32b12SVikas Manocha #define lastdec gd->arch.lastinc
239fa32b12SVikas Manocha 
24*6180ea7eSPatrick Delaunay static ulong get_timer_masked(void);
25*6180ea7eSPatrick Delaunay 
timer_init(void)269fa32b12SVikas Manocha int timer_init(void)
279fa32b12SVikas Manocha {
289fa32b12SVikas Manocha 	/* Timer1 clock configuration */
299fa32b12SVikas Manocha 	writel(TIMER1_CLK_CFG, &stv0991_cgu_regs->tim_freq);
309fa32b12SVikas Manocha 	writel(readl(&stv0991_cgu_regs->cgu_enable_2) |
319fa32b12SVikas Manocha 			TIMER1_CLK_EN, &stv0991_cgu_regs->cgu_enable_2);
329fa32b12SVikas Manocha 
339fa32b12SVikas Manocha 	/* Stop the timer */
349fa32b12SVikas Manocha 	writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
359fa32b12SVikas Manocha 	writel(GPT_PRESCALER_128, &gpt1_regs_ptr->psc);
369fa32b12SVikas Manocha 	/* Configure timer for auto-reload */
379fa32b12SVikas Manocha 	writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD,
389fa32b12SVikas Manocha 			&gpt1_regs_ptr->cr1);
399fa32b12SVikas Manocha 
409fa32b12SVikas Manocha 	/* load value for free running */
419fa32b12SVikas Manocha 	writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr);
429fa32b12SVikas Manocha 
439fa32b12SVikas Manocha 	/* start timer */
449fa32b12SVikas Manocha 	writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN,
459fa32b12SVikas Manocha 			&gpt1_regs_ptr->cr1);
469fa32b12SVikas Manocha 
479fa32b12SVikas Manocha 	/* Reset the timer */
489fa32b12SVikas Manocha 	lastdec = READ_TIMER();
499fa32b12SVikas Manocha 	timestamp = 0;
509fa32b12SVikas Manocha 
519fa32b12SVikas Manocha 	return 0;
529fa32b12SVikas Manocha }
539fa32b12SVikas Manocha 
549fa32b12SVikas Manocha /*
559fa32b12SVikas Manocha  * timer without interrupts
569fa32b12SVikas Manocha  */
get_timer(ulong base)579fa32b12SVikas Manocha ulong get_timer(ulong base)
589fa32b12SVikas Manocha {
599fa32b12SVikas Manocha 	return (get_timer_masked() / GPT_RESOLUTION) - base;
609fa32b12SVikas Manocha }
619fa32b12SVikas Manocha 
__udelay(unsigned long usec)629fa32b12SVikas Manocha void __udelay(unsigned long usec)
639fa32b12SVikas Manocha {
649fa32b12SVikas Manocha 	ulong tmo;
659fa32b12SVikas Manocha 	ulong start = get_timer_masked();
669fa32b12SVikas Manocha 	ulong tenudelcnt = CONFIG_STV0991_HZ_CLOCK / (1000 * 100);
679fa32b12SVikas Manocha 	ulong rndoff;
689fa32b12SVikas Manocha 
699fa32b12SVikas Manocha 	rndoff = (usec % 10) ? 1 : 0;
709fa32b12SVikas Manocha 
719fa32b12SVikas Manocha 	/* tenudelcnt timer tick gives 10 microsecconds delay */
729fa32b12SVikas Manocha 	tmo = ((usec / 10) + rndoff) * tenudelcnt;
739fa32b12SVikas Manocha 
749fa32b12SVikas Manocha 	while ((ulong) (get_timer_masked() - start) < tmo)
759fa32b12SVikas Manocha 		;
769fa32b12SVikas Manocha }
779fa32b12SVikas Manocha 
get_timer_masked(void)78*6180ea7eSPatrick Delaunay static ulong get_timer_masked(void)
799fa32b12SVikas Manocha {
809fa32b12SVikas Manocha 	ulong now = READ_TIMER();
819fa32b12SVikas Manocha 
829fa32b12SVikas Manocha 	if (now >= lastdec) {
839fa32b12SVikas Manocha 		/* normal mode */
849fa32b12SVikas Manocha 		timestamp += now - lastdec;
859fa32b12SVikas Manocha 	} else {
869fa32b12SVikas Manocha 		/* we have an overflow ... */
879fa32b12SVikas Manocha 		timestamp += now + GPT_FREE_RUNNING - lastdec;
889fa32b12SVikas Manocha 	}
899fa32b12SVikas Manocha 	lastdec = now;
909fa32b12SVikas Manocha 
919fa32b12SVikas Manocha 	return timestamp;
929fa32b12SVikas Manocha }
939fa32b12SVikas Manocha 
949fa32b12SVikas Manocha /*
959fa32b12SVikas Manocha  * This function is derived from PowerPC code (read timebase as long long).
969fa32b12SVikas Manocha  * On ARM it just returns the timer value.
979fa32b12SVikas Manocha  */
get_ticks(void)989fa32b12SVikas Manocha unsigned long long get_ticks(void)
999fa32b12SVikas Manocha {
1009fa32b12SVikas Manocha 	return get_timer(0);
1019fa32b12SVikas Manocha }
1029fa32b12SVikas Manocha 
1039fa32b12SVikas Manocha /*
1049fa32b12SVikas Manocha  * This function is derived from PowerPC code (timebase clock frequency).
1059fa32b12SVikas Manocha  * On ARM it returns the number of timer ticks per second.
1069fa32b12SVikas Manocha  */
get_tbclk(void)1079fa32b12SVikas Manocha ulong get_tbclk(void)
1089fa32b12SVikas Manocha {
1099fa32b12SVikas Manocha 	return CONFIG_STV0991_HZ;
1109fa32b12SVikas Manocha }
111