1 /* $NetBSD: interrupt.c,v 1.29 2010/12/20 00:25:43 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.29 2010/12/20 00:25:43 matt Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/malloc.h> 37 #include <sys/intr.h> 38 #include <sys/cpu.h> 39 40 #include <sh3/exception.h> 41 #include <sh3/clock.h> 42 #include <sh3/intcreg.h> 43 #include <sh3/tmureg.h> 44 45 static void intc_intr_priority(int, int); 46 static struct intc_intrhand *intc_alloc_ih(void); 47 static void intc_free_ih(struct intc_intrhand *); 48 static int intc_unknown_intr(void *); 49 50 #ifdef SH4 51 static void intpri_intr_enable(int); 52 static void intpri_intr_disable(int); 53 #endif 54 55 /* 56 * EVTCODE to intc_intrhand mapper. 57 * max #76 is SH4_INTEVT_TMU4 (0xb80) 58 */ 59 int8_t __intc_evtcode_to_ih[128]; 60 61 struct intc_intrhand __intc_intrhand[_INTR_N + 1] = { 62 /* Place holder interrupt handler for unregistered interrupt. */ 63 [0] = { .ih_func = intc_unknown_intr, .ih_level = 0xf0 } 64 }; 65 66 /* 67 * SH INTC support. 68 */ 69 void 70 intc_init(void) 71 { 72 73 switch (cpu_product) { 74 #ifdef SH3 75 case CPU_PRODUCT_7709: 76 case CPU_PRODUCT_7709A: 77 case CPU_PRODUCT_7706: 78 _reg_write_2(SH7709_IPRC, 0); 79 _reg_write_2(SH7709_IPRD, 0); 80 _reg_write_2(SH7709_IPRE, 0); 81 /* FALLTHROUGH */ 82 case CPU_PRODUCT_7708: 83 case CPU_PRODUCT_7708S: 84 case CPU_PRODUCT_7708R: 85 _reg_write_2(SH3_IPRA, 0); 86 _reg_write_2(SH3_IPRB, 0); 87 break; 88 #endif /* SH3 */ 89 90 #ifdef SH4 91 case CPU_PRODUCT_7751: 92 case CPU_PRODUCT_7751R: 93 _reg_write_4(SH4_INTPRI00, 0); 94 _reg_write_4(SH4_INTMSK00, INTMSK00_MASK_ALL); 95 /* FALLTHROUGH */ 96 case CPU_PRODUCT_7750S: 97 case CPU_PRODUCT_7750R: 98 _reg_write_2(SH4_IPRD, 0); 99 /* FALLTHROUGH */ 100 case CPU_PRODUCT_7750: 101 _reg_write_2(SH4_IPRA, 0); 102 _reg_write_2(SH4_IPRB, 0); 103 _reg_write_2(SH4_IPRC, 0); 104 break; 105 #endif /* SH4 */ 106 } 107 } 108 109 void * 110 intc_intr_establish(int evtcode, int trigger, int level, 111 int (*ih_func)(void *), void *ih_arg) 112 { 113 struct intc_intrhand *ih; 114 115 KDASSERT(evtcode >= 0x200 && level > 0); 116 117 ih = intc_alloc_ih(); 118 ih->ih_func = ih_func; 119 ih->ih_arg = ih_arg; 120 ih->ih_level = level << 4; /* convert to SR.IMASK format. */ 121 ih->ih_evtcode = evtcode; 122 123 /* Map interrupt handler */ 124 EVTCODE_TO_IH_INDEX(evtcode) = ih->ih_idx; 125 126 /* Priority */ 127 intc_intr_priority(evtcode, level); 128 129 /* Sense select (SH7709, SH7709A only) XXX notyet */ 130 131 return (ih); 132 } 133 134 void 135 intc_intr_disestablish(void *arg) 136 { 137 struct intc_intrhand *ih = arg; 138 int evtcode = ih->ih_evtcode; 139 140 /* Mask interrupt if IPR can manage it. if not, cascaded ICU will do */ 141 intc_intr_priority(evtcode, 0); 142 143 /* Unmap interrupt handler */ 144 EVTCODE_TO_IH_INDEX(evtcode) = 0; 145 146 intc_free_ih(ih); 147 } 148 149 void 150 intc_intr_disable(int evtcode) 151 { 152 int s; 153 154 s = _cpu_intr_suspend(); 155 KASSERT(EVTCODE_TO_IH_INDEX(evtcode) != 0); /* there is a handler */ 156 switch (evtcode) { 157 default: 158 intc_intr_priority(evtcode, 0); 159 break; 160 161 #ifdef SH4 162 case SH4_INTEVT_PCISERR: 163 case SH4_INTEVT_PCIDMA3: 164 case SH4_INTEVT_PCIDMA2: 165 case SH4_INTEVT_PCIDMA1: 166 case SH4_INTEVT_PCIDMA0: 167 case SH4_INTEVT_PCIPWON: 168 case SH4_INTEVT_PCIPWDWN: 169 case SH4_INTEVT_PCIERR: 170 case SH4_INTEVT_TMU3: 171 case SH4_INTEVT_TMU4: 172 intpri_intr_disable(evtcode); 173 break; 174 #endif 175 } 176 _cpu_intr_resume(s); 177 } 178 179 void 180 intc_intr_enable(int evtcode) 181 { 182 struct intc_intrhand *ih; 183 int s; 184 185 s = _cpu_intr_suspend(); 186 KASSERT(EVTCODE_TO_IH_INDEX(evtcode) != 0); /* there is a handler */ 187 switch (evtcode) { 188 default: 189 ih = EVTCODE_IH(evtcode); 190 /* ih_level is in the SR.IMASK format */ 191 intc_intr_priority(evtcode, (ih->ih_level >> 4)); 192 break; 193 194 #ifdef SH4 195 case SH4_INTEVT_PCISERR: 196 case SH4_INTEVT_PCIDMA3: 197 case SH4_INTEVT_PCIDMA2: 198 case SH4_INTEVT_PCIDMA1: 199 case SH4_INTEVT_PCIDMA0: 200 case SH4_INTEVT_PCIPWON: 201 case SH4_INTEVT_PCIPWDWN: 202 case SH4_INTEVT_PCIERR: 203 case SH4_INTEVT_TMU3: 204 case SH4_INTEVT_TMU4: 205 intpri_intr_enable(evtcode); 206 break; 207 #endif 208 } 209 _cpu_intr_resume(s); 210 } 211 212 213 /* 214 * int intc_intr_priority(int evtcode, int level) 215 * Setup interrupt priority register. 216 * SH7708, SH7708S, SH7708R, SH7750, SH7750S ... evtcode is INTEVT 217 * SH7709, SH7709A, SH7706 ... evtcode is INTEVT2 218 */ 219 static void 220 intc_intr_priority(int evtcode, int level) 221 { 222 volatile uint16_t *iprreg; 223 int pos; 224 uint16_t r; 225 226 #define __SH_IPR(_sh, _ipr, _pos) \ 227 do { \ 228 iprreg = (volatile uint16_t *)(SH ## _sh ## _IPR ## _ipr); \ 229 pos = (_pos); \ 230 } while (/*CONSTCOND*/0) 231 232 #define SH3_IPR(_ipr, _pos) __SH_IPR(3, _ipr, _pos) 233 #define SH4_IPR(_ipr, _pos) __SH_IPR(4, _ipr, _pos) 234 #define SH7709_IPR(_ipr, _pos) __SH_IPR(7709, _ipr, _pos) 235 236 #define SH_IPR(_ipr, _pos) \ 237 do { \ 238 if (CPU_IS_SH3) \ 239 SH3_IPR(_ipr, _pos); \ 240 else \ 241 SH4_IPR(_ipr, _pos); \ 242 } while (/*CONSTCOND*/0) 243 244 iprreg = 0; 245 pos = -1; 246 247 switch (evtcode) { 248 case SH_INTEVT_TMU0_TUNI0: 249 SH_IPR(A, 12); 250 break; 251 case SH_INTEVT_TMU1_TUNI1: 252 SH_IPR(A, 8); 253 break; 254 case SH_INTEVT_TMU2_TUNI2: 255 SH_IPR(A, 4); 256 break; 257 case SH_INTEVT_WDT_ITI: 258 SH_IPR(B, 12); 259 break; 260 case SH_INTEVT_SCI_ERI: 261 case SH_INTEVT_SCI_RXI: 262 case SH_INTEVT_SCI_TXI: 263 case SH_INTEVT_SCI_TEI: 264 SH_IPR(B, 4); 265 break; 266 } 267 268 #ifdef SH3 269 if (CPU_IS_SH3) { 270 switch (evtcode) { 271 case SH7709_INTEVT2_IRQ3: 272 SH7709_IPR(C, 12); 273 break; 274 case SH7709_INTEVT2_IRQ2: 275 SH7709_IPR(C, 8); 276 break; 277 case SH7709_INTEVT2_IRQ1: 278 SH7709_IPR(C, 4); 279 break; 280 case SH7709_INTEVT2_IRQ0: 281 SH7709_IPR(C, 0); 282 break; 283 case SH7709_INTEVT2_PINT07: 284 SH7709_IPR(D, 12); 285 break; 286 case SH7709_INTEVT2_PINT8F: 287 SH7709_IPR(D, 8); 288 break; 289 case SH7709_INTEVT2_IRQ5: 290 SH7709_IPR(D, 4); 291 break; 292 case SH7709_INTEVT2_IRQ4: 293 SH7709_IPR(D, 0); 294 break; 295 case SH7709_INTEVT2_DEI0: 296 case SH7709_INTEVT2_DEI1: 297 case SH7709_INTEVT2_DEI2: 298 case SH7709_INTEVT2_DEI3: 299 SH7709_IPR(E, 12); 300 break; 301 case SH7709_INTEVT2_IRDA_ERI: 302 case SH7709_INTEVT2_IRDA_RXI: 303 case SH7709_INTEVT2_IRDA_BRI: 304 case SH7709_INTEVT2_IRDA_TXI: 305 SH7709_IPR(E, 8); 306 break; 307 case SH7709_INTEVT2_SCIF_ERI: 308 case SH7709_INTEVT2_SCIF_RXI: 309 case SH7709_INTEVT2_SCIF_BRI: 310 case SH7709_INTEVT2_SCIF_TXI: 311 SH7709_IPR(E, 4); 312 break; 313 case SH7709_INTEVT2_ADC: 314 SH7709_IPR(E, 0); 315 break; 316 } 317 } 318 #endif /* SH3 */ 319 320 #ifdef SH4 321 if (CPU_IS_SH4) { 322 switch (evtcode) { 323 case SH4_INTEVT_SCIF_ERI: 324 case SH4_INTEVT_SCIF_RXI: 325 case SH4_INTEVT_SCIF_BRI: 326 case SH4_INTEVT_SCIF_TXI: 327 SH4_IPR(C, 4); 328 break; 329 330 #if 0 331 case SH4_INTEVT_PCISERR: 332 case SH4_INTEVT_PCIDMA3: 333 case SH4_INTEVT_PCIDMA2: 334 case SH4_INTEVT_PCIDMA1: 335 case SH4_INTEVT_PCIDMA0: 336 case SH4_INTEVT_PCIPWON: 337 case SH4_INTEVT_PCIPWDWN: 338 case SH4_INTEVT_PCIERR: 339 #endif 340 case SH4_INTEVT_TMU3: 341 case SH4_INTEVT_TMU4: 342 intpri_intr_priority(evtcode, level); 343 break; 344 } 345 } 346 #endif /* SH4 */ 347 348 /* 349 * XXX: This function gets called even for interrupts that 350 * don't have their priority defined by IPR registers. 351 */ 352 if (pos < 0) 353 return; 354 355 r = _reg_read_2(iprreg); 356 r = (r & ~(0xf << (pos))) | (level << (pos)); 357 _reg_write_2(iprreg, r); 358 } 359 360 /* 361 * Interrupt handler holder allocater. 362 */ 363 static struct intc_intrhand * 364 intc_alloc_ih(void) 365 { 366 /* #0 is reserved for unregistered interrupt. */ 367 struct intc_intrhand *ih = &__intc_intrhand[1]; 368 int i; 369 370 for (i = 1; i <= _INTR_N; i++, ih++) 371 if (ih->ih_idx == 0) { /* no driver uses this. */ 372 ih->ih_idx = i; /* register myself */ 373 return (ih); 374 } 375 376 panic("increase _INTR_N greater than %d", _INTR_N); 377 return (NULL); 378 } 379 380 static void 381 intc_free_ih(struct intc_intrhand *ih) 382 { 383 384 memset(ih, 0, sizeof(*ih)); 385 } 386 387 /* Place-holder for debugging */ 388 static int 389 intc_unknown_intr(void *arg) 390 { 391 392 printf("INTEVT=0x%x", _reg_read_4(SH_(INTEVT))); 393 if (cpu_product == CPU_PRODUCT_7709 || 394 cpu_product == CPU_PRODUCT_7709A || 395 cpu_product == CPU_PRODUCT_7706) 396 printf(" INTEVT2=0x%x", _reg_read_4(SH7709_INTEVT2)); 397 printf("\n"); 398 399 panic("unknown interrupt"); 400 /* NOTREACHED */ 401 return (0); 402 } 403 404 #ifdef SH4 /* SH7751 support */ 405 406 /* 407 * INTPRIxx 408 */ 409 void 410 intpri_intr_priority(int evtcode, int level) 411 { 412 volatile uint32_t *iprreg; 413 uint32_t r; 414 int pos; 415 416 if (!CPU_IS_SH4) 417 return; 418 419 switch (cpu_product) { 420 default: 421 return; 422 423 case CPU_PRODUCT_7751: 424 case CPU_PRODUCT_7751R: 425 break; 426 } 427 428 iprreg = (volatile uint32_t *)SH4_INTPRI00; 429 pos = -1; 430 431 switch (evtcode) { 432 case SH4_INTEVT_PCIDMA3: 433 case SH4_INTEVT_PCIDMA2: 434 case SH4_INTEVT_PCIDMA1: 435 case SH4_INTEVT_PCIDMA0: 436 case SH4_INTEVT_PCIPWDWN: 437 case SH4_INTEVT_PCIPWON: 438 case SH4_INTEVT_PCIERR: 439 pos = 0; 440 break; 441 442 case SH4_INTEVT_PCISERR: 443 pos = 4; 444 break; 445 446 case SH4_INTEVT_TMU3: 447 pos = 8; 448 break; 449 450 case SH4_INTEVT_TMU4: 451 pos = 12; 452 break; 453 } 454 455 if (pos < 0) { 456 return; 457 } 458 459 r = _reg_read_4(iprreg); 460 r = (r & ~(0xf << pos)) | (level << pos); 461 _reg_write_4(iprreg, r); 462 } 463 464 static void 465 intpri_intr_enable(int evtcode) 466 { 467 volatile uint32_t *iprreg; 468 uint32_t bit; 469 470 if (!CPU_IS_SH4) 471 return; 472 473 switch (cpu_product) { 474 default: 475 return; 476 477 case CPU_PRODUCT_7751: 478 case CPU_PRODUCT_7751R: 479 break; 480 } 481 482 iprreg = (volatile uint32_t *)SH4_INTMSKCLR00; 483 bit = 0; 484 485 switch (evtcode) { 486 case SH4_INTEVT_PCISERR: 487 case SH4_INTEVT_PCIDMA3: 488 case SH4_INTEVT_PCIDMA2: 489 case SH4_INTEVT_PCIDMA1: 490 case SH4_INTEVT_PCIDMA0: 491 case SH4_INTEVT_PCIPWON: 492 case SH4_INTEVT_PCIPWDWN: 493 case SH4_INTEVT_PCIERR: 494 bit = (1 << ((evtcode - SH4_INTEVT_PCISERR) >> 5)); 495 break; 496 497 case SH4_INTEVT_TMU3: 498 bit = INTREQ00_TUNI3; 499 break; 500 501 case SH4_INTEVT_TMU4: 502 bit = INTREQ00_TUNI4; 503 break; 504 } 505 506 if ((bit == 0) || (iprreg == NULL)) { 507 return; 508 } 509 510 _reg_write_4(iprreg, bit); 511 } 512 513 static void 514 intpri_intr_disable(int evtcode) 515 { 516 volatile uint32_t *iprreg; 517 uint32_t bit; 518 519 if (!CPU_IS_SH4) 520 return; 521 522 switch (cpu_product) { 523 default: 524 return; 525 526 case CPU_PRODUCT_7751: 527 case CPU_PRODUCT_7751R: 528 break; 529 } 530 531 iprreg = (volatile uint32_t *)SH4_INTMSK00; 532 bit = 0; 533 534 switch (evtcode) { 535 case SH4_INTEVT_PCISERR: 536 case SH4_INTEVT_PCIDMA3: 537 case SH4_INTEVT_PCIDMA2: 538 case SH4_INTEVT_PCIDMA1: 539 case SH4_INTEVT_PCIDMA0: 540 case SH4_INTEVT_PCIPWON: 541 case SH4_INTEVT_PCIPWDWN: 542 case SH4_INTEVT_PCIERR: 543 bit = (1 << ((evtcode - SH4_INTEVT_PCISERR) >> 5)); 544 break; 545 546 case SH4_INTEVT_TMU3: 547 bit = INTREQ00_TUNI3; 548 break; 549 550 case SH4_INTEVT_TMU4: 551 bit = INTREQ00_TUNI4; 552 break; 553 } 554 555 if ((bit == 0) || (iprreg == NULL)) { 556 return; 557 } 558 559 _reg_write_4(iprreg, bit); 560 } 561 #endif /* SH4 */ 562 563 bool 564 cpu_intr_p(void) 565 { 566 567 return curcpu()->ci_idepth >= 0; 568 } 569