1 | /* |
2 | * Copyright (C) 2013-2014 Altera Corporation |
3 | * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> |
4 | * Copyright (C) 2004 Microtronix Datacom Ltd. |
5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. |
9 | */ |
10 | |
11 | #include <linux/export.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/clockchips.h> |
14 | #include <linux/clocksource.h> |
15 | #include <linux/delay.h> |
16 | #include <linux/of.h> |
17 | #include <linux/of_address.h> |
18 | #include <linux/of_irq.h> |
19 | #include <linux/io.h> |
20 | #include <linux/slab.h> |
21 | |
22 | #define ALTR_TIMER_COMPATIBLE "altr,timer-1.0" |
23 | |
24 | #define ALTERA_TIMER_STATUS_REG 0 |
25 | #define ALTERA_TIMER_CONTROL_REG 4 |
26 | #define ALTERA_TIMER_PERIODL_REG 8 |
27 | #define ALTERA_TIMER_PERIODH_REG 12 |
28 | #define ALTERA_TIMER_SNAPL_REG 16 |
29 | #define ALTERA_TIMER_SNAPH_REG 20 |
30 | |
31 | #define ALTERA_TIMER_CONTROL_ITO_MSK (0x1) |
32 | #define ALTERA_TIMER_CONTROL_CONT_MSK (0x2) |
33 | #define ALTERA_TIMER_CONTROL_START_MSK (0x4) |
34 | #define ALTERA_TIMER_CONTROL_STOP_MSK (0x8) |
35 | |
36 | struct nios2_timer { |
37 | void __iomem *base; |
38 | unsigned long freq; |
39 | }; |
40 | |
41 | struct nios2_clockevent_dev { |
42 | struct nios2_timer timer; |
43 | struct clock_event_device ced; |
44 | }; |
45 | |
46 | struct nios2_clocksource { |
47 | struct nios2_timer timer; |
48 | struct clocksource cs; |
49 | }; |
50 | |
51 | static inline struct nios2_clockevent_dev * |
52 | to_nios2_clkevent(struct clock_event_device *evt) |
53 | { |
54 | return container_of(evt, struct nios2_clockevent_dev, ced); |
55 | } |
56 | |
57 | static inline struct nios2_clocksource * |
58 | to_nios2_clksource(struct clocksource *cs) |
59 | { |
60 | return container_of(cs, struct nios2_clocksource, cs); |
61 | } |
62 | |
63 | static u16 timer_readw(struct nios2_timer *timer, u32 offs) |
64 | { |
65 | return readw(addr: timer->base + offs); |
66 | } |
67 | |
68 | static void timer_writew(struct nios2_timer *timer, u16 val, u32 offs) |
69 | { |
70 | writew(val, addr: timer->base + offs); |
71 | } |
72 | |
73 | static inline unsigned long read_timersnapshot(struct nios2_timer *timer) |
74 | { |
75 | unsigned long count; |
76 | |
77 | timer_writew(timer, val: 0, ALTERA_TIMER_SNAPL_REG); |
78 | count = timer_readw(timer, ALTERA_TIMER_SNAPH_REG) << 16 | |
79 | timer_readw(timer, ALTERA_TIMER_SNAPL_REG); |
80 | |
81 | return count; |
82 | } |
83 | |
84 | static u64 nios2_timer_read(struct clocksource *cs) |
85 | { |
86 | struct nios2_clocksource *nios2_cs = to_nios2_clksource(cs); |
87 | unsigned long flags; |
88 | u32 count; |
89 | |
90 | local_irq_save(flags); |
91 | count = read_timersnapshot(timer: &nios2_cs->timer); |
92 | local_irq_restore(flags); |
93 | |
94 | /* Counter is counting down */ |
95 | return ~count; |
96 | } |
97 | |
98 | static struct nios2_clocksource nios2_cs = { |
99 | .cs = { |
100 | .name = "nios2-clksrc" , |
101 | .rating = 250, |
102 | .read = nios2_timer_read, |
103 | .mask = CLOCKSOURCE_MASK(32), |
104 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
105 | }, |
106 | }; |
107 | |
108 | cycles_t get_cycles(void) |
109 | { |
110 | /* Only read timer if it has been initialized */ |
111 | if (nios2_cs.timer.base) |
112 | return nios2_timer_read(cs: &nios2_cs.cs); |
113 | return 0; |
114 | } |
115 | EXPORT_SYMBOL(get_cycles); |
116 | |
117 | static void nios2_timer_start(struct nios2_timer *timer) |
118 | { |
119 | u16 ctrl; |
120 | |
121 | ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG); |
122 | ctrl |= ALTERA_TIMER_CONTROL_START_MSK; |
123 | timer_writew(timer, val: ctrl, ALTERA_TIMER_CONTROL_REG); |
124 | } |
125 | |
126 | static void nios2_timer_stop(struct nios2_timer *timer) |
127 | { |
128 | u16 ctrl; |
129 | |
130 | ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG); |
131 | ctrl |= ALTERA_TIMER_CONTROL_STOP_MSK; |
132 | timer_writew(timer, val: ctrl, ALTERA_TIMER_CONTROL_REG); |
133 | } |
134 | |
135 | static void nios2_timer_config(struct nios2_timer *timer, unsigned long period, |
136 | bool periodic) |
137 | { |
138 | u16 ctrl; |
139 | |
140 | /* The timer's actual period is one cycle greater than the value |
141 | * stored in the period register. */ |
142 | period--; |
143 | |
144 | ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG); |
145 | /* stop counter */ |
146 | timer_writew(timer, val: ctrl | ALTERA_TIMER_CONTROL_STOP_MSK, |
147 | ALTERA_TIMER_CONTROL_REG); |
148 | |
149 | /* write new count */ |
150 | timer_writew(timer, val: period, ALTERA_TIMER_PERIODL_REG); |
151 | timer_writew(timer, val: period >> 16, ALTERA_TIMER_PERIODH_REG); |
152 | |
153 | ctrl |= ALTERA_TIMER_CONTROL_START_MSK | ALTERA_TIMER_CONTROL_ITO_MSK; |
154 | if (periodic) |
155 | ctrl |= ALTERA_TIMER_CONTROL_CONT_MSK; |
156 | else |
157 | ctrl &= ~ALTERA_TIMER_CONTROL_CONT_MSK; |
158 | timer_writew(timer, val: ctrl, ALTERA_TIMER_CONTROL_REG); |
159 | } |
160 | |
161 | static int nios2_timer_set_next_event(unsigned long delta, |
162 | struct clock_event_device *evt) |
163 | { |
164 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt); |
165 | |
166 | nios2_timer_config(timer: &nios2_ced->timer, period: delta, periodic: false); |
167 | |
168 | return 0; |
169 | } |
170 | |
171 | static int nios2_timer_shutdown(struct clock_event_device *evt) |
172 | { |
173 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt); |
174 | struct nios2_timer *timer = &nios2_ced->timer; |
175 | |
176 | nios2_timer_stop(timer); |
177 | return 0; |
178 | } |
179 | |
180 | static int nios2_timer_set_periodic(struct clock_event_device *evt) |
181 | { |
182 | unsigned long period; |
183 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt); |
184 | struct nios2_timer *timer = &nios2_ced->timer; |
185 | |
186 | period = DIV_ROUND_UP(timer->freq, HZ); |
187 | nios2_timer_config(timer, period, periodic: true); |
188 | return 0; |
189 | } |
190 | |
191 | static int nios2_timer_resume(struct clock_event_device *evt) |
192 | { |
193 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt); |
194 | struct nios2_timer *timer = &nios2_ced->timer; |
195 | |
196 | nios2_timer_start(timer); |
197 | return 0; |
198 | } |
199 | |
200 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
201 | { |
202 | struct clock_event_device *evt = (struct clock_event_device *) dev_id; |
203 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt); |
204 | |
205 | /* Clear the interrupt condition */ |
206 | timer_writew(timer: &nios2_ced->timer, val: 0, ALTERA_TIMER_STATUS_REG); |
207 | evt->event_handler(evt); |
208 | |
209 | return IRQ_HANDLED; |
210 | } |
211 | |
212 | static int __init nios2_timer_get_base_and_freq(struct device_node *np, |
213 | void __iomem **base, u32 *freq) |
214 | { |
215 | *base = of_iomap(node: np, index: 0); |
216 | if (!*base) { |
217 | pr_crit("Unable to map reg for %pOFn\n" , np); |
218 | return -ENXIO; |
219 | } |
220 | |
221 | if (of_property_read_u32(np, propname: "clock-frequency" , out_value: freq)) { |
222 | pr_crit("Unable to get %pOFn clock frequency\n" , np); |
223 | return -EINVAL; |
224 | } |
225 | |
226 | return 0; |
227 | } |
228 | |
229 | static struct nios2_clockevent_dev nios2_ce = { |
230 | .ced = { |
231 | .name = "nios2-clkevent" , |
232 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
233 | .rating = 250, |
234 | .shift = 32, |
235 | .set_next_event = nios2_timer_set_next_event, |
236 | .set_state_shutdown = nios2_timer_shutdown, |
237 | .set_state_periodic = nios2_timer_set_periodic, |
238 | .set_state_oneshot = nios2_timer_shutdown, |
239 | .tick_resume = nios2_timer_resume, |
240 | }, |
241 | }; |
242 | |
243 | static __init int nios2_clockevent_init(struct device_node *timer) |
244 | { |
245 | void __iomem *iobase; |
246 | u32 freq; |
247 | int irq, ret; |
248 | |
249 | ret = nios2_timer_get_base_and_freq(np: timer, base: &iobase, freq: &freq); |
250 | if (ret) |
251 | return ret; |
252 | |
253 | irq = irq_of_parse_and_map(node: timer, index: 0); |
254 | if (!irq) { |
255 | pr_crit("Unable to parse timer irq\n" ); |
256 | return -EINVAL; |
257 | } |
258 | |
259 | nios2_ce.timer.base = iobase; |
260 | nios2_ce.timer.freq = freq; |
261 | |
262 | nios2_ce.ced.cpumask = cpumask_of(0); |
263 | nios2_ce.ced.irq = irq; |
264 | |
265 | nios2_timer_stop(timer: &nios2_ce.timer); |
266 | /* clear pending interrupt */ |
267 | timer_writew(timer: &nios2_ce.timer, val: 0, ALTERA_TIMER_STATUS_REG); |
268 | |
269 | ret = request_irq(irq, handler: timer_interrupt, IRQF_TIMER, name: timer->name, |
270 | dev: &nios2_ce.ced); |
271 | if (ret) { |
272 | pr_crit("Unable to setup timer irq\n" ); |
273 | return ret; |
274 | } |
275 | |
276 | clockevents_config_and_register(dev: &nios2_ce.ced, freq, min_delta: 1, ULONG_MAX); |
277 | |
278 | return 0; |
279 | } |
280 | |
281 | static __init int nios2_clocksource_init(struct device_node *timer) |
282 | { |
283 | unsigned int ctrl; |
284 | void __iomem *iobase; |
285 | u32 freq; |
286 | int ret; |
287 | |
288 | ret = nios2_timer_get_base_and_freq(np: timer, base: &iobase, freq: &freq); |
289 | if (ret) |
290 | return ret; |
291 | |
292 | nios2_cs.timer.base = iobase; |
293 | nios2_cs.timer.freq = freq; |
294 | |
295 | ret = clocksource_register_hz(cs: &nios2_cs.cs, hz: freq); |
296 | if (ret) |
297 | return ret; |
298 | |
299 | timer_writew(timer: &nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODL_REG); |
300 | timer_writew(timer: &nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODH_REG); |
301 | |
302 | /* interrupt disable + continuous + start */ |
303 | ctrl = ALTERA_TIMER_CONTROL_CONT_MSK | ALTERA_TIMER_CONTROL_START_MSK; |
304 | timer_writew(timer: &nios2_cs.timer, val: ctrl, ALTERA_TIMER_CONTROL_REG); |
305 | |
306 | /* Calibrate the delay loop directly */ |
307 | lpj_fine = freq / HZ; |
308 | |
309 | return 0; |
310 | } |
311 | |
312 | /* |
313 | * The first timer instance will use as a clockevent. If there are two or |
314 | * more instances, the second one gets used as clocksource and all |
315 | * others are unused. |
316 | */ |
317 | static int __init nios2_time_init(struct device_node *timer) |
318 | { |
319 | static int num_called; |
320 | int ret; |
321 | |
322 | switch (num_called) { |
323 | case 0: |
324 | ret = nios2_clockevent_init(timer); |
325 | break; |
326 | case 1: |
327 | ret = nios2_clocksource_init(timer); |
328 | break; |
329 | default: |
330 | ret = 0; |
331 | break; |
332 | } |
333 | |
334 | num_called++; |
335 | |
336 | return ret; |
337 | } |
338 | |
339 | void read_persistent_clock64(struct timespec64 *ts) |
340 | { |
341 | ts->tv_sec = mktime64(year: 2007, mon: 1, day: 1, hour: 0, min: 0, sec: 0); |
342 | ts->tv_nsec = 0; |
343 | } |
344 | |
345 | void __init time_init(void) |
346 | { |
347 | struct device_node *np; |
348 | int count = 0; |
349 | |
350 | for_each_compatible_node(np, NULL, ALTR_TIMER_COMPATIBLE) |
351 | count++; |
352 | |
353 | if (count < 2) |
354 | panic(fmt: "%d timer is found, it needs 2 timers in system\n" , count); |
355 | |
356 | timer_probe(); |
357 | } |
358 | |
359 | TIMER_OF_DECLARE(nios2_timer, ALTR_TIMER_COMPATIBLE, nios2_time_init); |
360 | |