Tue Mar 13 16:48:05 2018 UTC ()
Pull up following revision(s) (requested by mrg in ticket #1519):
	sys/arch/sparc/sparc/timer_sun4m.c: 1.33 1.34 1.31
	sys/arch/sparc/sparc/timer.c: 1.33
	sys/arch/sparc/sparc/timer.c: 1.33 1.34
	sys/arch/sparc/sparc/timerreg.h: 1.33 1.34 1.31 1.10
fix time goes backwards problems on sparc.
there are a few things here:
- there's a race between reading the limit register (which clears
  the interrupt and the limit bit) and increasing the latest offset.
  this can happen easily if an interrupt comes between the read and
  the call to tickle_tc() that increases the offset (i obverved this
  actually happening.)
- in early boot, sometimes the counter can cycle twice before the
  tickle happens.
to handle these issues, add two workarounds:
- if the limit bit isn't set, but the counter value is less than
  the previous value, and the offset hasn't changed, use the same
  fixup as if the limit bit was set.  this handles the first case
  above.
- add a hard-workaround for never allowing returning a smaller
  value (except during 32 bit overflow): if the result is less than
  the last result, add fixups until it does (or until it would
  overflow.)
the first workaround fixes general run-time issues, and the second
fixes issues only seen during boot.
also expand some comments in timer_sun4m.c and re-enable the sun4m
sub-microsecond tmr_ustolim4m() support (but it's always called with
at least 'tick' microseconds, so the end result is the same.)
fix hang at 4B microseconds (1h12 or so), and simplify part of the previous


(snj)
diff -r1.29 -r1.29.8.1 src/sys/arch/sparc/sparc/timer.c
diff -r1.28 -r1.28.8.1 src/sys/arch/sparc/sparc/timer_sun4m.c
diff -r1.9 -r1.9.118.1 src/sys/arch/sparc/sparc/timerreg.h

cvs diff -r1.29 -r1.29.8.1 src/sys/arch/sparc/sparc/timer.c (switch to unified diff)

--- src/sys/arch/sparc/sparc/timer.c 2011/07/17 23:18:23 1.29
+++ src/sys/arch/sparc/sparc/timer.c 2018/03/13 16:48:05 1.29.8.1
@@ -1,328 +1,379 @@ @@ -1,328 +1,379 @@
1/* $NetBSD: timer.c,v 1.29 2011/07/17 23:18:23 mrg Exp $ */ 1/* $NetBSD: timer.c,v 1.29.8.1 2018/03/13 16:48:05 snj Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1994 Gordon W. Ross 6 * Copyright (c) 1994 Gordon W. Ross
7 * Copyright (c) 1993 Adam Glass 7 * Copyright (c) 1993 Adam Glass
8 * Copyright (c) 1996 Paul Kranenburg 8 * Copyright (c) 1996 Paul Kranenburg
9 * Copyright (c) 1996 9 * Copyright (c) 1996
10 * The President and Fellows of Harvard College. All rights reserved. 10 * The President and Fellows of Harvard College. All rights reserved.
11 * 11 *
12 * This software was developed by the Computer Systems Engineering group 12 * This software was developed by the Computer Systems Engineering group
13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
14 * contributed to Berkeley. 14 * contributed to Berkeley.
15 * 15 *
16 * All advertising materials mentioning features or use of this software 16 * All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement: 17 * must display the following acknowledgement:
18 * This product includes software developed by Harvard University. 18 * This product includes software developed by Harvard University.
19 * This product includes software developed by the University of 19 * This product includes software developed by the University of
20 * California, Lawrence Berkeley Laboratory. 20 * California, Lawrence Berkeley Laboratory.
21 * 21 *
22 * Redistribution and use in source and binary forms, with or without 22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions 23 * modification, are permitted provided that the following conditions
24 * are met: 24 * are met:
25 * 25 *
26 * 1. Redistributions of source code must retain the above copyright 26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer. 27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright 28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the 29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution. 30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software 31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement: 32 * must display the following acknowledgement:
33 * This product includes software developed by the University of 33 * This product includes software developed by the University of
34 * California, Berkeley and its contributors. 34 * California, Berkeley and its contributors.
35 * This product includes software developed by Paul Kranenburg. 35 * This product includes software developed by Paul Kranenburg.
36 * This product includes software developed by Harvard University. 36 * This product includes software developed by Harvard University.
37 * 4. Neither the name of the University nor the names of its contributors 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 38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission. 39 * without specific prior written permission.
40 * 40 *
41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE. 51 * SUCH DAMAGE.
52 * 52 *
53 * @(#)clock.c 8.1 (Berkeley) 6/11/93 53 * @(#)clock.c 8.1 (Berkeley) 6/11/93
54 */ 54 */
55 55
56/* 56/*
57 * Kernel clocks provided by "timer" device. The hardclock is provided by 57 * Kernel clocks provided by "timer" device. The hardclock is provided by
58 * the timer register (aka system counter). The statclock is provided by 58 * the timer register (aka system counter). The statclock is provided by
59 * per CPU counter register(s) (aka processor counter(s)). 59 * per CPU counter register(s) (aka processor counter(s)).
60 */ 60 */
61 61
62#include <sys/cdefs.h> 62#include <sys/cdefs.h>
63__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.29 2011/07/17 23:18:23 mrg Exp $"); 63__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.29.8.1 2018/03/13 16:48:05 snj Exp $");
64 64
65#include <sys/param.h> 65#include <sys/param.h>
66#include <sys/kernel.h> 66#include <sys/kernel.h>
67#include <sys/device.h> 67#include <sys/device.h>
68#include <sys/systm.h> 68#include <sys/systm.h>
69#include <sys/timetc.h> 69#include <sys/timetc.h>
70 70
71#include <machine/autoconf.h> 71#include <machine/autoconf.h>
72#include <sys/bus.h> 72#include <sys/bus.h>
73 73
74#include <sparc/sparc/timerreg.h> 74#include <sparc/sparc/timerreg.h>
75#include <sparc/sparc/timervar.h> 75#include <sparc/sparc/timervar.h>
76 76
77static struct intrhand level10; 77static struct intrhand level10;
78static struct intrhand level14; 78static struct intrhand level14;
79 79
80static u_int timer_get_timecount(struct timecounter *); 80static u_int timer_get_timecount(struct timecounter *);
81 81
82/* 82/*
83 * timecounter local state 83 * timecounter local state
84 */ 84 */
85static struct counter { 85static struct counter {
86 volatile u_int *cntreg; /* counter register */ 86 __cpu_simple_lock_t lock; /* protects access to offset, reg, last* */
 87 volatile u_int *cntreg; /* counter register to read */
87 u_int limit; /* limit we count up to */ 88 u_int limit; /* limit we count up to */
88 u_int offset; /* accumulated offet due to wraps */ 89 u_int offset; /* accumulated offet due to wraps */
89 u_int shift; /* scaling for valid bits */ 90 u_int shift; /* scaling for valid bits */
90 u_int mask; /* valid bit mask */ 91 u_int mask; /* valid bit mask */
91} cntr; 92 u_int lastcnt; /* the last* values are used to notice */
 93 u_int lastres; /* and fix up cases where it would appear */
 94 u_int lastoffset; /* time went backwards. */
 95} cntr __aligned(CACHE_LINE_SIZE);
92 96
93/* 97/*
94 * define timecounter 98 * define timecounter
95 */ 99 */
96 100
97static struct timecounter counter_timecounter = { 101static struct timecounter counter_timecounter = {
98 timer_get_timecount, /* get_timecount */ 102 .tc_get_timecount = timer_get_timecount,
99 0, /* no poll_pps */ 103 .tc_poll_pps = NULL,
100 ~0u, /* counter_mask */ 104 .tc_counter_mask = ~0u,
101 0, /* frequency - set at initialisation */ 105 .tc_frequency = 0,
102 "timer-counter", /* name */ 106 .tc_name = "timer-counter",
103 100, /* quality */ 107 .tc_quality = 100,
104 &cntr /* private reference */ 108 .tc_priv = &cntr,
105}; 109};
106 110
107/* 111/*
108 * timer_get_timecount provide current counter value 112 * timer_get_timecount provide current counter value
109 */ 113 */
 114__attribute__((__optimize__("Os")))
110static u_int 115static u_int
111timer_get_timecount(struct timecounter *tc) 116timer_get_timecount(struct timecounter *tc)
112{ 117{
113 struct counter *ctr = (struct counter *)tc->tc_priv; 118 u_int cnt, res, fixup, offset;
114 
115 u_int c, res, r; 
116 int s; 119 int s;
117 120
118 121 /*
 122 * We use splhigh/__cpu_simple_lock here as we don't want
 123 * any mutex or lockdebug overhead. The lock protects a
 124 * bunch of the members of cntr that are written here to
 125 * deal with the various minor races to be observed and
 126 * worked around.
 127 */
119 s = splhigh(); 128 s = splhigh();
120 129
121 res = c = *ctr->cntreg; 130 __cpu_simple_lock(&cntr.lock);
 131 res = cnt = *cntr.cntreg;
122 132
123 res &= ~TMR_LIMIT; 133 res &= ~TMR_LIMIT;
 134 offset = cntr.offset;
124 135
125 if (c != res) { 136 /*
126 r = ctr->limit; 137 * There are 3 cases here:
 138 * - limit reached, interrupt not yet processed.
 139 * - count reset but offset the same, race between handling
 140 * the interrupt and tickle_tc() updating the offset.
 141 * - normal case.
 142 *
 143 * For the first two cases, add the limit so that we avoid
 144 * time going backwards.
 145 */
 146 if (cnt != res) {
 147 fixup = cntr.limit;
 148 } else if (res < cntr.lastcnt && offset == cntr.lastoffset) {
 149 fixup = cntr.limit;
127 } else { 150 } else {
128 r = 0; 151 fixup = 0;
129 } 152 }
 153
 154 cntr.lastcnt = res;
 155 cntr.lastoffset = offset;
130  156
131 res >>= ctr->shift; 157 res >>= cntr.shift;
132 res &= ctr->mask; 158 res &= cntr.mask;
133 159
134 res += r + ctr->offset; 160 res += fixup + offset;
135 161
 162 /*
 163 * This handles early-boot cases where the counter resets twice
 164 * before the offset is updated, and we have a stupid check to
 165 * ensure overflow hasn't happened.
 166 */
 167 if (res < cntr.lastres && res > (TMR_MASK+1) << 3)
 168 res = cntr.lastres + 1;
 169
 170 cntr.lastres = res;
 171
 172 __cpu_simple_unlock(&cntr.lock);
136 splx(s); 173 splx(s);
137 174
138 return res; 175 return res;
139} 176}
140 177
141void 178void
142tickle_tc(void) 179tickle_tc(void)
143{ 180{
 181
144 if (timecounter->tc_get_timecount == timer_get_timecount) { 182 if (timecounter->tc_get_timecount == timer_get_timecount) {
 183 /*
 184 * This could be protected by cntr.lock/splhigh but the update
 185 * happens at IPL10 already and as a 32 bit value it should
 186 * never be seen as a partial update, so skip it here. This
 187 * also probably slows down the actual offset update, making
 188 * one of the cases above more likely to need the workaround.
 189 */
145 cntr.offset += cntr.limit; 190 cntr.offset += cntr.limit;
146 } 191 }
147} 192}
148 193
149/* 194/*
150 * sun4/sun4c/sun4m common timer attach code 195 * sun4/sun4c/sun4m common timer attach code
151 */ 196 */
152void 197void
153timerattach(volatile int *cntreg, volatile int *limreg) 198timerattach(volatile int *cntreg, volatile int *limreg)
154{ 199{
155 u_int prec = 0, t0; 200 u_int prec = 0, t0;
156 void (*sched_intr_fn)(void *); 201 void (*sched_intr_fn)(void *);
157 202
158 /* 203 /*
159 * Calibrate delay() by tweaking the magic constant 204 * Calibrate delay() by tweaking the magic constant
160 * until a delay(100) actually reads (at least) 100 us on the clock. 205 * until a delay(100) actually reads (at least) 100 us on the clock.
161 * Note: sun4m clocks tick with 500ns periods. 206 * Note: sun4m clocks tick with 500ns periods.
162 */ 207 */
163 for (timerblurb = 1; ; timerblurb++) { 208 for (timerblurb = 1; ; timerblurb++) {
164 volatile int discard; 209 volatile int discard;
165 u_int t1; 210 u_int t1;
166 211
167 /* Reset counter register by writing some large limit value */ 212 /* Reset counter register by writing some large limit value */
168 discard = *limreg; 213 discard = *limreg;
169 *limreg = tmr_ustolim(TMR_MASK-1); 214 *limreg = tmr_ustolim(TMR_MASK-1);
170 215
171 t0 = *cntreg; 216 t0 = *cntreg;
172 delay(100); 217 delay(100);
173 t1 = *cntreg; 218 t1 = *cntreg;
174  219
175 prec |= (t0 ^ t1) | (*cntreg ^ *cntreg); 220 prec |= (t0 ^ t1) | (*cntreg ^ *cntreg);
176 221
177 if (t1 & TMR_LIMIT) 222 if (t1 & TMR_LIMIT)
178 panic("delay calibration"); 223 panic("delay calibration");
179 224
180 t0 = (t0 >> TMR_SHIFT) & TMR_MASK; 225 t0 = (t0 >> TMR_SHIFT) & TMR_MASK;
181 t1 = (t1 >> TMR_SHIFT) & TMR_MASK; 226 t1 = (t1 >> TMR_SHIFT) & TMR_MASK;
182 227
183 if (t1 >= t0 + 100) 228 if (t1 >= t0 + 100)
184 break; 229 break;
185 } 230 }
186 231
187 /* find lowest active bit */ 232 /* find lowest active bit */
188 for (t0 = 0; t0 < TMR_SHIFT; t0++) 233 for (t0 = 0; t0 < TMR_SHIFT; t0++)
189 if ((1 << t0) & prec) 234 if ((1 << t0) & prec)
190 break; 235 break;
191 236
 237 __cpu_simple_lock_init(&cntr.lock);
 238
192 cntr.shift = t0; 239 cntr.shift = t0;
193 cntr.mask = (1 << (31-t0))-1; 240 cntr.mask = (1 << (31-t0))-1;
194 counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1); 241 counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1);
195  242
196 printf(": delay constant %d, frequency = %" PRIu64 " Hz\n", 243 printf(": delay constant %d, frequency = %" PRIu64 " Hz\n",
197 timerblurb, counter_timecounter.tc_frequency); 244 timerblurb, counter_timecounter.tc_frequency);
198 245
199#if defined(SUN4) || defined(SUN4C) 246#if defined(SUN4) || defined(SUN4C)
200 if (CPU_ISSUN4 || CPU_ISSUN4C) { 247 if (CPU_ISSUN4 || CPU_ISSUN4C) {
201 timer_init = timer_init_4; 248 timer_init = timer_init_4;
202 sched_intr_fn = schedintr; 249 sched_intr_fn = schedintr;
203 level10.ih_fun = clockintr_4; 250 level10.ih_fun = clockintr_4;
204 level14.ih_fun = statintr_4; 251 level14.ih_fun = statintr_4;
205 cntr.limit = tmr_ustolim(tick); 252 cntr.limit = tmr_ustolim(tick);
206 } 253 }
207#endif 254#endif
208#if defined(SUN4M) 255#if defined(SUN4M)
209 if (CPU_ISSUN4M) { 256 if (CPU_ISSUN4M) {
210 timer_init = timer_init_4m; 257 timer_init = timer_init_4m;
211#if defined(MULTIPROCESSOR) 258#if defined(MULTIPROCESSOR)
212 if (sparc_ncpus > 1) 259 if (sparc_ncpus > 1)
213 sched_intr_fn = schedintr_4m; 260 sched_intr_fn = schedintr_4m;
214 else 261 else
215#endif 262#endif
216 sched_intr_fn = schedintr; 263 sched_intr_fn = schedintr;
217 level10.ih_fun = clockintr_4m; 264 level10.ih_fun = clockintr_4m;
218 level14.ih_fun = statintr_4m; 265 level14.ih_fun = statintr_4m;
219 cntr.limit = tmr_ustolim4m(tick); 266 cntr.limit = tmr_ustolim4m(tick);
220 } 267 }
221#endif 268#endif
 269
222 /* link interrupt handlers */ 270 /* link interrupt handlers */
223 intr_establish(10, 0, &level10, NULL, true); 271 intr_establish(10, 0, &level10, NULL, true);
224 intr_establish(14, 0, &level14, NULL, true); 272 intr_establish(14, 0, &level14, NULL, true);
225 273
226 /* Establish a soft interrupt at a lower level for schedclock */ 274 /* Establish a soft interrupt at a lower level for schedclock */
227 sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL); 275 sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL);
228 if (sched_cookie == NULL) 276 if (sched_cookie == NULL)
229 panic("timerattach: cannot establish schedintr"); 277 panic("timerattach: cannot establish schedintr");
230 278
231 cntr.cntreg = cntreg; 279 cntr.cntreg = cntreg;
232 cntr.limit >>= cntr.shift; 280 cntr.limit >>= cntr.shift;
233 281
 282 /* start at non-zero, so that cntr.oldoffset is less */
 283 cntr.offset = cntr.limit;
 284
234 tc_init(&counter_timecounter); 285 tc_init(&counter_timecounter);
235} 286}
236 287
237/* 288/*
238 * Both sun4 and sun4m can attach a timer on obio. 289 * Both sun4 and sun4m can attach a timer on obio.
239 * The sun4m OPENPROM calls the timer the "counter". 290 * The sun4m OPENPROM calls the timer the "counter".
240 * The sun4 timer must be probed. 291 * The sun4 timer must be probed.
241 */ 292 */
242static int 293static int
243timermatch_obio(device_t parent, cfdata_t cf, void *aux) 294timermatch_obio(device_t parent, cfdata_t cf, void *aux)
244{ 295{
245#if defined(SUN4) || defined(SUN4M) 296#if defined(SUN4) || defined(SUN4M)
246 union obio_attach_args *uoba = aux; 297 union obio_attach_args *uoba = aux;
247#endif 298#endif
248#if defined(SUN4) 299#if defined(SUN4)
249 struct obio4_attach_args *oba; 300 struct obio4_attach_args *oba;
250#endif 301#endif
251 302
252#if defined(SUN4M) 303#if defined(SUN4M)
253 if (uoba->uoba_isobio4 == 0) 304 if (uoba->uoba_isobio4 == 0)
254 return (strcmp("counter", uoba->uoba_sbus.sa_name) == 0); 305 return (strcmp("counter", uoba->uoba_sbus.sa_name) == 0);
255#endif /* SUN4M */ 306#endif /* SUN4M */
256 307
257 if (CPU_ISSUN4 == 0) { 308 if (CPU_ISSUN4 == 0) {
258 printf("timermatch_obio: attach args mixed up\n"); 309 printf("timermatch_obio: attach args mixed up\n");
259 return (0); 310 return (0);
260 } 311 }
261 312
262#if defined(SUN4) 313#if defined(SUN4)
263 /* Only these sun4s have "timer" (others have "oclock") */ 314 /* Only these sun4s have "timer" (others have "oclock") */
264 if (cpuinfo.cpu_type != CPUTYP_4_300 && 315 if (cpuinfo.cpu_type != CPUTYP_4_300 &&
265 cpuinfo.cpu_type != CPUTYP_4_400) 316 cpuinfo.cpu_type != CPUTYP_4_400)
266 return (0); 317 return (0);
267 318
268 /* Make sure there is something there */ 319 /* Make sure there is something there */
269 oba = &uoba->uoba_oba4; 320 oba = &uoba->uoba_oba4;
270 return (bus_space_probe(oba->oba_bustag, oba->oba_paddr, 321 return (bus_space_probe(oba->oba_bustag, oba->oba_paddr,
271 4, /* probe size */ 322 4, /* probe size */
272 0, /* offset */ 323 0, /* offset */
273 0, /* flags */ 324 0, /* flags */
274 NULL, NULL)); 325 NULL, NULL));
275#endif /* SUN4 */ 326#endif /* SUN4 */
276 panic("timermatch_obio: impossible"); 327 panic("timermatch_obio: impossible");
277} 328}
278 329
279static void 330static void
280timerattach_obio(device_t parent, device_t self, void *aux) 331timerattach_obio(device_t parent, device_t self, void *aux)
281{ 332{
282 union obio_attach_args *uoba = aux; 333 union obio_attach_args *uoba = aux;
283 334
284 if (uoba->uoba_isobio4 == 0) { 335 if (uoba->uoba_isobio4 == 0) {
285#if defined(SUN4M) 336#if defined(SUN4M)
286 /* sun4m timer at obio */ 337 /* sun4m timer at obio */
287 timerattach_obio_4m(parent, self, aux); 338 timerattach_obio_4m(parent, self, aux);
288#endif /* SUN4M */ 339#endif /* SUN4M */
289 return; 340 return;
290 } 341 }
291 342
292 if (uoba->uoba_isobio4 != 0) { 343 if (uoba->uoba_isobio4 != 0) {
293#if defined(SUN4) 344#if defined(SUN4)
294 /* sun4 timer at obio */ 345 /* sun4 timer at obio */
295 timerattach_obio_4(parent, self, aux); 346 timerattach_obio_4(parent, self, aux);
296#endif /* SUN4 */ 347#endif /* SUN4 */
297 } 348 }
298} 349}
299 350
300CFATTACH_DECL_NEW(timer_obio, 0, 351CFATTACH_DECL_NEW(timer_obio, 0,
301 timermatch_obio, timerattach_obio, NULL, NULL); 352 timermatch_obio, timerattach_obio, NULL, NULL);
302 353
303/* 354/*
304 * Only sun4c attaches a timer at mainbus 355 * Only sun4c attaches a timer at mainbus
305 */ 356 */
306static int 357static int
307timermatch_mainbus(device_t parent, cfdata_t cf, void *aux) 358timermatch_mainbus(device_t parent, cfdata_t cf, void *aux)
308{ 359{
309#if defined(SUN4C) 360#if defined(SUN4C)
310 struct mainbus_attach_args *ma = aux; 361 struct mainbus_attach_args *ma = aux;
311 362
312 return (strcmp("counter-timer", ma->ma_name) == 0); 363 return (strcmp("counter-timer", ma->ma_name) == 0);
313#else 364#else
314 return (0); 365 return (0);
315#endif 366#endif
316} 367}
317 368
318static void 369static void
319timerattach_mainbus(device_t parent, device_t self, void *aux) 370timerattach_mainbus(device_t parent, device_t self, void *aux)
320{ 371{
321 372
322#if defined(SUN4C) 373#if defined(SUN4C)
323 timerattach_mainbus_4c(parent, self, aux); 374 timerattach_mainbus_4c(parent, self, aux);
324#endif /* SUN4C */ 375#endif /* SUN4C */
325} 376}
326 377
327CFATTACH_DECL_NEW(timer_mainbus, 0, 378CFATTACH_DECL_NEW(timer_mainbus, 0,
328 timermatch_mainbus, timerattach_mainbus, NULL, NULL); 379 timermatch_mainbus, timerattach_mainbus, NULL, NULL);

cvs diff -r1.28 -r1.28.8.1 src/sys/arch/sparc/sparc/timer_sun4m.c (switch to unified diff)

--- src/sys/arch/sparc/sparc/timer_sun4m.c 2011/09/01 08:43:24 1.28
+++ src/sys/arch/sparc/sparc/timer_sun4m.c 2018/03/13 16:48:05 1.28.8.1
@@ -1,267 +1,271 @@ @@ -1,267 +1,271 @@
1/* $NetBSD: timer_sun4m.c,v 1.28 2011/09/01 08:43:24 martin Exp $ */ 1/* $NetBSD: timer_sun4m.c,v 1.28.8.1 2018/03/13 16:48:05 snj Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1994 Gordon W. Ross 6 * Copyright (c) 1994 Gordon W. Ross
7 * Copyright (c) 1993 Adam Glass 7 * Copyright (c) 1993 Adam Glass
8 * Copyright (c) 1996 Paul Kranenburg 8 * Copyright (c) 1996 Paul Kranenburg
9 * Copyright (c) 1996 9 * Copyright (c) 1996
10 * The President and Fellows of Harvard College. All rights reserved. 10 * The President and Fellows of Harvard College. All rights reserved.
11 * 11 *
12 * This software was developed by the Computer Systems Engineering group 12 * This software was developed by the Computer Systems Engineering group
13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
14 * contributed to Berkeley. 14 * contributed to Berkeley.
15 * 15 *
16 * All advertising materials mentioning features or use of this software 16 * All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement: 17 * must display the following acknowledgement:
18 * This product includes software developed by Harvard University. 18 * This product includes software developed by Harvard University.
19 * This product includes software developed by the University of 19 * This product includes software developed by the University of
20 * California, Lawrence Berkeley Laboratory. 20 * California, Lawrence Berkeley Laboratory.
21 * 21 *
22 * Redistribution and use in source and binary forms, with or without 22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions 23 * modification, are permitted provided that the following conditions
24 * are met: 24 * are met:
25 * 25 *
26 * 1. Redistributions of source code must retain the above copyright 26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer. 27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright 28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the 29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution. 30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software 31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement: 32 * must display the following acknowledgement:
33 * This product includes software developed by the University of 33 * This product includes software developed by the University of
34 * California, Berkeley and its contributors. 34 * California, Berkeley and its contributors.
35 * This product includes software developed by Paul Kranenburg. 35 * This product includes software developed by Paul Kranenburg.
36 * This product includes software developed by Harvard University. 36 * This product includes software developed by Harvard University.
37 * 4. Neither the name of the University nor the names of its contributors 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 38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission. 39 * without specific prior written permission.
40 * 40 *
41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE. 51 * SUCH DAMAGE.
52 * 52 *
53 * @(#)clock.c 8.1 (Berkeley) 6/11/93 53 * @(#)clock.c 8.1 (Berkeley) 6/11/93
54 */ 54 */
55 55
56/* 56/*
57 * Sun4m timer support. 57 * Sun4m timer support.
58 */ 58 */
59 59
60#include <sys/cdefs.h> 60#include <sys/cdefs.h>
61__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.28 2011/09/01 08:43:24 martin Exp $"); 61__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.28.8.1 2018/03/13 16:48:05 snj Exp $");
62 62
63#include <sys/param.h> 63#include <sys/param.h>
64#include <sys/kernel.h> 64#include <sys/kernel.h>
65#include <sys/device.h> 65#include <sys/device.h>
66#include <sys/systm.h> 66#include <sys/systm.h>
67#include <sys/cpu.h> 67#include <sys/cpu.h>
68 68
69#include <machine/autoconf.h> 69#include <machine/autoconf.h>
70#include <sys/bus.h> 70#include <sys/bus.h>
71 71
72#include <sparc/sparc/vaddrs.h> 72#include <sparc/sparc/vaddrs.h>
73#include <sparc/sparc/cpuvar.h> 73#include <sparc/sparc/cpuvar.h>
74#include <sparc/sparc/timerreg.h> 74#include <sparc/sparc/timerreg.h>
75#include <sparc/sparc/timervar.h> 75#include <sparc/sparc/timervar.h>
76 76
77struct timer_4m *timerreg4m; 77static struct timer_4m *timerreg4m;
78#define counterreg4m cpuinfo.counterreg_4m 78#define counterreg4m cpuinfo.counterreg_4m
79 79
80/* 80/*
81 * Set up the real-time and statistics clocks. 81 * Set up the real-time and statistics clocks.
82 * Leave stathz 0 only if no alternative timer is available. 82 * Leave stathz 0 only if no alternative timer is available.
83 * 83 *
84 * The frequencies of these clocks must be an even number of microseconds. 84 * The frequencies of these clocks must be an even number of microseconds.
85 */ 85 */
86void 86void
87timer_init_4m(void) 87timer_init_4m(void)
88{ 88{
89 struct cpu_info *cpi; 89 struct cpu_info *cpi;
90 int n; 90 int n;
91 91
92 timerreg4m->t_limit = tmr_ustolim4m(tick); 92 timerreg4m->t_limit = tmr_ustolim4m(tick);
93 for (CPU_INFO_FOREACH(n, cpi)) { 93 for (CPU_INFO_FOREACH(n, cpi)) {
94 cpi->counterreg_4m->t_limit = tmr_ustolim4m(statint); 94 cpi->counterreg_4m->t_limit = tmr_ustolim4m(statint);
95 } 95 }
96 icr_si_bic(SINTR_T); 96 icr_si_bic(SINTR_T);
97} 97}
98 98
99void 99void
100schedintr_4m(void *v) 100schedintr_4m(void *v)
101{ 101{
102 102
103 kpreempt_disable(); 103 kpreempt_disable();
104#ifdef MULTIPROCESSOR 104#ifdef MULTIPROCESSOR
105 /* 105 /*
106 * We call hardclock() here so that we make sure it is called on 106 * We call hardclock() here so that we make sure it is called on
107 * all CPUs. This function ends up being called on sun4m systems 107 * all CPUs. This function ends up being called on sun4m systems
108 * every tick. 108 * every tick.
109 */ 109 */
110 if (!CPU_IS_PRIMARY(curcpu())) 110 if (!CPU_IS_PRIMARY(curcpu()))
111 hardclock(v); 111 hardclock(v);
112 112
113 /* 113 /*
114 * The factor 8 is only valid for stathz==100. 114 * The factor 8 is only valid for stathz==100.
115 * See also clock.c 115 * See also clock.c
116 */ 116 */
117 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) 117 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0)
118#endif 118#endif
119 schedclock(curlwp); 119 schedclock(curlwp);
120 kpreempt_enable(); 120 kpreempt_enable();
121} 121}
122 122
123 123
124/* 124/*
125 * Level 10 (clock) interrupts from system counter. 125 * Level 10 (clock) interrupts from system counter.
126 */ 126 */
127int 127int
128clockintr_4m(void *cap) 128clockintr_4m(void *cap)
129{ 129{
130 130
131 KASSERT(CPU_IS_PRIMARY(curcpu())); 131 KASSERT(CPU_IS_PRIMARY(curcpu()));
132 /* 132 /*
133 * XXX this needs to be fixed in a more general way 133 * XXX this needs to be fixed in a more general way
134 * problem is that the kernel enables interrupts and THEN 134 * problem is that the kernel enables interrupts and THEN
135 * sets up clocks. In between there's an opportunity to catch 135 * sets up clocks. In between there's an opportunity to catch
136 * a timer interrupt - if we call hardclock() at that point we'll 136 * a timer interrupt - if we call hardclock() at that point we'll
137 * panic 137 * panic
138 * so for now just bail when cold 138 * so for now just bail when cold
139 * 139 *
140 * For MP, we defer calling hardclock() to the schedintr so 140 * For MP, we defer calling hardclock() to the schedintr so
141 * that we call it on all cpus. 141 * that we call it on all cpus.
142 */ 142 */
143 if (cold) 143 if (cold)
144 return 0; 144 return 0;
 145
145 kpreempt_disable(); 146 kpreempt_disable();
146 /* read the limit register to clear the interrupt */ 147
 148 /* Read the limit register to clear the interrupt. */
147 *((volatile int *)&timerreg4m->t_limit); 149 *((volatile int *)&timerreg4m->t_limit);
 150
 151 /* Update the timecounter offset. */
148 tickle_tc(); 152 tickle_tc();
149 hardclock((struct clockframe *)cap); 153 hardclock((struct clockframe *)cap);
150 kpreempt_enable(); 154 kpreempt_enable();
151 return (1); 155 return (1);
152} 156}
153 157
154/* 158/*
155 * Level 14 (stat clock) interrupts from processor counter. 159 * Level 14 (stat clock) interrupts from processor counter.
156 */ 160 */
157int 161int
158statintr_4m(void *cap) 162statintr_4m(void *cap)
159{ 163{
160 struct clockframe *frame = cap; 164 struct clockframe *frame = cap;
161 u_long newint; 165 u_long newint;
162 166
163 kpreempt_disable(); 167 kpreempt_disable();
164 168
165 /* read the limit register to clear the interrupt */ 169 /* read the limit register to clear the interrupt */
166 *((volatile int *)&counterreg4m->t_limit); 170 *((volatile int *)&counterreg4m->t_limit);
167 171
168 statclock(frame); 172 statclock(frame);
169 173
170 /* 174 /*
171 * Compute new randomized interval. 175 * Compute new randomized interval.
172 */ 176 */
173 newint = new_interval(); 177 newint = new_interval();
174 178
175 /* 179 /*
176 * Use the `non-resetting' limit register, so we don't 180 * Use the `non-resetting' limit register, so we don't
177 * loose the counter ticks that happened since this 181 * loose the counter ticks that happened since this
178 * interrupt was raised. 182 * interrupt was raised.
179 */ 183 */
180 counterreg4m->t_limit_nr = tmr_ustolim4m(newint); 184 counterreg4m->t_limit_nr = tmr_ustolim4m(newint);
181 185
182 /* 186 /*
183 * The factor 8 is only valid for stathz==100. 187 * The factor 8 is only valid for stathz==100.
184 * See also clock.c 188 * See also clock.c
185 */ 189 */
186#if !defined(MULTIPROCESSOR) 190#if !defined(MULTIPROCESSOR)
187 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) { 191 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) {
188#endif 192#endif
189 if (CLKF_LOPRI(frame, IPL_SCHED)) { 193 if (CLKF_LOPRI(frame, IPL_SCHED)) {
190 /* No need to schedule a soft interrupt */ 194 /* No need to schedule a soft interrupt */
191 spllowerschedclock(); 195 spllowerschedclock();
192 schedintr_4m(cap); 196 schedintr_4m(cap);
193 } else { 197 } else {
194 /* 198 /*
195 * We're interrupting a thread that may have the 199 * We're interrupting a thread that may have the
196 * scheduler lock; run schedintr_4m() on this CPU later. 200 * scheduler lock; run schedintr_4m() on this CPU later.
197 */ 201 */
198 raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */ 202 raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */
199 } 203 }
200#if !defined(MULTIPROCESSOR) 204#if !defined(MULTIPROCESSOR)
201 } 205 }
202#endif 206#endif
203 kpreempt_enable(); 207 kpreempt_enable();
204 208
205 return (1); 209 return (1);
206} 210}
207 211
208void 212void
209timerattach_obio_4m(device_t parent, device_t self, void *aux) 213timerattach_obio_4m(device_t parent, device_t self, void *aux)
210{ 214{
211 union obio_attach_args *uoba = aux; 215 union obio_attach_args *uoba = aux;
212 struct sbus_attach_args *sa = &uoba->uoba_sbus; 216 struct sbus_attach_args *sa = &uoba->uoba_sbus;
213 struct cpu_info *cpi; 217 struct cpu_info *cpi;
214 bus_space_handle_t bh; 218 bus_space_handle_t bh;
215 int i, n; 219 int i, n;
216 220
217 if (sa->sa_nreg < 2) { 221 if (sa->sa_nreg < 2) {
218 printf(": only %d register sets\n", sa->sa_nreg); 222 printf(": only %d register sets\n", sa->sa_nreg);
219 return; 223 return;
220 } 224 }
221 225
222 /* Map the system timer */ 226 /* Map the system timer */
223 i = sa->sa_nreg - 1; 227 i = sa->sa_nreg - 1;
224 if (bus_space_map2(sa->sa_bustag, 228 if (bus_space_map2(sa->sa_bustag,
225 BUS_ADDR(sa->sa_reg[i].oa_space, 229 BUS_ADDR(sa->sa_reg[i].oa_space,
226 sa->sa_reg[i].oa_base), 230 sa->sa_reg[i].oa_base),
227 sizeof(struct timer_4m), 231 sizeof(struct timer_4m),
228 BUS_SPACE_MAP_LINEAR, 232 BUS_SPACE_MAP_LINEAR,
229 TIMERREG_VA, &bh) != 0) { 233 TIMERREG_VA, &bh) != 0) {
230 printf(": can't map registers\n"); 234 printf(": can't map registers\n");
231 return; 235 return;
232 } 236 }
233 timerreg4m = (struct timer_4m *)TIMERREG_VA; 237 timerreg4m = (struct timer_4m *)TIMERREG_VA;
234 238
235 /* Map each CPU's counter */ 239 /* Map each CPU's counter */
236 for (i = 0; i < sa->sa_nreg - 1; i++) { 240 for (i = 0; i < sa->sa_nreg - 1; i++) {
237 /* 241 /*
238 * Check whether the CPU corresponding to this timer 242 * Check whether the CPU corresponding to this timer
239 * register is installed. 243 * register is installed.
240 */ 244 */
241 for (CPU_INFO_FOREACH(n, cpi)) { 245 for (CPU_INFO_FOREACH(n, cpi)) {
242 if ((i == 0 && sparc_ncpus == 1) || cpi->mid == i + 8) { 246 if ((i == 0 && sparc_ncpus == 1) || cpi->mid == i + 8) {
243 /* We got a corresponding MID. */ 247 /* We got a corresponding MID. */
244 break; 248 break;
245 } 249 }
246 cpi = NULL; 250 cpi = NULL;
247 } 251 }
248 if (cpi == NULL) 252 if (cpi == NULL)
249 continue; 253 continue;
250 254
251 if (sbus_bus_map(sa->sa_bustag, 255 if (sbus_bus_map(sa->sa_bustag,
252 sa->sa_reg[i].oa_space, 256 sa->sa_reg[i].oa_space,
253 sa->sa_reg[i].oa_base, 257 sa->sa_reg[i].oa_base,
254 sizeof(struct timer_4m), 258 sizeof(struct timer_4m),
255 BUS_SPACE_MAP_LINEAR, 259 BUS_SPACE_MAP_LINEAR,
256 &bh) != 0) { 260 &bh) != 0) {
257 printf(": can't map CPU counter %d\n", i); 261 printf(": can't map CPU counter %d\n", i);
258 return; 262 return;
259 } 263 }
260 cpi->counterreg_4m = (struct counter_4m *)bh; 264 cpi->counterreg_4m = (struct counter_4m *)bh;
261 } 265 }
262 266
263 /* Put processor counter in "timer" mode */ 267 /* Put processor counter in "timer" mode */
264 timerreg4m->t_cfg = 0; 268 timerreg4m->t_cfg = 0;
265 269
266 timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit); 270 timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit);
267} 271}

cvs diff -r1.9 -r1.9.118.1 src/sys/arch/sparc/sparc/timerreg.h (switch to unified diff)

--- src/sys/arch/sparc/sparc/timerreg.h 2005/11/16 03:00:23 1.9
+++ src/sys/arch/sparc/sparc/timerreg.h 2018/03/13 16:48:05 1.9.118.1
@@ -1,128 +1,131 @@ @@ -1,128 +1,131 @@
1/* $NetBSD: timerreg.h,v 1.9 2005/11/16 03:00:23 uwe Exp $ */ 1/* $NetBSD: timerreg.h,v 1.9.118.1 2018/03/13 16:48:05 snj Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This software was developed by the Computer Systems Engineering group 7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley. 9 * contributed to Berkeley.
10 * 10 *
11 * All advertising materials mentioning features or use of this software 11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement: 12 * must display the following acknowledgement:
13 * This product includes software developed by the University of 13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory. 14 * California, Lawrence Berkeley Laboratory.
15 * 15 *
16 * Redistribution and use in source and binary forms, with or without 16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions 17 * modification, are permitted provided that the following conditions
18 * are met: 18 * are met:
19 * 1. Redistributions of source code must retain the above copyright 19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer. 20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright 21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the 22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution. 23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors 24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software 25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission. 26 * without specific prior written permission.
27 * 27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE. 38 * SUCH DAMAGE.
39 * 39 *
40 * @(#)timerreg.h 8.1 (Berkeley) 6/11/93 40 * @(#)timerreg.h 8.1 (Berkeley) 6/11/93
41 */ 41 */
42 42
43/* 43/*
44 * Sun-4c counter/timer registers. The timers are implemented within 44 * Sun-4c counter/timer registers. The timers are implemented within
45 * the cache chip (!). The counter and limit fields below could be 45 * the cache chip (!). The counter and limit fields below could be
46 * defined as: 46 * defined as:
47 * 47 *
48 * struct { 48 * struct {
49 * u_int t_limit:1, // limit reached 49 * u_int t_limit:1, // limit reached
50 * t_usec:21, // counter value in microseconds 50 * t_usec:21, // counter value in microseconds
51 * t_mbz:10; // always zero 51 * t_mbz:10; // always zero
52 * }; 52 * };
53 * 53 *
54 * but this is more trouble than it is worth. 54 * but this is more trouble than it is worth.
55 * 55 *
56 * These timers work in a rather peculiar fashion. Most clock counters 56 * These timers work in a rather peculiar fashion. Most clock counters
57 * run to 0 (as, e.g., on the VAX, where the ICR counts up to 0 from a 57 * run to 0 (as, e.g., on the VAX, where the ICR counts up to 0 from a
58 * large unsigned number). On the Sun-4c, it counts up to a limit. But 58 * large unsigned number). On the Sun-4c, it counts up to a limit. But
59 * for some reason, when it reaches the limit, it resets to 1, not 0. 59 * for some reason, when it reaches the limit, it resets to 1, not 0.
60 * Thus, if the limit is set to 4, the counter counts like this: 60 * Thus, if the limit is set to 4, the counter counts like this:
61 * 61 *
62 * 1, 2, 3, 1, 2, 3, ... 62 * 1, 2, 3, 1, 2, 3, ...
63 * 63 *
64 * and if we want to divide by N we must set the limit register to N+1. 64 * and if we want to divide by N we must set the limit register to N+1.
65 * 65 *
66 * Sun-4m counters/timer registers are similar, with these exceptions: 66 * Sun-4m counters/timer registers are similar, with these exceptions:
67 * 67 *
68 * - the limit and counter registers have changed positions.. 68 * - the limit and counter registers have changed positions..
69 * - both limit and counter registers are 22 bits wide, but 69 * - both limit and counter registers are 22 bits wide, but
70 * they count in 500ns increments (bit 9 being the least 70 * they count in 500ns increments (bit 9 being the least
71 * significant bit). 71 * significant bit).
72 * 72 *
73 */ 73 */
74#ifndef _LOCORE 74#ifndef _LOCORE
75struct timer_4 { 75struct timer_4 {
76 volatile int t_counter; /* counter reg */ 76 volatile int t_counter; /* counter reg */
77 volatile int t_limit; /* limit reg */ 77 volatile int t_limit; /* limit reg */
78}; 78};
79 79
80struct timerreg_4 { 80struct timerreg_4 {
81 struct timer_4 t_c10; /* counter that interrupts at ipl 10 */ 81 struct timer_4 t_c10; /* counter that interrupts at ipl 10 */
82 struct timer_4 t_c14; /* counter that interrupts at ipl 14 */ 82 struct timer_4 t_c14; /* counter that interrupts at ipl 14 */
83}; 83};
84 84
85struct timer_4m { /* counter that interrupts at ipl 10 */ 85struct timer_4m { /* counter that interrupts at ipl 10 */
86 volatile int t_limit; /* limit register */ 86 volatile int t_limit; /* limit register */
87 volatile int t_counter; /* counter register */ 87 volatile int t_counter; /* counter register */
88 volatile int t_limit_nr; /* limit reg, non-resetting */ 88 volatile int t_limit_nr; /* limit reg, non-resetting */
89 volatile int t_reserved; 89 volatile int t_reserved;
90 volatile int t_cfg; /* a configuration register */ 90 volatile int t_cfg; /* a configuration register */
91/* 91/*
92 * Note: The SparcClassic manual only defines this one bit 92 * Note: The SparcClassic manual only defines this one bit
93 * I suspect there are more in multi-processor machines. 93 * I suspect there are more in multi-processor machines.
94 */ 94 */
95#define TMR_CFG_USER 1 95#define TMR_CFG_USER 1
96}; 96};
97 97
98struct counter_4m { /* counter that interrupts at ipl 14 */ 98struct counter_4m { /* counter that interrupts at ipl 14 */
99 volatile int t_limit; /* limit register */ 99 volatile int t_limit; /* limit register */
100 volatile int t_counter; /* counter register */ 100 volatile int t_counter; /* counter register */
101 volatile int t_limit_nr; /* limit reg, non-resetting */ 101 volatile int t_limit_nr; /* limit reg, non-resetting */
102 volatile int t_ss; /* Start/Stop register */ 102 volatile int t_ss; /* Start/Stop register */
103#define TMR_USER_RUN 1 103#define TMR_USER_RUN 1
104}; 104};
105#endif /* _LOCORE */ 105#endif /* _LOCORE */
106 106
107#define TMR_LIMIT 0x80000000 /* counter reached its limit */ 107#define TMR_LIMIT 0x80000000 /* counter reached its limit */
108#define TMR_SHIFT 10 /* shift to obtain microseconds */ 108#define TMR_SHIFT 10 /* shift to obtain microseconds */
109#define TMR_MASK 0x1fffff /* 21 bits */ 109#define TMR_MASK 0x1fffff /* 21 bits */
110 110
111/* 111/*
112 * Compute a limit that causes the timer to fire every n microseconds. 112 * Compute a limit that causes the timer to fire every n microseconds.
113 * The Sun4c requires that the timer register be initialized for n+1 113 * The Sun4c requires that the timer register be initialized for n+1
114 * microseconds, while the Sun4m requires it be initialized for n. Thus 114 * microseconds, while the Sun4m requires it be initialized for n. Thus
115 * the two versions of this function. 115 * the two versions of this function.
116 * 116 *
117 * Note that the manual for the chipset used in the Sun4m suggests that 117 * Note that the manual for the chipset used in the Sun4m suggests that
118 * the timer be set at n+0.5 microseconds; in practice, this produces 118 * the timer be set at n+0.5 microseconds; in practice, this produces
119 * a 50 ppm clock skew, which means that the 0.5 should not be there... 119 * a 50 ppm clock skew, which means that the 0.5 should not be there...
120 */ 120 */
121#define tmr_ustolim(n) (((n) + 1) << TMR_SHIFT) 121#define tmr_ustolim(n) (((n) + 1) << TMR_SHIFT)
122 122
123/*efine TMR_SHIFT4M 9 -* shift to obtain microseconds */ 123#define TMR_SHIFT4M 9 /* shift to obtain microseconds */
124/*efine tmr_ustolim4m(n) (((2*(n)) + 1) << TMR_SHIFT4M)*/ 124#if 1
 125#define tmr_ustolim4m(n) (((2*(n)) + 1) << TMR_SHIFT4M)
 126#else
125#define tmr_ustolim4m(n) ((n) << TMR_SHIFT) 127#define tmr_ustolim4m(n) ((n) << TMR_SHIFT)
 128#endif
126 129
127/* The number of microseconds represented by a counter register value */ 130/* The number of microseconds represented by a counter register value */
128#define tmr_cnttous(c) ((((c) >> TMR_SHIFT) & TMR_MASK) - 1) 131#define tmr_cnttous(c) ((((c) >> TMR_SHIFT) & TMR_MASK) - 1)