xref: /netbsd/sys/arch/sparc/sparc/timer_msiiep.c (revision c4a72b64)
1 /*	$NetBSD: timer_msiiep.c,v 1.4 2002/10/02 16:02:11 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  * Copyright (c) 1994 Gordon W. Ross
7  * Copyright (c) 1993 Adam Glass
8  * Copyright (c) 1996 Paul Kranenburg
9  * Copyright (c) 1996
10  * 	The President and Fellows of Harvard College. All rights reserved.
11  *
12  * This software was developed by the Computer Systems Engineering group
13  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
14  * contributed to Berkeley.
15  *
16  * All advertising materials mentioning features or use of this software
17  * must display the following acknowledgement:
18  *	This product includes software developed by Harvard University.
19  *	This product includes software developed by the University of
20  *	California, Lawrence Berkeley Laboratory.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  *
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *	This product includes software developed by the University of
34  *	California, Berkeley and its contributors.
35  *	This product includes software developed by Paul Kranenburg.
36  *	This product includes software developed by Harvard University.
37  * 4. Neither the name of the University nor the names of its contributors
38  *    may be used to endorse or promote products derived from this software
39  *    without specific prior written permission.
40  *
41  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  *	@(#)clock.c	8.1 (Berkeley) 6/11/93
54  */
55 
56 /*
57  * MicroSPARC-IIep timer support.
58  */
59 
60 #include <sys/param.h>
61 #include <sys/kernel.h>
62 #include <sys/device.h>
63 #include <sys/systm.h>
64 
65 #include <machine/bus.h>
66 
67 #include <sparc/sparc/timerreg.h>
68 #include <sparc/sparc/timervar.h>
69 
70 #include <sparc/sparc/msiiepreg.h>
71 #include <sparc/sparc/msiiepvar.h>
72 
73 static int timerok;
74 
75 static struct intrhand level10;
76 static struct intrhand level14;
77 
78 /* XXX: move this stuff to msiiepreg.h? */
79 
80 /* ms-IIep PCIC registers mapped at fixed VA (see vaddrs.h) */
81 #define	msiiep	((volatile struct msiiep_pcic_reg *)MSIIEP_PCIC_VA)
82 
83 /*
84  * ms-IIep counters tick every 4 cpu clock @100MHz.
85  * counter is reset to 1 when new limit is written.
86  */
87 #define	tmr_ustolimIIep(n)	((n) * 25 + 1)
88 
89 /*
90  * Set up the real-time and statistics clocks.
91  * Leave stathz 0 only if no alternative timer is available.
92  *
93  * The frequencies of these clocks must be an even number of microseconds.
94  */
95 static void
96 timer_init_msiiep(void)
97 {
98 
99 	/* ms-IIep kernels support *only* IIep */
100 	msiiep->pcic_sclr = tmr_ustolimIIep(tick);
101 	msiiep->pcic_pclr = tmr_ustolimIIep(statint);
102 	/* XXX: ensure interrupt target mask doesn't masks them? */
103 }
104 
105 /*
106  * Level 10 (clock) interrupts from system counter.
107  */
108 static int
109 clockintr_msiiep(void *cap)
110 {
111 	volatile int discard;
112 
113 	/* read the limit register to clear the interrupt */
114 	discard = msiiep->pcic_sclr;
115 	hardclock((struct clockframe *)cap);
116 	return (1);
117 }
118 
119 /*
120  * Level 14 (stat clock) interrupts from processor counter.
121  */
122 static int
123 statintr_msiiep(void *cap)
124 {
125 	volatile int discard;
126 	u_long newint;
127 
128 	/* read the limit register to clear the interrupt */
129 	discard = msiiep->pcic_pclr;
130 	if (timerok == 0) {
131 		/* Stop the clock */
132 		printf("note: counter running!\n");
133 		/*
134 		 * Turn interrupting processor counter
135 		 * into non-interrupting user timer.
136 		 */
137 		msiiep->pcic_pc_cfg = 1; /* make it a user timer */
138 		msiiep->pcic_pc_ctl = 0; /* stop user timer */
139 		return (1);
140 	}
141 
142 	statclock((struct clockframe *)cap);
143 
144 	/*
145 	 * Compute new randomized interval.
146 	 */
147 	newint = new_interval();
148 
149 	/*
150 	 * Use the `non-resetting' limit register, so we don't
151 	 * loose the counter ticks that happened since this
152 	 * interrupt was raised.
153 	 */
154 	msiiep->pcic_pclr_nr = tmr_ustolimIIep(newint);
155 	return (1);
156 }
157 
158 static int
159 timermatch_msiiep(struct device *parent, struct cfdata *cf, void *aux)
160 {
161 	struct msiiep_attach_args *msa = aux;
162 
163 	return (strcmp(msa->msa_name, "timer") == 0);
164 }
165 
166 static void
167 timerattach_msiiep(struct device *parent, struct device *self, void *aux)
168 {
169 
170 	/*
171 	 * Attach system and cpu counters (kernel hard and stat clocks)
172 	 * for ms-IIep. Counters are part of the PCIC and there's no
173 	 * PROM node for them.
174 	 */
175 
176 	/* Put processor counter in "counter" mode */
177 	msiiep->pcic_pc_ctl = 0; /* stop user timer (just in case) */
178 	msiiep->pcic_pc_cfg = 0; /* timer mode disabled (processor counter) */
179 
180 	/*
181 	 * Calibrate delay() by tweaking the magic constant
182 	 * until a delay(100) actually reads (at least) 100 us on the clock.
183 	 * Note: ms-IIep clocks ticks every 4 processor cycles.
184 	 */
185 	for (timerblurb = 1; ; ++timerblurb) {
186 		volatile int discard;
187 		int t;
188 
189 		discard = msiiep->pcic_pclr; /* clear the limit bit */
190 		msiiep->pcic_pclr = 0; /* reset counter to 1, free run */
191 		delay(100);
192 		t = msiiep->pcic_pccr;
193 
194 		if (t & TMR_LIMIT) /* cannot happen */
195 			panic("delay calibration");
196 
197 		/* counter ticks -> usec, inverse of tmr_ustolimIIep */
198 		t = (t - 1) / 25;
199 		if (t >= 100)
200 			break;
201 	}
202 	printf(": delay constant %d\n", timerblurb);
203 
204 	/*
205 	 * Set counter interrupt priority assignment:
206 	 * upper 4 bits are for system counter: level 10
207 	 * lower 4 bits are for processor counter: level 14
208 	 */
209 	msiiep->pcic_cipar = 0xae;
210 
211 	timer_init = timer_init_msiiep;
212 	level10.ih_fun = clockintr_msiiep;
213 	level14.ih_fun = statintr_msiiep;
214 
215 	/* link interrupt handlers */
216 	intr_establish(10, &level10);
217 	intr_establish(14, &level14);
218 
219 	timerok = 1;
220 }
221 
222 CFATTACH_DECL(timer_msiiep, sizeof(struct device),
223     timermatch_msiiep, timerattach_msiiep, NULL, NULL);
224