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 2135252254SThomas Gleixner srm_enable_irq(struct irq_data *d) 221da177e4SLinus Torvalds { 231da177e4SLinus Torvalds spin_lock(&srm_irq_lock); 2435252254SThomas Gleixner cserve_ena(d->irq - 16); 251da177e4SLinus Torvalds spin_unlock(&srm_irq_lock); 261da177e4SLinus Torvalds } 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds static void 2935252254SThomas Gleixner srm_disable_irq(struct irq_data *d) 301da177e4SLinus Torvalds { 311da177e4SLinus Torvalds spin_lock(&srm_irq_lock); 3235252254SThomas Gleixner cserve_dis(d->irq - 16); 331da177e4SLinus Torvalds spin_unlock(&srm_irq_lock); 341da177e4SLinus Torvalds } 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds /* Handle interrupts from the SRM, assuming no additional weirdness. */ 3744377f62SThomas Gleixner static struct irq_chip srm_irq_type = { 388ab1221cSThomas Gleixner .name = "SRM", 3935252254SThomas Gleixner .irq_unmask = srm_enable_irq, 4035252254SThomas Gleixner .irq_mask = srm_disable_irq, 4135252254SThomas Gleixner .irq_mask_ack = srm_disable_irq, 421da177e4SLinus Torvalds }; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds void __init 451da177e4SLinus Torvalds init_srm_irqs(long max, unsigned long ignore_mask) 461da177e4SLinus Torvalds { 471da177e4SLinus Torvalds long i; 481da177e4SLinus Torvalds 4970b66cbfSIvan Kokshaysky if (NR_IRQS <= 16) 5070b66cbfSIvan Kokshaysky return; 511da177e4SLinus Torvalds for (i = 16; i < max; ++i) { 521da177e4SLinus Torvalds if (i < 64 && ((ignore_mask >> i) & 1)) 531da177e4SLinus Torvalds continue; 54a9eb076bSThomas Gleixner irq_set_chip_and_handler(i, &srm_irq_type, handle_level_irq); 5535252254SThomas Gleixner irq_set_status_flags(i, IRQ_LEVEL); 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds void 607ca56053SAl Viro srm_device_interrupt(unsigned long vector) 611da177e4SLinus Torvalds { 621da177e4SLinus Torvalds int irq = (vector - 0x800) >> 4; 633dbb8c62SAl Viro handle_irq(irq); 641da177e4SLinus Torvalds } 65