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 #include <linux/interrupt.h>
21 #include <linux/init.h>
23 #include <asm/voyagergx.h>
24 #include <asm/rts7751r2d.h>
26 static void disable_voyagergx_irq(unsigned int irq
)
29 unsigned long mask
= 1 << (irq
- VOYAGER_IRQ_BASE
);
31 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq
, mask
);
32 val
= readl((void __iomem
*)VOYAGER_INT_MASK
);
34 writel(val
, (void __iomem
*)VOYAGER_INT_MASK
);
37 static void enable_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
= readl((void __iomem
*)VOYAGER_INT_MASK
);
45 writel(val
, (void __iomem
*)VOYAGER_INT_MASK
);
48 static void mask_and_ack_voyagergx(unsigned int irq
)
50 disable_voyagergx_irq(irq
);
53 static void end_voyagergx_irq(unsigned int irq
)
55 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
)))
56 enable_voyagergx_irq(irq
);
59 static unsigned int startup_voyagergx_irq(unsigned int irq
)
61 enable_voyagergx_irq(irq
);
65 static void shutdown_voyagergx_irq(unsigned int irq
)
67 disable_voyagergx_irq(irq
);
70 static struct hw_interrupt_type voyagergx_irq_type
= {
71 .typename
= "VOYAGERGX-IRQ",
72 .startup
= startup_voyagergx_irq
,
73 .shutdown
= shutdown_voyagergx_irq
,
74 .enable
= enable_voyagergx_irq
,
75 .disable
= disable_voyagergx_irq
,
76 .ack
= mask_and_ack_voyagergx
,
77 .end
= end_voyagergx_irq
,
80 static irqreturn_t
voyagergx_interrupt(int irq
, void *dev_id
)
83 "VoyagerGX: spurious interrupt, status: 0x%x\n",
84 (unsigned int)readl((void __iomem
*)INT_STATUS
));
89 int (*func
)(int, void *);
91 } voyagergx_demux
[VOYAGER_IRQ_NUM
];
93 void voyagergx_register_irq_demux(int irq
,
94 int (*demux
)(int irq
, void *dev
), void *dev
)
96 voyagergx_demux
[irq
- VOYAGER_IRQ_BASE
].func
= demux
;
97 voyagergx_demux
[irq
- VOYAGER_IRQ_BASE
].dev
= dev
;
100 void voyagergx_unregister_irq_demux(int irq
)
102 voyagergx_demux
[irq
- VOYAGER_IRQ_BASE
].func
= 0;
105 int voyagergx_irq_demux(int irq
)
108 if (irq
== IRQ_VOYAGER
) {
109 unsigned long i
= 0, bit
__attribute__ ((unused
));
110 unsigned long val
= readl((void __iomem
*)INT_STATUS
);
114 else if (val
& (1 << 2))
116 else if (val
& (1 << 6))
118 else if (val
& (1 << 10))
120 else if (val
& (1 << 11))
122 else if (val
& (1 << 12))
124 else if (val
& (1 << 17))
127 printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq
, val
);
128 pr_debug("voyagergx_irq_demux %d \n", i
);
129 if (i
< VOYAGER_IRQ_NUM
) {
130 irq
= VOYAGER_IRQ_BASE
+ i
;
131 if (voyagergx_demux
[i
].func
!= 0)
132 irq
= voyagergx_demux
[i
].func(irq
, voyagergx_demux
[i
].dev
);
138 static struct irqaction irq0
= {
140 .handler
= voyagergx_interrupt
,
141 .flags
= IRQF_DISABLED
,
142 .mask
= CPU_MASK_NONE
,
145 void __init
setup_voyagergx_irq(void)
149 printk(KERN_INFO
"VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
153 VOYAGER_IRQ_BASE
+ VOYAGER_IRQ_NUM
- 1);
155 for (i
=0; i
<VOYAGER_IRQ_NUM
; i
++) {
157 switch (VOYAGER_IRQ_BASE
+ i
) {
158 case VOYAGER_USBH_IRQ
:
159 case VOYAGER_8051_IRQ
:
160 case VOYAGER_UART0_IRQ
:
161 case VOYAGER_UART1_IRQ
:
162 case VOYAGER_AC97_IRQ
:
166 irq_desc
[VOYAGER_IRQ_BASE
+ i
].chip
= &voyagergx_irq_type
;
169 setup_irq(IRQ_VOYAGER
, &irq0
);