/* * linux/arch/sh/kernel/irq_intc2.c * * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. * * Interrupt handling for INTC2-based IRQ. * * These are the "new Hitachi style" interrupts, as present on the * Hitachi 7751 and the STM ST40 STB1. */ #include #include #include #include #include #include struct intc2_data { unsigned char msk_offset; unsigned char msk_shift; #ifdef CONFIG_CPU_SUBTYPE_ST40 int (*clear_irq) (int); #endif }; static struct intc2_data intc2_data[NR_INTC2_IRQS]; static void enable_intc2_irq(unsigned int irq); static void disable_intc2_irq(unsigned int irq); /* shutdown is same as "disable" */ #define shutdown_intc2_irq disable_intc2_irq static void mask_and_ack_intc2(unsigned int); static void end_intc2_irq(unsigned int irq); static unsigned int startup_intc2_irq(unsigned int irq) { enable_intc2_irq(irq); return 0; /* never anything pending */ } static struct hw_interrupt_type intc2_irq_type = { "INTC2-IRQ", startup_intc2_irq, shutdown_intc2_irq, enable_intc2_irq, disable_intc2_irq, mask_and_ack_intc2, end_intc2_irq }; static void disable_intc2_irq(unsigned int irq) { int irq_offset = irq - INTC2_FIRST_IRQ; int msk_shift, msk_offset; // Sanity check if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) return; msk_shift = intc2_data[irq_offset].msk_shift; msk_offset = intc2_data[irq_offset].msk_offset; ctrl_outl(1<=NR_INTC2_IRQS)) return; msk_shift = intc2_data[irq_offset].msk_shift; msk_offset = intc2_data[irq_offset].msk_offset; ctrl_outl(1<=NR_INTC2_IRQS)) return; disable_irq_nosync(irq); /* Fill the data we need */ intc2_data[irq_offset].msk_offset = msk_offset; intc2_data[irq_offset].msk_shift = msk_shift; #ifdef CONFIG_CPU_SUBTYPE_ST40 intc2_data[irq_offset].clear_irq = NULL; #endif /* Set the priority level */ local_irq_save(flags); ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset); ipr&=~(0xf<irq, p->ipr_offset, p->ipr_shift, p-> msk_offset, p->msk_shift, 13); } } /* Adds a termination callback to the interrupt */ void intc2_add_clear_irq(int irq, int (*fn)(int)) { if (irq < INTC2_FIRST_IRQ) return; intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; } #endif /* CONFIG_CPU_SUBTYPE_ST40 */