Commit 90890f17 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Ard Biesheuvel

ARM: footbridge: use GENERIC_IRQ_MULTI_HANDLER

Footbridge still uses the classic IRQ entry path in assembler,
but this is easily converted into an equivalent C version.

In this case, the correlation between IRQ numbers and bits in
the status register is non-obvious, and the priorities are
handled by manually checking each bit in a static order,
re-reading the status register after each handled event.

I moved the code into the new file and edited the syntax without
changing this sequence to keep the behavior as close as possible
to what it traditionally did.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Tested-by: default avatarMarc Zyngier <maz@kernel.org>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent c1fe8d05
...@@ -362,6 +362,7 @@ config ARCH_FOOTBRIDGE ...@@ -362,6 +362,7 @@ config ARCH_FOOTBRIDGE
select FOOTBRIDGE select FOOTBRIDGE
select NEED_MACH_IO_H if !MMU select NEED_MACH_IO_H if !MMU
select NEED_MACH_MEMORY_H select NEED_MACH_MEMORY_H
select GENERIC_IRQ_MULTI_HANDLER
help help
Support for systems based on the DC21285 companion chip Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
......
...@@ -27,6 +27,91 @@ ...@@ -27,6 +27,91 @@
#include "common.h" #include "common.h"
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/hardware/dec21285.h>
static int dc21285_get_irq(void)
{
void __iomem *irqstatus = (void __iomem *)CSR_IRQ_STATUS;
u32 mask = readl(irqstatus);
if (mask & IRQ_MASK_SDRAMPARITY)
return IRQ_SDRAMPARITY;
if (mask & IRQ_MASK_UART_RX)
return IRQ_CONRX;
if (mask & IRQ_MASK_DMA1)
return IRQ_DMA1;
if (mask & IRQ_MASK_DMA2)
return IRQ_DMA2;
if (mask & IRQ_MASK_IN0)
return IRQ_IN0;
if (mask & IRQ_MASK_IN1)
return IRQ_IN1;
if (mask & IRQ_MASK_IN2)
return IRQ_IN2;
if (mask & IRQ_MASK_IN3)
return IRQ_IN3;
if (mask & IRQ_MASK_PCI)
return IRQ_PCI;
if (mask & IRQ_MASK_DOORBELLHOST)
return IRQ_DOORBELLHOST;
if (mask & IRQ_MASK_I2OINPOST)
return IRQ_I2OINPOST;
if (mask & IRQ_MASK_TIMER1)
return IRQ_TIMER1;
if (mask & IRQ_MASK_TIMER2)
return IRQ_TIMER2;
if (mask & IRQ_MASK_TIMER3)
return IRQ_TIMER3;
if (mask & IRQ_MASK_UART_TX)
return IRQ_CONTX;
if (mask & IRQ_MASK_PCI_ABORT)
return IRQ_PCI_ABORT;
if (mask & IRQ_MASK_PCI_SERR)
return IRQ_PCI_SERR;
if (mask & IRQ_MASK_DISCARD_TIMER)
return IRQ_DISCARD_TIMER;
if (mask & IRQ_MASK_PCI_DPERR)
return IRQ_PCI_DPERR;
if (mask & IRQ_MASK_PCI_PERR)
return IRQ_PCI_PERR;
return 0;
}
static void dc21285_handle_irq(struct pt_regs *regs)
{
int irq;
do {
irq = dc21285_get_irq();
if (!irq)
break;
generic_handle_irq(irq);
} while (1);
}
unsigned int mem_fclk_21285 = 50000000; unsigned int mem_fclk_21285 = 50000000;
EXPORT_SYMBOL(mem_fclk_21285); EXPORT_SYMBOL(mem_fclk_21285);
...@@ -108,6 +193,8 @@ static void __init __fb_init_irq(void) ...@@ -108,6 +193,8 @@ static void __init __fb_init_irq(void)
void __init footbridge_init_irq(void) void __init footbridge_init_irq(void)
{ {
set_handle_irq(dc21285_handle_irq);
__fb_init_irq(); __fb_init_irq();
if (!footbridge_cfn_mode()) if (!footbridge_cfn_mode())
......
/*
* arch/arm/mach-footbridge/include/mach/entry-macro.S
*
* Low-level IRQ helper macros for footbridge-based platforms
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/hardware/dec21285.h>
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
.macro get_irqnr_preamble, base, tmp
mov \base, #dc21285_high
.if dc21285_low
orr \base, \base, #dc21285_low
.endif
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, [\base, #0x180] @ get interrupts
mov \irqnr, #IRQ_SDRAMPARITY
tst \irqstat, #IRQ_MASK_SDRAMPARITY
bne 1001f
tst \irqstat, #IRQ_MASK_UART_RX
movne \irqnr, #IRQ_CONRX
bne 1001f
tst \irqstat, #IRQ_MASK_DMA1
movne \irqnr, #IRQ_DMA1
bne 1001f
tst \irqstat, #IRQ_MASK_DMA2
movne \irqnr, #IRQ_DMA2
bne 1001f
tst \irqstat, #IRQ_MASK_IN0
movne \irqnr, #IRQ_IN0
bne 1001f
tst \irqstat, #IRQ_MASK_IN1
movne \irqnr, #IRQ_IN1
bne 1001f
tst \irqstat, #IRQ_MASK_IN2
movne \irqnr, #IRQ_IN2
bne 1001f
tst \irqstat, #IRQ_MASK_IN3
movne \irqnr, #IRQ_IN3
bne 1001f
tst \irqstat, #IRQ_MASK_PCI
movne \irqnr, #IRQ_PCI
bne 1001f
tst \irqstat, #IRQ_MASK_DOORBELLHOST
movne \irqnr, #IRQ_DOORBELLHOST
bne 1001f
tst \irqstat, #IRQ_MASK_I2OINPOST
movne \irqnr, #IRQ_I2OINPOST
bne 1001f
tst \irqstat, #IRQ_MASK_TIMER1
movne \irqnr, #IRQ_TIMER1
bne 1001f
tst \irqstat, #IRQ_MASK_TIMER2
movne \irqnr, #IRQ_TIMER2
bne 1001f
tst \irqstat, #IRQ_MASK_TIMER3
movne \irqnr, #IRQ_TIMER3
bne 1001f
tst \irqstat, #IRQ_MASK_UART_TX
movne \irqnr, #IRQ_CONTX
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_ABORT
movne \irqnr, #IRQ_PCI_ABORT
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_SERR
movne \irqnr, #IRQ_PCI_SERR
bne 1001f
tst \irqstat, #IRQ_MASK_DISCARD_TIMER
movne \irqnr, #IRQ_DISCARD_TIMER
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_DPERR
movne \irqnr, #IRQ_PCI_DPERR
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_PERR
movne \irqnr, #IRQ_PCI_PERR
1001:
.endm
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment