aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-10-06 04:35:48 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-10-06 04:35:48 -0400
commit525ccc452c79db41874c5edac3f67618a0997d6f (patch)
tree937987eae54debb7b23d4473089229a798bacc32 /arch/sh/kernel
parent580410005daecd8e9f0e1baa9ddadbb7f706e7e2 (diff)
sh: Convert INTC2 IRQ handler to irq_chip.
More struct irq_chip conversions, this time the INTC2 handlers. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/irq/intc2.c138
1 files changed, 24 insertions, 114 deletions
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index e30e4b7aa70e..d4b2bb7e08c7 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -10,93 +10,32 @@
10 * These are the "new Hitachi style" interrupts, as present on the 10 * These are the "new Hitachi style" interrupts, as present on the
11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. 11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
12 */ 12 */
13
14#include <linux/kernel.h> 13#include <linux/kernel.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/irq.h> 15#include <linux/irq.h>
17#include <asm/system.h> 16#include <asm/system.h>
18#include <asm/io.h> 17#include <asm/io.h>
19#include <asm/machvec.h>
20
21struct intc2_data {
22 unsigned char msk_offset;
23 unsigned char msk_shift;
24
25 int (*clear_irq) (int);
26};
27
28static struct intc2_data intc2_data[NR_INTC2_IRQS];
29
30static void enable_intc2_irq(unsigned int irq);
31static void disable_intc2_irq(unsigned int irq);
32
33/* shutdown is same as "disable" */
34#define shutdown_intc2_irq disable_intc2_irq
35
36static void mask_and_ack_intc2(unsigned int);
37static void end_intc2_irq(unsigned int irq);
38
39static unsigned int startup_intc2_irq(unsigned int irq)
40{
41 enable_intc2_irq(irq);
42 return 0; /* never anything pending */
43}
44
45static struct hw_interrupt_type intc2_irq_type = {
46 .typename = "INTC2-IRQ",
47 .startup = startup_intc2_irq,
48 .shutdown = shutdown_intc2_irq,
49 .enable = enable_intc2_irq,
50 .disable = disable_intc2_irq,
51 .ack = mask_and_ack_intc2,
52 .end = end_intc2_irq
53};
54 18
55static void disable_intc2_irq(unsigned int irq) 19static void disable_intc2_irq(unsigned int irq)
56{ 20{
57 int irq_offset = irq - INTC2_FIRST_IRQ; 21 struct intc2_data *p = get_irq_chip_data(irq);
58 int msk_shift, msk_offset; 22 ctrl_outl(1 << p->msk_shift,
59 23 INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
60 /* Sanity check */
61 if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
62 return;
63
64 msk_shift = intc2_data[irq_offset].msk_shift;
65 msk_offset = intc2_data[irq_offset].msk_offset;
66
67 ctrl_outl(1 << msk_shift,
68 INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset);
69} 24}
70 25
71static void enable_intc2_irq(unsigned int irq) 26static void enable_intc2_irq(unsigned int irq)
72{ 27{
73 int irq_offset = irq - INTC2_FIRST_IRQ; 28 struct intc2_data *p = get_irq_chip_data(irq);
74 int msk_shift, msk_offset; 29 ctrl_outl(1 << p->msk_shift,
75 30 INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
76 /* Sanity check */
77 if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
78 return;
79
80 msk_shift = intc2_data[irq_offset].msk_shift;
81 msk_offset = intc2_data[irq_offset].msk_offset;
82
83 ctrl_outl(1 << msk_shift,
84 INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset);
85}
86
87static void mask_and_ack_intc2(unsigned int irq)
88{
89 disable_intc2_irq(irq);
90} 31}
91 32
92static void end_intc2_irq(unsigned int irq) 33static struct irq_chip intc2_irq_chip = {
93{ 34 .typename = "intc2",
94 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 35 .mask = disable_intc2_irq,
95 enable_intc2_irq(irq); 36 .unmask = enable_intc2_irq,
96 37 .mask_ack = disable_intc2_irq,
97 if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) 38};
98 intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq);
99}
100 39
101/* 40/*
102 * Setup an INTC2 style interrupt. 41 * Setup an INTC2 style interrupt.
@@ -108,46 +47,30 @@ static void end_intc2_irq(unsigned int irq)
108 * | | | | 47 * | | | |
109 * make_intc2_irq(84, 0, 16, 0, 13); 48 * make_intc2_irq(84, 0, 16, 0, 13);
110 */ 49 */
111void make_intc2_irq(unsigned int irq, 50void make_intc2_irq(struct intc2_data *p)
112 unsigned int ipr_offset, unsigned int ipr_shift,
113 unsigned int msk_offset, unsigned int msk_shift,
114 unsigned int priority)
115{ 51{
116 int irq_offset = irq - INTC2_FIRST_IRQ;
117 unsigned int flags; 52 unsigned int flags;
118 unsigned long ipr; 53 unsigned long ipr;
119 54
120 if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) 55 disable_irq_nosync(p->irq);
121 return;
122
123 disable_irq_nosync(irq);
124
125 /* Fill the data we need */
126 intc2_data[irq_offset].msk_offset = msk_offset;
127 intc2_data[irq_offset].msk_shift = msk_shift;
128 intc2_data[irq_offset].clear_irq = NULL;
129 56
130 /* Set the priority level */ 57 /* Set the priority level */
131 local_irq_save(flags); 58 local_irq_save(flags);
132 59
133 ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); 60 ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset);
134 ipr &= ~(0xf << ipr_shift); 61 ipr &= ~(0xf << p->ipr_shift);
135 ipr |= priority << ipr_shift; 62 ipr |= p->priority << p->ipr_shift;
136 ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); 63 ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset);
137 64
138 local_irq_restore(flags); 65 local_irq_restore(flags);
139 66
140 irq_desc[irq].chip = &intc2_irq_type; 67 set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq);
68 set_irq_chip_data(p->irq, p);
141 69
142 disable_intc2_irq(irq); 70 enable_intc2_irq(p->irq);
143} 71}
144 72
145static struct intc2_init { 73static struct intc2_data intc2_irq_table[] = {
146 unsigned short irq;
147 unsigned char ipr_offset, ipr_shift;
148 unsigned char msk_offset, msk_shift;
149 unsigned char priority;
150} intc2_init_data[] __initdata = {
151#if defined(CONFIG_CPU_SUBTYPE_ST40) 74#if defined(CONFIG_CPU_SUBTYPE_ST40)
152 {64, 0, 0, 0, 0, 13}, /* PCI serr */ 75 {64, 0, 0, 0, 0, 13}, /* PCI serr */
153 {65, 0, 4, 0, 1, 13}, /* PCI err */ 76 {65, 0, 4, 0, 1, 13}, /* PCI err */
@@ -266,19 +189,6 @@ void __init init_IRQ_intc2(void)
266{ 189{
267 int i; 190 int i;
268 191
269 for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { 192 for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++)
270 struct intc2_init *p = intc2_init_data + i; 193 make_intc2_irq(intc2_irq_table + i);
271 make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
272 p-> msk_offset, p->msk_shift, p->priority);
273 }
274}
275
276/* Adds a termination callback to the interrupt */
277void intc2_add_clear_irq(int irq, int (*fn)(int))
278{
279 if (unlikely(irq < INTC2_FIRST_IRQ))
280 return;
281
282 intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
283} 194}
284