1 /* $NetBSD: algor_p6032_intr.c,v 1.5 2002/09/27 15:35:32 provos Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Platform-specific interrupt support for the Algorithmics P-6032. 41 * 42 * The Algorithmics P-6032's interrupts are wired to GPIO pins 43 * on the BONITO system controller. 44 */ 45 46 #include "opt_ddb.h" 47 48 #include <sys/param.h> 49 #include <sys/queue.h> 50 #include <sys/malloc.h> 51 #include <sys/systm.h> 52 #include <sys/device.h> 53 #include <sys/kernel.h> 54 55 #include <machine/bus.h> 56 #include <machine/autoconf.h> 57 #include <machine/intr.h> 58 59 #include <mips/locore.h> 60 61 #include <dev/ic/mc146818reg.h> 62 63 #include <algor/algor/algor_p6032reg.h> 64 #include <algor/algor/algor_p6032var.h> 65 66 #include <algor/algor/clockvar.h> 67 68 #include <dev/pci/pcireg.h> 69 #include <dev/pci/pcivar.h> 70 71 #include <dev/isa/isavar.h> 72 73 /* 74 * The P-6032 interrupts are wired up in the following way: 75 * 76 * GPIN0 ISA_NMI (in) 77 * GPIN1 ISA_INTR (in) 78 * GPIN2 ETH_INT~ (in) 79 * GPIN3 BONIDE_INT (in) 80 * 81 * GPIN4 ISA IRQ3 (in, also on piix4) 82 * GPIN5 ISA IRQ4 (in, also on piix4) 83 * 84 * GPIO0 PIRQ A~ (in) 85 * GPIO1 PIRQ B~ (in) 86 * GPIO2 PIRQ C~ (in) 87 * GPIO3 PIRQ D~ (in) 88 */ 89 90 #define NIRQMAPS 10 91 92 const char *p6032_intrnames[NIRQMAPS] = { 93 "gpin 0", 94 "gpin 1", 95 "gpin 2", 96 "gpin 3", 97 98 "gpin 4", 99 "gpin 5", 100 101 "gpio 0", 102 "gpio 1", 103 "gpio 2", 104 "gpio 3", 105 }; 106 107 struct p6032_irqmap { 108 int irqidx; 109 uint32_t intbit; 110 uint32_t gpioiebit; 111 int flags; 112 }; 113 114 #define IRQ_F_INVERT 0x01 /* invert polarity */ 115 #define IRQ_F_EDGE 0x02 /* edge trigger */ 116 #define IRQ_F_INT1 0x04 /* INT1, else INT0 */ 117 118 const struct p6032_irqmap p6032_irqmap[NIRQMAPS] = { 119 /* ISA NMI */ 120 { P6032_IRQ_GPIN0, BONITO_ICU_GPIN(0), 121 BONITO_GPIO_INR(0), IRQ_F_INT1 }, 122 123 /* ISA bridge */ 124 { P6032_IRQ_GPIN1, BONITO_ICU_GPIN(1), 125 BONITO_GPIO_INR(1), IRQ_F_INT1 }, 126 127 /* Ethernet */ 128 { P6032_IRQ_GPIN2, BONITO_ICU_GPIN(2), 129 BONITO_GPIO_INR(2), IRQ_F_INVERT }, 130 131 /* BONITO IDE */ 132 { P6032_IRQ_GPIN3, BONITO_ICU_GPIN(3), 133 BONITO_GPIO_INR(3), 0 }, 134 135 /* ISA IRQ3 */ 136 { P6032_IRQ_GPIN4, BONITO_ICU_GPIN(4), 137 BONITO_GPIO_INR(4), IRQ_F_INT1 }, 138 139 /* ISA IRQ4 */ 140 { P6032_IRQ_GPIN5, BONITO_ICU_GPIN(5), 141 BONITO_GPIO_INR(5), IRQ_F_INT1 }, 142 143 /* PIRQ A */ 144 { P6032_IRQ_GPIO0, BONITO_ICU_GPIO(0), 145 BONITO_GPIO_IOW(0), IRQ_F_INVERT }, 146 147 /* PIRQ B */ 148 { P6032_IRQ_GPIO1, BONITO_ICU_GPIO(1), 149 BONITO_GPIO_IOW(1), IRQ_F_INVERT }, 150 151 /* PIRQ C */ 152 { P6032_IRQ_GPIO2, BONITO_ICU_GPIO(2), 153 BONITO_GPIO_IOW(2), IRQ_F_INVERT }, 154 155 /* PIRQ D */ 156 { P6032_IRQ_GPIO3, BONITO_ICU_GPIO(3), 157 BONITO_GPIO_IOW(3), IRQ_F_INVERT }, 158 }; 159 160 struct p6032_intrhead { 161 struct evcnt intr_count; 162 int intr_refcnt; 163 }; 164 struct p6032_intrhead p6032_intrtab[NIRQMAPS]; 165 166 #define NINTRS 2 /* MIPS INT0 - INT1 */ 167 168 struct p6032_cpuintr { 169 LIST_HEAD(, algor_intrhand) cintr_list; 170 struct evcnt cintr_count; 171 }; 172 173 struct p6032_cpuintr p6032_cpuintrs[NINTRS]; 174 const char *p6032_cpuintrnames[NINTRS] = { 175 "int 0 (pci)", 176 "int 1 (isa)", 177 }; 178 179 void *algor_p6032_intr_establish(int, int (*)(void *), void *); 180 void algor_p6032_intr_disestablish(void *); 181 182 int algor_p6032_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 183 const char *algor_p6032_pci_intr_string(void *, pci_intr_handle_t); 184 const struct evcnt *algor_p6032_pci_intr_evcnt(void *, pci_intr_handle_t); 185 void *algor_p6032_pci_intr_establish(void *, pci_intr_handle_t, int, 186 int (*)(void *), void *); 187 void algor_p6032_pci_intr_disestablish(void *, void *); 188 void algor_p6032_pci_conf_interrupt(void *, int, int, int, int, int *); 189 190 void algor_p6032_iointr(u_int32_t, u_int32_t, u_int32_t, u_int32_t); 191 192 void 193 algor_p6032_intr_init(struct p6032_config *acp) 194 { 195 struct bonito_config *bc = &acp->ac_bonito; 196 const struct p6032_irqmap *irqmap; 197 int i; 198 199 for (i = 0; i < NINTRS; i++) { 200 LIST_INIT(&p6032_cpuintrs[i].cintr_list); 201 evcnt_attach_dynamic(&p6032_cpuintrs[i].cintr_count, 202 EVCNT_TYPE_INTR, NULL, "mips", p6032_cpuintrnames[i]); 203 } 204 evcnt_attach_static(&mips_int5_evcnt); 205 206 for (i = 0; i <= NIRQMAPS; i++) { 207 irqmap = &p6032_irqmap[i]; 208 209 evcnt_attach_dynamic(&p6032_intrtab[i].intr_count, 210 EVCNT_TYPE_INTR, NULL, "bonito", p6032_intrnames[i]); 211 212 bc->bc_gpioIE |= irqmap->gpioiebit; 213 if (irqmap->flags & IRQ_F_INVERT) 214 bc->bc_intPol |= irqmap->intbit; 215 if (irqmap->flags & IRQ_F_EDGE) 216 bc->bc_intEdge |= irqmap->intbit; 217 if (irqmap->flags & IRQ_F_INT1) 218 bc->bc_intSteer |= irqmap->intbit; 219 220 REGVAL(BONITO_INTENCLR) = irqmap->intbit; 221 } 222 223 REGVAL(BONITO_GPIOIE) = bc->bc_gpioIE; 224 REGVAL(BONITO_INTEDGE) = bc->bc_intEdge; 225 REGVAL(BONITO_INTSTEER) = bc->bc_intSteer; 226 REGVAL(BONITO_INTPOL) = bc->bc_intPol; 227 228 acp->ac_pc.pc_intr_v = NULL; 229 acp->ac_pc.pc_intr_map = algor_p6032_pci_intr_map; 230 acp->ac_pc.pc_intr_string = algor_p6032_pci_intr_string; 231 acp->ac_pc.pc_intr_evcnt = algor_p6032_pci_intr_evcnt; 232 acp->ac_pc.pc_intr_establish = algor_p6032_pci_intr_establish; 233 acp->ac_pc.pc_intr_disestablish = algor_p6032_pci_intr_disestablish; 234 acp->ac_pc.pc_conf_interrupt = algor_p6032_pci_conf_interrupt; 235 236 /* We let the PCI-ISA bridge code handle this. */ 237 acp->ac_pc.pc_pciide_compat_intr_establish = NULL; 238 239 algor_intr_establish = algor_p6032_intr_establish; 240 algor_intr_disestablish = algor_p6032_intr_disestablish; 241 algor_iointr = algor_p6032_iointr; 242 } 243 244 void 245 algor_p6032_cal_timer(bus_space_tag_t st, bus_space_handle_t sh) 246 { 247 u_long ctrdiff[4], startctr, endctr, cps; 248 u_int8_t regc; 249 int i; 250 251 /* Disable interrupts first. */ 252 bus_space_write_1(st, sh, 0, MC_REGB); 253 bus_space_write_1(st, sh, 1, MC_REGB_SQWE | MC_REGB_BINARY | 254 MC_REGB_24HR); 255 256 /* Initialize for 16Hz. */ 257 bus_space_write_1(st, sh, 0, MC_REGA); 258 bus_space_write_1(st, sh, 1, MC_BASE_32_KHz | MC_RATE_16_Hz); 259 260 /* Run the loop an extra time to prime the cache. */ 261 for (i = 0; i < 4; i++) { 262 led_display('h', 'z', '0' + i, ' '); 263 264 /* Enable the interrupt. */ 265 bus_space_write_1(st, sh, 0, MC_REGB); 266 bus_space_write_1(st, sh, 1, MC_REGB_PIE | MC_REGB_SQWE | 267 MC_REGB_BINARY | MC_REGB_24HR); 268 269 /* Go to REGC. */ 270 bus_space_write_1(st, sh, 0, MC_REGC); 271 272 /* Wait for it to happen. */ 273 startctr = mips3_cp0_count_read(); 274 do { 275 regc = bus_space_read_1(st, sh, 1); 276 endctr = mips3_cp0_count_read(); 277 } while ((regc & MC_REGC_IRQF) == 0); 278 279 /* Already ACK'd. */ 280 281 /* Disable. */ 282 bus_space_write_1(st, sh, 0, MC_REGB); 283 bus_space_write_1(st, sh, 1, MC_REGB_SQWE | MC_REGB_BINARY | 284 MC_REGB_24HR); 285 286 ctrdiff[i] = endctr - startctr; 287 } 288 289 /* Compute the number of cycles per second. */ 290 cps = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16; 291 292 /* Compute the number of ticks for hz. */ 293 cycles_per_hz = cps / hz; 294 295 /* Compute the delay divisor. */ 296 delay_divisor = (cps / 1000000) / 2; 297 298 printf("Timer calibration: %lu cycles/sec [(%lu, %lu) * 16]\n", 299 cps, ctrdiff[2], ctrdiff[3]); 300 printf("CPU clock speed = %lu.%02luMHz " 301 "(hz cycles = %lu, delay divisor = %u)\n", 302 cps / 1000000, (cps % 1000000) / 10000, 303 cycles_per_hz, delay_divisor); 304 } 305 306 void * 307 algor_p6032_intr_establish(int irq, int (*func)(void *), void *arg) 308 { 309 const struct p6032_irqmap *irqmap; 310 struct algor_intrhand *ih; 311 int s; 312 313 irqmap = &p6032_irqmap[irq]; 314 315 KASSERT(irq == irqmap->irqidx); 316 317 ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT); 318 if (ih == NULL) 319 return (NULL); 320 321 ih->ih_func = func; 322 ih->ih_arg = arg; 323 ih->ih_irq = 0; 324 ih->ih_irqmap = irqmap; 325 326 s = splhigh(); 327 328 /* 329 * First, link it into the tables. 330 */ 331 if (irqmap->flags & IRQ_F_INT1) 332 LIST_INSERT_HEAD(&p6032_cpuintrs[1].cintr_list, ih, ih_q); 333 else 334 LIST_INSERT_HEAD(&p6032_cpuintrs[0].cintr_list, ih, ih_q); 335 336 /* 337 * Now enable it. 338 */ 339 if (p6032_intrtab[irqmap->irqidx].intr_refcnt++ == 0) 340 REGVAL(BONITO_INTENSET) = irqmap->intbit; 341 342 splx(s); 343 344 return (ih); 345 } 346 347 void 348 algor_p6032_intr_disestablish(void *cookie) 349 { 350 const struct p6032_irqmap *irqmap; 351 struct algor_intrhand *ih = cookie; 352 int s; 353 354 irqmap = ih->ih_irqmap; 355 356 s = splhigh(); 357 358 /* 359 * First, remove it from the table. 360 */ 361 LIST_REMOVE(ih, ih_q); 362 363 /* 364 * Now, disable it, if there is nothing remaining on the 365 * list. 366 */ 367 if (p6032_intrtab[irqmap->irqidx].intr_refcnt-- == 1) 368 REGVAL(BONITO_INTENCLR) = irqmap->intbit; 369 370 splx(s); 371 372 free(ih, M_DEVBUF); 373 } 374 375 void 376 algor_p6032_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc, 377 u_int32_t ipending) 378 { 379 const struct p6032_irqmap *irqmap; 380 struct algor_intrhand *ih; 381 int level; 382 u_int32_t isr; 383 384 /* Check for DEBUG interrupts. */ 385 if (ipending & MIPS_INT_MASK_3) { 386 #ifdef DDB 387 printf("Debug switch -- entering debugger\n"); 388 led_display('D','D','B',' '); 389 Debugger(); 390 led_display('N','B','S','D'); 391 #else 392 printf("Debug switch ignored -- " 393 "no debugger configured\n"); 394 #endif 395 396 cause &= ~MIPS_INT_MASK_3; 397 } 398 399 /* 400 * Read the interrupt pending registers, mask them with the 401 * ones we have enabled, and service them in order of decreasing 402 * priority. 403 */ 404 isr = REGVAL(BONITO_INTISR) & REGVAL(BONITO_INTEN); 405 406 for (level = 1; level >= 0; level--) { 407 if ((ipending & (MIPS_INT_MASK_0 << level)) == 0) 408 continue; 409 p6032_cpuintrs[level].cintr_count.ev_count++; 410 for (ih = LIST_FIRST(&p6032_cpuintrs[level].cintr_list); 411 ih != NULL; ih = LIST_NEXT(ih, ih_q)) { 412 irqmap = ih->ih_irqmap; 413 if (isr & irqmap->intbit) { 414 p6032_intrtab[ 415 irqmap->irqidx].intr_count.ev_count++; 416 (*ih->ih_func)(ih->ih_arg); 417 } 418 } 419 cause &= ~(MIPS_INT_MASK_0 << level); 420 } 421 422 /* Re-enable anything that we have processed. */ 423 _splset(MIPS_SR_INT_IE | ((status & ~cause) & MIPS_HARD_INT_MASK)); 424 } 425 426 /***************************************************************************** 427 * PCI interrupt support 428 *****************************************************************************/ 429 430 int 431 algor_p6032_pci_intr_map(struct pci_attach_args *pa, 432 pci_intr_handle_t *ihp) 433 { 434 static const int pciirqmap[6/*device*/][4/*pin*/] = { 435 { P6032_IRQ_GPIO0, P6032_IRQ_GPIO1, 436 P6032_IRQ_GPIO2, P6032_IRQ_GPIO3 }, /* 13: slot 2 (p9) */ 437 438 { P6032_IRQ_GPIO1, P6032_IRQ_GPIO2, 439 P6032_IRQ_GPIO3, P6032_IRQ_GPIO0 }, /* 14: slot 3 (p10) */ 440 441 { P6032_IRQ_GPIO2, P6032_IRQ_GPIO3, 442 P6032_IRQ_GPIO0, P6032_IRQ_GPIO1 }, /* 15: slot 4 (p11) */ 443 444 { P6032_IRQ_GPIN2, -1, 445 -1, -1 }, /* 16: Ethernet */ 446 447 { P6032_IRQ_GPIO0, P6032_IRQ_GPIO1, 448 P6032_IRQ_GPIO2, P6032_IRQ_GPIO3 }, /* 17: southbridge */ 449 450 { P6032_IRQ_GPIO3, P6032_IRQ_GPIO0, 451 P6032_IRQ_GPIO1, P6032_IRQ_GPIO2 }, /* 18: slot 1 (p8) */ 452 }; 453 pcitag_t bustag = pa->pa_intrtag; 454 int buspin = pa->pa_intrpin; 455 pci_chipset_tag_t pc = pa->pa_pc; 456 int device, irq; 457 458 if (buspin == 0) { 459 /* No IRQ used. */ 460 return (1); 461 } 462 463 if (buspin > 4) { 464 printf("algor_p6032_pci_intr_map: bad interrupt pin %d\n", 465 buspin); 466 return (1); 467 } 468 469 pci_decompose_tag(pc, bustag, NULL, &device, NULL); 470 if (device < 13 || device > 18) { 471 printf("algor_p6032_pci_intr_map: bad device %d\n", 472 device); 473 return (1); 474 } 475 476 irq = pciirqmap[device - 13][buspin - 1]; 477 if (irq == -1) { 478 printf("algor_p6032_pci_intr_map: no mapping for " 479 "device %d pin %d\n", device, buspin); 480 return (1); 481 } 482 483 *ihp = irq; 484 return (0); 485 } 486 487 const char * 488 algor_p6032_pci_intr_string(void *v, pci_intr_handle_t ih) 489 { 490 491 if (ih >= NIRQMAPS) 492 panic("algor_p6032_intr_string: bogus IRQ %ld", ih); 493 494 return (p6032_intrnames[ih]); 495 } 496 497 const struct evcnt * 498 algor_p6032_pci_intr_evcnt(void *v, pci_intr_handle_t ih) 499 { 500 501 return (&p6032_intrtab[ih].intr_count); 502 } 503 504 void * 505 algor_p6032_pci_intr_establish(void *v, pci_intr_handle_t ih, int level, 506 int (*func)(void *), void *arg) 507 { 508 509 if (ih >= NIRQMAPS) 510 panic("algor_p6032_intr_establish: bogus IRQ %ld", ih); 511 512 return (algor_p6032_intr_establish(ih, func, arg)); 513 } 514 515 void 516 algor_p6032_pci_intr_disestablish(void *v, void *cookie) 517 { 518 519 return (algor_p6032_intr_disestablish(cookie)); 520 } 521 522 void 523 algor_p6032_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz, 524 int *iline) 525 { 526 527 /* 528 * We actually don't need to do anything; everything is handled 529 * in pci_intr_map(). 530 */ 531 *iline = 0; 532 } 533