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$");
42
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/time.h>
48 #include <sys/bus.h>
49 #include <sys/clock.h>
50 #include <sys/module.h>
51
52 #include <machine/bus.h>
53 #include <sys/rman.h>
54 #include <machine/resource.h>
55 #include <machine/intr.h>
56
57 #include <machine/cpufunc.h>
58
59 #include <machine/katelib.h>
60
61 #include <arm/sa11x0/sa11x0_reg.h>
62 #include <arm/sa11x0/sa11x0_var.h>
63 #include <arm/sa11x0/sa11x0_ostreg.h>
64
65 static int saost_probe(device_t);
66 static int saost_attach(device_t);
67
68 int gettick(void);
69 static void clockintr(void *);
70 #if 0
71 static void statintr(void *);
72 #endif
73 void rtcinit(void);
74
75 #if 0
76 static struct mtx clock_lock;
77 #endif
78
79 struct saost_softc {
80 device_t sc_dev;
81 bus_addr_t sc_baseaddr;
82 bus_space_tag_t sc_iot;
83 bus_space_handle_t sc_ioh;
84
85 u_int32_t sc_clock_count;
86 u_int32_t sc_statclock_count;
87 u_int32_t sc_statclock_step;
88 };
89
90 static struct saost_softc *saost_sc = NULL;
91
92 #define TIMER_FREQUENCY 3686400 /* 3.6864MHz */
93 #define TICKS_PER_MICROSECOND (TIMER_FREQUENCY/1000000)
94
95 #ifndef STATHZ
96 #define STATHZ 64
97 #endif
98
99 static device_method_t saost_methods[] = {
100 DEVMETHOD(device_probe, saost_probe),
101 DEVMETHOD(device_attach, saost_attach),
102 {0, 0},
103 };
104
105 static driver_t saost_driver = {
106 "saost",
107 saost_methods,
108 sizeof(struct saost_softc),
109 };
110 static devclass_t saost_devclass;
111
112 DRIVER_MODULE(saost, saip, saost_driver, saost_devclass, 0, 0);
113 static int
114 saost_probe(device_t dev)
115 {
116
117 return (0);
118 }
119
120 static int
121 saost_attach(device_t dev)
122 {
123 struct saost_softc *sc = device_get_softc(dev);
124 struct sa11x0_softc *sa = device_get_softc(device_get_parent(dev));
125
126 sc->sc_dev = dev;
127 sc->sc_iot = sa->sc_iot;
128 sc->sc_baseaddr = 0x90000000;
129
130 saost_sc = sc;
131
132 if(bus_space_map(sa->sc_iot, sc->sc_baseaddr, 8, 0,
133 &sc->sc_ioh))
134 panic("%s: Cannot map registers", device_get_name(dev));
135
136 /* disable all channel and clear interrupt status */
137 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 0);
138 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf);
139 return (0);
140
141 }
142
143 static void
144 clockintr(arg)
145 void *arg;
146 {
147 struct clockframe *frame = arg;
148 u_int32_t oscr, nextmatch, oldmatch;
149 int s;
150
151 #if 0
152 mtx_lock_spin(&clock_lock);
153 #endif
154 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
155 SAOST_SR, 1);
156
157 /* schedule next clock intr */
158 oldmatch = saost_sc->sc_clock_count;
159 nextmatch = oldmatch + TIMER_FREQUENCY / hz;
160
161 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
162 SAOST_CR);
163
164 if ((nextmatch > oldmatch &&
165 (oscr > nextmatch || oscr < oldmatch)) ||
166 (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) {
167 /*
168 * we couldn't set the matching register in time.
169 * just set it to some value so that next interrupt happens.
170 * XXX is it possible to compansate lost interrupts?
171 */
172
173 s = splhigh();
174 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
175 SAOST_CR);
176 nextmatch = oscr + 10;
177 splx(s);
178 }
179 saost_sc->sc_clock_count = nextmatch;
180 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0,
181 nextmatch);
182 hardclock(frame);
183 #if 0
184 mtx_unlock_spin(&clock_lock);
185 #endif
186 }
187
188 #if 0
189 static void
190 statintr(arg)
191 void *arg;
192 {
193 struct clockframe *frame = arg;
194 u_int32_t oscr, nextmatch, oldmatch;
195 int s;
196
197 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
198 SAOST_SR, 2);
199
200 /* schedule next clock intr */
201 oldmatch = saost_sc->sc_statclock_count;
202 nextmatch = oldmatch + saost_sc->sc_statclock_step;
203
204 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1,
205 nextmatch);
206 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
207 SAOST_CR);
208
209 if ((nextmatch > oldmatch &&
210 (oscr > nextmatch || oscr < oldmatch)) ||
211 (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) {
212 /*
213 * we couldn't set the matching register in time.
214 * just set it to some value so that next interrupt happens.
215 * XXX is it possible to compansate lost interrupts?
216 */
217
218 s = splhigh();
219 oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
220 SAOST_CR);
221 nextmatch = oscr + 10;
222 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
223 SAOST_MR1, nextmatch);
224 splx(s);
225 }
226
227 saost_sc->sc_statclock_count = nextmatch;
228 statclock(frame);
229
230 }
231 #endif
232
233 #if 0
234 void
235 setstatclockrate(int hz)
236 {
237 u_int32_t count;
238
239 saost_sc->sc_statclock_step = TIMER_FREQUENCY / hz;
240 count = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR);
241 count += saost_sc->sc_statclock_step;
242 saost_sc->sc_statclock_count = count;
243 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
244 SAOST_MR1, count);
245 }
246 #endif
247 void
248 cpu_initclocks()
249 {
250 device_t dev = saost_sc->sc_dev;
251
252 stathz = STATHZ;
253 profhz = stathz;
254 #if 0
255 mtx_init(&clock_lock, "SA1110 Clock locké", NULL, MTX_SPIN);
256 #endif
257 saost_sc->sc_statclock_step = TIMER_FREQUENCY / stathz;
258 struct resource *irq1, *irq2;
259 int rid = 0;
260 void *ih1/*, *ih2 */;
261
262 printf("clock: hz=%d stathz = %d\n", hz, stathz);
263
264 /* Use the channels 0 and 1 for hardclock and statclock, respectively */
265 saost_sc->sc_clock_count = TIMER_FREQUENCY / hz;
266 saost_sc->sc_statclock_count = TIMER_FREQUENCY / stathz;
267
268 irq1 = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0,
269 ~0, 1, RF_ACTIVE);
270 rid = 1;
271 irq2 = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
272 RF_ACTIVE);
273 bus_setup_intr(dev, irq1, INTR_TYPE_CLK | INTR_FAST, clockintr, NULL,
274 &ih1);
275 #if 0
276 bus_setup_intr(dev, irq2, INTR_TYPE_CLK | INTR_FAST, statintr, NULL
277 ,&ih2);
278 #endif
279 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf);
280 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 3);
281 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0,
282 saost_sc->sc_clock_count);
283 #if 0
284 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1,
285 0);
286 #endif
287 /* Zero the counter value */
288 bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR, 0);
289 }
290
291 int
292 gettick()
293 {
294 int counter;
295 u_int savedints;
296 savedints = disable_interrupts(I32_bit);
297
298 counter = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
299 SAOST_CR);
300
301 restore_interrupts(savedints);
302 return counter;
303 }
304
305 void
306 DELAY(usecs)
307 int usecs;
308 {
309 u_int32_t tick, otick, delta;
310 int j, csec, usec;
311
312 csec = usecs / 10000;
313 usec = usecs % 10000;
314
315 usecs = (TIMER_FREQUENCY / 100) * csec
316 + (TIMER_FREQUENCY / 100) * usec / 10000;
317
318 if (! saost_sc) {
319 /* clock isn't initialized yet */
320 for(; usecs > 0; usecs--)
321 for(j = 100; j > 0; j--)
322 ;
323 return;
324 }
325
326 #if 0
327 mtx_lock_spin(&clock_lock);
328 #endif
329 otick = gettick();
330
331 while (1) {
332 for(j = 100; j > 0; j--)
333 ;
334 tick = gettick();
335 delta = tick - otick;
336 if (delta > usecs) {
337 break;
338 }
339 usecs -= delta;
340 otick = tick;
341 }
342 #if 0
343 mtx_unlock_spin(&clock_lock);
344 #endif
345 }
346
347 void
348 cpu_startprofclock(void)
349 {
350 printf("STARTPROFCLOCK\n");
351 }
352
353 void
354 cpu_stopprofclock(void)
355 {
356 }
Cache object: d8aba7bd9081413e5cc6c8915712a41a
|