1 /*-
2 * Copyright (c) 2009 Yohanes Nugroho <yohanes@gmail.com>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/malloc.h>
35 #include <sys/rman.h>
36 #include <sys/timetc.h>
37 #include <sys/watchdog.h>
38 #include <machine/bus.h>
39 #include <machine/cpu.h>
40 #include <machine/intr.h>
41
42 #include "econa_reg.h"
43 #include "econa_var.h"
44
45 #define INITIAL_TIMECOUNTER (0xffffffff)
46
47 static int timers_initialized = 0;
48
49 #define HZ 100
50
51 extern unsigned int CPU_clock;
52 extern unsigned int AHB_clock;
53 extern unsigned int APB_clock;
54
55 static unsigned long timer_counter = 0;
56
57 struct ec_timer_softc {
58 struct resource * timer_res[3];
59 bus_space_tag_t timer_bst;
60 bus_space_handle_t timer_bsh;
61 struct mtx timer_mtx;
62 };
63
64 static struct resource_spec ec_timer_spec[] = {
65 { SYS_RES_MEMORY, 0, RF_ACTIVE },
66 { SYS_RES_IRQ, 0, RF_ACTIVE },
67 { SYS_RES_IRQ, 1, RF_ACTIVE },
68 { -1, 0 }
69 };
70
71 static unsigned ec_timer_get_timecount(struct timecounter *);
72
73 static struct timecounter ec_timecounter = {
74 .tc_get_timecount = ec_timer_get_timecount,
75 .tc_name = "CPU Timer",
76 /* This is assigned on the fly in the init sequence */
77 .tc_frequency = 0,
78 .tc_counter_mask = ~0u,
79 .tc_quality = 1000,
80 };
81
82 static struct ec_timer_softc *timer_softc = NULL;
83
84 static inline
85 void write_4(unsigned int val, unsigned int addr)
86 {
87 bus_space_write_4(timer_softc->timer_bst,
88 timer_softc->timer_bsh, addr, val);
89
90 }
91
92 static inline
93 unsigned int read_4(unsigned int addr)
94 {
95
96 return bus_space_read_4(timer_softc->timer_bst,
97 timer_softc->timer_bsh, addr);
98 }
99
100 #define uSECS_PER_TICK (1000000 / APB_clock)
101 #define TICKS2USECS(x) ((x) * uSECS_PER_TICK)
102
103 static unsigned
104 read_timer_counter_noint(void)
105 {
106
107 arm_mask_irq(0);
108 unsigned int v = read_4(TIMER_TM1_COUNTER_REG);
109 arm_unmask_irq(0);
110 return v;
111 }
112
113 void
114 DELAY(int usec)
115 {
116 uint32_t val, val_temp;
117 int nticks;
118
119 if (!timers_initialized) {
120 for (; usec > 0; usec--)
121 for (val = 100; val > 0; val--)
122 ;
123 return;
124 }
125
126 val = read_timer_counter_noint();
127 nticks = (((APB_clock / 1000) * usec) / 1000) + 100;
128
129 while (nticks > 0) {
130 val_temp = read_timer_counter_noint();
131 if (val > val_temp)
132 nticks -= (val - val_temp);
133 else
134 nticks -= (val + (timer_counter - val_temp));
135
136 val = val_temp;
137 }
138
139 }
140
141 /*
142 * Setup timer
143 */
144 static inline void
145 setup_timer(unsigned int counter_value)
146 {
147 unsigned int control_value;
148 unsigned int mask_value;
149
150 control_value = read_4(TIMER_TM_CR_REG);
151
152 mask_value = read_4(TIMER_TM_INTR_MASK_REG);
153 write_4(counter_value, TIMER_TM1_COUNTER_REG);
154 write_4(counter_value, TIMER_TM1_LOAD_REG);
155 write_4(0, TIMER_TM1_MATCH1_REG);
156 write_4(0,TIMER_TM1_MATCH2_REG);
157
158 control_value &= ~(TIMER1_CLOCK_SOURCE);
159 control_value |= TIMER1_UP_DOWN_COUNT;
160
161 write_4(0, TIMER_TM2_COUNTER_REG);
162 write_4(0, TIMER_TM2_LOAD_REG);
163 write_4(~0u, TIMER_TM2_MATCH1_REG);
164 write_4(~0u,TIMER_TM2_MATCH2_REG);
165
166 control_value &= ~(TIMER2_CLOCK_SOURCE);
167 control_value &= ~(TIMER2_UP_DOWN_COUNT);
168
169 mask_value &= ~(63);
170
171 write_4(control_value, TIMER_TM_CR_REG);
172 write_4(mask_value, TIMER_TM_INTR_MASK_REG);
173 }
174
175 /*
176 * Enable timer
177 */
178 static inline void
179 timer_enable(void)
180 {
181 unsigned int control_value;
182
183 control_value = read_4(TIMER_TM_CR_REG);
184
185 control_value |= TIMER1_OVERFLOW_ENABLE;
186 control_value |= TIMER1_ENABLE;
187 control_value |= TIMER2_OVERFLOW_ENABLE;
188 control_value |= TIMER2_ENABLE;
189
190 write_4(control_value, TIMER_TM_CR_REG);
191 }
192
193 static inline unsigned int
194 read_second_timer_counter(void)
195 {
196
197 return read_4(TIMER_TM2_COUNTER_REG);
198 }
199
200 /*
201 * Get timer interrupt status
202 */
203 static inline unsigned int
204 read_timer_interrupt_status(void)
205 {
206
207 return read_4(TIMER_TM_INTR_STATUS_REG);
208 }
209
210 /*
211 * Clear timer interrupt status
212 */
213 static inline void
214 clear_timer_interrupt_status(unsigned int irq)
215 {
216 unsigned int interrupt_status;
217
218 interrupt_status = read_4(TIMER_TM_INTR_STATUS_REG);
219 if (irq == 0) {
220 if (interrupt_status & (TIMER1_MATCH1_INTR))
221 interrupt_status &= ~(TIMER1_MATCH1_INTR);
222 if (interrupt_status & (TIMER1_MATCH2_INTR))
223 interrupt_status &= ~(TIMER1_MATCH2_INTR);
224 if (interrupt_status & (TIMER1_OVERFLOW_INTR))
225 interrupt_status &= ~(TIMER1_OVERFLOW_INTR);
226 }
227 if (irq == 1) {
228 if (interrupt_status & (TIMER2_MATCH1_INTR))
229 interrupt_status &= ~(TIMER2_MATCH1_INTR);
230 if (interrupt_status & (TIMER2_MATCH2_INTR))
231 interrupt_status &= ~(TIMER2_MATCH2_INTR);
232 if (interrupt_status & (TIMER2_OVERFLOW_INTR))
233 interrupt_status &= ~(TIMER2_OVERFLOW_INTR);
234 }
235
236 write_4(interrupt_status, TIMER_TM_INTR_STATUS_REG);
237 }
238
239 static unsigned
240 ec_timer_get_timecount(struct timecounter *a)
241 {
242 unsigned int ticks1;
243 arm_mask_irq(1);
244 ticks1 = read_second_timer_counter();
245 arm_unmask_irq(1);
246 return ticks1;
247 }
248
249 /*
250 * Setup timer
251 */
252 static inline void
253 do_setup_timer(void)
254 {
255
256 timer_counter = APB_clock/HZ;
257 /*
258 * setup timer-related values
259 */
260 setup_timer(timer_counter);
261 }
262
263 void
264 cpu_initclocks(void)
265 {
266
267 ec_timecounter.tc_frequency = APB_clock;
268 tc_init(&ec_timecounter);
269 timer_enable();
270 timers_initialized = 1;
271 }
272
273 void
274 cpu_startprofclock(void)
275 {
276
277 }
278
279 void
280 cpu_stopprofclock(void)
281 {
282
283 }
284
285 static int
286 ec_timer_probe(device_t dev)
287 {
288
289 device_set_desc(dev, "Econa CPU Timer");
290 return (0);
291 }
292
293 static int
294 ec_reset(void *arg)
295 {
296
297 arm_mask_irq(1);
298 clear_timer_interrupt_status(1);
299 arm_unmask_irq(1);
300 return (FILTER_HANDLED);
301 }
302
303 static int
304 ec_hardclock(void *arg)
305 {
306 struct trapframe *frame;
307 unsigned int val;
308 /*clear timer interrupt status*/
309
310 arm_mask_irq(0);
311
312 val = read_4(TIMER_INTERRUPT_STATUS_REG);
313 val &= ~(TIMER1_OVERFLOW_INTERRUPT);
314 write_4(val, TIMER_INTERRUPT_STATUS_REG);
315
316 frame = (struct trapframe *)arg;
317 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
318
319 arm_unmask_irq(0);
320
321 return (FILTER_HANDLED);
322 }
323
324 static int
325 ec_timer_attach(device_t dev)
326 {
327 struct ec_timer_softc *sc;
328 int error;
329 void *ihl;
330
331
332 if (timer_softc != NULL)
333 return (ENXIO);
334
335 sc = (struct ec_timer_softc *)device_get_softc(dev);
336
337 timer_softc = sc;
338
339 error = bus_alloc_resources(dev, ec_timer_spec, sc->timer_res);
340 if (error) {
341 device_printf(dev, "could not allocate resources\n");
342 return (ENXIO);
343 }
344
345 sc->timer_bst = rman_get_bustag(sc->timer_res[0]);
346 sc->timer_bsh = rman_get_bushandle(sc->timer_res[0]);
347
348 do_setup_timer();
349
350 if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
351 ec_hardclock, NULL, NULL, &ihl) != 0) {
352 bus_release_resources(dev, ec_timer_spec, sc->timer_res);
353 device_printf(dev, "could not setup hardclock interrupt\n");
354 return (ENXIO);
355 }
356
357 if (bus_setup_intr(dev, sc->timer_res[2], INTR_TYPE_CLK,
358 ec_reset, NULL, NULL, &ihl) != 0) {
359 bus_release_resources(dev, ec_timer_spec, sc->timer_res);
360 device_printf(dev, "could not setup timer interrupt\n");
361 return (ENXIO);
362 }
363
364 return (0);
365 }
366
367 static device_method_t ec_timer_methods[] = {
368 DEVMETHOD(device_probe, ec_timer_probe),
369 DEVMETHOD(device_attach, ec_timer_attach),
370 { 0, 0 }
371 };
372
373 static driver_t ec_timer_driver = {
374 "timer",
375 ec_timer_methods,
376 sizeof(struct ec_timer_softc),
377 };
378
379 static devclass_t ec_timer_devclass;
380
381 DRIVER_MODULE(timer, econaarm, ec_timer_driver, ec_timer_devclass, 0, 0);
Cache object: ad523c91e061cbc1285a2f23f4c2cc5c
|