1 /* $NetBSD: clock.c,v 1.5 2002/10/02 16:02:23 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Matthew Fredette 5 * Copyright (c) 1994 Gordon W. Ross 6 * Copyright (c) 1993 Adam Glass 7 * Copyright (c) 1988 University of Utah. 8 * Copyright (c) 1982, 1990, 1993 9 * The Regents of the University of California. All rights reserved. 10 * 11 * This code is derived from software contributed to Berkeley by 12 * the Systems Programming Group of the University of Utah Computer 13 * Science Department. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. All advertising materials mentioning features or use of this software 24 * must display the following acknowledgement: 25 * This product includes software developed by the University of 26 * California, Berkeley and its contributors. 27 * 4. Neither the name of the University nor the names of its contributors 28 * may be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 * SUCH DAMAGE. 42 * 43 * from: Utah Hdr: clock.c 1.18 91/01/21$ 44 * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 45 */ 46 47 /* 48 * Machine-dependent clock routines for the Am9513 49 * Written by Matthew Fredette, based on the sun3 clock.c by 50 * Adam Glass and Gordon Ross. 51 */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/time.h> 56 #include <sys/kernel.h> 57 #include <sys/device.h> 58 59 #include <machine/autoconf.h> 60 #include <machine/cpu.h> 61 #include <machine/leds.h> 62 63 #include <sun2/sun2/control.h> 64 #include <sun2/sun2/enable.h> 65 #include <sun2/sun2/machdep.h> 66 67 #include <dev/clock_subr.h> 68 #include <dev/ic/am9513reg.h> 69 70 /* 71 * Carefully define the basic CPU clock rate so 72 * that time-of-day calculations don't float 73 * 74 * Note that the CLK_BASIC is divided by 4 before we can count with it, 75 * e.g. F1 ticks CLK_BASIC/4 times a second. 76 */ 77 #define SUN2_CLK_BASIC (19660800) 78 #define SUN2_CLK_TICKS(func, hz) (((SUN2_CLK_BASIC / 4) / AM9513_CM_SOURCE_Fn_DIV(func)) / (hz)) 79 80 /* These define which counters are used for what. */ 81 #define SUN2_CLK_NMI AM9513_TIMER1 /* Non Maskable Interrupts */ 82 #define SUN2_CLK_TIMER AM9513_TIMER2 /* Timer 2 */ 83 #define SUN2_CLK_UNUSED AM9513_TIMER3 /* Unused timer */ 84 #define SUN2_CLK_FAST_LO AM9513_TIMER4 /* Timer 4 for realtime, low order */ 85 #define SUN2_CLK_FAST_HI AM9513_TIMER5 /* Timer 5 for realtime, high order */ 86 87 #define CLOCK_PRI 5 88 #define IREG_CLK_BITS (IREG_CLOCK_ENAB_7 | IREG_CLOCK_ENAB_5) 89 90 void _isr_clock __P((void)); /* in locore.s */ 91 void clock_intr __P((struct clockframe)); 92 93 static bus_space_tag_t am9513_bt; 94 static bus_space_handle_t am9513_bh; 95 #define am9513_write_clk_cmd(val) bus_space_write_2(am9513_bt, am9513_bh, AM9513_CLK_CMD, val) 96 #define am9513_write_clk_data(val) bus_space_write_2(am9513_bt, am9513_bh, AM9513_CLK_DATA, val) 97 98 static int clock_match __P((struct device *, struct cfdata *, void *args)); 99 static void clock_attach __P((struct device *, struct device *, void *)); 100 101 CFATTACH_DECL(clock, sizeof(struct device), 102 clock_match, clock_attach, NULL, NULL); 103 104 static int 105 clock_match(parent, cf, args) 106 struct device *parent; 107 struct cfdata *cf; 108 void *args; 109 { 110 struct obio_attach_args *oba = args; 111 bus_space_handle_t bh; 112 int matched; 113 114 /* This driver only supports one unit. */ 115 if (cf->cf_unit != 0) 116 return (0); 117 118 /* Make sure there is something there... */ 119 if (bus_space_map(oba->oba_bustag, oba->oba_paddr, sizeof(struct am9513), 120 0, &bh)) 121 return (0); 122 matched = (bus_space_peek_2(oba->oba_bustag, bh, 0, NULL) == 0); 123 bus_space_unmap(oba->oba_bustag, bh, sizeof(struct am9513)); 124 if (!matched) 125 return (0); 126 127 /* Default interrupt priority. */ 128 if (oba->oba_pri == -1) 129 oba->oba_pri = CLOCK_PRI; 130 131 return (1); 132 } 133 134 static void 135 clock_attach(parent, self, args) 136 struct device *parent; 137 struct device *self; 138 void *args; 139 { 140 struct obio_attach_args *oba = args; 141 bus_space_handle_t bh; 142 143 printf("\n"); 144 145 /* Get a mapping for it. */ 146 if (bus_space_map(oba->oba_bustag, oba->oba_paddr, sizeof(struct am9513), 0, &bh)) 147 panic("clock_attach"); 148 am9513_bt = oba->oba_bustag; 149 am9513_bh = bh; 150 151 /* 152 * Set the clock to the correct interrupt rate, but 153 * do not enable the interrupt until cpu_initclocks. 154 */ 155 156 /* Disarm the timer and NMI. */ 157 am9513_write_clk_cmd(AM9513_CMD_DISARM(SUN2_CLK_TIMER | SUN2_CLK_NMI)); 158 am9513_write_clk_cmd(AM9513_CMD_CLEAR_OUTPUT(SUN2_CLK_TIMER)); 159 am9513_write_clk_cmd(AM9513_CMD_CLEAR_OUTPUT(SUN2_CLK_NMI)); 160 161 /* Set the clock to 100 Hz, but do not enable it yet. */ 162 am9513_write_clk_cmd(AM9513_CMD_LOAD_MODE(SUN2_CLK_TIMER)); 163 am9513_write_clk_data((AM9513_CM_MODE_D 164 | AM9513_CM_SOURCE_F2 165 | AM9513_CM_OUTPUT_TC_TOGGLED)); 166 am9513_write_clk_cmd(AM9513_CMD_LOAD_LOAD(SUN2_CLK_TIMER)); 167 am9513_write_clk_data(SUN2_CLK_TICKS(AM9513_CM_SOURCE_F2, 100)); 168 169 /* 170 * Can not hook up the ISR until cpu_initclocks() 171 * because hardclock is not ready until then. 172 * For now, the handler is _isr_autovec(), which 173 * will complain if it gets clock interrupts. 174 */ 175 } 176 177 /* 178 * Set or clear the desired clock bits in the interrupt 179 * register. We have to be extremely careful that we do it 180 * in such a manner that we don't get ourselves lost. 181 * XXX: Watch out! It's really easy to break this! 182 */ 183 void 184 set_clk_mode(prom_clock, on) 185 int prom_clock; 186 int on; 187 { 188 int timer; 189 190 #ifdef DIAGNOSTIC 191 /* Assertion: were are at splhigh! */ 192 if ((getsr() & PSL_IPL) < PSL_IPL7) 193 panic("set_clk_mode: bad ipl"); 194 #endif 195 196 /* Get the timer we're talking about. */ 197 timer = (prom_clock ? SUN2_CLK_NMI : SUN2_CLK_TIMER); 198 199 /* First, turn off the "master" enable bit. */ 200 enable_reg_and(~ENA_INTS); 201 202 /* 203 * Arm the timer we're supposed to turn on. 204 */ 205 if (on) { 206 am9513_write_clk_cmd(AM9513_CMD_ARM(timer)); 207 } 208 209 /* 210 * Disarm and clear the timers we're supposed to turn off. 211 */ 212 else { 213 am9513_write_clk_cmd(AM9513_CMD_DISARM(timer)); 214 am9513_write_clk_cmd(AM9513_CMD_CLEAR_OUTPUT(timer)); 215 } 216 217 /* Finally, turn the "master" enable back on. */ 218 enable_reg_or(ENA_INTS); 219 } 220 221 /* 222 * Set up the real-time clock (enable clock interrupts). 223 * Leave stathz 0 since there is no secondary clock available. 224 * Note that clock interrupts MUST STAY DISABLED until here. 225 */ 226 void 227 cpu_initclocks(void) 228 { 229 int s; 230 231 s = splhigh(); 232 233 /* Install isr (in locore.s) that calls clock_intr(). */ 234 isr_add_custom(5, (void*)_isr_clock); 235 236 /* Now enable the clock at level 5 in the interrupt reg. */ 237 set_clk_mode(0, 1); 238 239 splx(s); 240 } 241 242 /* 243 * This doesn't need to do anything, as we have only one timer and 244 * profhz==stathz==hz. 245 */ 246 void 247 setstatclockrate(newhz) 248 int newhz; 249 { 250 /* nothing */ 251 } 252 253 /* 254 * This is is called by the "custom" interrupt handler. 255 * Note that we can get ZS interrupts while this runs, 256 * and zshard may touch the interrupt_reg, so we must 257 * be careful to use the single_inst_* macros to modify 258 * the interrupt register atomically. 259 */ 260 void 261 clock_intr(cf) 262 struct clockframe cf; 263 { 264 265 /* Read the clock interrupt register. */ 266 am9513_write_clk_cmd(AM9513_CMD_CLEAR_OUTPUT(SUN2_CLK_TIMER)); 267 268 { /* Entertainment! */ 269 #ifdef LED_IDLE_CHECK 270 /* With this option, LEDs move only when CPU is idle. */ 271 extern char _Idle[]; /* locore.s */ 272 if (cf.cf_pc == (long)_Idle) 273 #endif 274 leds_intr(); 275 } 276 277 /* Call common clock interrupt handler. */ 278 hardclock(&cf); 279 } 280 281 282 /* 283 * Return the best possible estimate of the time in the timeval 284 * to which tvp points. We do this by returning the current time 285 * plus the amount of time since the last clock interrupt. 286 * 287 * Check that this time is no less than any previously-reported time, 288 * which could happen around the time of a clock adjustment. Just for 289 * fun, we guarantee that the time will be greater than the value 290 * obtained by a previous call. 291 */ 292 void 293 microtime(tvp) 294 register struct timeval *tvp; 295 { 296 int s = splhigh(); 297 static struct timeval lasttime; 298 299 *tvp = time; 300 tvp->tv_usec++; /* XXX */ 301 while (tvp->tv_usec >= 1000000) { 302 tvp->tv_sec++; 303 tvp->tv_usec -= 1000000; 304 } 305 if (tvp->tv_sec == lasttime.tv_sec && 306 tvp->tv_usec <= lasttime.tv_usec && 307 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) 308 { 309 tvp->tv_sec++; 310 tvp->tv_usec -= 1000000; 311 } 312 lasttime = *tvp; 313 splx(s); 314 } 315