fix to allow usb modules to compile
[linux-2.4.21-pre4.git] / arch / ppc / kernel / gt64260_pic.c
1 /*
2  * arch/ppc/kernel/gt64260_pic.c
3  * 
4  * Interrupt controller support for Galileo's GT64260.
5  *
6  * Author: Chris Zankel <chris@mvista.com>
7  * Modified by: Mark A. Greer <mgreer@mvista.com>
8  *
9  * Based on sources from Rabeeh Khoury / Galileo Technology
10  *
11  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
12  * the terms of the GNU General Public License version 2.1.  This program
13  * is licensed "as is" without any warranty of any kind, whether express
14  * or implied.
15  */
16
17 /*
18  * This file contains the specific functions to support the GT64260
19  * interrupt controller.
20  *
21  * The GT64260 has two main interrupt registers (high and low) that
22  * summarizes the interrupts generated by the units of the GT64260.
23  * Each bit is assigned to an interrupt number, where the low register
24  * are assigned from IRQ0 to IRQ31 and the high cause register
25  * from IRQ32 to IRQ63 
26  * The GPP (General Purpose Port) interrupts are assigned from IRQ64 (GPP0) 
27  * to IRQ95 (GPP31). 
28  * get_irq() returns the lowest interrupt number that is currently asserted.
29  *
30  * Note: 
31  *  - This driver does not initialize the GPP when used as an interrupt 
32  *    input.
33  *  - *** WARNING *** Only level sensitive GPP interrupts are supported
34  */
35
36 #include <linux/stddef.h>
37 #include <linux/init.h>
38 #include <linux/sched.h>
39 #include <linux/signal.h>
40 #include <linux/stddef.h>
41 #include <linux/delay.h>
42 #include <linux/irq.h>
43
44 #include <asm/io.h>
45 #include <asm/processor.h>
46 #include <asm/system.h>
47 #include <asm/irq.h>
48 #include <asm/gt64260.h>
49
50
51 #define GPP_LEVEL_INTERRUPTS
52
53 /* #define ENABLE_ECC_INT_HANDLER */    /* currently broken.. causes deadlock of some kind */
54 /* #define ECC_DEBUG */
55
56 /* ========================== forward declaration ========================== */
57
58 static void gt64260_unmask_irq(unsigned int);
59 static void gt64260_mask_irq(unsigned int);
60 static void gt64260_end_irq(unsigned int irq);
61
62 /* ========================== local declarations =========================== */
63
64 struct hw_interrupt_type gt64260_pic = {
65         " GT64260_PIC ",                /* typename */
66         NULL,                           /* startup */
67         NULL,                           /* shutdown */
68         gt64260_unmask_irq,             /* enable */
69         gt64260_mask_irq,               /* disable */
70         gt64260_mask_irq,               /* mask and ack */
71         gt64260_end_irq,                /* end */
72         NULL                            /* set_affinity */
73 };
74
75 u32 gt64260_irq_base = 0;      /* GT64260 handles the next 96 IRQs from here */
76
77 #ifdef ENABLE_ECC_INT_HANDLER
78 static u32
79 gt_ecc_irq_ack(void)
80 {
81     /* NOTE: If ecc_irq_ack is called during mask_and_ack,
82      * we lose data_hi and data_lo if we get a new ECC error between
83      * the time ack gets called and gt_ecc_irq gets called since reading addr
84      * allows new data to get latched in. FIXME!!
85      * See GT PIC documentation. */
86     /* Currently, we DON'T have a mask_and_ack_irq, so this code is fine */
87     static u32 last_addr=0;     /* store local copy since irq_ack overwrites */
88     u32 addr=gt_read(GT64260_SDRAM_ERR_ADDR);
89     gt_write(GT64260_SDRAM_ERR_ADDR,addr & (~3));
90
91     if(addr&3) last_addr=addr;
92     return last_addr;
93 }
94
95 static void
96 gt_ecc_irq(s32 irq, void *dev_id, struct pt_regs *regs)
97 {
98
99     u32 addr;
100 #ifdef ECC_DEBUG
101     u32 data_lo, data_hi,type;
102     printk("ecc ERR: NIP=%08x LINK=%08x\n", regs->nip, regs->link);
103
104     data_lo=gt_read(GT64260_SDRAM_ERR_DATA_LO);
105     data_hi=gt_read(GT64260_SDRAM_ERR_DATA_HI);
106 #endif
107
108     addr=gt_ecc_irq_ack();
109
110 #ifdef ECC_DEBUG
111     type=addr&3;
112
113     printk("data:%08x:%08x addr:%08x type:%d\n", data_hi, data_lo, addr&(~3), type);
114
115     printk("rcvd:%08x calc:%08x cntl:%08x cnt:%08x\n",
116             gt_read(GT64260_SDRAM_ERR_ECC_RCVD),
117             gt_read(GT64260_SDRAM_ERR_ECC_CALC),
118             gt_read(GT64260_SDRAM_ERR_ECC_CNTL),
119             gt_read(GT64260_SDRAM_ERR_ECC_ERR_CNT));
120
121     gt_write(GT64260_SDRAM_ERR_ECC_ERR_CNT,0);
122 #endif /* ECC_DEBUG */
123
124 }
125 #endif /* ENABLE_ECC_INT_HANDLER */
126
127
128 /* gt64260_init_irq()
129  *
130  *  This function initializes the interrupt controller. It assigns
131  *  all interrupts from IRQ0 to IRQ95 to the gt64260 interrupt controller.
132  *
133  * Input Variable(s):
134  *  None.
135  *
136  * Outpu. Variable(s):
137  *  None.
138  *
139  * Returns:
140  *  void
141  *
142  * Note:
143  *  We register all GPP inputs as interrupt source, but disable them.
144  */
145
146 __init void
147 gt64260_init_irq(void)
148 {
149         int i;
150
151         if ( ppc_md.progress ) ppc_md.progress("gt64260_init_irq: enter", 0x0);
152
153         ppc_cached_irq_mask[0] = 0;
154 #if defined(CONFIG_MOT_MVP) || defined(CONFIG_HXEB100)
155         ppc_cached_irq_mask[1] = 0x07000000; /* Enable GPP intrs */
156         ppc_cached_irq_mask[2] = 0x08000020;
157 #else
158         ppc_cached_irq_mask[1] = 0x0f000000; /* Enable GPP intrs */
159         ppc_cached_irq_mask[2] = 0;
160 #endif
161
162         /* disable all interrupts and clear current interrupts */
163         gt_write(GT64260_GPP_INTR_MASK, ppc_cached_irq_mask[2]);
164         gt_write(GT64260_GPP_INTR_CAUSE,0);
165         gt_write(GT64260_IC_CPU_INTR_MASK_LO, ppc_cached_irq_mask[0]);
166         gt_write(GT64260_IC_CPU_INTR_MASK_HI, ppc_cached_irq_mask[1]);
167
168         /* use the gt64260 for all (possible) interrupt sources */
169         for( i = gt64260_irq_base;  i < (gt64260_irq_base + 96);  i++ )  {
170                 irq_desc[i].handler = &gt64260_pic;
171         }
172
173 #ifdef GPP_LEVEL_INTERRUPTS
174         if(gt64260_revision != GT64260)  {
175                 if ( ppc_md.progress )
176                         ppc_md.progress("gt64260_init_irq: GPP -> levelint ", 0x0);
177                 /* #FEr MISC-4 */
178                 /* Mark GPP intrs level sensitive */
179                 gt_set_bits(GT64260_COMM_ARBITER_CNTL, (1<<10));
180
181                 for(i=gt64260_irq_base+64;i<gt64260_irq_base+64+32;i++)
182                         irq_desc[i].status |= IRQ_LEVEL;
183         }
184 #endif
185
186 #ifdef ENABLE_ECC_INT_HANDLER
187         request_irq(gt64260_irq_base + 17, gt_ecc_irq, 0, "GT64260 SDRAM ECC Error", 0);
188 #endif
189
190         if ( ppc_md.progress ) ppc_md.progress("gt64260_init_irq: exit", 0x0);
191         
192 }
193
194
195 /* gt64260_get_irq()
196  *
197  *  This function returns the lowest interrupt number of all interrupts that
198  *  are currently asserted. 
199  *
200  * Input Variable(s):
201  *  struct pt_regs*     not used
202  *
203  * Output Variable(s):
204  *  None.
205  *
206  * Returns:
207  *  int <interrupt number> or -2 (bogus interrupt)
208  * 
209  */
210 int
211 gt64260_get_irq(struct pt_regs *regs)
212 {
213         int irq;
214         int irq_gpp;
215         int cpu;
216
217         cpu = smp_processor_id();
218         irq = gt_read(GT64260_IC_MAIN_CAUSE_LO);
219         irq = __ilog2((irq & 0x3dfffffe) & ppc_cached_irq_mask[0]);
220
221         if (irq == -1) {
222                 irq = gt_read(GT64260_IC_MAIN_CAUSE_HI);
223 #if defined(CONFIG_MOT_MVP) || defined(CONFIG_HXEB100)
224                 /* Okay, this whole irq mess needs a rewrite bad, but who
225                  * am I to argue with a deadline? -- Troy
226                  */
227                 if (cpu == 1){
228                         irq = __ilog2((irq & 0x08000000));
229                 }else{
230                         irq = __ilog2((irq & 0x07000db7) & ppc_cached_irq_mask[1]);
231                 }
232 #else
233                 irq = __ilog2((irq & 0x0f000db7) & ppc_cached_irq_mask[1]);
234 #endif
235
236                 if (irq == -1) {
237                         irq = -2;   /* bogus interrupt, should never happen */
238                 }
239                 else if (irq < 24) {
240                         irq += 32;
241                 }
242                 else {
243                         irq_gpp = gt_read(GT64260_GPP_INTR_CAUSE);
244 #if defined(CONFIG_MOT_MVP) || defined(CONFIG_HXEB100)
245                         if (cpu == 1){
246                                 irq_gpp = __ilog2((irq_gpp & 0x08000000));
247                         }else{
248                                 irq_gpp = __ilog2(irq_gpp & ppc_cached_irq_mask[2] & ~0x08000000);
249                         }
250 #else
251                         irq_gpp = __ilog2(irq_gpp & ppc_cached_irq_mask[2]);
252 #endif
253
254                         if (irq_gpp == -1) {
255                                 irq = -2;
256                         } else {
257                                 irq = irq_gpp + 64;
258                         }
259                 }
260         }
261
262         if( irq < 0 )  {
263                 return( irq );
264         } else  {
265                 return( gt64260_irq_base + irq );
266         }
267 }
268
269 /* gt64260_unmask_irq()
270  *
271  *  This function enables an interrupt.
272  *
273  * Input Variable(s):
274  *  unsigned int        interrupt number (IRQ0...IRQ95).
275  *
276  * Output Variable(s):
277  *  None.
278  *
279  * Returns:
280  *  void
281  */
282
283 void
284 gt64260_unmask_irq(unsigned int irq)
285 {
286         unsigned long flags;
287
288         irq -= gt64260_irq_base;
289         spin_lock_irqsave(&gt64260_lock, flags);
290
291         if (irq > 31) {
292                 if (irq > 63) {
293                         /* unmask GPP irq */
294                         set_bit(irq-64, &ppc_cached_irq_mask[2]);
295                         gt_write(GT64260_GPP_INTR_MASK, ppc_cached_irq_mask[2]);
296                 } else {
297                         /* unmask high interrupt register */
298                         set_bit(irq-32, &ppc_cached_irq_mask[1]);
299                         gt_write(GT64260_IC_CPU_INTR_MASK_HI, 
300                                      ppc_cached_irq_mask[1]);
301                 }
302         } else {
303                 /* unmask low interrupt register */
304                 set_bit(irq, &ppc_cached_irq_mask[0]);
305                 gt_write(GT64260_IC_CPU_INTR_MASK_LO, ppc_cached_irq_mask[0]);
306         }
307         spin_unlock_irqrestore(&gt64260_lock, flags);
308 }
309
310
311 /* gt64260_mask_irq()
312  *
313  *  This function disables the requested interrupt.
314  *
315  * Input Variable(s):
316  *  unsigned int        interrupt number (IRQ0...IRQ95).
317  *
318  * Output Variable(s):
319  *  None.
320  *
321  * Returns:
322  *  void
323  */
324
325 static void
326 gt64260_mask_irq(unsigned int irq)
327 {
328         unsigned long flags;
329
330         irq -= gt64260_irq_base;
331         spin_lock_irqsave(&gt64260_lock, flags);
332         if (irq > 31) {
333                 if (irq > 63) {
334                         /* mask GPP irq */
335                         clear_bit(irq-64, &ppc_cached_irq_mask[2]);
336                         gt_write(GT64260_GPP_INTR_MASK, ppc_cached_irq_mask[2]);
337                 } else {
338                         /* mask high interrupt register */
339                         clear_bit(irq-32, &ppc_cached_irq_mask[1]);
340                         gt_write(GT64260_IC_CPU_INTR_MASK_HI, 
341                                      ppc_cached_irq_mask[1]);
342                 }
343         } else {
344                 /* mask low interrupt register */
345                 clear_bit(irq, &ppc_cached_irq_mask[0]);
346                 gt_write(GT64260_IC_CPU_INTR_MASK_LO, ppc_cached_irq_mask[0]);
347         }
348         spin_unlock_irqrestore(&gt64260_lock, flags);
349
350         if (irq == 36) { /* Seems necessary for SDMA interrupts */
351                 udelay(1);
352         }
353 }
354
355
356 /* gt64260_end_irq()
357  *
358  * This function unmasks the irq, if its not disabled or in progress
359  *
360  * Input Variable(s):
361  *  unsigned int        interrupt number (IRQ0...IRQ95).
362  *
363  * Output Variable(s):
364  *  None.
365  *
366  * Returns:
367  *  void
368  */
369 static void
370 gt64260_end_irq(unsigned int irq)
371 {
372         int local_irq = irq - gt64260_irq_base;
373
374         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
375                 /* FEr MISC-4 */
376                 if ((local_irq > 63) && (irq_desc[irq].status & IRQ_LEVEL)) {
377                         gt_write(GT64260_GPP_INTR_CAUSE,
378                                  ~(1<<(local_irq-64)));
379                 }
380
381                 gt64260_unmask_irq(irq);
382         }
383 }