Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clocksource/mxs_timer.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0+
2
//
3
// Copyright (C) 2000-2001 Deep Blue Solutions
4
// Copyright (C) 2002 Shane Nay ([email protected])
5
// Copyright (C) 2006-2007 Pavel Pisa ([email protected])
6
// Copyright (C) 2008 Juergen Beisert ([email protected])
7
// Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
8
9
#include <linux/err.h>
10
#include <linux/interrupt.h>
11
#include <linux/irq.h>
12
#include <linux/clockchips.h>
13
#include <linux/clk.h>
14
#include <linux/of.h>
15
#include <linux/of_address.h>
16
#include <linux/of_irq.h>
17
#include <linux/stmp_device.h>
18
#include <linux/sched_clock.h>
19
20
/*
21
* There are 2 versions of the timrot on Freescale MXS-based SoCs.
22
* The v1 on MX23 only gets 16 bits counter, while v2 on MX28
23
* extends the counter to 32 bits.
24
*
25
* The implementation uses two timers, one for clock_event and
26
* another for clocksource. MX28 uses timrot 0 and 1, while MX23
27
* uses 0 and 2.
28
*/
29
30
#define MX23_TIMROT_VERSION_OFFSET 0x0a0
31
#define MX28_TIMROT_VERSION_OFFSET 0x120
32
#define BP_TIMROT_MAJOR_VERSION 24
33
#define BV_TIMROT_VERSION_1 0x01
34
#define BV_TIMROT_VERSION_2 0x02
35
#define timrot_is_v1() (timrot_major_version == BV_TIMROT_VERSION_1)
36
37
/*
38
* There are 4 registers for each timrotv2 instance, and 2 registers
39
* for each timrotv1. So address step 0x40 in macros below strides
40
* one instance of timrotv2 while two instances of timrotv1.
41
*
42
* As the result, HW_TIMROT_XXXn(1) defines the address of timrot1
43
* on MX28 while timrot2 on MX23.
44
*/
45
/* common between v1 and v2 */
46
#define HW_TIMROT_ROTCTRL 0x00
47
#define HW_TIMROT_TIMCTRLn(n) (0x20 + (n) * 0x40)
48
/* v1 only */
49
#define HW_TIMROT_TIMCOUNTn(n) (0x30 + (n) * 0x40)
50
/* v2 only */
51
#define HW_TIMROT_RUNNING_COUNTn(n) (0x30 + (n) * 0x40)
52
#define HW_TIMROT_FIXED_COUNTn(n) (0x40 + (n) * 0x40)
53
54
#define BM_TIMROT_TIMCTRLn_RELOAD (1 << 6)
55
#define BM_TIMROT_TIMCTRLn_UPDATE (1 << 7)
56
#define BM_TIMROT_TIMCTRLn_IRQ_EN (1 << 14)
57
#define BM_TIMROT_TIMCTRLn_IRQ (1 << 15)
58
#define BP_TIMROT_TIMCTRLn_SELECT 0
59
#define BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL 0x8
60
#define BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL 0xb
61
#define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS 0xf
62
63
static struct clock_event_device mxs_clockevent_device;
64
65
static void __iomem *mxs_timrot_base;
66
static u32 timrot_major_version;
67
68
static inline void timrot_irq_disable(void)
69
{
70
__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base +
71
HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
72
}
73
74
static inline void timrot_irq_enable(void)
75
{
76
__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base +
77
HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_SET);
78
}
79
80
static void timrot_irq_acknowledge(void)
81
{
82
__raw_writel(BM_TIMROT_TIMCTRLn_IRQ, mxs_timrot_base +
83
HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
84
}
85
86
static u64 timrotv1_get_cycles(struct clocksource *cs)
87
{
88
return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
89
& 0xffff0000) >> 16);
90
}
91
92
static int timrotv1_set_next_event(unsigned long evt,
93
struct clock_event_device *dev)
94
{
95
/* timrot decrements the count */
96
__raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0));
97
98
return 0;
99
}
100
101
static int timrotv2_set_next_event(unsigned long evt,
102
struct clock_event_device *dev)
103
{
104
/* timrot decrements the count */
105
__raw_writel(evt, mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(0));
106
107
return 0;
108
}
109
110
static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id)
111
{
112
struct clock_event_device *evt = dev_id;
113
114
timrot_irq_acknowledge();
115
evt->event_handler(evt);
116
117
return IRQ_HANDLED;
118
}
119
120
static void mxs_irq_clear(char *state)
121
{
122
/* Disable interrupt in timer module */
123
timrot_irq_disable();
124
125
/* Set event time into the furthest future */
126
if (timrot_is_v1())
127
__raw_writel(0xffff, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
128
else
129
__raw_writel(0xffffffff,
130
mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
131
132
/* Clear pending interrupt */
133
timrot_irq_acknowledge();
134
pr_debug("%s: changing mode to %s\n", __func__, state);
135
}
136
137
static int mxs_shutdown(struct clock_event_device *evt)
138
{
139
mxs_irq_clear("shutdown");
140
141
return 0;
142
}
143
144
static int mxs_set_oneshot(struct clock_event_device *evt)
145
{
146
if (clockevent_state_oneshot(evt))
147
mxs_irq_clear("oneshot");
148
timrot_irq_enable();
149
return 0;
150
}
151
152
static struct clock_event_device mxs_clockevent_device = {
153
.name = "mxs_timrot",
154
.features = CLOCK_EVT_FEAT_ONESHOT,
155
.set_state_shutdown = mxs_shutdown,
156
.set_state_oneshot = mxs_set_oneshot,
157
.tick_resume = mxs_shutdown,
158
.set_next_event = timrotv2_set_next_event,
159
.rating = 200,
160
};
161
162
static int __init mxs_clockevent_init(struct clk *timer_clk)
163
{
164
if (timrot_is_v1())
165
mxs_clockevent_device.set_next_event = timrotv1_set_next_event;
166
mxs_clockevent_device.cpumask = cpumask_of(0);
167
clockevents_config_and_register(&mxs_clockevent_device,
168
clk_get_rate(timer_clk),
169
timrot_is_v1() ? 0xf : 0x2,
170
timrot_is_v1() ? 0xfffe : 0xfffffffe);
171
172
return 0;
173
}
174
175
static struct clocksource clocksource_mxs = {
176
.name = "mxs_timer",
177
.rating = 200,
178
.read = timrotv1_get_cycles,
179
.mask = CLOCKSOURCE_MASK(16),
180
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
181
};
182
183
static u64 notrace mxs_read_sched_clock_v2(void)
184
{
185
return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
186
}
187
188
static int __init mxs_clocksource_init(struct clk *timer_clk)
189
{
190
unsigned int c = clk_get_rate(timer_clk);
191
192
if (timrot_is_v1())
193
clocksource_register_hz(&clocksource_mxs, c);
194
else {
195
clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
196
"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
197
sched_clock_register(mxs_read_sched_clock_v2, 32, c);
198
}
199
200
return 0;
201
}
202
203
static int __init mxs_timer_init(struct device_node *np)
204
{
205
struct clk *timer_clk;
206
int irq, ret;
207
208
mxs_timrot_base = of_iomap(np, 0);
209
WARN_ON(!mxs_timrot_base);
210
211
timer_clk = of_clk_get(np, 0);
212
if (IS_ERR(timer_clk)) {
213
pr_err("%s: failed to get clk\n", __func__);
214
return PTR_ERR(timer_clk);
215
}
216
217
ret = clk_prepare_enable(timer_clk);
218
if (ret)
219
return ret;
220
221
/*
222
* Initialize timers to a known state
223
*/
224
stmp_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);
225
226
/* get timrot version */
227
timrot_major_version = __raw_readl(mxs_timrot_base +
228
(of_device_is_compatible(np, "fsl,imx23-timrot") ?
229
MX23_TIMROT_VERSION_OFFSET :
230
MX28_TIMROT_VERSION_OFFSET));
231
timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;
232
233
/* one for clock_event */
234
__raw_writel((timrot_is_v1() ?
235
BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
236
BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
237
BM_TIMROT_TIMCTRLn_UPDATE |
238
BM_TIMROT_TIMCTRLn_IRQ_EN,
239
mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
240
241
/* another for clocksource */
242
__raw_writel((timrot_is_v1() ?
243
BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
244
BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
245
BM_TIMROT_TIMCTRLn_RELOAD,
246
mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));
247
248
/* set clocksource timer fixed count to the maximum */
249
if (timrot_is_v1())
250
__raw_writel(0xffff,
251
mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
252
else
253
__raw_writel(0xffffffff,
254
mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
255
256
/* init and register the timer to the framework */
257
ret = mxs_clocksource_init(timer_clk);
258
if (ret)
259
return ret;
260
261
ret = mxs_clockevent_init(timer_clk);
262
if (ret)
263
return ret;
264
265
/* Make irqs happen */
266
irq = irq_of_parse_and_map(np, 0);
267
if (irq <= 0)
268
return -EINVAL;
269
270
return request_irq(irq, mxs_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
271
"MXS Timer Tick", &mxs_clockevent_device);
272
}
273
TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
274
275