1/* 2 * arch/powerpc/sysdev/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 <linux/device.h> 23#include <linux/bootmem.h> 24#include <linux/spinlock.h> 25#include <asm/irq.h> 26#include <asm/io.h> 27#include <asm/prom.h> 28#include <asm/ipic.h> 29 30#include "ipic.h" 31 32static struct ipic * primary_ipic; 33static DEFINE_SPINLOCK(ipic_lock); 34 35static struct ipic_info ipic_info[] = { 36 [9] = { 37 .pend = IPIC_SIPNR_H, 38 .mask = IPIC_SIMSR_H, 39 .prio = IPIC_SIPRR_D, 40 .force = IPIC_SIFCR_H, 41 .bit = 24, 42 .prio_mask = 0, 43 }, 44 [10] = { 45 .pend = IPIC_SIPNR_H, 46 .mask = IPIC_SIMSR_H, 47 .prio = IPIC_SIPRR_D, 48 .force = IPIC_SIFCR_H, 49 .bit = 25, 50 .prio_mask = 1, 51 }, 52 [11] = { 53 .pend = IPIC_SIPNR_H, 54 .mask = IPIC_SIMSR_H, 55 .prio = IPIC_SIPRR_D, 56 .force = IPIC_SIFCR_H, 57 .bit = 26, 58 .prio_mask = 2, 59 }, 60 [14] = { 61 .pend = IPIC_SIPNR_H, 62 .mask = IPIC_SIMSR_H, 63 .prio = IPIC_SIPRR_D, 64 .force = IPIC_SIFCR_H, 65 .bit = 29, 66 .prio_mask = 5, 67 }, 68 [15] = { 69 .pend = IPIC_SIPNR_H, 70 .mask = IPIC_SIMSR_H, 71 .prio = IPIC_SIPRR_D, 72 .force = IPIC_SIFCR_H, 73 .bit = 30, 74 .prio_mask = 6, 75 }, 76 [16] = { 77 .pend = IPIC_SIPNR_H, 78 .mask = IPIC_SIMSR_H, 79 .prio = IPIC_SIPRR_D, 80 .force = IPIC_SIFCR_H, 81 .bit = 31, 82 .prio_mask = 7, 83 }, 84 [17] = { 85 .pend = IPIC_SEPNR, 86 .mask = IPIC_SEMSR, 87 .prio = IPIC_SMPRR_A, 88 .force = IPIC_SEFCR, 89 .bit = 1, 90 .prio_mask = 5, 91 }, 92 [18] = { 93 .pend = IPIC_SEPNR, 94 .mask = IPIC_SEMSR, 95 .prio = IPIC_SMPRR_A, 96 .force = IPIC_SEFCR, 97 .bit = 2, 98 .prio_mask = 6, 99 }, 100 [19] = { 101 .pend = IPIC_SEPNR, 102 .mask = IPIC_SEMSR, 103 .prio = IPIC_SMPRR_A, 104 .force = IPIC_SEFCR, 105 .bit = 3, 106 .prio_mask = 7, 107 }, 108 [20] = { 109 .pend = IPIC_SEPNR, 110 .mask = IPIC_SEMSR, 111 .prio = IPIC_SMPRR_B, 112 .force = IPIC_SEFCR, 113 .bit = 4, 114 .prio_mask = 4, 115 }, 116 [21] = { 117 .pend = IPIC_SEPNR, 118 .mask = IPIC_SEMSR, 119 .prio = IPIC_SMPRR_B, 120 .force = IPIC_SEFCR, 121 .bit = 5, 122 .prio_mask = 5, 123 }, 124 [22] = { 125 .pend = IPIC_SEPNR, 126 .mask = IPIC_SEMSR, 127 .prio = IPIC_SMPRR_B, 128 .force = IPIC_SEFCR, 129 .bit = 6, 130 .prio_mask = 6, 131 }, 132 [23] = { 133 .pend = IPIC_SEPNR, 134 .mask = IPIC_SEMSR, 135 .prio = IPIC_SMPRR_B, 136 .force = IPIC_SEFCR, 137 .bit = 7, 138 .prio_mask = 7, 139 }, 140 [32] = { 141 .pend = IPIC_SIPNR_H, 142 .mask = IPIC_SIMSR_H, 143 .prio = IPIC_SIPRR_A, 144 .force = IPIC_SIFCR_H, 145 .bit = 0, 146 .prio_mask = 0, 147 }, 148 [33] = { 149 .pend = IPIC_SIPNR_H, 150 .mask = IPIC_SIMSR_H, 151 .prio = IPIC_SIPRR_A, 152 .force = IPIC_SIFCR_H, 153 .bit = 1, 154 .prio_mask = 1, 155 }, 156 [34] = { 157 .pend = IPIC_SIPNR_H, 158 .mask = IPIC_SIMSR_H, 159 .prio = IPIC_SIPRR_A, 160 .force = IPIC_SIFCR_H, 161 .bit = 2, 162 .prio_mask = 2, 163 }, 164 [35] = { 165 .pend = IPIC_SIPNR_H, 166 .mask = IPIC_SIMSR_H, 167 .prio = IPIC_SIPRR_A, 168 .force = IPIC_SIFCR_H, 169 .bit = 3, 170 .prio_mask = 3, 171 }, 172 [36] = { 173 .pend = IPIC_SIPNR_H, 174 .mask = IPIC_SIMSR_H, 175 .prio = IPIC_SIPRR_A, 176 .force = IPIC_SIFCR_H, 177 .bit = 4, 178 .prio_mask = 4, 179 }, 180 [37] = { 181 .pend = IPIC_SIPNR_H, 182 .mask = IPIC_SIMSR_H, 183 .prio = IPIC_SIPRR_A, 184 .force = IPIC_SIFCR_H, 185 .bit = 5, 186 .prio_mask = 5, 187 }, 188 [38] = { 189 .pend = IPIC_SIPNR_H, 190 .mask = IPIC_SIMSR_H, 191 .prio = IPIC_SIPRR_A, 192 .force = IPIC_SIFCR_H, 193 .bit = 6, 194 .prio_mask = 6, 195 }, 196 [39] = { 197 .pend = IPIC_SIPNR_H, 198 .mask = IPIC_SIMSR_H, 199 .prio = IPIC_SIPRR_A, 200 .force = IPIC_SIFCR_H, 201 .bit = 7, 202 .prio_mask = 7, 203 }, 204 [48] = { 205 .pend = IPIC_SEPNR, 206 .mask = IPIC_SEMSR, 207 .prio = IPIC_SMPRR_A, 208 .force = IPIC_SEFCR, 209 .bit = 0, 210 .prio_mask = 4, 211 }, 212 [64] = { 213 .pend = IPIC_SIPNR_L, 214 .mask = IPIC_SIMSR_L, 215 .prio = IPIC_SMPRR_A, 216 .force = IPIC_SIFCR_L, 217 .bit = 0, 218 .prio_mask = 0, 219 }, 220 [65] = { 221 .pend = IPIC_SIPNR_L, 222 .mask = IPIC_SIMSR_L, 223 .prio = IPIC_SMPRR_A, 224 .force = IPIC_SIFCR_L, 225 .bit = 1, 226 .prio_mask = 1, 227 }, 228 [66] = { 229 .pend = IPIC_SIPNR_L, 230 .mask = IPIC_SIMSR_L, 231 .prio = IPIC_SMPRR_A, 232 .force = IPIC_SIFCR_L, 233 .bit = 2, 234 .prio_mask = 2, 235 }, 236 [67] = { 237 .pend = IPIC_SIPNR_L, 238 .mask = IPIC_SIMSR_L, 239 .prio = IPIC_SMPRR_A, 240 .force = IPIC_SIFCR_L, 241 .bit = 3, 242 .prio_mask = 3, 243 }, 244 [68] = { 245 .pend = IPIC_SIPNR_L, 246 .mask = IPIC_SIMSR_L, 247 .prio = IPIC_SMPRR_B, 248 .force = IPIC_SIFCR_L, 249 .bit = 4, 250 .prio_mask = 0, 251 }, 252 [69] = { 253 .pend = IPIC_SIPNR_L, 254 .mask = IPIC_SIMSR_L, 255 .prio = IPIC_SMPRR_B, 256 .force = IPIC_SIFCR_L, 257 .bit = 5, 258 .prio_mask = 1, 259 }, 260 [70] = { 261 .pend = IPIC_SIPNR_L, 262 .mask = IPIC_SIMSR_L, 263 .prio = IPIC_SMPRR_B, 264 .force = IPIC_SIFCR_L, 265 .bit = 6, 266 .prio_mask = 2, 267 }, 268 [71] = { 269 .pend = IPIC_SIPNR_L, 270 .mask = IPIC_SIMSR_L, 271 .prio = IPIC_SMPRR_B, 272 .force = IPIC_SIFCR_L, 273 .bit = 7, 274 .prio_mask = 3, 275 }, 276 [72] = { 277 .pend = IPIC_SIPNR_L, 278 .mask = IPIC_SIMSR_L, 279 .prio = 0, 280 .force = IPIC_SIFCR_L, 281 .bit = 8, 282 }, 283 [73] = { 284 .pend = IPIC_SIPNR_L, 285 .mask = IPIC_SIMSR_L, 286 .prio = 0, 287 .force = IPIC_SIFCR_L, 288 .bit = 9, 289 }, 290 [74] = { 291 .pend = IPIC_SIPNR_L, 292 .mask = IPIC_SIMSR_L, 293 .prio = 0, 294 .force = IPIC_SIFCR_L, 295 .bit = 10, 296 }, 297 [75] = { 298 .pend = IPIC_SIPNR_L, 299 .mask = IPIC_SIMSR_L, 300 .prio = 0, 301 .force = IPIC_SIFCR_L, 302 .bit = 11, 303 }, 304 [76] = { 305 .pend = IPIC_SIPNR_L, 306 .mask = IPIC_SIMSR_L, 307 .prio = 0, 308 .force = IPIC_SIFCR_L, 309 .bit = 12, 310 }, 311 [77] = { 312 .pend = IPIC_SIPNR_L, 313 .mask = IPIC_SIMSR_L, 314 .prio = 0, 315 .force = IPIC_SIFCR_L, 316 .bit = 13, 317 }, 318 [78] = { 319 .pend = IPIC_SIPNR_L, 320 .mask = IPIC_SIMSR_L, 321 .prio = 0, 322 .force = IPIC_SIFCR_L, 323 .bit = 14, 324 }, 325 [79] = { 326 .pend = IPIC_SIPNR_L, 327 .mask = IPIC_SIMSR_L, 328 .prio = 0, 329 .force = IPIC_SIFCR_L, 330 .bit = 15, 331 }, 332 [80] = { 333 .pend = IPIC_SIPNR_L, 334 .mask = IPIC_SIMSR_L, 335 .prio = 0, 336 .force = IPIC_SIFCR_L, 337 .bit = 16, 338 }, 339 [84] = { 340 .pend = IPIC_SIPNR_L, 341 .mask = IPIC_SIMSR_L, 342 .prio = 0, 343 .force = IPIC_SIFCR_L, 344 .bit = 20, 345 }, 346 [85] = { 347 .pend = IPIC_SIPNR_L, 348 .mask = IPIC_SIMSR_L, 349 .prio = 0, 350 .force = IPIC_SIFCR_L, 351 .bit = 21, 352 }, 353 [90] = { 354 .pend = IPIC_SIPNR_L, 355 .mask = IPIC_SIMSR_L, 356 .prio = 0, 357 .force = IPIC_SIFCR_L, 358 .bit = 26, 359 }, 360 [91] = { 361 .pend = IPIC_SIPNR_L, 362 .mask = IPIC_SIMSR_L, 363 .prio = 0, 364 .force = IPIC_SIFCR_L, 365 .bit = 27, 366 }, 367}; 368 369static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) 370{ 371 return in_be32(base + (reg >> 2)); 372} 373 374static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) 375{ 376 out_be32(base + (reg >> 2), value); 377} 378 379static inline struct ipic * ipic_from_irq(unsigned int virq) 380{ 381 return primary_ipic; 382} 383 384#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) 385 386static void ipic_unmask_irq(unsigned int virq) 387{ 388 struct ipic *ipic = ipic_from_irq(virq); 389 unsigned int src = ipic_irq_to_hw(virq); 390 unsigned long flags; 391 u32 temp; 392 393 spin_lock_irqsave(&ipic_lock, flags); 394 395 temp = ipic_read(ipic->regs, ipic_info[src].mask); 396 temp |= (1 << (31 - ipic_info[src].bit)); 397 ipic_write(ipic->regs, ipic_info[src].mask, temp); 398 399 spin_unlock_irqrestore(&ipic_lock, flags); 400} 401 402static void ipic_mask_irq(unsigned int virq) 403{ 404 struct ipic *ipic = ipic_from_irq(virq); 405 unsigned int src = ipic_irq_to_hw(virq); 406 unsigned long flags; 407 u32 temp; 408 409 spin_lock_irqsave(&ipic_lock, flags); 410 411 temp = ipic_read(ipic->regs, ipic_info[src].mask); 412 temp &= ~(1 << (31 - ipic_info[src].bit)); 413 ipic_write(ipic->regs, ipic_info[src].mask, temp); 414 415 spin_unlock_irqrestore(&ipic_lock, flags); 416} 417 418static void ipic_ack_irq(unsigned int virq) 419{ 420 struct ipic *ipic = ipic_from_irq(virq); 421 unsigned int src = ipic_irq_to_hw(virq); 422 unsigned long flags; 423 u32 temp; 424 425 spin_lock_irqsave(&ipic_lock, flags); 426 427 temp = ipic_read(ipic->regs, ipic_info[src].pend); 428 temp |= (1 << (31 - ipic_info[src].bit)); 429 ipic_write(ipic->regs, ipic_info[src].pend, temp); 430 431 spin_unlock_irqrestore(&ipic_lock, flags); 432} 433 434static void ipic_mask_irq_and_ack(unsigned int virq) 435{ 436 struct ipic *ipic = ipic_from_irq(virq); 437 unsigned int src = ipic_irq_to_hw(virq); 438 unsigned long flags; 439 u32 temp; 440 441 spin_lock_irqsave(&ipic_lock, flags); 442 443 temp = ipic_read(ipic->regs, ipic_info[src].mask); 444 temp &= ~(1 << (31 - ipic_info[src].bit)); 445 ipic_write(ipic->regs, ipic_info[src].mask, temp); 446 447 temp = ipic_read(ipic->regs, ipic_info[src].pend); 448 temp |= (1 << (31 - ipic_info[src].bit)); 449 ipic_write(ipic->regs, ipic_info[src].pend, temp); 450 451 spin_unlock_irqrestore(&ipic_lock, flags); 452} 453 454static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) 455{ 456 struct ipic *ipic = ipic_from_irq(virq); 457 unsigned int src = ipic_irq_to_hw(virq); 458 struct irq_desc *desc = get_irq_desc(virq); 459 unsigned int vold, vnew, edibit; 460 461 if (flow_type == IRQ_TYPE_NONE) 462 flow_type = IRQ_TYPE_LEVEL_LOW; 463 464 /* ipic supports only low assertion and high-to-low change senses 465 */ 466 if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { 467 printk(KERN_ERR "ipic: sense type 0x%x not supported\n", 468 flow_type); 469 return -EINVAL; 470 } 471 472 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 473 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 474 if (flow_type & IRQ_TYPE_LEVEL_LOW) { 475 desc->status |= IRQ_LEVEL; 476 desc->handle_irq = handle_level_irq; 477 } else { 478 desc->handle_irq = handle_edge_irq; 479 } 480 481 /* only EXT IRQ senses are programmable on ipic 482 * internal IRQ senses are LEVEL_LOW 483 */ 484 if (src == IPIC_IRQ_EXT0) 485 edibit = 15; 486 else 487 if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) 488 edibit = (14 - (src - IPIC_IRQ_EXT1)); 489 else 490 return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; 491 492 vold = ipic_read(ipic->regs, IPIC_SECNR); 493 if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { 494 vnew = vold | (1 << edibit); 495 } else { 496 vnew = vold & ~(1 << edibit); 497 } 498 if (vold != vnew) 499 ipic_write(ipic->regs, IPIC_SECNR, vnew); 500 return 0; 501} 502 503static struct irq_chip ipic_irq_chip = { 504 .typename = " IPIC ", 505 .unmask = ipic_unmask_irq, 506 .mask = ipic_mask_irq, 507 .mask_ack = ipic_mask_irq_and_ack, 508 .ack = ipic_ack_irq, 509 .set_type = ipic_set_irq_type, 510}; 511 512static int ipic_host_match(struct irq_host *h, struct device_node *node) 513{ 514 struct ipic *ipic = h->host_data; 515 516 /* Exact match, unless ipic node is NULL */ 517 return ipic->of_node == NULL || ipic->of_node == node; 518} 519 520static int ipic_host_map(struct irq_host *h, unsigned int virq, 521 irq_hw_number_t hw) 522{ 523 struct ipic *ipic = h->host_data; 524 struct irq_chip *chip; 525 526 /* Default chip */ 527 chip = &ipic->hc_irq; 528 529 set_irq_chip_data(virq, ipic); 530 set_irq_chip_and_handler(virq, chip, handle_level_irq); 531 532 /* Set default irq type */ 533 set_irq_type(virq, IRQ_TYPE_NONE); 534 535 return 0; 536} 537 538static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, 539 u32 *intspec, unsigned int intsize, 540 irq_hw_number_t *out_hwirq, unsigned int *out_flags) 541 542{ 543 /* interrupt sense values coming from the device tree equal either 544 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) 545 */ 546 *out_hwirq = intspec[0]; 547 if (intsize > 1) 548 *out_flags = intspec[1]; 549 else 550 *out_flags = IRQ_TYPE_NONE; 551 return 0; 552} 553 554static struct irq_host_ops ipic_host_ops = { 555 .match = ipic_host_match, 556 .map = ipic_host_map, 557 .xlate = ipic_host_xlate, 558}; 559 560struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) 561{ 562 struct ipic *ipic; 563 struct resource res; 564 u32 temp = 0, ret; 565 566 ipic = alloc_bootmem(sizeof(struct ipic)); 567 if (ipic == NULL) 568 return NULL; 569 570 memset(ipic, 0, sizeof(struct ipic)); 571 ipic->of_node = of_node_get(node); 572 573 ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 574 NR_IPIC_INTS, 575 &ipic_host_ops, 0); 576 if (ipic->irqhost == NULL) { 577 of_node_put(node); 578 return NULL; 579 } 580 581 ret = of_address_to_resource(node, 0, &res); 582 if (ret) { 583 of_node_put(node); 584 return NULL; 585 } 586 587 ipic->regs = ioremap(res.start, res.end - res.start + 1); 588 589 ipic->irqhost->host_data = ipic; 590 ipic->hc_irq = ipic_irq_chip; 591 592 /* init hw */ 593 ipic_write(ipic->regs, IPIC_SICNR, 0x0); 594 595 /* default priority scheme is grouped. If spread mode is required 596 * configure SICFR accordingly */ 597 if (flags & IPIC_SPREADMODE_GRP_A) 598 temp |= SICFR_IPSA; 599 if (flags & IPIC_SPREADMODE_GRP_D) 600 temp |= SICFR_IPSD; 601 if (flags & IPIC_SPREADMODE_MIX_A) 602 temp |= SICFR_MPSA; 603 if (flags & IPIC_SPREADMODE_MIX_B) 604 temp |= SICFR_MPSB; 605 606 ipic_write(ipic->regs, IPIC_SICNR, temp); 607 608 /* handle MCP route */ 609 temp = 0; 610 if (flags & IPIC_DISABLE_MCP_OUT) 611 temp = SERCR_MCPR; 612 ipic_write(ipic->regs, IPIC_SERCR, temp); 613 614 /* handle routing of IRQ0 to MCP */ 615 temp = ipic_read(ipic->regs, IPIC_SEMSR); 616 617 if (flags & IPIC_IRQ0_MCP) 618 temp |= SEMSR_SIRQ0; 619 else 620 temp &= ~SEMSR_SIRQ0; 621 622 ipic_write(ipic->regs, IPIC_SEMSR, temp); 623 624 primary_ipic = ipic; 625 irq_set_default_host(primary_ipic->irqhost); 626 627 printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, 628 primary_ipic->regs); 629 630 return ipic; 631} 632 633int ipic_set_priority(unsigned int virq, unsigned int priority) 634{ 635 struct ipic *ipic = ipic_from_irq(virq); 636 unsigned int src = ipic_irq_to_hw(virq); 637 u32 temp; 638 639 if (priority > 7) 640 return -EINVAL; 641 if (src > 127) 642 return -EINVAL; 643 if (ipic_info[src].prio == 0) 644 return -EINVAL; 645 646 temp = ipic_read(ipic->regs, ipic_info[src].prio); 647 648 if (priority < 4) { 649 temp &= ~(0x7 << (20 + (3 - priority) * 3)); 650 temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); 651 } else { 652 temp &= ~(0x7 << (4 + (7 - priority) * 3)); 653 temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); 654 } 655 656 ipic_write(ipic->regs, ipic_info[src].prio, temp); 657 658 return 0; 659} 660 661void ipic_set_highest_priority(unsigned int virq) 662{ 663 struct ipic *ipic = ipic_from_irq(virq); 664 unsigned int src = ipic_irq_to_hw(virq); 665 u32 temp; 666 667 temp = ipic_read(ipic->regs, IPIC_SICFR); 668 669 /* clear and set HPI */ 670 temp &= 0x7f000000; 671 temp |= (src & 0x7f) << 24; 672 673 ipic_write(ipic->regs, IPIC_SICFR, temp); 674} 675 676void ipic_set_default_priority(void) 677{ 678 ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT); 679 ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT); 680 ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT); 681 ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT); 682} 683 684void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) 685{ 686 struct ipic *ipic = primary_ipic; 687 u32 temp; 688 689 temp = ipic_read(ipic->regs, IPIC_SERMR); 690 temp |= (1 << (31 - mcp_irq)); 691 ipic_write(ipic->regs, IPIC_SERMR, temp); 692} 693 694void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) 695{ 696 struct ipic *ipic = primary_ipic; 697 u32 temp; 698 699 temp = ipic_read(ipic->regs, IPIC_SERMR); 700 temp &= (1 << (31 - mcp_irq)); 701 ipic_write(ipic->regs, IPIC_SERMR, temp); 702} 703 704u32 ipic_get_mcp_status(void) 705{ 706 return ipic_read(primary_ipic->regs, IPIC_SERMR); 707} 708 709void ipic_clear_mcp_status(u32 mask) 710{ 711 ipic_write(primary_ipic->regs, IPIC_SERMR, mask); 712} 713 714/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ 715unsigned int ipic_get_irq(void) 716{ 717 int irq; 718 719 BUG_ON(primary_ipic == NULL); 720 721#define IPIC_SIVCR_VECTOR_MASK 0x7f 722 irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; 723 724 if (irq == 0) /* 0 --> no irq is pending */ 725 return NO_IRQ; 726 727 return irq_linear_revmap(primary_ipic->irqhost, irq); 728} 729 730static struct sysdev_class ipic_sysclass = { 731 set_kset_name("ipic"), 732}; 733 734static struct sys_device device_ipic = { 735 .id = 0, 736 .cls = &ipic_sysclass, 737}; 738 739static int __init init_ipic_sysfs(void) 740{ 741 int rc; 742 743 if (!primary_ipic->regs) 744 return -ENODEV; 745 printk(KERN_DEBUG "Registering ipic with sysfs...\n"); 746 747 rc = sysdev_class_register(&ipic_sysclass); 748 if (rc) { 749 printk(KERN_ERR "Failed registering ipic sys class\n"); 750 return -ENODEV; 751 } 752 rc = sysdev_register(&device_ipic); 753 if (rc) { 754 printk(KERN_ERR "Failed registering ipic sys device\n"); 755 return -ENODEV; 756 } 757 return 0; 758} 759 760subsys_initcall(init_ipic_sysfs); 761