1 1.32 thorpej /* $NetBSD: int.c,v 1.32 2020/11/21 17:18:31 thorpej Exp $ */ 2 1.1 sekiya 3 1.1 sekiya /* 4 1.20 rumble * Copyright (c) 2009 Stephen M. Rumble 5 1.1 sekiya * Copyright (c) 2004 Christopher SEKIYA 6 1.1 sekiya * All rights reserved. 7 1.1 sekiya * 8 1.1 sekiya * Redistribution and use in source and binary forms, with or without 9 1.1 sekiya * modification, are permitted provided that the following conditions 10 1.1 sekiya * are met: 11 1.1 sekiya * 1. Redistributions of source code must retain the above copyright 12 1.1 sekiya * notice, this list of conditions and the following disclaimer. 13 1.1 sekiya * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 sekiya * notice, this list of conditions and the following disclaimer in the 15 1.1 sekiya * documentation and/or other materials provided with the distribution. 16 1.1 sekiya * 3. The name of the author may not be used to endorse or promote products 17 1.1 sekiya * derived from this software without specific prior written permission. 18 1.1 sekiya * 19 1.1 sekiya * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 sekiya * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 sekiya * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 sekiya * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 sekiya * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 1.1 sekiya * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 1.1 sekiya * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 1.1 sekiya * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 1.1 sekiya * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 1.1 sekiya * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 1.1 sekiya */ 30 1.1 sekiya 31 1.1 sekiya /* 32 1.20 rumble * INT1/INT2/INT3 interrupt controllers (IP6, IP10, IP12, IP20, IP22, IP24...) 33 1.1 sekiya */ 34 1.1 sekiya 35 1.1 sekiya #include <sys/cdefs.h> 36 1.32 thorpej __KERNEL_RCSID(0, "$NetBSD: int.c,v 1.32 2020/11/21 17:18:31 thorpej Exp $"); 37 1.1 sekiya 38 1.22 matt #define __INTR_PRIVATE 39 1.1 sekiya #include "opt_cputype.h" 40 1.1 sekiya 41 1.1 sekiya #include <sys/param.h> 42 1.1 sekiya #include <sys/proc.h> 43 1.1 sekiya #include <sys/systm.h> 44 1.14 rumble #include <sys/timetc.h> 45 1.1 sekiya #include <sys/kernel.h> 46 1.1 sekiya #include <sys/device.h> 47 1.32 thorpej #include <sys/kmem.h> 48 1.1 sekiya 49 1.1 sekiya #include <dev/ic/i8253reg.h> 50 1.1 sekiya #include <machine/sysconf.h> 51 1.1 sekiya #include <machine/machtype.h> 52 1.24 dyoung #include <sys/bus.h> 53 1.1 sekiya #include <mips/locore.h> 54 1.1 sekiya 55 1.1 sekiya #include <mips/cache.h> 56 1.1 sekiya 57 1.20 rumble #include <sgimips/dev/int1reg.h> 58 1.1 sekiya #include <sgimips/dev/int2reg.h> 59 1.3 sekiya #include <sgimips/dev/int2var.h> 60 1.1 sekiya 61 1.1 sekiya static bus_space_handle_t ioh; 62 1.1 sekiya static bus_space_tag_t iot; 63 1.1 sekiya 64 1.25 chs static int int_match(device_t, cfdata_t, void *); 65 1.25 chs static void int_attach(device_t, device_t, void *); 66 1.20 rumble static void *int1_intr_establish(int, int, int (*)(void *), void *); 67 1.20 rumble static void *int2_intr_establish(int, int, int (*)(void *), void *); 68 1.22 matt static void int1_local_intr(vaddr_t, uint32_t, uint32_t); 69 1.22 matt static void int2_local0_intr(vaddr_t, uint32_t, uint32_t); 70 1.22 matt static void int2_local1_intr(vaddr_t, uint32_t, uint32_t); 71 1.20 rumble static int int2_mappable_intr(void *); 72 1.13 rumble static void int_8254_cal(void); 73 1.14 rumble static u_int int_8254_get_timecount(struct timecounter *); 74 1.22 matt static void int_8254_intr0(vaddr_t, uint32_t, uint32_t); 75 1.22 matt static void int_8254_intr1(vaddr_t, uint32_t, uint32_t); 76 1.13 rumble 77 1.13 rumble #ifdef MIPS3 78 1.25 chs static u_long int2_cpu_freq(device_t); 79 1.20 rumble static u_long int2_cal_timer(void); 80 1.13 rumble #endif 81 1.1 sekiya 82 1.14 rumble static struct timecounter int_8254_timecounter = { 83 1.31 rin .tc_get_timecount = int_8254_get_timecount, 84 1.31 rin .tc_counter_mask = ~0u, 85 1.31 rin .tc_name = "int i8254", 86 1.31 rin .tc_quality = 100, 87 1.14 rumble }; 88 1.14 rumble 89 1.14 rumble static u_long int_8254_tc_count; 90 1.14 rumble 91 1.25 chs CFATTACH_DECL_NEW(int, 0, 92 1.19 tsutsui int_match, int_attach, NULL, NULL); 93 1.1 sekiya 94 1.1 sekiya static int 95 1.25 chs int_match(device_t parent, cfdata_t match, void *aux) 96 1.1 sekiya { 97 1.6 pooka 98 1.20 rumble switch (mach_type) { 99 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 100 1.20 rumble case MACH_SGI_IP12: 101 1.20 rumble case MACH_SGI_IP20: 102 1.20 rumble case MACH_SGI_IP22: 103 1.1 sekiya return 1; 104 1.20 rumble } 105 1.1 sekiya 106 1.1 sekiya return 0; 107 1.1 sekiya } 108 1.1 sekiya 109 1.1 sekiya static void 110 1.25 chs int_attach(device_t parent, device_t self, void *aux) 111 1.1 sekiya { 112 1.19 tsutsui uint32_t address; 113 1.29 macallan int i; 114 1.29 macallan 115 1.29 macallan for (i = 0; i < NINTR; i++) { 116 1.29 macallan intrtab[i].ih_fun = NULL; 117 1.29 macallan snprintf(intrtab[i].ih_evname, 7, "%d", i); 118 1.29 macallan } 119 1.1 sekiya 120 1.20 rumble switch (mach_type) { 121 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 122 1.20 rumble address = INT1_IP6_IP10; 123 1.20 rumble break; 124 1.20 rumble 125 1.20 rumble case MACH_SGI_IP12: 126 1.20 rumble address = INT2_IP12; 127 1.20 rumble break; 128 1.20 rumble 129 1.20 rumble case MACH_SGI_IP20: 130 1.20 rumble address = INT2_IP20; 131 1.20 rumble break; 132 1.20 rumble 133 1.20 rumble case MACH_SGI_IP22: 134 1.1 sekiya if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) 135 1.20 rumble address = INT2_IP22; 136 1.1 sekiya else 137 1.20 rumble address = INT2_IP24; 138 1.20 rumble break; 139 1.20 rumble 140 1.20 rumble default: 141 1.1 sekiya panic("\nint0: passed match, but failed attach?"); 142 1.20 rumble } 143 1.1 sekiya 144 1.16 rumble printf(" addr 0x%x\n", address); 145 1.10 tsutsui 146 1.28 macallan iot = normal_memt; 147 1.28 macallan /* 148 1.28 macallan * XXX INT1 registers are spread *way* out, but for now this should 149 1.28 macallan * work 150 1.28 macallan */ 151 1.28 macallan bus_space_map(iot, address, 0x100, 0, &ioh); 152 1.1 sekiya 153 1.1 sekiya switch (mach_type) { 154 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 155 1.20 rumble /* Clean out interrupt masks */ 156 1.20 rumble bus_space_write_1(iot, ioh, INT1_LOCAL_MASK, 0); 157 1.20 rumble 158 1.20 rumble /* Turn off timers and clear interrupts */ 159 1.20 rumble bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL, 160 1.20 rumble (TIMER_SEL0 | TIMER_16BIT | TIMER_SWSTROBE)); 161 1.20 rumble bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL, 162 1.20 rumble (TIMER_SEL1 | TIMER_16BIT | TIMER_SWSTROBE)); 163 1.20 rumble bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL, 164 1.20 rumble (TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE)); 165 1.20 rumble wbflush(); 166 1.20 rumble delay(4); 167 1.20 rumble bus_space_read_1(iot, ioh, INT1_TIMER_0_ACK); 168 1.20 rumble bus_space_read_1(iot, ioh, INT1_TIMER_1_ACK); 169 1.20 rumble 170 1.20 rumble platform.intr_establish = int1_intr_establish; 171 1.20 rumble platform.intr1 = int1_local_intr; 172 1.20 rumble platform.intr2 = int_8254_intr0; 173 1.19 tsutsui platform.intr4 = int_8254_intr1; 174 1.19 tsutsui int_8254_cal(); 175 1.19 tsutsui break; 176 1.20 rumble 177 1.20 rumble case MACH_SGI_IP12: 178 1.19 tsutsui case MACH_SGI_IP20: 179 1.19 tsutsui case MACH_SGI_IP22: 180 1.20 rumble /* Clean out interrupt masks */ 181 1.20 rumble bus_space_write_1(iot, ioh, INT2_LOCAL0_MASK, 0); 182 1.20 rumble bus_space_write_1(iot, ioh, INT2_LOCAL1_MASK, 0); 183 1.20 rumble bus_space_write_1(iot, ioh, INT2_MAP_MASK0, 0); 184 1.20 rumble bus_space_write_1(iot, ioh, INT2_MAP_MASK1, 0); 185 1.20 rumble 186 1.20 rumble /* Reset timer interrupts */ 187 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, 188 1.20 rumble (TIMER_SEL0 | TIMER_16BIT | TIMER_SWSTROBE)); 189 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, 190 1.20 rumble (TIMER_SEL1 | TIMER_16BIT | TIMER_SWSTROBE)); 191 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, 192 1.20 rumble (TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE)); 193 1.20 rumble wbflush(); 194 1.20 rumble delay(4); 195 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x03); 196 1.20 rumble 197 1.20 rumble if (mach_type == MACH_SGI_IP12) { 198 1.20 rumble platform.intr_establish = int2_intr_establish; 199 1.20 rumble platform.intr1 = int2_local0_intr; 200 1.20 rumble platform.intr2 = int2_local1_intr; 201 1.20 rumble platform.intr3 = int_8254_intr0; 202 1.20 rumble platform.intr4 = int_8254_intr1; 203 1.20 rumble int_8254_cal(); 204 1.20 rumble } else { 205 1.20 rumble platform.intr_establish = int2_intr_establish; 206 1.20 rumble platform.intr0 = int2_local0_intr; 207 1.20 rumble platform.intr1 = int2_local1_intr; 208 1.20 rumble #ifdef MIPS3 209 1.20 rumble curcpu()->ci_cpu_freq = int2_cpu_freq(self); 210 1.20 rumble #endif 211 1.19 tsutsui } 212 1.20 rumble break; 213 1.1 sekiya 214 1.19 tsutsui default: 215 1.19 tsutsui panic("int0: unsupported machine type %i\n", mach_type); 216 1.1 sekiya } 217 1.1 sekiya 218 1.1 sekiya curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / (2 * hz); 219 1.1 sekiya curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / (2 * 1000000); 220 1.1 sekiya 221 1.1 sekiya if (mach_type == MACH_SGI_IP22) { 222 1.1 sekiya /* Wire interrupts 7, 11 to mappable interrupt 0,1 handlers */ 223 1.20 rumble intrtab[7].ih_fun = int2_mappable_intr; 224 1.1 sekiya intrtab[7].ih_arg = (void*) 0; 225 1.29 macallan snprintf(intrtab[7].ih_evname, 7, "map0"); 226 1.1 sekiya 227 1.20 rumble intrtab[11].ih_fun = int2_mappable_intr; 228 1.1 sekiya intrtab[11].ih_arg = (void*) 1; 229 1.29 macallan snprintf(intrtab[11].ih_evname, 7, "map1"); 230 1.29 macallan } 231 1.29 macallan 232 1.29 macallan for (i = 0; i < NINTR; i++) { 233 1.29 macallan evcnt_attach_dynamic(&intrtab[i].ih_evcnt, 234 1.29 macallan EVCNT_TYPE_INTR, NULL, 235 1.29 macallan "int", intrtab[i].ih_evname); 236 1.1 sekiya } 237 1.1 sekiya } 238 1.1 sekiya 239 1.1 sekiya int 240 1.20 rumble int2_mappable_intr(void *arg) 241 1.1 sekiya { 242 1.1 sekiya int i; 243 1.1 sekiya int ret; 244 1.1 sekiya int intnum; 245 1.19 tsutsui uint32_t mstat; 246 1.19 tsutsui uint32_t mmask; 247 1.21 matt int which = (intptr_t)arg; 248 1.8 sekiya struct sgimips_intrhand *ih; 249 1.1 sekiya 250 1.1 sekiya ret = 0; 251 1.20 rumble mstat = bus_space_read_1(iot, ioh, INT2_MAP_STATUS); 252 1.20 rumble mmask = bus_space_read_1(iot, ioh, INT2_MAP_MASK0 + (which << 2)); 253 1.1 sekiya 254 1.1 sekiya mstat &= mmask; 255 1.1 sekiya 256 1.1 sekiya for (i = 0; i < 8; i++) { 257 1.1 sekiya intnum = i + 16 + (which << 3); 258 1.1 sekiya if (mstat & (1 << i)) { 259 1.29 macallan intrtab[intnum].ih_evcnt.ev_count++; 260 1.8 sekiya for (ih = &intrtab[intnum]; ih != NULL; 261 1.19 tsutsui ih = ih->ih_next) { 262 1.8 sekiya if (ih->ih_fun != NULL) 263 1.8 sekiya ret |= (ih->ih_fun)(ih->ih_arg); 264 1.8 sekiya else 265 1.8 sekiya printf("int0: unexpected mapped " 266 1.8 sekiya "interrupt %d\n", intnum); 267 1.8 sekiya } 268 1.1 sekiya } 269 1.1 sekiya } 270 1.1 sekiya 271 1.1 sekiya return ret; 272 1.1 sekiya } 273 1.1 sekiya 274 1.20 rumble static void 275 1.22 matt int1_local_intr(vaddr_t pc, uint32_t status, uint32_t ipend) 276 1.20 rumble { 277 1.20 rumble int i; 278 1.20 rumble uint16_t stat; 279 1.20 rumble uint8_t mask; 280 1.20 rumble struct sgimips_intrhand *ih; 281 1.20 rumble 282 1.20 rumble stat = bus_space_read_2(iot, ioh, INT1_LOCAL_STATUS); 283 1.20 rumble mask = bus_space_read_1(iot, ioh, INT1_LOCAL_MASK); 284 1.20 rumble 285 1.20 rumble /* for STATUS, a 0 bit means interrupt is pending */ 286 1.20 rumble stat = ~stat & mask; 287 1.20 rumble 288 1.22 matt for (i = 0; stat != 0; i++, stat >>= 1) { 289 1.22 matt if (stat & 1) { 290 1.29 macallan intrtab[i].ih_evcnt.ev_count++; 291 1.20 rumble for (ih = &intrtab[i]; ih != NULL; ih = ih->ih_next) { 292 1.20 rumble if (ih->ih_fun != NULL) 293 1.20 rumble (ih->ih_fun)(ih->ih_arg); 294 1.20 rumble else 295 1.20 rumble printf("int0: unexpected local " 296 1.20 rumble "interrupt %d\n", i); 297 1.20 rumble } 298 1.20 rumble } 299 1.20 rumble } 300 1.20 rumble } 301 1.20 rumble 302 1.1 sekiya void 303 1.22 matt int2_local0_intr(vaddr_t pc, uint32_t status, uint32_t ipending) 304 1.1 sekiya { 305 1.1 sekiya int i; 306 1.19 tsutsui uint32_t l0stat; 307 1.19 tsutsui uint32_t l0mask; 308 1.8 sekiya struct sgimips_intrhand *ih; 309 1.1 sekiya 310 1.20 rumble l0stat = bus_space_read_1(iot, ioh, INT2_LOCAL0_STATUS); 311 1.20 rumble l0mask = bus_space_read_1(iot, ioh, INT2_LOCAL0_MASK); 312 1.1 sekiya 313 1.12 rumble l0stat &= l0mask; 314 1.1 sekiya 315 1.1 sekiya for (i = 0; i < 8; i++) { 316 1.12 rumble if (l0stat & (1 << i)) { 317 1.29 macallan intrtab[i].ih_evcnt.ev_count++; 318 1.8 sekiya for (ih = &intrtab[i]; ih != NULL; ih = ih->ih_next) { 319 1.8 sekiya if (ih->ih_fun != NULL) 320 1.8 sekiya (ih->ih_fun)(ih->ih_arg); 321 1.8 sekiya else 322 1.8 sekiya printf("int0: unexpected local0 " 323 1.8 sekiya "interrupt %d\n", i); 324 1.8 sekiya } 325 1.1 sekiya } 326 1.1 sekiya } 327 1.1 sekiya } 328 1.1 sekiya 329 1.1 sekiya void 330 1.22 matt int2_local1_intr(vaddr_t pc, uint32_t status, uint32_t ipending) 331 1.1 sekiya { 332 1.1 sekiya int i; 333 1.19 tsutsui uint32_t l1stat; 334 1.19 tsutsui uint32_t l1mask; 335 1.8 sekiya struct sgimips_intrhand *ih; 336 1.1 sekiya 337 1.20 rumble l1stat = bus_space_read_1(iot, ioh, INT2_LOCAL1_STATUS); 338 1.20 rumble l1mask = bus_space_read_1(iot, ioh, INT2_LOCAL1_MASK); 339 1.1 sekiya 340 1.1 sekiya l1stat &= l1mask; 341 1.1 sekiya 342 1.1 sekiya for (i = 0; i < 8; i++) { 343 1.1 sekiya if (l1stat & (1 << i)) { 344 1.29 macallan intrtab[i].ih_evcnt.ev_count++; 345 1.8 sekiya for (ih = &intrtab[8+i]; ih != NULL; ih = ih->ih_next) { 346 1.8 sekiya if (ih->ih_fun != NULL) 347 1.8 sekiya (ih->ih_fun)(ih->ih_arg); 348 1.8 sekiya else 349 1.8 sekiya printf("int0: unexpected local1 " 350 1.8 sekiya " interrupt %x\n", 8 + i); 351 1.8 sekiya } 352 1.1 sekiya } 353 1.1 sekiya } 354 1.1 sekiya } 355 1.1 sekiya 356 1.1 sekiya void * 357 1.20 rumble int1_intr_establish(int level, int ipl, int (*handler) (void *), void *arg) 358 1.20 rumble { 359 1.20 rumble uint8_t mask; 360 1.20 rumble 361 1.20 rumble if (level < 0 || level >= NINTR) 362 1.20 rumble panic("invalid interrupt level"); 363 1.20 rumble 364 1.20 rumble if (intrtab[level].ih_fun == NULL) { 365 1.20 rumble intrtab[level].ih_fun = handler; 366 1.20 rumble intrtab[level].ih_arg = arg; 367 1.20 rumble intrtab[level].ih_next = NULL; 368 1.20 rumble } else { 369 1.20 rumble struct sgimips_intrhand *n, *ih; 370 1.20 rumble 371 1.32 thorpej ih = kmem_alloc(sizeof *ih, KM_SLEEP); 372 1.20 rumble ih->ih_fun = handler; 373 1.20 rumble ih->ih_arg = arg; 374 1.20 rumble ih->ih_next = NULL; 375 1.20 rumble 376 1.20 rumble for (n = &intrtab[level]; n->ih_next != NULL; n = n->ih_next) 377 1.20 rumble ; 378 1.20 rumble 379 1.20 rumble n->ih_next = ih; 380 1.20 rumble 381 1.20 rumble return NULL; /* vector already set */ 382 1.20 rumble } 383 1.20 rumble 384 1.20 rumble if (level < 8) { 385 1.20 rumble mask = bus_space_read_1(iot, ioh, INT1_LOCAL_MASK); 386 1.20 rumble mask |= (1 << level); 387 1.20 rumble bus_space_write_1(iot, ioh, INT1_LOCAL_MASK, mask); 388 1.20 rumble } else { 389 1.20 rumble printf("int0: level >= 16 (%d)\n", level); 390 1.20 rumble } 391 1.20 rumble 392 1.20 rumble return NULL; 393 1.20 rumble } 394 1.20 rumble 395 1.20 rumble void * 396 1.20 rumble int2_intr_establish(int level, int ipl, int (*handler) (void *), void *arg) 397 1.1 sekiya { 398 1.19 tsutsui uint32_t mask; 399 1.1 sekiya 400 1.1 sekiya if (level < 0 || level >= NINTR) 401 1.1 sekiya panic("invalid interrupt level"); 402 1.1 sekiya 403 1.8 sekiya if (intrtab[level].ih_fun == NULL) { 404 1.8 sekiya intrtab[level].ih_fun = handler; 405 1.8 sekiya intrtab[level].ih_arg = arg; 406 1.8 sekiya intrtab[level].ih_next = NULL; 407 1.8 sekiya } else { 408 1.19 tsutsui struct sgimips_intrhand *n, *ih; 409 1.8 sekiya 410 1.32 thorpej ih = kmem_alloc(sizeof *ih, KM_SLEEP); 411 1.8 sekiya ih->ih_fun = handler; 412 1.8 sekiya ih->ih_arg = arg; 413 1.8 sekiya ih->ih_next = NULL; 414 1.8 sekiya 415 1.8 sekiya for (n = &intrtab[level]; n->ih_next != NULL; n = n->ih_next) 416 1.10 tsutsui ; 417 1.10 tsutsui 418 1.8 sekiya n->ih_next = ih; 419 1.8 sekiya 420 1.19 tsutsui return NULL; /* vector already set */ 421 1.1 sekiya } 422 1.1 sekiya 423 1.1 sekiya if (level < 8) { 424 1.20 rumble mask = bus_space_read_1(iot, ioh, INT2_LOCAL0_MASK); 425 1.1 sekiya mask |= (1 << level); 426 1.20 rumble bus_space_write_1(iot, ioh, INT2_LOCAL0_MASK, mask); 427 1.1 sekiya } else if (level < 16) { 428 1.20 rumble mask = bus_space_read_1(iot, ioh, INT2_LOCAL1_MASK); 429 1.1 sekiya mask |= (1 << (level - 8)); 430 1.20 rumble bus_space_write_1(iot, ioh, INT2_LOCAL1_MASK, mask); 431 1.1 sekiya } else if (level < 24) { 432 1.1 sekiya /* Map0 interrupt maps to l0 bit 7, so turn that on too */ 433 1.20 rumble mask = bus_space_read_1(iot, ioh, INT2_LOCAL0_MASK); 434 1.1 sekiya mask |= (1 << 7); 435 1.20 rumble bus_space_write_1(iot, ioh, INT2_LOCAL0_MASK, mask); 436 1.1 sekiya 437 1.20 rumble mask = bus_space_read_1(iot, ioh, INT2_MAP_MASK0); 438 1.1 sekiya mask |= (1 << (level - 16)); 439 1.20 rumble bus_space_write_1(iot, ioh, INT2_MAP_MASK0, mask); 440 1.1 sekiya } else { 441 1.1 sekiya /* Map1 interrupt maps to l1 bit 3, so turn that on too */ 442 1.20 rumble mask = bus_space_read_1(iot, ioh, INT2_LOCAL1_MASK); 443 1.1 sekiya mask |= (1 << 3); 444 1.20 rumble bus_space_write_1(iot, ioh, INT2_LOCAL1_MASK, mask); 445 1.1 sekiya 446 1.20 rumble mask = bus_space_read_1(iot, ioh, INT2_MAP_MASK1); 447 1.1 sekiya mask |= (1 << (level - 24)); 448 1.20 rumble bus_space_write_1(iot, ioh, INT2_MAP_MASK1, mask); 449 1.1 sekiya } 450 1.1 sekiya 451 1.19 tsutsui return NULL; 452 1.1 sekiya } 453 1.1 sekiya 454 1.4 pooka #ifdef MIPS3 455 1.13 rumble static u_long 456 1.25 chs int2_cpu_freq(device_t self) 457 1.20 rumble { 458 1.20 rumble int i; 459 1.20 rumble unsigned long cps; 460 1.20 rumble unsigned long ctrdiff[3]; 461 1.20 rumble 462 1.20 rumble /* calibrate timer */ 463 1.20 rumble int2_cal_timer(); 464 1.20 rumble 465 1.20 rumble cps = 0; 466 1.20 rumble for (i = 0; 467 1.20 rumble i < sizeof(ctrdiff) / sizeof(ctrdiff[0]); i++) { 468 1.20 rumble do { 469 1.20 rumble ctrdiff[i] = int2_cal_timer(); 470 1.20 rumble } while (ctrdiff[i] == 0); 471 1.20 rumble 472 1.20 rumble cps += ctrdiff[i]; 473 1.20 rumble } 474 1.20 rumble 475 1.20 rumble cps = cps / (sizeof(ctrdiff) / sizeof(ctrdiff[0])); 476 1.20 rumble 477 1.20 rumble printf("%s: bus %luMHz, CPU %luMHz\n", 478 1.25 chs device_xname(self), cps / 10000, cps / 5000); 479 1.20 rumble 480 1.20 rumble /* R4k/R4400/R4600/R5k count at half CPU frequency */ 481 1.20 rumble return (2 * cps * hz); 482 1.20 rumble } 483 1.20 rumble 484 1.20 rumble static u_long 485 1.20 rumble int2_cal_timer(void) 486 1.1 sekiya { 487 1.1 sekiya int s; 488 1.1 sekiya int roundtime; 489 1.1 sekiya int sampletime; 490 1.27 macallan int msb; 491 1.1 sekiya unsigned long startctr, endctr; 492 1.1 sekiya 493 1.1 sekiya /* 494 1.1 sekiya * NOTE: HZ must be greater than 15 for this to work, as otherwise 495 1.20 rumble * we'll overflow the counter. We round the answer to nearest 1 496 1.1 sekiya * MHz of the master (2x) clock. 497 1.1 sekiya */ 498 1.1 sekiya roundtime = (1000000 / hz) / 2; 499 1.1 sekiya sampletime = (1000000 / hz) + 0xff; 500 1.1 sekiya 501 1.1 sekiya s = splhigh(); 502 1.1 sekiya 503 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, 504 1.19 tsutsui (TIMER_SEL2 | TIMER_16BIT | TIMER_RATEGEN)); 505 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_2, (sampletime & 0xff)); 506 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_2, (sampletime >> 8)); 507 1.1 sekiya 508 1.1 sekiya startctr = mips3_cp0_count_read(); 509 1.1 sekiya 510 1.1 sekiya /* Wait for the MSB to count down to zero */ 511 1.1 sekiya do { 512 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, TIMER_SEL2); 513 1.27 macallan (void)bus_space_read_1(iot, ioh, INT2_TIMER_2); 514 1.20 rumble msb = bus_space_read_1(iot, ioh, INT2_TIMER_2) & 0xff; 515 1.1 sekiya 516 1.1 sekiya endctr = mips3_cp0_count_read(); 517 1.1 sekiya } while (msb); 518 1.1 sekiya 519 1.1 sekiya /* Turn off timer */ 520 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, 521 1.19 tsutsui (TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE)); 522 1.1 sekiya 523 1.1 sekiya splx(s); 524 1.1 sekiya 525 1.1 sekiya return (endctr - startctr) / roundtime * roundtime; 526 1.1 sekiya } 527 1.4 pooka #endif /* MIPS3 */ 528 1.1 sekiya 529 1.14 rumble /* 530 1.20 rumble * A master clock is wired to TIMER_2, which in turn clocks the two other 531 1.20 rumble * timers. The master frequencies are as follows: 532 1.20 rumble * IP6, IP10: 3.6864MHz 533 1.20 rumble * IP12, IP20, IP22: 1MHz 534 1.20 rumble * IP17: 10MHz 535 1.14 rumble * 536 1.20 rumble * TIMER_0 and TIMER_1 interrupts are tied to MIPS interrupts as follows: 537 1.20 rumble * IP6, IP10: TIMER_0: INT2, TIMER_1: INT4 538 1.20 rumble * IP12: TIMER_0: INT3, TIMER_1: INT4 539 1.20 rumble * IP17, IP20, IP22: TIMER_0: INT2, TIMER_1: INT3 540 1.20 rumble * 541 1.20 rumble * NB: Apparently int2 doesn't like counting down from one, but two works. 542 1.14 rumble */ 543 1.1 sekiya void 544 1.1 sekiya int_8254_cal(void) 545 1.1 sekiya { 546 1.20 rumble bus_size_t timer_control, timer_0, timer_1, timer_2; 547 1.1 sekiya int s; 548 1.1 sekiya 549 1.20 rumble switch (mach_type) { 550 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 551 1.20 rumble int_8254_timecounter.tc_frequency = 3686400 / 8; 552 1.20 rumble timer_control = INT1_TIMER_CONTROL; 553 1.20 rumble timer_0 = INT1_TIMER_0; 554 1.20 rumble timer_1 = INT1_TIMER_1; 555 1.20 rumble timer_2 = INT1_TIMER_2; 556 1.20 rumble break; 557 1.20 rumble 558 1.20 rumble case MACH_SGI_IP12: 559 1.20 rumble int_8254_timecounter.tc_frequency = 1000000 / 8; 560 1.20 rumble timer_control = INT2_TIMER_CONTROL; 561 1.20 rumble timer_0 = INT2_TIMER_0; 562 1.20 rumble timer_1 = INT2_TIMER_1; 563 1.20 rumble timer_2 = INT2_TIMER_2; 564 1.20 rumble break; 565 1.20 rumble 566 1.20 rumble default: 567 1.20 rumble panic("int_8254_cal"); 568 1.20 rumble } 569 1.20 rumble 570 1.1 sekiya s = splhigh(); 571 1.1 sekiya 572 1.20 rumble /* Timer0 is our hz. */ 573 1.20 rumble bus_space_write_1(iot, ioh, timer_control, 574 1.20 rumble TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 575 1.20 rumble bus_space_write_1(iot, ioh, timer_0, 576 1.20 rumble (int_8254_timecounter.tc_frequency / hz) % 256); 577 1.14 rumble wbflush(); 578 1.14 rumble delay(4); 579 1.20 rumble bus_space_write_1(iot, ioh, timer_0, 580 1.20 rumble (int_8254_timecounter.tc_frequency / hz) / 256); 581 1.14 rumble 582 1.20 rumble /* Timer1 is for timecounting. */ 583 1.20 rumble bus_space_write_1(iot, ioh, timer_control, 584 1.20 rumble TIMER_SEL1 | TIMER_RATEGEN | TIMER_16BIT); 585 1.20 rumble bus_space_write_1(iot, ioh, timer_1, 0xff); 586 1.1 sekiya wbflush(); 587 1.1 sekiya delay(4); 588 1.20 rumble bus_space_write_1(iot, ioh, timer_1, 0xff); 589 1.1 sekiya 590 1.20 rumble /* Timer2 clocks timer0 and timer1. */ 591 1.20 rumble bus_space_write_1(iot, ioh, timer_control, 592 1.20 rumble TIMER_SEL2 | TIMER_RATEGEN | TIMER_16BIT); 593 1.20 rumble bus_space_write_1(iot, ioh, timer_2, 8); 594 1.1 sekiya wbflush(); 595 1.1 sekiya delay(4); 596 1.20 rumble bus_space_write_1(iot, ioh, timer_2, 0); 597 1.14 rumble 598 1.14 rumble splx(s); 599 1.20 rumble 600 1.20 rumble tc_init(&int_8254_timecounter); 601 1.14 rumble } 602 1.14 rumble 603 1.14 rumble static u_int 604 1.14 rumble int_8254_get_timecount(struct timecounter *tc) 605 1.14 rumble { 606 1.14 rumble int s; 607 1.14 rumble u_int count; 608 1.20 rumble u_char lo, hi; 609 1.14 rumble 610 1.14 rumble s = splhigh(); 611 1.14 rumble 612 1.20 rumble switch (mach_type) { 613 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 614 1.20 rumble bus_space_write_1(iot, ioh, INT1_TIMER_CONTROL, 615 1.20 rumble TIMER_SEL1 | TIMER_LATCH); 616 1.20 rumble lo = bus_space_read_1(iot, ioh, INT1_TIMER_1); 617 1.20 rumble hi = bus_space_read_1(iot, ioh, INT1_TIMER_1); 618 1.20 rumble break; 619 1.20 rumble 620 1.20 rumble case MACH_SGI_IP12: 621 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CONTROL, 622 1.20 rumble TIMER_SEL1 | TIMER_LATCH); 623 1.20 rumble lo = bus_space_read_1(iot, ioh, INT2_TIMER_1); 624 1.20 rumble hi = bus_space_read_1(iot, ioh, INT2_TIMER_1); 625 1.20 rumble break; 626 1.20 rumble 627 1.20 rumble default: 628 1.20 rumble panic("int_8254_get_timecount"); 629 1.20 rumble } 630 1.20 rumble 631 1.14 rumble count = 0xffff - ((hi << 8) | lo); 632 1.14 rumble splx(s); 633 1.14 rumble 634 1.20 rumble return (int_8254_tc_count + count); 635 1.14 rumble } 636 1.14 rumble 637 1.14 rumble static void 638 1.22 matt int_8254_intr0(vaddr_t pc, uint32_t status, uint32_t ipending) 639 1.15 rumble { 640 1.15 rumble struct clockframe cf; 641 1.15 rumble 642 1.15 rumble cf.pc = pc; 643 1.15 rumble cf.sr = status; 644 1.23 tsutsui cf.intr = (curcpu()->ci_idepth > 1); 645 1.15 rumble 646 1.15 rumble hardclock(&cf); 647 1.15 rumble 648 1.20 rumble switch (mach_type) { 649 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 650 1.20 rumble bus_space_read_1(iot, ioh, INT1_TIMER_0_ACK); 651 1.20 rumble break; 652 1.20 rumble 653 1.20 rumble case MACH_SGI_IP12: 654 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x01); 655 1.20 rumble break; 656 1.20 rumble 657 1.20 rumble default: 658 1.20 rumble panic("int_8254_intr0"); 659 1.20 rumble } 660 1.15 rumble } 661 1.15 rumble 662 1.15 rumble static void 663 1.22 matt int_8254_intr1(vaddr_t pc, uint32_t status, uint32_t ipending) 664 1.14 rumble { 665 1.14 rumble int s; 666 1.14 rumble 667 1.14 rumble s = splhigh(); 668 1.14 rumble 669 1.14 rumble int_8254_tc_count += 0xffff; 670 1.20 rumble switch (mach_type) { 671 1.20 rumble case MACH_SGI_IP6 | MACH_SGI_IP10: 672 1.20 rumble bus_space_read_1(iot, ioh, INT1_TIMER_1_ACK); 673 1.20 rumble break; 674 1.20 rumble 675 1.20 rumble case MACH_SGI_IP12: 676 1.20 rumble bus_space_write_1(iot, ioh, INT2_TIMER_CLEAR, 0x02); 677 1.20 rumble break; 678 1.20 rumble 679 1.20 rumble default: 680 1.20 rumble panic("int_8254_intr1"); 681 1.20 rumble } 682 1.14 rumble 683 1.1 sekiya splx(s); 684 1.1 sekiya } 685 1.3 sekiya 686 1.3 sekiya void 687 1.19 tsutsui int2_wait_fifo(uint32_t flag) 688 1.3 sekiya { 689 1.19 tsutsui 690 1.8 sekiya if (ioh == 0) 691 1.8 sekiya delay(5000); 692 1.8 sekiya else 693 1.20 rumble while (bus_space_read_1(iot, ioh, INT2_LOCAL0_STATUS) & flag) 694 1.8 sekiya ; 695 1.3 sekiya } 696