1 /* $NetBSD: sa11x0_ost.c,v 1.11 2003/07/15 00:24:51 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 1997 Mark Brinicombe.
5 * Copyright (c) 1997 Causality Limited.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD: releng/9.0/sys/arm/sa11x0/sa11x0_ost.c 178429 2008-04-22 19:38:30Z phk $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/time.h>
47 #include <sys/bus.h>
48 #include <sys/module.h>
49
50 #include <machine/bus.h>
51 #include <sys/rman.h>
52 #include <machine/resource.h>
53 #include <machine/intr.h>
54
55 #include <machine/cpu.h>
56 #include <machine/cpufunc.h>
57 #include <machine/frame.h>
58
59 #include <arm/sa11x0/sa11x0_reg.h>
60 #include <arm/sa11x0/sa11x0_var.h>
61 #include <arm/sa11x0/sa11x0_ostreg.h>
62
63 static int saost_probe(device_t);
64 static int saost_attach(device_t);
65
66 int gettick(void);
67 static int clockintr(void *);
68 #if 0
69 static int statintr(void *);
70 #endif
71 void rtcinit(void);
72
73 #if 0
74 static struct mtx clock_lock;
75 #endif
76
77 struct saost_softc {
78 device_t sc_dev;
79 bus_addr_t sc_baseaddr;
80 bus_space_tag_t sc_iot;
81 bus_space_handle_t sc_ioh;
82
83 u_int32_t sc_clock_count;
84 u_int32_t sc_statclock_count;
85 u_int32_t sc_statclock_step;
86 };
87
88 static struct saost_softc *saost_sc = NULL;
89
90 #define TIMER_FREQUENCY 3686400 /* 3.6864MHz */
91 #define TICKS_PER_MICROSECOND (TIMER_FREQUENCY/1000000)
92
93 #ifndef STATHZ
94 #define STATHZ 64
95 #endif
96
97 static device_method_t saost_methods[] = {
98 DEVMETHOD(device_probe, saost_probe),
99 DEVMETHOD(device_attach, saost_attach),
100 {0, 0},
101 };
102
103 static driver_t saost_driver = {
104 "saost",
105 saost_methods,
106 sizeof(struct saost_softc),
107 };
108 static devclass_t saost_devclass;
109
110 DRIVER_MODULE(saost, saip, saost_driver, saost_devclass, 0, 0);
111 static int
112 saost_probe(device_t dev)
113 {
114
115 return (0);
116 }
117
118 static int
119 saost_attach(device_t dev)
120 {
121 struct saost_softc *sc = device_get_softc(dev);
122 struct sa11x0_softc *sa = device_get_softc(device_get_parent(dev));
123
124 sc->sc_dev = dev;
125 sc->sc_iot = sa->sc_iot;
126 sc->sc_baseaddr = 0x90000000;
127
128 saost_sc = sc;
129
130 if(bus_space_map(sa->sc_iot, sc->sc_baseaddr, 8, 0,
131 &sc->sc_ioh))
132 panic("%s: Cannot map registers", device_get_name(dev));
133
134 /* disable all channel and clear interrupt status */
135 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 0);
136 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf);
137 return (0);
138
139 }
140
141 static int
142 clockintr(arg)
143 void *arg;
144 {
145 struct trapframe *frame = arg;
146 u_int32_t oscr, nextmatch, oldmatch;
147 int s;
148
149 #if 0
150 mtx_lock_spin(&clock_lock);
151 #endif
152 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
153 SAOST_SR, 1);
154
155 /* schedule next clock intr */
156 oldmatch = saost_sc->sc_clock_count;
157 nextmatch = oldmatch + TIMER_FREQUENCY / hz;
158
159 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
160 SAOST_CR);
161
162 if ((nextmatch > oldmatch &&
163 (oscr > nextmatch || oscr < oldmatch)) ||
164 (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) {
165 /*
166 * we couldn't set the matching register in time.
167 * just set it to some value so that next interrupt happens.
168 * XXX is it possible to compansate lost interrupts?
169 */
170
171 s = splhigh();
172 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
173 SAOST_CR);
174 nextmatch = oscr + 10;
175 splx(s);
176 }
177 saost_sc->sc_clock_count = nextmatch;
178 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0,
179 nextmatch);
180 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
181 #if 0
182 mtx_unlock_spin(&clock_lock);
183 #endif
184 return (FILTER_HANDLED);
185 }
186
187 #if 0
188 static int
189 statintr(arg)
190 void *arg;
191 {
192 struct trapframe *frame = arg;
193 u_int32_t oscr, nextmatch, oldmatch;
194 int s;
195
196 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
197 SAOST_SR, 2);
198
199 /* schedule next clock intr */
200 oldmatch = saost_sc->sc_statclock_count;
201 nextmatch = oldmatch + saost_sc->sc_statclock_step;
202
203 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1,
204 nextmatch);
205 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
206 SAOST_CR);
207
208 if ((nextmatch > oldmatch &&
209 (oscr > nextmatch || oscr < oldmatch)) ||
210 (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) {
211 /*
212 * we couldn't set the matching register in time.
213 * just set it to some value so that next interrupt happens.
214 * XXX is it possible to compansate lost interrupts?
215 */
216
217 s = splhigh();
218 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
219 SAOST_CR);
220 nextmatch = oscr + 10;
221 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
222 SAOST_MR1, nextmatch);
223 splx(s);
224 }
225
226 saost_sc->sc_statclock_count = nextmatch;
227 statclock(TRAPF_USERMODE(frame));
228 return (FILTER_HANDLED);
229 }
230 #endif
231
232 #if 0
233 void
234 setstatclockrate(int hz)
235 {
236 u_int32_t count;
237
238 saost_sc->sc_statclock_step = TIMER_FREQUENCY / hz;
239 count = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR);
240 count += saost_sc->sc_statclock_step;
241 saost_sc->sc_statclock_count = count;
242 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
243 SAOST_MR1, count);
244 }
245 #endif
246 void
247 cpu_initclocks()
248 {
249 device_t dev = saost_sc->sc_dev;
250
251 stathz = STATHZ;
252 profhz = stathz;
253 #if 0
254 mtx_init(&clock_lock, "SA1110 Clock locké", NULL, MTX_SPIN);
255 #endif
256 saost_sc->sc_statclock_step = TIMER_FREQUENCY / stathz;
257 struct resource *irq1, *irq2;
258 int rid = 0;
259 void *ih1/*, *ih2 */;
260
261 printf("clock: hz=%d stathz = %d\n", hz, stathz);
262
263 /* Use the channels 0 and 1 for hardclock and statclock, respectively */
264 saost_sc->sc_clock_count = TIMER_FREQUENCY / hz;
265 saost_sc->sc_statclock_count = TIMER_FREQUENCY / stathz;
266
267 irq1 = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0,
268 ~0, 1, RF_ACTIVE);
269 rid = 1;
270 irq2 = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
271 RF_ACTIVE);
272 bus_setup_intr(dev, irq1, INTR_TYPE_CLK, clockintr, NULL, NULL,
273 &ih1);
274 #if 0
275 bus_setup_intr(dev, irq2, INTR_TYPE_CLK, statintr, NULL, NULL,
276 ,&ih2);
277 #endif
278 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf);
279 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 3);
280 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0,
281 saost_sc->sc_clock_count);
282 #if 0
283 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1,
284 0);
285 #endif
286 /* Zero the counter value */
287 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR, 0);
288 }
289
290 int
291 gettick()
292 {
293 int counter;
294 u_int savedints;
295 savedints = disable_interrupts(I32_bit);
296
297 counter = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
298 SAOST_CR);
299
300 restore_interrupts(savedints);
301 return counter;
302 }
303
304 void
305 DELAY(usecs)
306 int usecs;
307 {
308 u_int32_t tick, otick, delta;
309 int j, csec, usec;
310
311 csec = usecs / 10000;
312 usec = usecs % 10000;
313
314 usecs = (TIMER_FREQUENCY / 100) * csec
315 + (TIMER_FREQUENCY / 100) * usec / 10000;
316
317 if (! saost_sc) {
318 /* clock isn't initialized yet */
319 for(; usecs > 0; usecs--)
320 for(j = 100; j > 0; j--)
321 ;
322 return;
323 }
324
325 #if 0
326 mtx_lock_spin(&clock_lock);
327 #endif
328 otick = gettick();
329
330 while (1) {
331 for(j = 100; j > 0; j--)
332 ;
333 tick = gettick();
334 delta = tick - otick;
335 if (delta > usecs) {
336 break;
337 }
338 usecs -= delta;
339 otick = tick;
340 }
341 #if 0
342 mtx_unlock_spin(&clock_lock);
343 #endif
344 }
345
346 void
347 cpu_startprofclock(void)
348 {
349 printf("STARTPROFCLOCK\n");
350 }
351
352 void
353 cpu_stopprofclock(void)
354 {
355 }
Cache object: c5580a703e99ed2ecfdd479c2b462d92
|