11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Handle interrupts from the SRM, assuming no additional weirdness. 31da177e4SLinus Torvalds */ 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds #include <linux/init.h> 61da177e4SLinus Torvalds #include <linux/sched.h> 71da177e4SLinus Torvalds #include <linux/irq.h> 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include "proto.h" 101da177e4SLinus Torvalds #include "irq_impl.h" 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds /* 141da177e4SLinus Torvalds * Is the palcode SMP safe? In other words: can we call cserve_ena/dis 151da177e4SLinus Torvalds * at the same time in multiple CPUs? To be safe I added a spinlock 161da177e4SLinus Torvalds * but it can be removed trivially if the palcode is robust against smp. 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds DEFINE_SPINLOCK(srm_irq_lock); 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds static inline void 211da177e4SLinus Torvalds srm_enable_irq(unsigned int irq) 221da177e4SLinus Torvalds { 231da177e4SLinus Torvalds spin_lock(&srm_irq_lock); 241da177e4SLinus Torvalds cserve_ena(irq - 16); 251da177e4SLinus Torvalds spin_unlock(&srm_irq_lock); 261da177e4SLinus Torvalds } 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds static void 291da177e4SLinus Torvalds srm_disable_irq(unsigned int irq) 301da177e4SLinus Torvalds { 311da177e4SLinus Torvalds spin_lock(&srm_irq_lock); 321da177e4SLinus Torvalds cserve_dis(irq - 16); 331da177e4SLinus Torvalds spin_unlock(&srm_irq_lock); 341da177e4SLinus Torvalds } 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds static unsigned int 371da177e4SLinus Torvalds srm_startup_irq(unsigned int irq) 381da177e4SLinus Torvalds { 391da177e4SLinus Torvalds srm_enable_irq(irq); 401da177e4SLinus Torvalds return 0; 411da177e4SLinus Torvalds } 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds static void 441da177e4SLinus Torvalds srm_end_irq(unsigned int irq) 451da177e4SLinus Torvalds { 461da177e4SLinus Torvalds if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 471da177e4SLinus Torvalds srm_enable_irq(irq); 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* Handle interrupts from the SRM, assuming no additional weirdness. */ 5144377f62SThomas Gleixner static struct irq_chip srm_irq_type = { 528ab1221cSThomas Gleixner .name = "SRM", 531da177e4SLinus Torvalds .startup = srm_startup_irq, 541da177e4SLinus Torvalds .shutdown = srm_disable_irq, 551da177e4SLinus Torvalds .enable = srm_enable_irq, 561da177e4SLinus Torvalds .disable = srm_disable_irq, 571da177e4SLinus Torvalds .ack = srm_disable_irq, 581da177e4SLinus Torvalds .end = srm_end_irq, 591da177e4SLinus Torvalds }; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds void __init 621da177e4SLinus Torvalds init_srm_irqs(long max, unsigned long ignore_mask) 631da177e4SLinus Torvalds { 641da177e4SLinus Torvalds long i; 651da177e4SLinus Torvalds 6670b66cbfSIvan Kokshaysky if (NR_IRQS <= 16) 6770b66cbfSIvan Kokshaysky return; 681da177e4SLinus Torvalds for (i = 16; i < max; ++i) { 691da177e4SLinus Torvalds if (i < 64 && ((ignore_mask >> i) & 1)) 701da177e4SLinus Torvalds continue; 711da177e4SLinus Torvalds irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; 72d1bef4edSIngo Molnar irq_desc[i].chip = &srm_irq_type; 731da177e4SLinus Torvalds } 741da177e4SLinus Torvalds } 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds void 777ca56053SAl Viro srm_device_interrupt(unsigned long vector) 781da177e4SLinus Torvalds { 791da177e4SLinus Torvalds int irq = (vector - 0x800) >> 4; 803dbb8c62SAl Viro handle_irq(irq); 811da177e4SLinus Torvalds } 82