summaryrefslogtreecommitdiff
path: root/arch/mips/mach-jz47xx/jz4780/timer.c
blob: 82bb9e8c3bfafc72ced6d19428e7530fa0bb327f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
// SPDX-License-Identifier: GPL-2.0+
/*
 * JZ4780 timer
 *
 * Copyright (c) 2013 Imagination Technologies
 * Author: Paul Burton <paul.burton@imgtec.com>
 */

#include <config.h>
#include <common.h>
#include <div64.h>
#include <init.h>
#include <irq_func.h>
#include <time.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <mach/jz4780.h>

#define TCU_TSR		0x1C	/* Timer Stop Register */
#define TCU_TSSR	0x2C	/* Timer Stop Set Register */
#define TCU_TSCR	0x3C	/* Timer Stop Clear Register */
#define TCU_TER		0x10	/* Timer Counter Enable Register */
#define TCU_TESR	0x14	/* Timer Counter Enable Set Register */
#define TCU_TECR	0x18	/* Timer Counter Enable Clear Register */
#define TCU_TFR		0x20	/* Timer Flag Register */
#define TCU_TFSR	0x24	/* Timer Flag Set Register */
#define TCU_TFCR	0x28	/* Timer Flag Clear Register */
#define TCU_TMR		0x30	/* Timer Mask Register */
#define TCU_TMSR	0x34	/* Timer Mask Set Register */
#define TCU_TMCR	0x38	/* Timer Mask Clear Register */
/* n = 0,1,2,3,4,5 */
#define TCU_TDFR(n)	(0x40 + (n) * 0x10)	/* Timer Data Full Reg */
#define TCU_TDHR(n)	(0x44 + (n) * 0x10)	/* Timer Data Half Reg */
#define TCU_TCNT(n)	(0x48 + (n) * 0x10)	/* Timer Counter Reg */
#define TCU_TCSR(n)	(0x4C + (n) * 0x10)	/* Timer Control Reg */

#define TCU_OSTCNTL	0xe4
#define TCU_OSTCNTH	0xe8
#define TCU_OSTCSR	0xec
#define TCU_OSTCNTHBUF	0xfc

/* Register definitions */
#define TCU_TCSR_PWM_SD		BIT(9)
#define TCU_TCSR_PWM_INITL_HIGH	BIT(8)
#define TCU_TCSR_PWM_EN		BIT(7)
#define TCU_TCSR_PRESCALE_BIT	3
#define TCU_TCSR_PRESCALE_MASK	(0x7 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_PRESCALE1	(0x0 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_PRESCALE4	(0x1 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_PRESCALE16	(0x2 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_PRESCALE64	(0x3 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_PRESCALE256	(0x4 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_PRESCALE1024	(0x5 << TCU_TCSR_PRESCALE_BIT)
#define TCU_TCSR_EXT_EN		BIT(2)
#define TCU_TCSR_RTC_EN		BIT(1)
#define TCU_TCSR_PCK_EN		BIT(0)

#define TCU_TER_TCEN5		BIT(5)
#define TCU_TER_TCEN4		BIT(4)
#define TCU_TER_TCEN3		BIT(3)
#define TCU_TER_TCEN2		BIT(2)
#define TCU_TER_TCEN1		BIT(1)
#define TCU_TER_TCEN0		BIT(0)

#define TCU_TESR_TCST5		BIT(5)
#define TCU_TESR_TCST4		BIT(4)
#define TCU_TESR_TCST3		BIT(3)
#define TCU_TESR_TCST2		BIT(2)
#define TCU_TESR_TCST1		BIT(1)
#define TCU_TESR_TCST0		BIT(0)

#define TCU_TECR_TCCL5		BIT(5)
#define TCU_TECR_TCCL4		BIT(4)
#define TCU_TECR_TCCL3		BIT(3)
#define TCU_TECR_TCCL2		BIT(2)
#define TCU_TECR_TCCL1		BIT(1)
#define TCU_TECR_TCCL0		BIT(0)

#define TCU_TFR_HFLAG5		BIT(21)
#define TCU_TFR_HFLAG4		BIT(20)
#define TCU_TFR_HFLAG3		BIT(19)
#define TCU_TFR_HFLAG2		BIT(18)
#define TCU_TFR_HFLAG1		BIT(17)
#define TCU_TFR_HFLAG0		BIT(16)
#define TCU_TFR_FFLAG5		BIT(5)
#define TCU_TFR_FFLAG4		BIT(4)
#define TCU_TFR_FFLAG3		BIT(3)
#define TCU_TFR_FFLAG2		BIT(2)
#define TCU_TFR_FFLAG1		BIT(1)
#define TCU_TFR_FFLAG0		BIT(0)

#define TCU_TFSR_HFLAG5		BIT(21)
#define TCU_TFSR_HFLAG4		BIT(20)
#define TCU_TFSR_HFLAG3		BIT(19)
#define TCU_TFSR_HFLAG2		BIT(18)
#define TCU_TFSR_HFLAG1		BIT(17)
#define TCU_TFSR_HFLAG0		BIT(16)
#define TCU_TFSR_FFLAG5		BIT(5)
#define TCU_TFSR_FFLAG4		BIT(4)
#define TCU_TFSR_FFLAG3		BIT(3)
#define TCU_TFSR_FFLAG2		BIT(2)
#define TCU_TFSR_FFLAG1		BIT(1)
#define TCU_TFSR_FFLAG0		BIT(0)

#define TCU_TFCR_HFLAG5		BIT(21)
#define TCU_TFCR_HFLAG4		BIT(20)
#define TCU_TFCR_HFLAG3		BIT(19)
#define TCU_TFCR_HFLAG2		BIT(18)
#define TCU_TFCR_HFLAG1		BIT(17)
#define TCU_TFCR_HFLAG0		BIT(16)
#define TCU_TFCR_FFLAG5		BIT(5)
#define TCU_TFCR_FFLAG4		BIT(4)
#define TCU_TFCR_FFLAG3		BIT(3)
#define TCU_TFCR_FFLAG2		BIT(2)
#define TCU_TFCR_FFLAG1		BIT(1)
#define TCU_TFCR_FFLAG0		BIT(0)

#define TCU_TMR_HMASK5		BIT(21)
#define TCU_TMR_HMASK4		BIT(20)
#define TCU_TMR_HMASK3		BIT(19)
#define TCU_TMR_HMASK2		BIT(18)
#define TCU_TMR_HMASK1		BIT(17)
#define TCU_TMR_HMASK0		BIT(16)
#define TCU_TMR_FMASK5		BIT(5)
#define TCU_TMR_FMASK4		BIT(4)
#define TCU_TMR_FMASK3		BIT(3)
#define TCU_TMR_FMASK2		BIT(2)
#define TCU_TMR_FMASK1		BIT(1)
#define TCU_TMR_FMASK0		BIT(0)

#define TCU_TMSR_HMST5		BIT(21)
#define TCU_TMSR_HMST4		BIT(20)
#define TCU_TMSR_HMST3		BIT(19)
#define TCU_TMSR_HMST2		BIT(18)
#define TCU_TMSR_HMST1		BIT(17)
#define TCU_TMSR_HMST0		BIT(16)
#define TCU_TMSR_FMST5		BIT(5)
#define TCU_TMSR_FMST4		BIT(4)
#define TCU_TMSR_FMST3		BIT(3)
#define TCU_TMSR_FMST2		BIT(2)
#define TCU_TMSR_FMST1		BIT(1)
#define TCU_TMSR_FMST0		BIT(0)

#define TCU_TMCR_HMCL5		BIT(21)
#define TCU_TMCR_HMCL4		BIT(20)
#define TCU_TMCR_HMCL3		BIT(19)
#define TCU_TMCR_HMCL2		BIT(18)
#define TCU_TMCR_HMCL1		BIT(17)
#define TCU_TMCR_HMCL0		BIT(16)
#define TCU_TMCR_FMCL5		BIT(5)
#define TCU_TMCR_FMCL4		BIT(4)
#define TCU_TMCR_FMCL3		BIT(3)
#define TCU_TMCR_FMCL2		BIT(2)
#define TCU_TMCR_FMCL1		BIT(1)
#define TCU_TMCR_FMCL0		BIT(0)

#define TCU_TSR_WDTS		BIT(16)
#define TCU_TSR_STOP5		BIT(5)
#define TCU_TSR_STOP4		BIT(4)
#define TCU_TSR_STOP3		BIT(3)
#define TCU_TSR_STOP2		BIT(2)
#define TCU_TSR_STOP1		BIT(1)
#define TCU_TSR_STOP0		BIT(0)

#define TCU_TSSR_WDTSS		BIT(16)
#define TCU_TSSR_STPS5		BIT(5)
#define TCU_TSSR_STPS4		BIT(4)
#define TCU_TSSR_STPS3		BIT(3)
#define TCU_TSSR_STPS2		BIT(2)
#define TCU_TSSR_STPS1		BIT(1)
#define TCU_TSSR_STPS0		BIT(0)

#define TCU_TSSR_WDTSC		BIT(16)
#define TCU_TSSR_STPC5		BIT(5)
#define TCU_TSSR_STPC4		BIT(4)
#define TCU_TSSR_STPC3		BIT(3)
#define TCU_TSSR_STPC2		BIT(2)
#define TCU_TSSR_STPC1		BIT(1)
#define TCU_TSSR_STPC0		BIT(0)

#define TER_OSTEN		BIT(15)

#define OSTCSR_CNT_MD		BIT(15)
#define OSTCSR_SD		BIT(9)
#define OSTCSR_PRESCALE_16	(0x2 << 3)
#define OSTCSR_EXT_EN		BIT(2)

int timer_init(void)
{
	void __iomem *regs = (void __iomem *)TCU_BASE;

	writel(OSTCSR_SD, regs + TCU_OSTCSR);
	reset_timer();
	writel(OSTCSR_CNT_MD | OSTCSR_EXT_EN | OSTCSR_PRESCALE_16,
	       regs + TCU_OSTCSR);
	writew(TER_OSTEN, regs + TCU_TESR);
	return 0;
}

void reset_timer(void)
{
	void __iomem *regs = (void __iomem *)TCU_BASE;

	writel(0, regs + TCU_OSTCNTH);
	writel(0, regs + TCU_OSTCNTL);
}

static u64 get_timer64(void)
{
	void __iomem *regs = (void __iomem *)TCU_BASE;
	u32 low = readl(regs + TCU_OSTCNTL);
	u32 high = readl(regs + TCU_OSTCNTHBUF);

	return ((u64)high << 32) | low;
}

ulong get_timer(ulong base)
{
	return lldiv(get_timer64(), 3000) - base;
}

void __udelay(unsigned long usec)
{
	/* OST count increments at 3MHz */
	u64 end = get_timer64() + ((u64)usec * 3);

	while (get_timer64() < end)
		;
}

unsigned long long get_ticks(void)
{
	return get_timer64();
}

void jz4780_tcu_wdt_start(void)
{
	void __iomem *tcu_regs = (void __iomem *)TCU_BASE;

	/* Enable WDT clock */
	writel(TCU_TSSR_WDTSC, tcu_regs + TCU_TSCR);
}