blob: f6dcbf199c7497283fc0fb3399c9db494c5d6f3c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Macpaul Lin83dbca72011-10-11 22:33:18 +00002/*
3 * (C) Copyright 2009 Faraday Technology
4 * Po-Yu Chuang <ratbert@faraday-tech.com>
5 *
6 * Copyright (C) 2011 Andes Technology Corporation
7 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
8 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
Macpaul Lin83dbca72011-10-11 22:33:18 +00009 */
rick6d564b82017-05-17 10:59:20 +080010#ifndef CONFIG_TIMER
Macpaul Lin83dbca72011-10-11 22:33:18 +000011#include <common.h>
Tom Rini8c70baa2021-12-14 13:36:40 -050012#include <clock_legacy.h>
Simon Glass97589732020-05-10 11:40:02 -060013#include <init.h>
Simon Glass9b61c7c2019-11-14 12:57:41 -070014#include <irq_func.h>
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Simon Glass495a5dc2019-11-14 12:57:30 -070016#include <time.h>
Macpaul Lin83dbca72011-10-11 22:33:18 +000017#include <asm/io.h>
18#include <faraday/fttmr010.h>
Simon Glassdbd79542020-05-10 11:40:11 -060019#include <linux/delay.h>
Macpaul Lin83dbca72011-10-11 22:33:18 +000020
21static ulong timestamp;
22static ulong lastdec;
23
24int timer_init(void)
25{
Macpaul Linf4a7b802011-11-23 13:56:50 +080026 struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
Macpaul Lin83dbca72011-10-11 22:33:18 +000027 unsigned int cr;
28
29 debug("%s()\n", __func__);
30
31 /* disable timers */
32 writel(0, &tmr->cr);
33
34#ifdef CONFIG_FTTMR010_EXT_CLK
35 /* use 32768Hz oscillator for RTC, WDT, TIMER */
36 ftpmu010_32768osc_enable();
37#endif
38
39 /* setup timer */
40 writel(TIMER_LOAD_VAL, &tmr->timer3_load);
41 writel(TIMER_LOAD_VAL, &tmr->timer3_counter);
42 writel(0, &tmr->timer3_match1);
43 writel(0, &tmr->timer3_match2);
44
45 /* we don't want timer to issue interrupts */
46 writel(FTTMR010_TM3_MATCH1 |
47 FTTMR010_TM3_MATCH2 |
48 FTTMR010_TM3_OVERFLOW,
49 &tmr->interrupt_mask);
50
51 cr = readl(&tmr->cr);
52#ifdef CONFIG_FTTMR010_EXT_CLK
53 cr |= FTTMR010_TM3_CLOCK; /* use external clock */
54#endif
55 cr |= FTTMR010_TM3_ENABLE;
56 writel(cr, &tmr->cr);
57
58 /* init the timestamp and lastdec value */
59 reset_timer_masked();
60
61 return 0;
62}
63
64/*
65 * timer without interrupts
66 */
67
68/*
69 * reset time
70 */
71void reset_timer_masked(void)
72{
Macpaul Linf4a7b802011-11-23 13:56:50 +080073 struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
Macpaul Lin83dbca72011-10-11 22:33:18 +000074
75 /* capure current decrementer value time */
76#ifdef CONFIG_FTTMR010_EXT_CLK
77 lastdec = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
78#else
Axel Lin55edeb52013-07-08 14:29:52 +080079 lastdec = readl(&tmr->timer3_counter) /
Tom Rini8c70baa2021-12-14 13:36:40 -050080 (get_board_sys_clk() / 2 / CONFIG_SYS_HZ);
Macpaul Lin83dbca72011-10-11 22:33:18 +000081#endif
82 timestamp = 0; /* start "advancing" time stamp from 0 */
83
84 debug("%s(): lastdec = %lx\n", __func__, lastdec);
85}
86
87void reset_timer(void)
88{
89 debug("%s()\n", __func__);
90 reset_timer_masked();
91}
92
93/*
94 * return timer ticks
95 */
96ulong get_timer_masked(void)
97{
Macpaul Linf4a7b802011-11-23 13:56:50 +080098 struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
Macpaul Lin83dbca72011-10-11 22:33:18 +000099
100 /* current tick value */
101#ifdef CONFIG_FTTMR010_EXT_CLK
102 ulong now = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
103#else
Axel Lin55edeb52013-07-08 14:29:52 +0800104 ulong now = readl(&tmr->timer3_counter) /
Tom Rini8c70baa2021-12-14 13:36:40 -0500105 (get_board_sys_clk() / 2 / CONFIG_SYS_HZ);
Macpaul Lin83dbca72011-10-11 22:33:18 +0000106#endif
107
108 debug("%s(): now = %lx, lastdec = %lx\n", __func__, now, lastdec);
109
110 if (lastdec >= now) {
111 /*
112 * normal mode (non roll)
113 * move stamp fordward with absoulte diff ticks
114 */
115 timestamp += lastdec - now;
116 } else {
117 /*
118 * we have overflow of the count down timer
119 *
120 * nts = ts + ld + (TLV - now)
121 * ts=old stamp, ld=time that passed before passing through -1
122 * (TLV-now) amount of time after passing though -1
123 * nts = new "advancing time stamp"...it could also roll and
124 * cause problems.
125 */
126 timestamp += lastdec + TIMER_LOAD_VAL - now;
127 }
128
129 lastdec = now;
130
131 debug("%s() returns %lx\n", __func__, timestamp);
132
133 return timestamp;
134}
135
136/*
137 * return difference between timer ticks and base
138 */
139ulong get_timer(ulong base)
140{
141 debug("%s(%lx)\n", __func__, base);
142 return get_timer_masked() - base;
143}
144
145void set_timer(ulong t)
146{
147 debug("%s(%lx)\n", __func__, t);
148 timestamp = t;
149}
150
151/* delay x useconds AND preserve advance timestamp value */
152void __udelay(unsigned long usec)
153{
Macpaul Linf4a7b802011-11-23 13:56:50 +0800154 struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
Macpaul Lin83dbca72011-10-11 22:33:18 +0000155
156#ifdef CONFIG_FTTMR010_EXT_CLK
157 long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
158#else
Tom Rini8c70baa2021-12-14 13:36:40 -0500159 long tmo = usec * ((get_board_sys_clk() / 2) / 1000) / 1000;
Macpaul Lin83dbca72011-10-11 22:33:18 +0000160#endif
161 unsigned long now, last = readl(&tmr->timer3_counter);
162
163 debug("%s(%lu)\n", __func__, usec);
164 while (tmo > 0) {
165 now = readl(&tmr->timer3_counter);
166 if (now > last) /* count down timer overflow */
167 tmo -= TIMER_LOAD_VAL + last - now;
168 else
169 tmo -= last - now;
170 last = now;
171 }
172}
173
174/*
175 * This function is derived from PowerPC code (read timebase as long long).
176 * On ARM it just returns the timer value.
177 */
178unsigned long long get_ticks(void)
179{
180 debug("%s()\n", __func__);
181 return get_timer(0);
182}
183
184/*
185 * This function is derived from PowerPC code (timebase clock frequency).
186 * On ARM it returns the number of timer ticks per second.
187 */
188ulong get_tbclk(void)
189{
190 debug("%s()\n", __func__);
191#ifdef CONFIG_FTTMR010_EXT_CLK
192 return CONFIG_SYS_HZ;
193#else
Tom Rini8c70baa2021-12-14 13:36:40 -0500194 return get_board_sys_clk();
Macpaul Lin83dbca72011-10-11 22:33:18 +0000195#endif
196}
rick6d564b82017-05-17 10:59:20 +0800197#endif /* CONFIG_TIMER */