1 /* 2 * include/asm-ppc/ipic.c 3 * 4 * IPIC routines implementations. 5 * 6 * Copyright 2005 Freescale Semiconductor, Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/errno.h> 16 #include <linux/reboot.h> 17 #include <linux/slab.h> 18 #include <linux/stddef.h> 19 #include <linux/sched.h> 20 #include <linux/signal.h> 21 #include <linux/sysdev.h> 22 #include <asm/irq.h> 23 #include <asm/io.h> 24 #include <asm/ipic.h> 25 #include <asm/mpc83xx.h> 26 27 #include "ipic.h" 28 29 static struct ipic p_ipic; 30 static struct ipic * primary_ipic; 31 32 static struct ipic_info ipic_info[] = { 33 [9] = { 34 .pend = IPIC_SIPNR_H, 35 .mask = IPIC_SIMSR_H, 36 .prio = IPIC_SIPRR_D, 37 .force = IPIC_SIFCR_H, 38 .bit = 24, 39 .prio_mask = 0, 40 }, 41 [10] = { 42 .pend = IPIC_SIPNR_H, 43 .mask = IPIC_SIMSR_H, 44 .prio = IPIC_SIPRR_D, 45 .force = IPIC_SIFCR_H, 46 .bit = 25, 47 .prio_mask = 1, 48 }, 49 [11] = { 50 .pend = IPIC_SIPNR_H, 51 .mask = IPIC_SIMSR_H, 52 .prio = IPIC_SIPRR_D, 53 .force = IPIC_SIFCR_H, 54 .bit = 26, 55 .prio_mask = 2, 56 }, 57 [14] = { 58 .pend = IPIC_SIPNR_H, 59 .mask = IPIC_SIMSR_H, 60 .prio = IPIC_SIPRR_D, 61 .force = IPIC_SIFCR_H, 62 .bit = 29, 63 .prio_mask = 5, 64 }, 65 [15] = { 66 .pend = IPIC_SIPNR_H, 67 .mask = IPIC_SIMSR_H, 68 .prio = IPIC_SIPRR_D, 69 .force = IPIC_SIFCR_H, 70 .bit = 30, 71 .prio_mask = 6, 72 }, 73 [16] = { 74 .pend = IPIC_SIPNR_H, 75 .mask = IPIC_SIMSR_H, 76 .prio = IPIC_SIPRR_D, 77 .force = IPIC_SIFCR_H, 78 .bit = 31, 79 .prio_mask = 7, 80 }, 81 [17] = { 82 .pend = IPIC_SEPNR, 83 .mask = IPIC_SEMSR, 84 .prio = IPIC_SMPRR_A, 85 .force = IPIC_SEFCR, 86 .bit = 1, 87 .prio_mask = 5, 88 }, 89 [18] = { 90 .pend = IPIC_SEPNR, 91 .mask = IPIC_SEMSR, 92 .prio = IPIC_SMPRR_A, 93 .force = IPIC_SEFCR, 94 .bit = 2, 95 .prio_mask = 6, 96 }, 97 [19] = { 98 .pend = IPIC_SEPNR, 99 .mask = IPIC_SEMSR, 100 .prio = IPIC_SMPRR_A, 101 .force = IPIC_SEFCR, 102 .bit = 3, 103 .prio_mask = 7, 104 }, 105 [20] = { 106 .pend = IPIC_SEPNR, 107 .mask = IPIC_SEMSR, 108 .prio = IPIC_SMPRR_B, 109 .force = IPIC_SEFCR, 110 .bit = 4, 111 .prio_mask = 4, 112 }, 113 [21] = { 114 .pend = IPIC_SEPNR, 115 .mask = IPIC_SEMSR, 116 .prio = IPIC_SMPRR_B, 117 .force = IPIC_SEFCR, 118 .bit = 5, 119 .prio_mask = 5, 120 }, 121 [22] = { 122 .pend = IPIC_SEPNR, 123 .mask = IPIC_SEMSR, 124 .prio = IPIC_SMPRR_B, 125 .force = IPIC_SEFCR, 126 .bit = 6, 127 .prio_mask = 6, 128 }, 129 [23] = { 130 .pend = IPIC_SEPNR, 131 .mask = IPIC_SEMSR, 132 .prio = IPIC_SMPRR_B, 133 .force = IPIC_SEFCR, 134 .bit = 7, 135 .prio_mask = 7, 136 }, 137 [32] = { 138 .pend = IPIC_SIPNR_H, 139 .mask = IPIC_SIMSR_H, 140 .prio = IPIC_SIPRR_A, 141 .force = IPIC_SIFCR_H, 142 .bit = 0, 143 .prio_mask = 0, 144 }, 145 [33] = { 146 .pend = IPIC_SIPNR_H, 147 .mask = IPIC_SIMSR_H, 148 .prio = IPIC_SIPRR_A, 149 .force = IPIC_SIFCR_H, 150 .bit = 1, 151 .prio_mask = 1, 152 }, 153 [34] = { 154 .pend = IPIC_SIPNR_H, 155 .mask = IPIC_SIMSR_H, 156 .prio = IPIC_SIPRR_A, 157 .force = IPIC_SIFCR_H, 158 .bit = 2, 159 .prio_mask = 2, 160 }, 161 [35] = { 162 .pend = IPIC_SIPNR_H, 163 .mask = IPIC_SIMSR_H, 164 .prio = IPIC_SIPRR_A, 165 .force = IPIC_SIFCR_H, 166 .bit = 3, 167 .prio_mask = 3, 168 }, 169 [36] = { 170 .pend = IPIC_SIPNR_H, 171 .mask = IPIC_SIMSR_H, 172 .prio = IPIC_SIPRR_A, 173 .force = IPIC_SIFCR_H, 174 .bit = 4, 175 .prio_mask = 4, 176 }, 177 [37] = { 178 .pend = IPIC_SIPNR_H, 179 .mask = IPIC_SIMSR_H, 180 .prio = IPIC_SIPRR_A, 181 .force = IPIC_SIFCR_H, 182 .bit = 5, 183 .prio_mask = 5, 184 }, 185 [38] = { 186 .pend = IPIC_SIPNR_H, 187 .mask = IPIC_SIMSR_H, 188 .prio = IPIC_SIPRR_A, 189 .force = IPIC_SIFCR_H, 190 .bit = 6, 191 .prio_mask = 6, 192 }, 193 [39] = { 194 .pend = IPIC_SIPNR_H, 195 .mask = IPIC_SIMSR_H, 196 .prio = IPIC_SIPRR_A, 197 .force = IPIC_SIFCR_H, 198 .bit = 7, 199 .prio_mask = 7, 200 }, 201 [48] = { 202 .pend = IPIC_SEPNR, 203 .mask = IPIC_SEMSR, 204 .prio = IPIC_SMPRR_A, 205 .force = IPIC_SEFCR, 206 .bit = 0, 207 .prio_mask = 4, 208 }, 209 [64] = { 210 .pend = IPIC_SIPNR_H, 211 .mask = IPIC_SIMSR_L, 212 .prio = IPIC_SMPRR_A, 213 .force = IPIC_SIFCR_L, 214 .bit = 0, 215 .prio_mask = 0, 216 }, 217 [65] = { 218 .pend = IPIC_SIPNR_H, 219 .mask = IPIC_SIMSR_L, 220 .prio = IPIC_SMPRR_A, 221 .force = IPIC_SIFCR_L, 222 .bit = 1, 223 .prio_mask = 1, 224 }, 225 [66] = { 226 .pend = IPIC_SIPNR_H, 227 .mask = IPIC_SIMSR_L, 228 .prio = IPIC_SMPRR_A, 229 .force = IPIC_SIFCR_L, 230 .bit = 2, 231 .prio_mask = 2, 232 }, 233 [67] = { 234 .pend = IPIC_SIPNR_H, 235 .mask = IPIC_SIMSR_L, 236 .prio = IPIC_SMPRR_A, 237 .force = IPIC_SIFCR_L, 238 .bit = 3, 239 .prio_mask = 3, 240 }, 241 [68] = { 242 .pend = IPIC_SIPNR_H, 243 .mask = IPIC_SIMSR_L, 244 .prio = IPIC_SMPRR_B, 245 .force = IPIC_SIFCR_L, 246 .bit = 4, 247 .prio_mask = 0, 248 }, 249 [69] = { 250 .pend = IPIC_SIPNR_H, 251 .mask = IPIC_SIMSR_L, 252 .prio = IPIC_SMPRR_B, 253 .force = IPIC_SIFCR_L, 254 .bit = 5, 255 .prio_mask = 1, 256 }, 257 [70] = { 258 .pend = IPIC_SIPNR_H, 259 .mask = IPIC_SIMSR_L, 260 .prio = IPIC_SMPRR_B, 261 .force = IPIC_SIFCR_L, 262 .bit = 6, 263 .prio_mask = 2, 264 }, 265 [71] = { 266 .pend = IPIC_SIPNR_H, 267 .mask = IPIC_SIMSR_L, 268 .prio = IPIC_SMPRR_B, 269 .force = IPIC_SIFCR_L, 270 .bit = 7, 271 .prio_mask = 3, 272 }, 273 [72] = { 274 .pend = IPIC_SIPNR_H, 275 .mask = IPIC_SIMSR_L, 276 .prio = 0, 277 .force = IPIC_SIFCR_L, 278 .bit = 8, 279 }, 280 [73] = { 281 .pend = IPIC_SIPNR_H, 282 .mask = IPIC_SIMSR_L, 283 .prio = 0, 284 .force = IPIC_SIFCR_L, 285 .bit = 9, 286 }, 287 [74] = { 288 .pend = IPIC_SIPNR_H, 289 .mask = IPIC_SIMSR_L, 290 .prio = 0, 291 .force = IPIC_SIFCR_L, 292 .bit = 10, 293 }, 294 [75] = { 295 .pend = IPIC_SIPNR_H, 296 .mask = IPIC_SIMSR_L, 297 .prio = 0, 298 .force = IPIC_SIFCR_L, 299 .bit = 11, 300 }, 301 [76] = { 302 .pend = IPIC_SIPNR_H, 303 .mask = IPIC_SIMSR_L, 304 .prio = 0, 305 .force = IPIC_SIFCR_L, 306 .bit = 12, 307 }, 308 [77] = { 309 .pend = IPIC_SIPNR_H, 310 .mask = IPIC_SIMSR_L, 311 .prio = 0, 312 .force = IPIC_SIFCR_L, 313 .bit = 13, 314 }, 315 [78] = { 316 .pend = IPIC_SIPNR_H, 317 .mask = IPIC_SIMSR_L, 318 .prio = 0, 319 .force = IPIC_SIFCR_L, 320 .bit = 14, 321 }, 322 [79] = { 323 .pend = IPIC_SIPNR_H, 324 .mask = IPIC_SIMSR_L, 325 .prio = 0, 326 .force = IPIC_SIFCR_L, 327 .bit = 15, 328 }, 329 [80] = { 330 .pend = IPIC_SIPNR_H, 331 .mask = IPIC_SIMSR_L, 332 .prio = 0, 333 .force = IPIC_SIFCR_L, 334 .bit = 16, 335 }, 336 [84] = { 337 .pend = IPIC_SIPNR_H, 338 .mask = IPIC_SIMSR_L, 339 .prio = 0, 340 .force = IPIC_SIFCR_L, 341 .bit = 20, 342 }, 343 [85] = { 344 .pend = IPIC_SIPNR_H, 345 .mask = IPIC_SIMSR_L, 346 .prio = 0, 347 .force = IPIC_SIFCR_L, 348 .bit = 21, 349 }, 350 [90] = { 351 .pend = IPIC_SIPNR_H, 352 .mask = IPIC_SIMSR_L, 353 .prio = 0, 354 .force = IPIC_SIFCR_L, 355 .bit = 26, 356 }, 357 [91] = { 358 .pend = IPIC_SIPNR_H, 359 .mask = IPIC_SIMSR_L, 360 .prio = 0, 361 .force = IPIC_SIFCR_L, 362 .bit = 27, 363 }, 364 }; 365 366 static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) 367 { 368 return in_be32(base + (reg >> 2)); 369 } 370 371 static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) 372 { 373 out_be32(base + (reg >> 2), value); 374 } 375 376 static inline struct ipic * ipic_from_irq(unsigned int irq) 377 { 378 return primary_ipic; 379 } 380 381 static void ipic_enable_irq(unsigned int irq) 382 { 383 struct ipic *ipic = ipic_from_irq(irq); 384 unsigned int src = irq - ipic->irq_offset; 385 u32 temp; 386 387 temp = ipic_read(ipic->regs, ipic_info[src].mask); 388 temp |= (1 << (31 - ipic_info[src].bit)); 389 ipic_write(ipic->regs, ipic_info[src].mask, temp); 390 } 391 392 static void ipic_disable_irq(unsigned int irq) 393 { 394 struct ipic *ipic = ipic_from_irq(irq); 395 unsigned int src = irq - ipic->irq_offset; 396 u32 temp; 397 398 temp = ipic_read(ipic->regs, ipic_info[src].mask); 399 temp &= ~(1 << (31 - ipic_info[src].bit)); 400 ipic_write(ipic->regs, ipic_info[src].mask, temp); 401 } 402 403 static void ipic_disable_irq_and_ack(unsigned int irq) 404 { 405 struct ipic *ipic = ipic_from_irq(irq); 406 unsigned int src = irq - ipic->irq_offset; 407 u32 temp; 408 409 ipic_disable_irq(irq); 410 411 temp = ipic_read(ipic->regs, ipic_info[src].pend); 412 temp |= (1 << (31 - ipic_info[src].bit)); 413 ipic_write(ipic->regs, ipic_info[src].pend, temp); 414 } 415 416 static void ipic_end_irq(unsigned int irq) 417 { 418 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 419 ipic_enable_irq(irq); 420 } 421 422 struct hw_interrupt_type ipic = { 423 .typename = " IPIC ", 424 .enable = ipic_enable_irq, 425 .disable = ipic_disable_irq, 426 .ack = ipic_disable_irq_and_ack, 427 .end = ipic_end_irq, 428 }; 429 430 void __init ipic_init(phys_addr_t phys_addr, 431 unsigned int flags, 432 unsigned int irq_offset, 433 unsigned char *senses, 434 unsigned int senses_count) 435 { 436 u32 i, temp = 0; 437 438 primary_ipic = &p_ipic; 439 primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); 440 441 primary_ipic->irq_offset = irq_offset; 442 443 ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); 444 445 /* default priority scheme is grouped. If spread mode is required 446 * configure SICFR accordingly */ 447 if (flags & IPIC_SPREADMODE_GRP_A) 448 temp |= SICFR_IPSA; 449 if (flags & IPIC_SPREADMODE_GRP_D) 450 temp |= SICFR_IPSD; 451 if (flags & IPIC_SPREADMODE_MIX_A) 452 temp |= SICFR_MPSA; 453 if (flags & IPIC_SPREADMODE_MIX_B) 454 temp |= SICFR_MPSB; 455 456 ipic_write(primary_ipic->regs, IPIC_SICNR, temp); 457 458 /* handle MCP route */ 459 temp = 0; 460 if (flags & IPIC_DISABLE_MCP_OUT) 461 temp = SERCR_MCPR; 462 ipic_write(primary_ipic->regs, IPIC_SERCR, temp); 463 464 /* handle routing of IRQ0 to MCP */ 465 temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); 466 467 if (flags & IPIC_IRQ0_MCP) 468 temp |= SEMSR_SIRQ0; 469 else 470 temp &= ~SEMSR_SIRQ0; 471 472 ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); 473 474 for (i = 0 ; i < NR_IPIC_INTS ; i++) { 475 irq_desc[i+irq_offset].handler = &ipic; 476 irq_desc[i+irq_offset].status = IRQ_LEVEL; 477 } 478 479 temp = 0; 480 for (i = 0 ; i < senses_count ; i++) { 481 if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { 482 temp |= 1 << (15 - i); 483 if (i != 0) 484 irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; 485 else 486 irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; 487 } 488 } 489 ipic_write(primary_ipic->regs, IPIC_SECNR, temp); 490 491 printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, 492 senses_count, primary_ipic->regs); 493 } 494 495 int ipic_set_priority(unsigned int irq, unsigned int priority) 496 { 497 struct ipic *ipic = ipic_from_irq(irq); 498 unsigned int src = irq - ipic->irq_offset; 499 u32 temp; 500 501 if (priority > 7) 502 return -EINVAL; 503 if (src > 127) 504 return -EINVAL; 505 if (ipic_info[src].prio == 0) 506 return -EINVAL; 507 508 temp = ipic_read(ipic->regs, ipic_info[src].prio); 509 510 if (priority < 4) { 511 temp &= ~(0x7 << (20 + (3 - priority) * 3)); 512 temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); 513 } else { 514 temp &= ~(0x7 << (4 + (7 - priority) * 3)); 515 temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); 516 } 517 518 ipic_write(ipic->regs, ipic_info[src].prio, temp); 519 520 return 0; 521 } 522 523 void ipic_set_highest_priority(unsigned int irq) 524 { 525 struct ipic *ipic = ipic_from_irq(irq); 526 unsigned int src = irq - ipic->irq_offset; 527 u32 temp; 528 529 temp = ipic_read(ipic->regs, IPIC_SICFR); 530 531 /* clear and set HPI */ 532 temp &= 0x7f000000; 533 temp |= (src & 0x7f) << 24; 534 535 ipic_write(ipic->regs, IPIC_SICFR, temp); 536 } 537 538 void ipic_set_default_priority(void) 539 { 540 ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); 541 ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); 542 ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); 543 ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); 544 ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); 545 ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); 546 ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); 547 ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); 548 549 ipic_set_priority(MPC83xx_IRQ_UART1, 0); 550 ipic_set_priority(MPC83xx_IRQ_UART2, 1); 551 ipic_set_priority(MPC83xx_IRQ_SEC2, 2); 552 ipic_set_priority(MPC83xx_IRQ_IIC1, 5); 553 ipic_set_priority(MPC83xx_IRQ_IIC2, 6); 554 ipic_set_priority(MPC83xx_IRQ_SPI, 7); 555 ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); 556 ipic_set_priority(MPC83xx_IRQ_PIT, 1); 557 ipic_set_priority(MPC83xx_IRQ_PCI1, 2); 558 ipic_set_priority(MPC83xx_IRQ_PCI2, 3); 559 ipic_set_priority(MPC83xx_IRQ_EXT0, 4); 560 ipic_set_priority(MPC83xx_IRQ_EXT1, 5); 561 ipic_set_priority(MPC83xx_IRQ_EXT2, 6); 562 ipic_set_priority(MPC83xx_IRQ_EXT3, 7); 563 ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); 564 ipic_set_priority(MPC83xx_IRQ_MU, 1); 565 ipic_set_priority(MPC83xx_IRQ_SBA, 2); 566 ipic_set_priority(MPC83xx_IRQ_DMA, 3); 567 ipic_set_priority(MPC83xx_IRQ_EXT4, 4); 568 ipic_set_priority(MPC83xx_IRQ_EXT5, 5); 569 ipic_set_priority(MPC83xx_IRQ_EXT6, 6); 570 ipic_set_priority(MPC83xx_IRQ_EXT7, 7); 571 } 572 573 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) 574 { 575 struct ipic *ipic = primary_ipic; 576 u32 temp; 577 578 temp = ipic_read(ipic->regs, IPIC_SERMR); 579 temp |= (1 << (31 - mcp_irq)); 580 ipic_write(ipic->regs, IPIC_SERMR, temp); 581 } 582 583 void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) 584 { 585 struct ipic *ipic = primary_ipic; 586 u32 temp; 587 588 temp = ipic_read(ipic->regs, IPIC_SERMR); 589 temp &= (1 << (31 - mcp_irq)); 590 ipic_write(ipic->regs, IPIC_SERMR, temp); 591 } 592 593 u32 ipic_get_mcp_status(void) 594 { 595 return ipic_read(primary_ipic->regs, IPIC_SERMR); 596 } 597 598 void ipic_clear_mcp_status(u32 mask) 599 { 600 ipic_write(primary_ipic->regs, IPIC_SERMR, mask); 601 } 602 603 /* Return an interrupt vector or -1 if no interrupt is pending. */ 604 int ipic_get_irq(struct pt_regs *regs) 605 { 606 int irq; 607 608 irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; 609 610 if (irq == 0) /* 0 --> no irq is pending */ 611 irq = -1; 612 613 return irq; 614 } 615 616 static struct sysdev_class ipic_sysclass = { 617 set_kset_name("ipic"), 618 }; 619 620 static struct sys_device device_ipic = { 621 .id = 0, 622 .cls = &ipic_sysclass, 623 }; 624 625 static int __init init_ipic_sysfs(void) 626 { 627 int rc; 628 629 if (!primary_ipic->regs) 630 return -ENODEV; 631 printk(KERN_DEBUG "Registering ipic with sysfs...\n"); 632 633 rc = sysdev_class_register(&ipic_sysclass); 634 if (rc) { 635 printk(KERN_ERR "Failed registering ipic sys class\n"); 636 return -ENODEV; 637 } 638 rc = sysdev_register(&device_ipic); 639 if (rc) { 640 printk(KERN_ERR "Failed registering ipic sys device\n"); 641 return -ENODEV; 642 } 643 return 0; 644 } 645 646 subsys_initcall(init_ipic_sysfs); 647