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