1 /* -------------------------------------------------------------------- */
2 /* setup_voyagergx.c: */
3 /* -------------------------------------------------------------------- */
4 /* This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 Copyright 2003 (c) Lineo uSolutions,Inc.
20 /* -------------------------------------------------------------------- */
24 #include <linux/config.h>
25 #include <linux/sched.h>
26 #include <linux/module.h>
27 #include <linux/kernel.h>
28 #include <linux/param.h>
29 #include <linux/ioport.h>
30 #include <linux/interrupt.h>
31 #include <linux/init.h>
32 #include <linux/irq.h>
36 #include <asm/rts7751r2d/rts7751r2d.h>
37 #include <asm/rts7751r2d/voyagergx_reg.h>
39 static void disable_voyagergx_irq(unsigned int irq
)
41 unsigned long flags
, val
;
42 unsigned long mask
= 1 << (irq
- VOYAGER_IRQ_BASE
);
44 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq
, mask
);
45 local_irq_save(flags
);
46 val
= inl(VOYAGER_INT_MASK
);
48 outl(val
, VOYAGER_INT_MASK
);
49 local_irq_restore(flags
);
53 static void enable_voyagergx_irq(unsigned int irq
)
55 unsigned long flags
, val
;
56 unsigned long mask
= 1 << (irq
- VOYAGER_IRQ_BASE
);
58 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq
, mask
);
59 local_irq_save(flags
);
60 val
= inl(VOYAGER_INT_MASK
);
62 outl(val
, VOYAGER_INT_MASK
);
63 local_irq_restore(flags
);
67 static void mask_and_ack_voyagergx(unsigned int irq
)
69 disable_voyagergx_irq(irq
);
72 static void end_voyagergx_irq(unsigned int irq
)
74 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
)))
75 enable_voyagergx_irq(irq
);
78 static unsigned int startup_voyagergx_irq(unsigned int irq
)
80 enable_voyagergx_irq(irq
);
84 static void shutdown_voyagergx_irq(unsigned int irq
)
86 disable_voyagergx_irq(irq
);
89 static struct hw_interrupt_type voyagergx_irq_type
= {
90 .typename
= "VOYAGERGX-IRQ",
91 .startup
= startup_voyagergx_irq
,
92 .shutdown
= shutdown_voyagergx_irq
,
93 .enable
= enable_voyagergx_irq
,
94 .disable
= disable_voyagergx_irq
,
95 .ack
= mask_and_ack_voyagergx
,
96 .end
= end_voyagergx_irq
,
99 static irqreturn_t
voyagergx_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
102 "VoyagerGX: spurious interrupt, status: 0x%x\n",
108 /*====================================================*/
111 int (*func
)(int, void *);
113 } voyagergx_demux
[VOYAGER_IRQ_NUM
];
115 void voyagergx_register_irq_demux(int irq
,
116 int (*demux
)(int irq
, void *dev
), void *dev
)
118 voyagergx_demux
[irq
- VOYAGER_IRQ_BASE
].func
= demux
;
119 voyagergx_demux
[irq
- VOYAGER_IRQ_BASE
].dev
= dev
;
122 void voyagergx_unregister_irq_demux(int irq
)
124 voyagergx_demux
[irq
- VOYAGER_IRQ_BASE
].func
= 0;
127 int voyagergx_irq_demux(int irq
)
130 if (irq
== IRQ_VOYAGER
) {
131 unsigned long i
= 0, bit
__attribute__ ((unused
));
132 unsigned long val
= inl(INT_STATUS
);
134 if ( val
& ( 1 << 1 )){
136 } else if ( val
& ( 1 << 2 )){
138 } else if ( val
& ( 1 << 6 )){
140 } else if( val
& ( 1 << 10 )){
142 } else if( val
& ( 1 << 11 )){
144 } else if( val
& ( 1 << 12 )){
146 } else if( val
& ( 1 << 17 )){
149 printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq
, val
);
151 pr_debug("voyagergx_irq_demux %d \n", i
);
153 for (bit
= 1, i
= 0 ; i
< VOYAGER_IRQ_NUM
; bit
<<= 1, i
++)
157 if (i
< VOYAGER_IRQ_NUM
) {
158 irq
= VOYAGER_IRQ_BASE
+ i
;
159 if (voyagergx_demux
[i
].func
!= 0)
160 irq
= voyagergx_demux
[i
].func(irq
, voyagergx_demux
[i
].dev
);
166 static struct irqaction irq0
= {
168 .handler
= voyagergx_interrupt
,
169 .flags
= SA_INTERRUPT
,
170 .mask
= CPU_MASK_NONE
,
173 void __init
setup_voyagergx_irq(void)
177 printk(KERN_INFO
"VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
181 VOYAGER_IRQ_BASE
+ VOYAGER_IRQ_NUM
- 1);
183 for (i
=0; i
<VOYAGER_IRQ_NUM
; i
++) {
185 switch (VOYAGER_IRQ_BASE
+ i
) {
186 case VOYAGER_USBH_IRQ
:
187 case VOYAGER_8051_IRQ
:
188 case VOYAGER_UART0_IRQ
:
189 case VOYAGER_UART1_IRQ
:
190 case VOYAGER_AC97_IRQ
:
194 irq_desc
[VOYAGER_IRQ_BASE
+ i
].chip
= &voyagergx_irq_type
;
197 setup_irq(IRQ_VOYAGER
, &irq0
);