2 * linux/arch/sh/kernel/irq_intc2.c
4 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
9 * Interrupt handling for INTC2-based IRQ.
11 * These are the "new Hitachi style" interrupts, as present on the
12 * Hitachi 7751 and the STM ST40 STB1.
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/irq.h>
19 #include <asm/system.h>
21 #include <asm/machvec.h>
25 unsigned int addr; /* Address of Interrupt Priority Register */
26 int mask; /*Mask to apply */
30 static struct intc2_data intc2_data[NR_INTC2_IRQS];
32 static void enable_intc2_irq(unsigned int irq);
33 static void disable_intc2_irq(unsigned int irq);
35 /* shutdown is same as "disable" */
36 #define shutdown_intc2_irq disable_intc2_irq
38 static void mask_and_ack_intc2(unsigned int);
39 static void end_intc2_irq(unsigned int irq);
41 static unsigned int startup_intc2_irq(unsigned int irq)
43 enable_intc2_irq(irq);
44 return 0; /* never anything pending */
47 static struct hw_interrupt_type intc2_irq_type = {
57 static void disable_intc2_irq(unsigned int irq)
60 int offset=irq-INTC2_FIRST_IRQ;
64 if(offset<0 || offset>=NR_INTC2_IRQS) return;
66 addr=intc2_data[offset].addr+INTC2_INTMSK_OFFSET;
68 local_irq_save(flags);
70 val|=intc2_data[offset].mask;
73 local_irq_restore(flags);
76 static void enable_intc2_irq(unsigned int irq)
78 int offset=irq-INTC2_FIRST_IRQ;
81 if(offset<0 || offset>=NR_INTC2_IRQS) return;
83 ctrl_outl(intc2_data[offset].mask,
84 intc2_data[offset].addr+INTC2_INTMSKCLR_OFFSET);
88 static void mask_and_ack_intc2(unsigned int irq)
90 disable_intc2_irq(irq);
93 static void end_intc2_irq(unsigned int irq)
95 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
96 enable_intc2_irq(irq);
99 void make_intc2_irq(unsigned int irq, unsigned int addr,
100 unsigned int group,int pos, int priority)
102 int offset=irq-INTC2_FIRST_IRQ;
105 if(offset<0 || offset>=NR_INTC2_IRQS) {
109 disable_irq_nosync(irq);
110 /* Fill the data we need */
111 intc2_data[offset].addr=addr;
112 intc2_data[offset].mask=1<<pos;
114 /* Set the priority level */
115 local_irq_save(flags);
116 val=ctrl_inl(addr+INTC2_INTPRI_OFFSET);
117 val|=(priority)<< (group<<4);
118 ctrl_outl(val,addr+INTC2_INTPRI_OFFSET);
119 local_irq_restore(flags);
121 irq_desc[irq].handler=&intc2_irq_type;
123 disable_intc2_irq(irq);