blob: 695bdd7a5cc0a87da08403039fc1337a06d5fe55 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Vikas Manocha33913c52014-11-18 10:42:22 -08002/*
Patrice Chotardcc551162017-10-23 09:53:59 +02003 * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
4 * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
Vikas Manocha33913c52014-11-18 10:42:22 -08005 */
6
7#include <common.h>
Simon Glass495a5dc2019-11-14 12:57:30 -07008#include <time.h>
Vikas Manocha33913c52014-11-18 10:42:22 -08009#include <asm/io.h>
10#include <asm/arch-stv0991/hardware.h>
11#include <asm/arch-stv0991/stv0991_cgu.h>
12#include <asm/arch-stv0991/stv0991_gpt.h>
13
14static struct stv0991_cgu_regs *const stv0991_cgu_regs = \
15 (struct stv0991_cgu_regs *) (CGU_BASE_ADDR);
16
17#define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING)
18#define GPT_RESOLUTION (CONFIG_STV0991_HZ_CLOCK / CONFIG_STV0991_HZ)
19
20DECLARE_GLOBAL_DATA_PTR;
21
22#define timestamp gd->arch.tbl
23#define lastdec gd->arch.lastinc
24
Patrick Delaunay9858a602018-10-05 11:33:52 +020025static ulong get_timer_masked(void);
26
Vikas Manocha33913c52014-11-18 10:42:22 -080027int timer_init(void)
28{
29 /* Timer1 clock configuration */
30 writel(TIMER1_CLK_CFG, &stv0991_cgu_regs->tim_freq);
31 writel(readl(&stv0991_cgu_regs->cgu_enable_2) |
32 TIMER1_CLK_EN, &stv0991_cgu_regs->cgu_enable_2);
33
34 /* Stop the timer */
35 writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
36 writel(GPT_PRESCALER_128, &gpt1_regs_ptr->psc);
37 /* Configure timer for auto-reload */
38 writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD,
39 &gpt1_regs_ptr->cr1);
40
41 /* load value for free running */
42 writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr);
43
44 /* start timer */
45 writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN,
46 &gpt1_regs_ptr->cr1);
47
48 /* Reset the timer */
49 lastdec = READ_TIMER();
50 timestamp = 0;
51
52 return 0;
53}
54
55/*
56 * timer without interrupts
57 */
58ulong get_timer(ulong base)
59{
60 return (get_timer_masked() / GPT_RESOLUTION) - base;
61}
62
63void __udelay(unsigned long usec)
64{
65 ulong tmo;
66 ulong start = get_timer_masked();
67 ulong tenudelcnt = CONFIG_STV0991_HZ_CLOCK / (1000 * 100);
68 ulong rndoff;
69
70 rndoff = (usec % 10) ? 1 : 0;
71
72 /* tenudelcnt timer tick gives 10 microsecconds delay */
73 tmo = ((usec / 10) + rndoff) * tenudelcnt;
74
75 while ((ulong) (get_timer_masked() - start) < tmo)
76 ;
77}
78
Patrick Delaunay9858a602018-10-05 11:33:52 +020079static ulong get_timer_masked(void)
Vikas Manocha33913c52014-11-18 10:42:22 -080080{
81 ulong now = READ_TIMER();
82
83 if (now >= lastdec) {
84 /* normal mode */
85 timestamp += now - lastdec;
86 } else {
87 /* we have an overflow ... */
88 timestamp += now + GPT_FREE_RUNNING - lastdec;
89 }
90 lastdec = now;
91
92 return timestamp;
93}
94
Vikas Manocha33913c52014-11-18 10:42:22 -080095/*
96 * This function is derived from PowerPC code (read timebase as long long).
97 * On ARM it just returns the timer value.
98 */
99unsigned long long get_ticks(void)
100{
101 return get_timer(0);
102}
103
104/*
105 * This function is derived from PowerPC code (timebase clock frequency).
106 * On ARM it returns the number of timer ticks per second.
107 */
108ulong get_tbclk(void)
109{
110 return CONFIG_STV0991_HZ;
111}