aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-02-02 17:38:04 +0900
committerPaul Mundt <lethal@linux-sh.org>2010-02-02 17:38:04 +0900
commitc7a967273a539a9a38413753c58125e777e2d30d (patch)
tree70c57dcad74c8272ee5f079f3138615aee0214ed
parente9867c569970d8afb4b882bafbbe81426bd46333 (diff)
sh: mach-se: Convert SH7724 solution engine FPGA to sparseirq.
This uses the new create_irq_nr() to build up the FPGA's desired virtual IRQ mapping and permits us to finally flip on sparseirq for this board. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/Kconfig2
-rw-r--r--arch/sh/boards/mach-se/7724/irq.c38
2 files changed, 28 insertions, 12 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index bae53831c06..0f023bb62f9 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -731,7 +731,7 @@ config GUSA_RB
config SPARSE_IRQ
def_bool y
depends on SUPERH32 && !SH_DREAMCAST && !SH_HIGHLANDER && \
- !SH_RTS7751R2D && !HD64461 && !SH_7724_SOLUTION_ENGINE
+ !SH_RTS7751R2D && !HD64461
help
This enables support for sparse irqs. This is useful in general
as most CPUs have a fairly sparse array of IRQ vectors, which
diff --git a/arch/sh/boards/mach-se/7724/irq.c b/arch/sh/boards/mach-se/7724/irq.c
index e5e021a7d1e..0942be2daef 100644
--- a/arch/sh/boards/mach-se/7724/irq.c
+++ b/arch/sh/boards/mach-se/7724/irq.c
@@ -93,18 +93,15 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
{
struct fpga_irq set = get_fpga_irq(irq);
unsigned short intv = __raw_readw(set.sraddr);
- struct irq_desc *ext_desc;
unsigned int ext_irq = set.base;
intv &= set.mask;
- while (intv) {
- if (intv & 0x0001) {
- ext_desc = irq_desc + ext_irq;
- handle_level_irq(ext_irq, ext_desc);
- }
- intv >>= 1;
- ext_irq++;
+ for (; intv; intv >>= 1, ext_irq++) {
+ if (!(intv & 1))
+ continue;
+
+ generic_handle_irq(ext_irq);
}
}
@@ -113,7 +110,7 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
*/
void __init init_se7724_IRQ(void)
{
- int i;
+ int i, nid = cpu_to_node(boot_cpu_data);
__raw_writew(0xffff, IRQ0_MR); /* mask all */
__raw_writew(0xffff, IRQ1_MR); /* mask all */
@@ -123,10 +120,29 @@ void __init init_se7724_IRQ(void)
__raw_writew(0x0000, IRQ2_SR); /* clear irq */
__raw_writew(0x002a, IRQ_MODE); /* set irq type */
- for (i = 0; i < SE7724_FPGA_IRQ_NR; i++)
- set_irq_chip_and_handler_name(SE7724_FPGA_IRQ_BASE + i,
+ for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) {
+ int irq, wanted;
+
+ wanted = SE7724_FPGA_IRQ_BASE + i;
+
+ irq = create_irq_nr(wanted, nid);
+ if (unlikely(irq == 0)) {
+ pr_err("%s: failed hooking irq %d for FPGA\n",
+ __func__, wanted);
+ return;
+ }
+
+ if (unlikely(irq != wanted)) {
+ pr_err("%s: got irq %d but wanted %d, bailing.\n",
+ __func__, irq, wanted);
+ destroy_irq(irq);
+ return;
+ }
+
+ set_irq_chip_and_handler_name(irq,
&se7724_irq_chip,
handle_level_irq, "level");
+ }
set_irq_chained_handler(IRQ0_IRQ, se7724_irq_demux);
set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);