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