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/sched.h>
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/param.h>
28 #include <linux/ioport.h>
29 #include <linux/interrupt.h>
30 #include <linux/init.h>
31 #include <linux/irq.h>
35 #include <asm/voyagergx.h>
37 static void disable_voyagergx_irq(unsigned int irq)
40 unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
42 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
43 val = inl(VOYAGER_INT_MASK);
45 outl(val, VOYAGER_INT_MASK);
48 static void enable_voyagergx_irq(unsigned int irq)
51 unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
53 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
54 val = inl(VOYAGER_INT_MASK);
56 outl(val, VOYAGER_INT_MASK);
59 static void mask_and_ack_voyagergx(unsigned int irq)
61 disable_voyagergx_irq(irq);
64 static void end_voyagergx_irq(unsigned int irq)
66 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
67 enable_voyagergx_irq(irq);
70 static unsigned int startup_voyagergx_irq(unsigned int irq)
72 enable_voyagergx_irq(irq);
76 static void shutdown_voyagergx_irq(unsigned int irq)
78 disable_voyagergx_irq(irq);
81 static struct hw_interrupt_type voyagergx_irq_type = {
82 .typename = "VOYAGERGX-IRQ",
83 .startup = startup_voyagergx_irq,
84 .shutdown = shutdown_voyagergx_irq,
85 .enable = enable_voyagergx_irq,
86 .disable = disable_voyagergx_irq,
87 .ack = mask_and_ack_voyagergx,
88 .end = end_voyagergx_irq,
91 static irqreturn_t voyagergx_interrupt(int irq, void *dev_id,
95 "VoyagerGX: spurious interrupt, status: 0x%x\n",
101 int (*func)(int, void *);
103 } voyagergx_demux[VOYAGER_IRQ_NUM];
105 void voyagergx_register_irq_demux(int irq,
106 int (*demux)(int irq, void *dev), void *dev)
108 voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
109 voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
112 void voyagergx_unregister_irq_demux(int irq)
114 voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
117 int voyagergx_irq_demux(int irq)
120 if (irq == IRQ_VOYAGER ) {
121 unsigned long i = 0, bit __attribute__ ((unused));
122 unsigned long val = inl(INT_STATUS);
124 if ( val & ( 1 << 1 )){
126 } else if ( val & ( 1 << 2 )){
128 } else if ( val & ( 1 << 6 )){
130 } else if( val & ( 1 << 10 )){
132 } else if( val & ( 1 << 11 )){
134 } else if( val & ( 1 << 12 )){
136 } else if( val & ( 1 << 17 )){
139 printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
141 pr_debug("voyagergx_irq_demux %d \n", i);
143 for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
147 if (i < VOYAGER_IRQ_NUM) {
148 irq = VOYAGER_IRQ_BASE + i;
149 if (voyagergx_demux[i].func != 0)
150 irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
156 static struct irqaction irq0 = {
158 .handler = voyagergx_interrupt,
159 .flags = IRQF_DISABLED,
160 .mask = CPU_MASK_NONE,
163 void __init setup_voyagergx_irq(void)
167 printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
171 VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1);
173 for (i=0; i<VOYAGER_IRQ_NUM; i++) {
175 switch (VOYAGER_IRQ_BASE + i) {
176 case VOYAGER_USBH_IRQ:
177 case VOYAGER_8051_IRQ:
178 case VOYAGER_UART0_IRQ:
179 case VOYAGER_UART1_IRQ:
180 case VOYAGER_AC97_IRQ:
184 irq_desc[VOYAGER_IRQ_BASE + i].chip = &voyagergx_irq_type;
187 setup_irq(IRQ_VOYAGER, &irq0);