import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / sh / stboards / irq.c
1 /* 
2  * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3  *
4  * May be copied or modified under the terms of the GNU General Public
5  * License.  See linux/COPYING for more information.                            
6  *
7  * Looks after interrupts on the HARP board.
8  *
9  * Bases on the IPR irq system
10  */
11
12 #include <linux/config.h>
13 #include <linux/init.h>
14 #include <linux/irq.h>
15
16 #include <asm/system.h>
17 #include <asm/io.h>
18
19 #include "harp.h"
20
21
22 #define NUM_EXTERNAL_IRQS 16
23
24 // Early versions of the STB1 Overdrive required this nasty frig
25 //#define INVERT_INTMASK_WRITES
26
27 static void enable_harp_irq(unsigned int irq);
28 static void disable_harp_irq(unsigned int irq);
29
30 /* shutdown is same as "disable" */
31 #define shutdown_harp_irq disable_harp_irq
32
33 static void mask_and_ack_harp(unsigned int);
34 static void end_harp_irq(unsigned int irq);
35
36 static unsigned int startup_harp_irq(unsigned int irq)
37 {
38         enable_harp_irq(irq);
39         return 0;               /* never anything pending */
40 }
41
42 static struct hw_interrupt_type harp_irq_type = {
43         "Harp-IRQ",
44         startup_harp_irq,
45         shutdown_harp_irq,
46         enable_harp_irq,
47         disable_harp_irq,
48         mask_and_ack_harp,
49         end_harp_irq
50 };
51
52 static void disable_harp_irq(unsigned int irq)
53 {
54         unsigned val, flags;
55         unsigned maskReg;
56         unsigned mask;
57         int pri;
58
59         if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
60                 return;
61
62         pri = 15 - irq;
63
64         if (pri < 8) {
65                 maskReg = EPLD_INTMASK0;
66         } else {
67                 maskReg = EPLD_INTMASK1;
68                 pri -= 8;
69         }
70
71         save_and_cli(flags);
72         mask = ctrl_inl(maskReg);
73         mask &= (~(1 << pri));
74 #if defined(INVERT_INTMASK_WRITES)
75         mask ^= 0xff;
76 #endif
77         ctrl_outl(mask, maskReg);
78         restore_flags(flags);
79 }
80
81 static void enable_harp_irq(unsigned int irq)
82 {
83         unsigned flags;
84         unsigned maskReg;
85         unsigned mask;
86         int pri;
87
88         if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
89                 return;
90
91         pri = 15 - irq;
92
93         if (pri < 8) {
94                 maskReg = EPLD_INTMASK0;
95         } else {
96                 maskReg = EPLD_INTMASK1;
97                 pri -= 8;
98         }
99
100         save_and_cli(flags);
101         mask = ctrl_inl(maskReg);
102
103
104         mask |= (1 << pri);
105
106 #if defined(INVERT_INTMASK_WRITES)
107         mask ^= 0xff;
108 #endif
109         ctrl_outl(mask, maskReg);
110
111         restore_flags(flags);
112 }
113
114 /* This functions sets the desired irq handler to be an overdrive type */
115 static void __init make_harp_irq(unsigned int irq)
116 {
117         disable_irq_nosync(irq);
118         irq_desc[irq].handler = &harp_irq_type;
119         disable_harp_irq(irq);
120 }
121
122 static void mask_and_ack_harp(unsigned int irq)
123 {
124         disable_harp_irq(irq);
125 }
126
127 static void end_harp_irq(unsigned int irq)
128 {
129         enable_harp_irq(irq);
130 }
131
132 void __init init_harp_irq(void)
133 {
134         int i;
135
136 #if !defined(INVERT_INTMASK_WRITES)
137         // On the harp these are set to enable an interrupt
138         ctrl_outl(0x00, EPLD_INTMASK0);
139         ctrl_outl(0x00, EPLD_INTMASK1);
140 #else
141         // On the Overdrive the data is inverted before being stored in the reg
142         ctrl_outl(0xff, EPLD_INTMASK0);
143         ctrl_outl(0xff, EPLD_INTMASK1);
144 #endif
145
146         for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
147                 make_harp_irq(i);
148         }
149 }