1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Rockchip timer support |
4 | * |
5 | * Copyright (C) Daniel Lezcano <daniel.lezcano@linaro.org> |
6 | */ |
7 | #include <linux/clk.h> |
8 | #include <linux/clockchips.h> |
9 | #include <linux/init.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/sched_clock.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/of.h> |
14 | #include <linux/of_address.h> |
15 | #include <linux/of_irq.h> |
16 | |
17 | #define TIMER_NAME "rk_timer" |
18 | |
19 | #define TIMER_LOAD_COUNT0 0x00 |
20 | #define TIMER_LOAD_COUNT1 0x04 |
21 | #define TIMER_CURRENT_VALUE0 0x08 |
22 | #define TIMER_CURRENT_VALUE1 0x0C |
23 | #define TIMER_CONTROL_REG3288 0x10 |
24 | #define TIMER_CONTROL_REG3399 0x1c |
25 | #define TIMER_INT_STATUS 0x18 |
26 | |
27 | #define TIMER_DISABLE 0x0 |
28 | #define TIMER_ENABLE 0x1 |
29 | #define TIMER_MODE_FREE_RUNNING (0 << 1) |
30 | #define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) |
31 | #define TIMER_INT_UNMASK (1 << 2) |
32 | |
33 | struct rk_timer { |
34 | void __iomem *base; |
35 | void __iomem *ctrl; |
36 | struct clk *clk; |
37 | struct clk *pclk; |
38 | u32 freq; |
39 | int irq; |
40 | }; |
41 | |
42 | struct rk_clkevt { |
43 | struct clock_event_device ce; |
44 | struct rk_timer timer; |
45 | }; |
46 | |
47 | static struct rk_clkevt *rk_clkevt; |
48 | static struct rk_timer *rk_clksrc; |
49 | |
50 | static inline struct rk_timer *rk_timer(struct clock_event_device *ce) |
51 | { |
52 | return &container_of(ce, struct rk_clkevt, ce)->timer; |
53 | } |
54 | |
55 | static inline void rk_timer_disable(struct rk_timer *timer) |
56 | { |
57 | writel_relaxed(TIMER_DISABLE, timer->ctrl); |
58 | } |
59 | |
60 | static inline void rk_timer_enable(struct rk_timer *timer, u32 flags) |
61 | { |
62 | writel_relaxed(TIMER_ENABLE | flags, timer->ctrl); |
63 | } |
64 | |
65 | static void rk_timer_update_counter(unsigned long cycles, |
66 | struct rk_timer *timer) |
67 | { |
68 | writel_relaxed(cycles, timer->base + TIMER_LOAD_COUNT0); |
69 | writel_relaxed(0, timer->base + TIMER_LOAD_COUNT1); |
70 | } |
71 | |
72 | static void rk_timer_interrupt_clear(struct rk_timer *timer) |
73 | { |
74 | writel_relaxed(1, timer->base + TIMER_INT_STATUS); |
75 | } |
76 | |
77 | static inline int rk_timer_set_next_event(unsigned long cycles, |
78 | struct clock_event_device *ce) |
79 | { |
80 | struct rk_timer *timer = rk_timer(ce); |
81 | |
82 | rk_timer_disable(timer); |
83 | rk_timer_update_counter(cycles, timer); |
84 | rk_timer_enable(timer, TIMER_MODE_USER_DEFINED_COUNT | |
85 | TIMER_INT_UNMASK); |
86 | return 0; |
87 | } |
88 | |
89 | static int rk_timer_shutdown(struct clock_event_device *ce) |
90 | { |
91 | struct rk_timer *timer = rk_timer(ce); |
92 | |
93 | rk_timer_disable(timer); |
94 | return 0; |
95 | } |
96 | |
97 | static int rk_timer_set_periodic(struct clock_event_device *ce) |
98 | { |
99 | struct rk_timer *timer = rk_timer(ce); |
100 | |
101 | rk_timer_disable(timer); |
102 | rk_timer_update_counter(cycles: timer->freq / HZ - 1, timer); |
103 | rk_timer_enable(timer, TIMER_MODE_FREE_RUNNING | TIMER_INT_UNMASK); |
104 | return 0; |
105 | } |
106 | |
107 | static irqreturn_t rk_timer_interrupt(int irq, void *dev_id) |
108 | { |
109 | struct clock_event_device *ce = dev_id; |
110 | struct rk_timer *timer = rk_timer(ce); |
111 | |
112 | rk_timer_interrupt_clear(timer); |
113 | |
114 | if (clockevent_state_oneshot(dev: ce)) |
115 | rk_timer_disable(timer); |
116 | |
117 | ce->event_handler(ce); |
118 | |
119 | return IRQ_HANDLED; |
120 | } |
121 | |
122 | static u64 notrace rk_timer_sched_read(void) |
123 | { |
124 | return ~readl_relaxed(rk_clksrc->base + TIMER_CURRENT_VALUE0); |
125 | } |
126 | |
127 | static int __init |
128 | rk_timer_probe(struct rk_timer *timer, struct device_node *np) |
129 | { |
130 | struct clk *timer_clk; |
131 | struct clk *pclk; |
132 | int ret = -EINVAL, irq; |
133 | u32 ctrl_reg = TIMER_CONTROL_REG3288; |
134 | |
135 | timer->base = of_iomap(node: np, index: 0); |
136 | if (!timer->base) { |
137 | pr_err("Failed to get base address for '%s'\n" , TIMER_NAME); |
138 | return -ENXIO; |
139 | } |
140 | |
141 | if (of_device_is_compatible(device: np, "rockchip,rk3399-timer" )) |
142 | ctrl_reg = TIMER_CONTROL_REG3399; |
143 | |
144 | timer->ctrl = timer->base + ctrl_reg; |
145 | |
146 | pclk = of_clk_get_by_name(np, name: "pclk" ); |
147 | if (IS_ERR(ptr: pclk)) { |
148 | ret = PTR_ERR(ptr: pclk); |
149 | pr_err("Failed to get pclk for '%s'\n" , TIMER_NAME); |
150 | goto out_unmap; |
151 | } |
152 | |
153 | ret = clk_prepare_enable(clk: pclk); |
154 | if (ret) { |
155 | pr_err("Failed to enable pclk for '%s'\n" , TIMER_NAME); |
156 | goto out_unmap; |
157 | } |
158 | timer->pclk = pclk; |
159 | |
160 | timer_clk = of_clk_get_by_name(np, name: "timer" ); |
161 | if (IS_ERR(ptr: timer_clk)) { |
162 | ret = PTR_ERR(ptr: timer_clk); |
163 | pr_err("Failed to get timer clock for '%s'\n" , TIMER_NAME); |
164 | goto out_timer_clk; |
165 | } |
166 | |
167 | ret = clk_prepare_enable(clk: timer_clk); |
168 | if (ret) { |
169 | pr_err("Failed to enable timer clock\n" ); |
170 | goto out_timer_clk; |
171 | } |
172 | timer->clk = timer_clk; |
173 | |
174 | timer->freq = clk_get_rate(clk: timer_clk); |
175 | |
176 | irq = irq_of_parse_and_map(node: np, index: 0); |
177 | if (!irq) { |
178 | ret = -EINVAL; |
179 | pr_err("Failed to map interrupts for '%s'\n" , TIMER_NAME); |
180 | goto out_irq; |
181 | } |
182 | timer->irq = irq; |
183 | |
184 | rk_timer_interrupt_clear(timer); |
185 | rk_timer_disable(timer); |
186 | return 0; |
187 | |
188 | out_irq: |
189 | clk_disable_unprepare(clk: timer_clk); |
190 | out_timer_clk: |
191 | clk_disable_unprepare(clk: pclk); |
192 | out_unmap: |
193 | iounmap(addr: timer->base); |
194 | |
195 | return ret; |
196 | } |
197 | |
198 | static void __init rk_timer_cleanup(struct rk_timer *timer) |
199 | { |
200 | clk_disable_unprepare(clk: timer->clk); |
201 | clk_disable_unprepare(clk: timer->pclk); |
202 | iounmap(addr: timer->base); |
203 | } |
204 | |
205 | static int __init rk_clkevt_init(struct device_node *np) |
206 | { |
207 | struct clock_event_device *ce; |
208 | int ret = -EINVAL; |
209 | |
210 | rk_clkevt = kzalloc(size: sizeof(struct rk_clkevt), GFP_KERNEL); |
211 | if (!rk_clkevt) { |
212 | ret = -ENOMEM; |
213 | goto out; |
214 | } |
215 | |
216 | ret = rk_timer_probe(timer: &rk_clkevt->timer, np); |
217 | if (ret) |
218 | goto out_probe; |
219 | |
220 | ce = &rk_clkevt->ce; |
221 | ce->name = TIMER_NAME; |
222 | ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | |
223 | CLOCK_EVT_FEAT_DYNIRQ; |
224 | ce->set_next_event = rk_timer_set_next_event; |
225 | ce->set_state_shutdown = rk_timer_shutdown; |
226 | ce->set_state_periodic = rk_timer_set_periodic; |
227 | ce->irq = rk_clkevt->timer.irq; |
228 | ce->cpumask = cpu_possible_mask; |
229 | ce->rating = 250; |
230 | |
231 | ret = request_irq(irq: rk_clkevt->timer.irq, handler: rk_timer_interrupt, IRQF_TIMER, |
232 | TIMER_NAME, dev: ce); |
233 | if (ret) { |
234 | pr_err("Failed to initialize '%s': %d\n" , |
235 | TIMER_NAME, ret); |
236 | goto out_irq; |
237 | } |
238 | |
239 | clockevents_config_and_register(dev: &rk_clkevt->ce, |
240 | freq: rk_clkevt->timer.freq, min_delta: 1, UINT_MAX); |
241 | return 0; |
242 | |
243 | out_irq: |
244 | rk_timer_cleanup(timer: &rk_clkevt->timer); |
245 | out_probe: |
246 | kfree(objp: rk_clkevt); |
247 | out: |
248 | /* Leave rk_clkevt not NULL to prevent future init */ |
249 | rk_clkevt = ERR_PTR(error: ret); |
250 | return ret; |
251 | } |
252 | |
253 | static int __init rk_clksrc_init(struct device_node *np) |
254 | { |
255 | int ret = -EINVAL; |
256 | |
257 | rk_clksrc = kzalloc(size: sizeof(struct rk_timer), GFP_KERNEL); |
258 | if (!rk_clksrc) { |
259 | ret = -ENOMEM; |
260 | goto out; |
261 | } |
262 | |
263 | ret = rk_timer_probe(timer: rk_clksrc, np); |
264 | if (ret) |
265 | goto out_probe; |
266 | |
267 | rk_timer_update_counter(UINT_MAX, timer: rk_clksrc); |
268 | rk_timer_enable(timer: rk_clksrc, flags: 0); |
269 | |
270 | ret = clocksource_mmio_init(rk_clksrc->base + TIMER_CURRENT_VALUE0, |
271 | TIMER_NAME, rk_clksrc->freq, 250, 32, |
272 | clocksource_mmio_readl_down); |
273 | if (ret) { |
274 | pr_err("Failed to register clocksource\n" ); |
275 | goto out_clocksource; |
276 | } |
277 | |
278 | sched_clock_register(read: rk_timer_sched_read, bits: 32, rate: rk_clksrc->freq); |
279 | return 0; |
280 | |
281 | out_clocksource: |
282 | rk_timer_cleanup(timer: rk_clksrc); |
283 | out_probe: |
284 | kfree(objp: rk_clksrc); |
285 | out: |
286 | /* Leave rk_clksrc not NULL to prevent future init */ |
287 | rk_clksrc = ERR_PTR(error: ret); |
288 | return ret; |
289 | } |
290 | |
291 | static int __init rk_timer_init(struct device_node *np) |
292 | { |
293 | if (!rk_clkevt) |
294 | return rk_clkevt_init(np); |
295 | |
296 | if (!rk_clksrc) |
297 | return rk_clksrc_init(np); |
298 | |
299 | pr_err("Too many timer definitions for '%s'\n" , TIMER_NAME); |
300 | return -EINVAL; |
301 | } |
302 | |
303 | TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer" , rk_timer_init); |
304 | TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer" , rk_timer_init); |
305 | |