Skip to content

Commit

Permalink
MIPS: Alchemy: chain IRQ controllers to MIPS IRQ controller
Browse files Browse the repository at this point in the history
IC and GPIC are now chain handlers of the traditional MIPS IRQ controller.

Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2933/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Manuel Lauss authored and Ralf Baechle committed Dec 8, 2011
1 parent f267c88 commit 894cc87
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 49 deletions.
26 changes: 13 additions & 13 deletions arch/mips/alchemy/common/gpioint.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,12 @@ static struct syscore_ops alchemy_gpic_pmops = {
.resume = alchemy_gpic_resume,
};

static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d)
{
int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC);
generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i);
}

static void __init alchemy_gpic_init_irq(const struct gpic_devint_data *dints)
{
int i;
Expand Down Expand Up @@ -383,7 +389,10 @@ static void __init alchemy_gpic_init_irq(const struct gpic_devint_data *dints)
dints++;
}

set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, alchemy_gpic_dispatch);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, alchemy_gpic_dispatch);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, alchemy_gpic_dispatch);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, alchemy_gpic_dispatch);
}

/**********************************************************************/
Expand All @@ -397,17 +406,8 @@ void __init arch_init_irq(void)
}
}

#define CAUSEF_GPIC (CAUSEF_IP2 | CAUSEF_IP3 | CAUSEF_IP4 | CAUSEF_IP5)

void plat_irq_dispatch(void)
asmlinkage void plat_irq_dispatch(void)
{
unsigned long i, c = read_c0_cause() & read_c0_status();

if (c & CAUSEF_IP7) /* c0 timer */
do_IRQ(MIPS_CPU_IRQ_BASE + 7);
else if (likely(c & CAUSEF_GPIC)) {
i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC);
do_IRQ(i + ALCHEMY_GPIC_INT_BASE);
} else
spurious_interrupt();
unsigned long r = (read_c0_status() & read_c0_cause()) >> 8;
do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff));
}
62 changes: 26 additions & 36 deletions arch/mips/alchemy/common/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,41 +459,6 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type)
return ret;
}

asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause();
unsigned long s, off;

if (pending & CAUSEF_IP7) {
off = MIPS_CPU_IRQ_BASE + 7;
goto handle;
} else if (pending & CAUSEF_IP2) {
s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ0INT;
off = AU1000_INTC0_INT_BASE;
} else if (pending & CAUSEF_IP3) {
s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ1INT;
off = AU1000_INTC0_INT_BASE;
} else if (pending & CAUSEF_IP4) {
s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ0INT;
off = AU1000_INTC1_INT_BASE;
} else if (pending & CAUSEF_IP5) {
s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ1INT;
off = AU1000_INTC1_INT_BASE;
} else
goto spurious;

s = __raw_readl((void __iomem *)s);
if (unlikely(!s)) {
spurious:
spurious_interrupt();
return;
}
off += __ffs(s);
handle:
do_IRQ(off);
}


static inline void ic_init(void __iomem *base)
{
/* initialize interrupt controller to a safe state */
Expand Down Expand Up @@ -562,6 +527,22 @@ static struct syscore_ops alchemy_ic_syscore_ops = {
.resume = alchemy_ic_resume,
};

/* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */
#define DISP(name, base, addr) \
static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d) \
{ \
unsigned long r = __raw_readl((void __iomem *)KSEG1ADDR(addr)); \
if (likely(r)) \
generic_handle_irq(base + __ffs(r)); \
else \
spurious_interrupt(); \
}

DISP(ic0r0, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ0INT)
DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT)
DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT)
DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT)

static void __init au1000_init_irq(struct au1xxx_irqmap *map)
{
unsigned int bit, irq_nr;
Expand Down Expand Up @@ -603,7 +584,10 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map)
++map;
}

set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, au1000_ic0r0_dispatch);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, au1000_ic0r1_dispatch);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, au1000_ic1r0_dispatch);
irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, au1000_ic1r1_dispatch);
}

void __init arch_init_irq(void)
Expand All @@ -626,3 +610,9 @@ void __init arch_init_irq(void)
break;
}
}

asmlinkage void plat_irq_dispatch(void)
{
unsigned long r = (read_c0_status() & read_c0_cause()) >> 8;
do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff));
}

0 comments on commit 894cc87

Please sign in to comment.