Annotation of sys/arch/mvme68k/dev/clock.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: clock.c,v 1.13 2004/07/30 22:29:44 miod Exp $ */
2:
3: /*
4: * Copyright (c) 1995 Theo de Raadt
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: *
27: * Copyright (c) 1992, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * This software was developed by the Computer Systems Engineering group
31: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
32: * contributed to Berkeley.
33: *
34: * All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Lawrence Berkeley Laboratory.
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that the following conditions
41: * are met:
42: * 1. Redistributions of source code must retain the above copyright
43: * notice, this list of conditions and the following disclaimer.
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in the
46: * documentation and/or other materials provided with the distribution.
47: * 3. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)clock.c 8.1 (Berkeley) 6/11/93
64: */
65:
66: #include <sys/param.h>
67: #include <sys/device.h>
68: #include <sys/kernel.h>
69: #include <sys/systm.h>
70:
71: #include <machine/psl.h>
72: #include <machine/autoconf.h>
73: #include <machine/cpu.h>
74:
75: #include "pcc.h"
76: #include "mc.h"
77: #include "pcctwo.h"
78:
79: #if NPCC > 0
80: #include <mvme68k/dev/pccreg.h>
81: #endif
82: #if NPCCTWO > 0
83: #include <mvme68k/dev/pcctworeg.h>
84: #include <mvme68k/dev/vme.h>
85: extern struct vme2reg *sys_vme2;
86: #endif
87: #if NMC > 0
88: #include <mvme68k/dev/mcreg.h>
89: #endif
90:
91: /*
92: * Statistics clock interval and variance, in usec. Variance must be a
93: * power of two. Since this gives us an even number, not an odd number,
94: * we discard one case and compensate. That is, a variance of 8192 would
95: * give us offsets in [0..8191]. Instead, we take offsets in [1..8191].
96: * This is symmetric about the point 2048, or statvar/2, and thus averages
97: * to that value (assuming uniform random numbers).
98: */
99: int statvar = 8192;
100: int statmin; /* statclock interval - 1/2*variance */
101:
102: struct clocksoftc {
103: struct device sc_dev;
104: struct intrhand sc_profih;
105: struct intrhand sc_statih;
106: };
107:
108: void clockattach(struct device *, struct device *, void *);
109: int clockmatch(struct device *, void *, void *);
110:
111: struct cfattach clock_ca = {
112: sizeof(struct clocksoftc), clockmatch, clockattach
113: };
114:
115: struct cfdriver clock_cd = {
116: NULL, "clock", DV_DULL
117: };
118:
119: int clockintr(void *);
120: int statintr(void *);
121:
122: int clockbus;
123: u_char stat_reset, prof_reset;
124:
125: /*
126: * Every machine must have a clock tick device of some sort; for this
127: * platform this file manages it, no matter what form it takes.
128: */
129: int
130: clockmatch(parent, vcf, args)
131: struct device *parent;
132: void *vcf, *args;
133: {
134: return (1);
135: }
136:
137: void
138: clockattach(parent, self, args)
139: struct device *parent, *self;
140: void *args;
141: {
142: struct confargs *ca = args;
143: struct clocksoftc *sc = (struct clocksoftc *)self;
144:
145: sc->sc_profih.ih_fn = clockintr;
146: sc->sc_profih.ih_arg = 0;
147: sc->sc_profih.ih_wantframe = 1;
148: sc->sc_profih.ih_ipl = ca->ca_ipl;
149:
150: sc->sc_statih.ih_fn = statintr;
151: sc->sc_statih.ih_arg = 0;
152: sc->sc_statih.ih_wantframe = 1;
153: sc->sc_statih.ih_ipl = ca->ca_ipl;
154:
155: clockbus = ca->ca_bustype;
156: switch (ca->ca_bustype) {
157: #if NPCC > 0
158: case BUS_PCC:
159: prof_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
160: stat_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
161: pccintr_establish(PCCV_TIMER1, &sc->sc_profih, "clock");
162: pccintr_establish(PCCV_TIMER2, &sc->sc_statih, "stat");
163: break;
164: #endif
165: #if NMC > 0
166: case BUS_MC:
167: prof_reset = ca->ca_ipl | MC_IRQ_IEN | MC_IRQ_ICLR;
168: stat_reset = ca->ca_ipl | MC_IRQ_IEN | MC_IRQ_ICLR;
169: mcintr_establish(MCV_TIMER1, &sc->sc_profih, "clock");
170: mcintr_establish(MCV_TIMER2, &sc->sc_statih, "stat");
171: break;
172: #endif
173: #if NPCCTWO > 0
174: case BUS_PCCTWO:
175: prof_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
176: stat_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
177: pcctwointr_establish(PCC2V_TIMER1, &sc->sc_profih, "clock");
178: pcctwointr_establish(PCC2V_TIMER2, &sc->sc_statih, "stat");
179: break;
180: #endif
181: }
182:
183: printf("\n");
184: }
185:
186: /*
187: * clockintr: ack intr and call hardclock
188: */
189: int
190: clockintr(arg)
191: void *arg;
192: {
193: switch (clockbus) {
194: #if NPCC > 0
195: case BUS_PCC:
196: sys_pcc->pcc_t1irq = prof_reset;
197: break;
198: #endif
199: #if NMC > 0
200: case BUS_MC:
201: sys_mc->mc_t1irq = prof_reset;
202: break;
203: #endif
204: #if NPCCTWO > 0
205: case BUS_PCCTWO:
206: sys_pcc2->pcc2_t1irq = prof_reset;
207: break;
208: #endif
209: }
210:
211: hardclock(arg);
212: return (1);
213: }
214:
215: /*
216: * Set up real-time clock; we don't have a statistics clock at
217: * present.
218: */
219: void
220: cpu_initclocks()
221: {
222: register int statint, minint;
223:
224: if (1000000 % hz) {
225: printf("cannot get %d Hz clock; using 100 Hz\n", hz);
226: hz = 100;
227: tick = 1000000 / hz;
228: }
229: if (stathz == 0)
230: stathz = hz;
231: if (1000000 % stathz) {
232: printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
233: stathz = 100;
234: }
235: profhz = stathz; /* always */
236:
237: statint = 1000000 / stathz;
238: minint = statint / 2 + 100;
239: while (statvar > minint)
240: statvar >>= 1;
241: switch (clockbus) {
242: #if NPCC > 0
243: case BUS_PCC:
244: sys_pcc->pcc_t1pload = pcc_timer_us2lim(tick);
245: sys_pcc->pcc_t1ctl = PCC_TIMERCLEAR;
246: sys_pcc->pcc_t1ctl = PCC_TIMERSTART;
247: sys_pcc->pcc_t1irq = prof_reset;
248:
249: sys_pcc->pcc_t2pload = pcc_timer_us2lim(statint);
250: sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
251: sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
252: sys_pcc->pcc_t2irq = stat_reset;
253: break;
254: #endif
255: #if NMC > 0
256: case BUS_MC:
257: /* profclock */
258: sys_mc->mc_t1ctl = 0;
259: sys_mc->mc_t1cmp = mc_timer_us2lim(tick);
260: sys_mc->mc_t1count = 0;
261: sys_mc->mc_t1ctl = MC_TCTL_CEN | MC_TCTL_COC | MC_TCTL_COVF;
262: sys_mc->mc_t1irq = prof_reset;
263:
264: /* statclock */
265: sys_mc->mc_t2ctl = 0;
266: sys_mc->mc_t2cmp = mc_timer_us2lim(statint);
267: sys_mc->mc_t2count = 0;
268: sys_mc->mc_t2ctl = MC_TCTL_CEN | MC_TCTL_COC | MC_TCTL_COVF;
269: sys_mc->mc_t2irq = stat_reset;
270: break;
271: #endif
272: #if NPCCTWO > 0
273: case BUS_PCCTWO:
274: /* profclock */
275: sys_pcc2->pcc2_t1ctl = 0;
276: sys_pcc2->pcc2_t1cmp = pcc2_timer_us2lim(tick);
277: sys_pcc2->pcc2_t1count = 0;
278: sys_pcc2->pcc2_t1ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
279: PCC2_TCTL_COVF;
280: sys_pcc2->pcc2_t1irq = prof_reset;
281:
282: /* statclock */
283: sys_pcc2->pcc2_t2ctl = 0;
284: sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(statint);
285: sys_pcc2->pcc2_t2count = 0;
286: sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
287: PCC2_TCTL_COVF;
288: sys_pcc2->pcc2_t2irq = stat_reset;
289: break;
290: #endif
291: }
292: statmin = statint - (statvar >> 1);
293: }
294:
295: void
296: setstatclockrate(newhz)
297: int newhz;
298: {
299: }
300:
301: int
302: statintr(cap)
303: void *cap;
304: {
305: register u_long newint, r, var;
306:
307: switch (clockbus) {
308: #if NPCC > 0
309: case BUS_PCC:
310: sys_pcc->pcc_t2irq = stat_reset;
311: break;
312: #endif
313: #if NMC > 0
314: case BUS_MC:
315: sys_mc->mc_t2irq = stat_reset;
316: break;
317: #endif
318: #if NPCCTWO > 0
319: case BUS_PCCTWO:
320: sys_pcc2->pcc2_t2irq = stat_reset;
321: break;
322: #endif
323: }
324:
325: statclock((struct clockframe *)cap);
326:
327: /*
328: * Compute new randomized interval. The intervals are uniformly
329: * distributed on [statint - statvar / 2, statint + statvar / 2],
330: * and therefore have mean statint, giving a stathz frequency clock.
331: */
332: var = statvar;
333: do {
334: r = random() & (var - 1);
335: } while (r == 0);
336: newint = statmin + r;
337:
338: switch (clockbus) {
339: #if NPCC > 0
340: case BUS_PCC:
341: sys_pcc->pcc_t2pload = pcc_timer_us2lim(newint);
342: sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
343: sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
344: sys_pcc->pcc_t2irq = stat_reset;
345: break;
346: #endif
347: #if NMC > 0
348: case BUS_MC:
349: sys_mc->mc_t2ctl = 0;
350: sys_mc->mc_t2cmp = mc_timer_us2lim(newint);
351: sys_mc->mc_t2count = 0; /* should I? */
352: sys_mc->mc_t2irq = stat_reset;
353: sys_mc->mc_t2ctl = MC_TCTL_CEN | MC_TCTL_COC;
354: break;
355: #endif
356: #if NPCCTWO > 0
357: case BUS_PCCTWO:
358: sys_pcc2->pcc2_t2ctl = 0;
359: sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(newint);
360: sys_pcc2->pcc2_t2count = 0; /* should I? */
361: sys_pcc2->pcc2_t2irq = stat_reset;
362: sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC;
363: break;
364: #endif
365: }
366: return (1);
367: }
368:
369: void
370: delay(us)
371: int us;
372: {
373: #if (NPCC > 0) || (NPCCTWO > 0)
374: volatile register int c;
375: #endif
376:
377: switch (clockbus) {
378: #if NPCC > 0
379: case BUS_PCC:
380: /*
381: * XXX MVME147 doesn't have a 3rd free-running timer,
382: * so we use a stupid loop. Fix the code to watch t1:
383: * the profiling timer.
384: */
385: c = 2 * us;
386: while (--c > 0)
387: ;
388: break;
389: #endif
390: #if NMC > 0
391: case BUS_MC:
392: /*
393: * Reset and restart a free-running timer 1MHz, watch
394: * for it to reach the required count.
395: */
396: sys_mc->mc_t3irq = 0;
397: sys_mc->mc_t3ctl = 0;
398: sys_mc->mc_t3count = 0;
399: sys_mc->mc_t3ctl = MC_TCTL_CEN | MC_TCTL_COVF;
400:
401: while (sys_mc->mc_t3count < us)
402: ;
403: break;
404: #endif
405: #if NPCCTWO > 0
406: case BUS_PCCTWO:
407: /*
408: * Use the first VMEChip2 timer in polling mode whenever
409: * possible. However, since clock attaches before vme,
410: * use a tight loop if necessary.
411: */
412: {
413: struct vme2reg *vme2;
414:
415: if (sys_vme2 != NULL)
416: vme2 = sys_vme2;
417: else
418: vme2 = (struct vme2reg *)IIOV(0xfff40000);
419:
420: vme2->vme2_t1cmp = 0xffffffff;
421: vme2->vme2_t1count = 0;
422: vme2->vme2_tctl |= VME2_TCTL_CEN;
423:
424: while (vme2->vme2_t1count < us)
425: ;
426:
427: vme2->vme2_tctl &= ~VME2_TCTL_CEN;
428: }
429: break;
430: #endif
431: }
432: }
CVSweb