at v2.6.24-rc4 710 lines 19 kB view raw
1/* 2 * Copyright (C) 1997 Geert Uytterhoeven 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file COPYING in the main directory of this archive 6 * for more details. 7 * 8 * This is a duplicate of open_pic.c that deals with U3s MPIC on 9 * G5 PowerMacs. It's the same file except it's using big endian 10 * register accesses 11 */ 12 13#include <linux/types.h> 14#include <linux/kernel.h> 15#include <linux/sched.h> 16#include <linux/init.h> 17#include <linux/interrupt.h> 18#include <linux/sysdev.h> 19#include <linux/errno.h> 20#include <asm/ptrace.h> 21#include <asm/signal.h> 22#include <asm/io.h> 23#include <asm/irq.h> 24#include <asm/sections.h> 25#include <asm/open_pic.h> 26#include <asm/i8259.h> 27#include <asm/machdep.h> 28 29#include "open_pic_defs.h" 30 31void *OpenPIC2_Addr; 32static volatile struct OpenPIC *OpenPIC2 = NULL; 33/* 34 * We define OpenPIC_InitSenses table thusly: 35 * bit 0x1: sense, 0 for edge and 1 for level. 36 * bit 0x2: polarity, 0 for negative, 1 for positive. 37 */ 38extern u_int OpenPIC_NumInitSenses; 39extern u_char *OpenPIC_InitSenses; 40extern int use_of_interrupt_tree; 41 42static u_int NumProcessors; 43static u_int NumSources; 44static int open_pic2_irq_offset; 45static volatile OpenPIC_Source *ISR[NR_IRQS]; 46 47/* Global Operations */ 48static void openpic2_disable_8259_pass_through(void); 49static void openpic2_set_priority(u_int pri); 50static void openpic2_set_spurious(u_int vector); 51 52/* Timer Interrupts */ 53static void openpic2_inittimer(u_int timer, u_int pri, u_int vector); 54static void openpic2_maptimer(u_int timer, u_int cpumask); 55 56/* Interrupt Sources */ 57static void openpic2_enable_irq(u_int irq); 58static void openpic2_disable_irq(u_int irq); 59static void openpic2_initirq(u_int irq, u_int pri, u_int vector, int polarity, 60 int is_level); 61static void openpic2_mapirq(u_int irq, u_int cpumask, u_int keepmask); 62 63/* 64 * These functions are not used but the code is kept here 65 * for completeness and future reference. 66 */ 67static void openpic2_reset(void); 68#ifdef notused 69static void openpic2_enable_8259_pass_through(void); 70static u_int openpic2_get_priority(void); 71static u_int openpic2_get_spurious(void); 72static void openpic2_set_sense(u_int irq, int sense); 73#endif /* notused */ 74 75/* 76 * Description of the openpic for the higher-level irq code 77 */ 78static void openpic2_end_irq(unsigned int irq_nr); 79static void openpic2_ack_irq(unsigned int irq_nr); 80 81struct hw_interrupt_type open_pic2 = { 82 .typename = " OpenPIC2 ", 83 .enable = openpic2_enable_irq, 84 .disable = openpic2_disable_irq, 85 .ack = openpic2_ack_irq, 86 .end = openpic2_end_irq, 87}; 88 89/* 90 * Accesses to the current processor's openpic registers 91 * On cascaded controller, this is only CPU 0 92 */ 93#define THIS_CPU Processor[0] 94#define DECL_THIS_CPU 95#define CHECK_THIS_CPU 96 97#if 1 98#define check_arg_ipi(ipi) \ 99 if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \ 100 printk("open_pic.c:%d: illegal ipi %d\n", __LINE__, ipi); 101#define check_arg_timer(timer) \ 102 if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \ 103 printk("open_pic.c:%d: illegal timer %d\n", __LINE__, timer); 104#define check_arg_vec(vec) \ 105 if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \ 106 printk("open_pic.c:%d: illegal vector %d\n", __LINE__, vec); 107#define check_arg_pri(pri) \ 108 if (pri < 0 || pri >= OPENPIC_NUM_PRI) \ 109 printk("open_pic.c:%d: illegal priority %d\n", __LINE__, pri); 110/* 111 * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's 112 * data has probably been corrupted and we're going to panic or deadlock later 113 * anyway --Troy 114 */ 115extern unsigned long* _get_SP(void); 116#define check_arg_irq(irq) \ 117 if (irq < open_pic2_irq_offset || irq >= NumSources+open_pic2_irq_offset \ 118 || ISR[irq - open_pic2_irq_offset] == 0) { \ 119 printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \ 120 /*print_backtrace(_get_SP());*/ } 121#define check_arg_cpu(cpu) \ 122 if (cpu < 0 || cpu >= NumProcessors){ \ 123 printk("open_pic2.c:%d: illegal cpu %d\n", __LINE__, cpu); \ 124 /*print_backtrace(_get_SP());*/ } 125#else 126#define check_arg_ipi(ipi) do {} while (0) 127#define check_arg_timer(timer) do {} while (0) 128#define check_arg_vec(vec) do {} while (0) 129#define check_arg_pri(pri) do {} while (0) 130#define check_arg_irq(irq) do {} while (0) 131#define check_arg_cpu(cpu) do {} while (0) 132#endif 133 134static u_int openpic2_read(volatile u_int *addr) 135{ 136 u_int val; 137 138 val = in_be32(addr); 139 return val; 140} 141 142static inline void openpic2_write(volatile u_int *addr, u_int val) 143{ 144 out_be32(addr, val); 145} 146 147static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask) 148{ 149 u_int val = openpic2_read(addr); 150 return val & mask; 151} 152 153inline void openpic2_writefield(volatile u_int *addr, u_int mask, 154 u_int field) 155{ 156 u_int val = openpic2_read(addr); 157 openpic2_write(addr, (val & ~mask) | (field & mask)); 158} 159 160static inline void openpic2_clearfield(volatile u_int *addr, u_int mask) 161{ 162 openpic2_writefield(addr, mask, 0); 163} 164 165static inline void openpic2_setfield(volatile u_int *addr, u_int mask) 166{ 167 openpic2_writefield(addr, mask, mask); 168} 169 170static void openpic2_safe_writefield(volatile u_int *addr, u_int mask, 171 u_int field) 172{ 173 openpic2_setfield(addr, OPENPIC_MASK); 174 while (openpic2_read(addr) & OPENPIC_ACTIVITY); 175 openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK); 176} 177 178static void openpic2_reset(void) 179{ 180 openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, 181 OPENPIC_CONFIG_RESET); 182 while (openpic2_readfield(&OpenPIC2->Global.Global_Configuration0, 183 OPENPIC_CONFIG_RESET)) 184 mb(); 185} 186 187void __init openpic2_set_sources(int first_irq, int num_irqs, void *first_ISR) 188{ 189 volatile OpenPIC_Source *src = first_ISR; 190 int i, last_irq; 191 192 last_irq = first_irq + num_irqs; 193 if (last_irq > NumSources) 194 NumSources = last_irq; 195 if (src == 0) 196 src = &((struct OpenPIC *)OpenPIC2_Addr)->Source[first_irq]; 197 for (i = first_irq; i < last_irq; ++i, ++src) 198 ISR[i] = src; 199} 200 201/* 202 * The `offset' parameter defines where the interrupts handled by the 203 * OpenPIC start in the space of interrupt numbers that the kernel knows 204 * about. In other words, the OpenPIC's IRQ0 is numbered `offset' in the 205 * kernel's interrupt numbering scheme. 206 * We assume there is only one OpenPIC. 207 */ 208void __init openpic2_init(int offset) 209{ 210 u_int t, i; 211 u_int timerfreq; 212 const char *version; 213 214 if (!OpenPIC2_Addr) { 215 printk("No OpenPIC2 found !\n"); 216 return; 217 } 218 OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr; 219 220 if (ppc_md.progress) ppc_md.progress("openpic: enter", 0x122); 221 222 t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0); 223 switch (t & OPENPIC_FEATURE_VERSION_MASK) { 224 case 1: 225 version = "1.0"; 226 break; 227 case 2: 228 version = "1.2"; 229 break; 230 case 3: 231 version = "1.3"; 232 break; 233 default: 234 version = "?"; 235 break; 236 } 237 NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >> 238 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1; 239 if (NumSources == 0) 240 openpic2_set_sources(0, 241 ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >> 242 OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1, 243 NULL); 244 printk("OpenPIC (2) Version %s (%d CPUs and %d IRQ sources) at %p\n", 245 version, NumProcessors, NumSources, OpenPIC2); 246 timerfreq = openpic2_read(&OpenPIC2->Global.Timer_Frequency); 247 if (timerfreq) 248 printk("OpenPIC timer frequency is %d.%06d MHz\n", 249 timerfreq / 1000000, timerfreq % 1000000); 250 251 open_pic2_irq_offset = offset; 252 253 /* Initialize timer interrupts */ 254 if ( ppc_md.progress ) ppc_md.progress("openpic2: timer",0x3ba); 255 for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { 256 /* Disabled, Priority 0 */ 257 openpic2_inittimer(i, 0, OPENPIC2_VEC_TIMER+i+offset); 258 /* No processor */ 259 openpic2_maptimer(i, 0); 260 } 261 262 /* Initialize external interrupts */ 263 if (ppc_md.progress) ppc_md.progress("openpic2: external",0x3bc); 264 265 openpic2_set_priority(0xf); 266 267 /* Init all external sources, including possibly the cascade. */ 268 for (i = 0; i < NumSources; i++) { 269 int sense; 270 271 if (ISR[i] == 0) 272 continue; 273 274 /* the bootloader may have left it enabled (bad !) */ 275 openpic2_disable_irq(i+offset); 276 277 sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \ 278 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE); 279 280 if (sense & IRQ_SENSE_MASK) 281 irq_desc[i+offset].status = IRQ_LEVEL; 282 283 /* Enabled, Priority 8 */ 284 openpic2_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK), 285 (sense & IRQ_SENSE_MASK)); 286 /* Processor 0 */ 287 openpic2_mapirq(i, 1<<0, 0); 288 } 289 290 /* Init descriptors */ 291 for (i = offset; i < NumSources + offset; i++) 292 irq_desc[i].chip = &open_pic2; 293 294 /* Initialize the spurious interrupt */ 295 if (ppc_md.progress) ppc_md.progress("openpic2: spurious",0x3bd); 296 openpic2_set_spurious(OPENPIC2_VEC_SPURIOUS+offset); 297 298 openpic2_disable_8259_pass_through(); 299 openpic2_set_priority(0); 300 301 if (ppc_md.progress) ppc_md.progress("openpic2: exit",0x222); 302} 303 304#ifdef notused 305static void openpic2_enable_8259_pass_through(void) 306{ 307 openpic2_clearfield(&OpenPIC2->Global.Global_Configuration0, 308 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); 309} 310#endif /* notused */ 311 312/* This can't be __init, it is used in openpic_sleep_restore_intrs */ 313static void openpic2_disable_8259_pass_through(void) 314{ 315 openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, 316 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); 317} 318 319/* 320 * Find out the current interrupt 321 */ 322u_int openpic2_irq(void) 323{ 324 u_int vec; 325 DECL_THIS_CPU; 326 327 CHECK_THIS_CPU; 328 vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge, 329 OPENPIC_VECTOR_MASK); 330 return vec; 331} 332 333void openpic2_eoi(void) 334{ 335 DECL_THIS_CPU; 336 337 CHECK_THIS_CPU; 338 openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0); 339 /* Handle PCI write posting */ 340 (void)openpic2_read(&OpenPIC2->THIS_CPU.EOI); 341} 342 343#ifdef notused 344static u_int openpic2_get_priority(void) 345{ 346 DECL_THIS_CPU; 347 348 CHECK_THIS_CPU; 349 return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority, 350 OPENPIC_CURRENT_TASK_PRIORITY_MASK); 351} 352#endif /* notused */ 353 354static void __init openpic2_set_priority(u_int pri) 355{ 356 DECL_THIS_CPU; 357 358 CHECK_THIS_CPU; 359 check_arg_pri(pri); 360 openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority, 361 OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri); 362} 363 364/* 365 * Get/set the spurious vector 366 */ 367#ifdef notused 368static u_int openpic2_get_spurious(void) 369{ 370 return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, 371 OPENPIC_VECTOR_MASK); 372} 373#endif /* notused */ 374 375/* This can't be __init, it is used in openpic_sleep_restore_intrs */ 376static void openpic2_set_spurious(u_int vec) 377{ 378 check_arg_vec(vec); 379 openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, 380 vec); 381} 382 383static DEFINE_SPINLOCK(openpic2_setup_lock); 384 385/* 386 * Initialize a timer interrupt (and disable it) 387 * 388 * timer: OpenPIC timer number 389 * pri: interrupt source priority 390 * vec: the vector it will produce 391 */ 392static void __init openpic2_inittimer(u_int timer, u_int pri, u_int vec) 393{ 394 check_arg_timer(timer); 395 check_arg_pri(pri); 396 check_arg_vec(vec); 397 openpic2_safe_writefield(&OpenPIC2->Global.Timer[timer].Vector_Priority, 398 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK, 399 (pri << OPENPIC_PRIORITY_SHIFT) | vec); 400} 401 402/* 403 * Map a timer interrupt to one or more CPUs 404 */ 405static void __init openpic2_maptimer(u_int timer, u_int cpumask) 406{ 407 check_arg_timer(timer); 408 openpic2_write(&OpenPIC2->Global.Timer[timer].Destination, 409 cpumask); 410} 411 412/* 413 * Initalize the interrupt source which will generate an NMI. 414 * This raises the interrupt's priority from 8 to 9. 415 * 416 * irq: The logical IRQ which generates an NMI. 417 */ 418void __init 419openpic2_init_nmi_irq(u_int irq) 420{ 421 check_arg_irq(irq); 422 openpic2_safe_writefield(&ISR[irq - open_pic2_irq_offset]->Vector_Priority, 423 OPENPIC_PRIORITY_MASK, 424 9 << OPENPIC_PRIORITY_SHIFT); 425} 426 427/* 428 * 429 * All functions below take an offset'ed irq argument 430 * 431 */ 432 433 434/* 435 * Enable/disable an external interrupt source 436 * 437 * Externally called, irq is an offseted system-wide interrupt number 438 */ 439static void openpic2_enable_irq(u_int irq) 440{ 441 volatile u_int *vpp; 442 443 check_arg_irq(irq); 444 vpp = &ISR[irq - open_pic2_irq_offset]->Vector_Priority; 445 openpic2_clearfield(vpp, OPENPIC_MASK); 446 /* make sure mask gets to controller before we return to user */ 447 do { 448 mb(); /* sync is probably useless here */ 449 } while (openpic2_readfield(vpp, OPENPIC_MASK)); 450} 451 452static void openpic2_disable_irq(u_int irq) 453{ 454 volatile u_int *vpp; 455 u32 vp; 456 457 check_arg_irq(irq); 458 vpp = &ISR[irq - open_pic2_irq_offset]->Vector_Priority; 459 openpic2_setfield(vpp, OPENPIC_MASK); 460 /* make sure mask gets to controller before we return to user */ 461 do { 462 mb(); /* sync is probably useless here */ 463 vp = openpic2_readfield(vpp, OPENPIC_MASK | OPENPIC_ACTIVITY); 464 } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK)); 465} 466 467 468/* 469 * Initialize an interrupt source (and disable it!) 470 * 471 * irq: OpenPIC interrupt number 472 * pri: interrupt source priority 473 * vec: the vector it will produce 474 * pol: polarity (1 for positive, 0 for negative) 475 * sense: 1 for level, 0 for edge 476 */ 477static void __init 478openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense) 479{ 480 openpic2_safe_writefield(&ISR[irq]->Vector_Priority, 481 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | 482 OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK, 483 (pri << OPENPIC_PRIORITY_SHIFT) | vec | 484 (pol ? OPENPIC_POLARITY_POSITIVE : 485 OPENPIC_POLARITY_NEGATIVE) | 486 (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE)); 487} 488 489/* 490 * Map an interrupt source to one or more CPUs 491 */ 492static void openpic2_mapirq(u_int irq, u_int physmask, u_int keepmask) 493{ 494 if (ISR[irq] == 0) 495 return; 496 if (keepmask != 0) 497 physmask |= openpic2_read(&ISR[irq]->Destination) & keepmask; 498 openpic2_write(&ISR[irq]->Destination, physmask); 499} 500 501#ifdef notused 502/* 503 * Set the sense for an interrupt source (and disable it!) 504 * 505 * sense: 1 for level, 0 for edge 506 */ 507static void openpic2_set_sense(u_int irq, int sense) 508{ 509 if (ISR[irq] != 0) 510 openpic2_safe_writefield(&ISR[irq]->Vector_Priority, 511 OPENPIC_SENSE_LEVEL, 512 (sense ? OPENPIC_SENSE_LEVEL : 0)); 513} 514#endif /* notused */ 515 516/* No spinlocks, should not be necessary with the OpenPIC 517 * (1 register = 1 interrupt and we have the desc lock). 518 */ 519static void openpic2_ack_irq(unsigned int irq_nr) 520{ 521 openpic2_disable_irq(irq_nr); 522 openpic2_eoi(); 523} 524 525static void openpic2_end_irq(unsigned int irq_nr) 526{ 527 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 528 openpic2_enable_irq(irq_nr); 529} 530 531int 532openpic2_get_irq(void) 533{ 534 int irq = openpic2_irq(); 535 536 if (irq == (OPENPIC2_VEC_SPURIOUS + open_pic2_irq_offset)) 537 irq = -1; 538 return irq; 539} 540 541#ifdef CONFIG_PM 542 543/* 544 * We implement the IRQ controller as a sysdev and put it 545 * to sleep at powerdown stage (the callback is named suspend, 546 * but it's old semantics, for the Device Model, it's really 547 * powerdown). The possible problem is that another sysdev that 548 * happens to be suspend after this one will have interrupts off, 549 * that may be an issue... For now, this isn't an issue on pmac 550 * though... 551 */ 552 553static u32 save_ipi_vp[OPENPIC_NUM_IPI]; 554static u32 save_irq_src_vp[OPENPIC_MAX_SOURCES]; 555static u32 save_irq_src_dest[OPENPIC_MAX_SOURCES]; 556static u32 save_cpu_task_pri[OPENPIC_MAX_PROCESSORS]; 557static int openpic_suspend_count; 558 559static void openpic2_cached_enable_irq(u_int irq) 560{ 561 check_arg_irq(irq); 562 save_irq_src_vp[irq - open_pic2_irq_offset] &= ~OPENPIC_MASK; 563} 564 565static void openpic2_cached_disable_irq(u_int irq) 566{ 567 check_arg_irq(irq); 568 save_irq_src_vp[irq - open_pic2_irq_offset] |= OPENPIC_MASK; 569} 570 571/* WARNING: Can be called directly by the cpufreq code with NULL parameter, 572 * we need something better to deal with that... Maybe switch to S1 for 573 * cpufreq changes 574 */ 575int openpic2_suspend(struct sys_device *sysdev, pm_message_t state) 576{ 577 int i; 578 unsigned long flags; 579 580 spin_lock_irqsave(&openpic2_setup_lock, flags); 581 582 if (openpic_suspend_count++ > 0) { 583 spin_unlock_irqrestore(&openpic2_setup_lock, flags); 584 return 0; 585 } 586 587 open_pic2.enable = openpic2_cached_enable_irq; 588 open_pic2.disable = openpic2_cached_disable_irq; 589 590 for (i=0; i<NumProcessors; i++) { 591 save_cpu_task_pri[i] = openpic2_read(&OpenPIC2->Processor[i].Current_Task_Priority); 592 openpic2_writefield(&OpenPIC2->Processor[i].Current_Task_Priority, 593 OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf); 594 } 595 596 for (i=0; i<OPENPIC_NUM_IPI; i++) 597 save_ipi_vp[i] = openpic2_read(&OpenPIC2->Global.IPI_Vector_Priority(i)); 598 for (i=0; i<NumSources; i++) { 599 if (ISR[i] == 0) 600 continue; 601 save_irq_src_vp[i] = openpic2_read(&ISR[i]->Vector_Priority) & ~OPENPIC_ACTIVITY; 602 save_irq_src_dest[i] = openpic2_read(&ISR[i]->Destination); 603 } 604 605 spin_unlock_irqrestore(&openpic2_setup_lock, flags); 606 607 return 0; 608} 609 610/* WARNING: Can be called directly by the cpufreq code with NULL parameter, 611 * we need something better to deal with that... Maybe switch to S1 for 612 * cpufreq changes 613 */ 614int openpic2_resume(struct sys_device *sysdev) 615{ 616 int i; 617 unsigned long flags; 618 u32 vppmask = OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | 619 OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK | 620 OPENPIC_MASK; 621 622 spin_lock_irqsave(&openpic2_setup_lock, flags); 623 624 if ((--openpic_suspend_count) > 0) { 625 spin_unlock_irqrestore(&openpic2_setup_lock, flags); 626 return 0; 627 } 628 629 openpic2_reset(); 630 631 /* OpenPIC sometimes seem to need some time to be fully back up... */ 632 do { 633 openpic2_set_spurious(OPENPIC2_VEC_SPURIOUS+open_pic2_irq_offset); 634 } while(openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK) 635 != (OPENPIC2_VEC_SPURIOUS + open_pic2_irq_offset)); 636 637 openpic2_disable_8259_pass_through(); 638 639 for (i=0; i<OPENPIC_NUM_IPI; i++) 640 openpic2_write(&OpenPIC2->Global.IPI_Vector_Priority(i), 641 save_ipi_vp[i]); 642 for (i=0; i<NumSources; i++) { 643 if (ISR[i] == 0) 644 continue; 645 openpic2_write(&ISR[i]->Destination, save_irq_src_dest[i]); 646 openpic2_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]); 647 /* make sure mask gets to controller before we return to user */ 648 do { 649 openpic2_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]); 650 } while (openpic2_readfield(&ISR[i]->Vector_Priority, vppmask) 651 != (save_irq_src_vp[i] & vppmask)); 652 } 653 for (i=0; i<NumProcessors; i++) 654 openpic2_write(&OpenPIC2->Processor[i].Current_Task_Priority, 655 save_cpu_task_pri[i]); 656 657 open_pic2.enable = openpic2_enable_irq; 658 open_pic2.disable = openpic2_disable_irq; 659 660 spin_unlock_irqrestore(&openpic2_setup_lock, flags); 661 662 return 0; 663} 664 665#endif /* CONFIG_PM */ 666 667/* HACK ALERT */ 668static struct sysdev_class openpic2_sysclass = { 669 set_kset_name("openpic2"), 670}; 671 672static struct sys_device device_openpic2 = { 673 .id = 0, 674 .cls = &openpic2_sysclass, 675}; 676 677static struct sysdev_driver driver_openpic2 = { 678#ifdef CONFIG_PM 679 .suspend = &openpic2_suspend, 680 .resume = &openpic2_resume, 681#endif /* CONFIG_PM */ 682}; 683 684static int __init init_openpic2_sysfs(void) 685{ 686 int rc; 687 688 if (!OpenPIC2_Addr) 689 return -ENODEV; 690 printk(KERN_DEBUG "Registering openpic2 with sysfs...\n"); 691 rc = sysdev_class_register(&openpic2_sysclass); 692 if (rc) { 693 printk(KERN_ERR "Failed registering openpic sys class\n"); 694 return -ENODEV; 695 } 696 rc = sysdev_register(&device_openpic2); 697 if (rc) { 698 printk(KERN_ERR "Failed registering openpic sys device\n"); 699 return -ENODEV; 700 } 701 rc = sysdev_driver_register(&openpic2_sysclass, &driver_openpic2); 702 if (rc) { 703 printk(KERN_ERR "Failed registering openpic sys driver\n"); 704 return -ENODEV; 705 } 706 return 0; 707} 708 709subsys_initcall(init_openpic2_sysfs); 710