1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/arch/alpha/kernel/irq_pyxis.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * IRQ Code common to all PYXIS core logic chips. 7*1da177e4SLinus Torvalds */ 8*1da177e4SLinus Torvalds 9*1da177e4SLinus Torvalds #include <linux/init.h> 10*1da177e4SLinus Torvalds #include <linux/sched.h> 11*1da177e4SLinus Torvalds #include <linux/irq.h> 12*1da177e4SLinus Torvalds 13*1da177e4SLinus Torvalds #include <asm/io.h> 14*1da177e4SLinus Torvalds #include <asm/core_cia.h> 15*1da177e4SLinus Torvalds 16*1da177e4SLinus Torvalds #include "proto.h" 17*1da177e4SLinus Torvalds #include "irq_impl.h" 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds 20*1da177e4SLinus Torvalds /* Note mask bit is true for ENABLED irqs. */ 21*1da177e4SLinus Torvalds static unsigned long cached_irq_mask; 22*1da177e4SLinus Torvalds 23*1da177e4SLinus Torvalds static inline void 24*1da177e4SLinus Torvalds pyxis_update_irq_hw(unsigned long mask) 25*1da177e4SLinus Torvalds { 26*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_MASK = mask; 27*1da177e4SLinus Torvalds mb(); 28*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_MASK; 29*1da177e4SLinus Torvalds } 30*1da177e4SLinus Torvalds 31*1da177e4SLinus Torvalds static inline void 32*1da177e4SLinus Torvalds pyxis_enable_irq(unsigned int irq) 33*1da177e4SLinus Torvalds { 34*1da177e4SLinus Torvalds pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16)); 35*1da177e4SLinus Torvalds } 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds static void 38*1da177e4SLinus Torvalds pyxis_disable_irq(unsigned int irq) 39*1da177e4SLinus Torvalds { 40*1da177e4SLinus Torvalds pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16))); 41*1da177e4SLinus Torvalds } 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds static unsigned int 44*1da177e4SLinus Torvalds pyxis_startup_irq(unsigned int irq) 45*1da177e4SLinus Torvalds { 46*1da177e4SLinus Torvalds pyxis_enable_irq(irq); 47*1da177e4SLinus Torvalds return 0; 48*1da177e4SLinus Torvalds } 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds static void 51*1da177e4SLinus Torvalds pyxis_end_irq(unsigned int irq) 52*1da177e4SLinus Torvalds { 53*1da177e4SLinus Torvalds if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 54*1da177e4SLinus Torvalds pyxis_enable_irq(irq); 55*1da177e4SLinus Torvalds } 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds static void 58*1da177e4SLinus Torvalds pyxis_mask_and_ack_irq(unsigned int irq) 59*1da177e4SLinus Torvalds { 60*1da177e4SLinus Torvalds unsigned long bit = 1UL << (irq - 16); 61*1da177e4SLinus Torvalds unsigned long mask = cached_irq_mask &= ~bit; 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds /* Disable the interrupt. */ 64*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_MASK = mask; 65*1da177e4SLinus Torvalds wmb(); 66*1da177e4SLinus Torvalds /* Ack PYXIS PCI interrupt. */ 67*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_REQ = bit; 68*1da177e4SLinus Torvalds mb(); 69*1da177e4SLinus Torvalds /* Re-read to force both writes. */ 70*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_MASK; 71*1da177e4SLinus Torvalds } 72*1da177e4SLinus Torvalds 73*1da177e4SLinus Torvalds static struct hw_interrupt_type pyxis_irq_type = { 74*1da177e4SLinus Torvalds .typename = "PYXIS", 75*1da177e4SLinus Torvalds .startup = pyxis_startup_irq, 76*1da177e4SLinus Torvalds .shutdown = pyxis_disable_irq, 77*1da177e4SLinus Torvalds .enable = pyxis_enable_irq, 78*1da177e4SLinus Torvalds .disable = pyxis_disable_irq, 79*1da177e4SLinus Torvalds .ack = pyxis_mask_and_ack_irq, 80*1da177e4SLinus Torvalds .end = pyxis_end_irq, 81*1da177e4SLinus Torvalds }; 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds void 84*1da177e4SLinus Torvalds pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs) 85*1da177e4SLinus Torvalds { 86*1da177e4SLinus Torvalds unsigned long pld; 87*1da177e4SLinus Torvalds unsigned int i; 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds /* Read the interrupt summary register of PYXIS */ 90*1da177e4SLinus Torvalds pld = *(vulp)PYXIS_INT_REQ; 91*1da177e4SLinus Torvalds pld &= cached_irq_mask; 92*1da177e4SLinus Torvalds 93*1da177e4SLinus Torvalds /* 94*1da177e4SLinus Torvalds * Now for every possible bit set, work through them and call 95*1da177e4SLinus Torvalds * the appropriate interrupt handler. 96*1da177e4SLinus Torvalds */ 97*1da177e4SLinus Torvalds while (pld) { 98*1da177e4SLinus Torvalds i = ffz(~pld); 99*1da177e4SLinus Torvalds pld &= pld - 1; /* clear least bit set */ 100*1da177e4SLinus Torvalds if (i == 7) 101*1da177e4SLinus Torvalds isa_device_interrupt(vector, regs); 102*1da177e4SLinus Torvalds else 103*1da177e4SLinus Torvalds handle_irq(16+i, regs); 104*1da177e4SLinus Torvalds } 105*1da177e4SLinus Torvalds } 106*1da177e4SLinus Torvalds 107*1da177e4SLinus Torvalds void __init 108*1da177e4SLinus Torvalds init_pyxis_irqs(unsigned long ignore_mask) 109*1da177e4SLinus Torvalds { 110*1da177e4SLinus Torvalds long i; 111*1da177e4SLinus Torvalds 112*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_MASK = 0; /* disable all */ 113*1da177e4SLinus Torvalds *(vulp)PYXIS_INT_REQ = -1; /* flush all */ 114*1da177e4SLinus Torvalds mb(); 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds /* Send -INTA pulses to clear any pending interrupts ...*/ 117*1da177e4SLinus Torvalds *(vuip) CIA_IACK_SC; 118*1da177e4SLinus Torvalds 119*1da177e4SLinus Torvalds for (i = 16; i < 48; ++i) { 120*1da177e4SLinus Torvalds if ((ignore_mask >> i) & 1) 121*1da177e4SLinus Torvalds continue; 122*1da177e4SLinus Torvalds irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; 123*1da177e4SLinus Torvalds irq_desc[i].handler = &pyxis_irq_type; 124*1da177e4SLinus Torvalds } 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds setup_irq(16+7, &isa_cascade_irqaction); 127*1da177e4SLinus Torvalds } 128