diff options
author | David Howells <dhowells@redhat.com> | 2010-10-27 17:28:58 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2010-10-27 17:28:58 +0100 |
commit | 6044cf1d9426dfd5cdc1e7b9cf8eaed6418e1ff6 (patch) | |
tree | 3f6f209d37328ce1635df8f5d0b5df1cef1afe30 | |
parent | 730c1fad0ee22a170d2ee76a904709ee304931c0 (diff) |
MN10300: ASB2364: Handle the IRQ multiplexer in the FPGA
Handle the IRQ multiplexer in the FPGA by implementing a cascade interrupt
driver for it.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | arch/mn10300/include/asm/irq.h | 12 | ||||
-rw-r--r-- | arch/mn10300/kernel/irq.c | 13 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2364/Makefile | 2 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2364/include/unit/fpga-regs.h | 24 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2364/include/unit/irq.h | 35 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2364/irq-fpga.c | 96 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2364/unit-init.c | 3 |
7 files changed, 166 insertions, 19 deletions
diff --git a/arch/mn10300/include/asm/irq.h b/arch/mn10300/include/asm/irq.h index b7b8e175b16..1a73fb3f60c 100644 --- a/arch/mn10300/include/asm/irq.h +++ b/arch/mn10300/include/asm/irq.h @@ -21,11 +21,15 @@ /* this number is used when no interrupt has been assigned */ #define NO_IRQ INT_MAX -/* hardware irq numbers */ -#ifdef CONFIG_SMP -#define NR_IRQS GxICR_NUM_EXT_IRQS +/* + * hardware irq numbers + * - the ASB2364 has an FPGA with an IRQ multiplexer on it + */ +#ifdef CONFIG_MN10300_UNIT_ASB2364 +#include <unit/irq.h> #else -#define NR_IRQS GxICR_NUM_IRQS +#define NR_CPU_IRQS GxICR_NUM_IRQS +#define NR_IRQS NR_CPU_IRQS #endif /* external hardware irq numbers */ diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 2f66a45dcd1..c2e44597c22 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -381,9 +381,16 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%3d: ", i); for_each_present_cpu(cpu) seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); - seq_printf(p, " %14s.%u", irq_desc[i].chip->name, - (GxICR(i) & GxICR_LEVEL) >> - GxICR_LEVEL_SHIFT); + + if (i < NR_CPU_IRQS) + seq_printf(p, " %14s.%u", + irq_desc[i].chip->name, + (GxICR(i) & GxICR_LEVEL) >> + GxICR_LEVEL_SHIFT); + else + seq_printf(p, " %14s", + irq_desc[i].chip->name); + seq_printf(p, " %s", action->name); for (action = action->next; diff --git a/arch/mn10300/unit-asb2364/Makefile b/arch/mn10300/unit-asb2364/Makefile index 6dd27d65877..e9d9b90ef6d 100644 --- a/arch/mn10300/unit-asb2364/Makefile +++ b/arch/mn10300/unit-asb2364/Makefile @@ -7,4 +7,4 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -obj-y := unit-init.o leds.o +obj-y := unit-init.o leds.o irq-fpga.o diff --git a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h index a039a50c91d..7cf12054db6 100644 --- a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h +++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h @@ -14,17 +14,19 @@ #define ASB2364_FPGA_REG_RESET_USB __SYSREG(0xa900130c, u16) #define ASB2364_FPGA_REG_RESET_AV __SYSREG(0xa9001310, u16) -#define ASB2364_FPGA_REG_IRQ_LAN __SYSREG(0xa9001510, u16) -#define ASB2364_FPGA_REG_IRQ_UART __SYSREG(0xa9001514, u16) -#define ASB2364_FPGA_REG_IRQ_I2C __SYSREG(0xa9001518, u16) -#define ASB2364_FPGA_REG_IRQ_USB __SYSREG(0xa900151c, u16) -#define ASB2364_FPGA_REG_IRQ_FPGA __SYSREG(0xa9001524, u16) - -#define ASB2364_FPGA_REG_MASK_LAN __SYSREG(0xa9001590, u16) -#define ASB2364_FPGA_REG_MASK_UART __SYSREG(0xa9001594, u16) -#define ASB2364_FPGA_REG_MASK_I2C __SYSREG(0xa9001598, u16) -#define ASB2364_FPGA_REG_MASK_USB __SYSREG(0xa900159c, u16) -#define ASB2364_FPGA_REG_MASK_FPGA __SYSREG(0xa90015a4, u16) +#define ASB2364_FPGA_REG_IRQ(X) __SYSREG(0xa9001590+((X)*4), u16) +#define ASB2364_FPGA_REG_IRQ_LAN ASB2364_FPGA_REG_IRQ(0) +#define ASB2364_FPGA_REG_IRQ_UART ASB2364_FPGA_REG_IRQ(1) +#define ASB2364_FPGA_REG_IRQ_I2C ASB2364_FPGA_REG_IRQ(2) +#define ASB2364_FPGA_REG_IRQ_USB ASB2364_FPGA_REG_IRQ(3) +#define ASB2364_FPGA_REG_IRQ_FPGA ASB2364_FPGA_REG_IRQ(5) + +#define ASB2364_FPGA_REG_MASK(X) __SYSREG(0xa9001590+((X)*4), u16) +#define ASB2364_FPGA_REG_MASK_LAN ASB2364_FPGA_REG_MASK(0) +#define ASB2364_FPGA_REG_MASK_UART ASB2364_FPGA_REG_MASK(1) +#define ASB2364_FPGA_REG_MASK_I2C ASB2364_FPGA_REG_MASK(2) +#define ASB2364_FPGA_REG_MASK_USB ASB2364_FPGA_REG_MASK(3) +#define ASB2364_FPGA_REG_MASK_FPGA ASB2364_FPGA_REG_MASK(5) #define ASB2364_FPGA_REG_CPLD5_SET1 __SYSREG(0xa9002500, u16) #define ASB2364_FPGA_REG_CPLD5_SET2 __SYSREG(0xa9002504, u16) diff --git a/arch/mn10300/unit-asb2364/include/unit/irq.h b/arch/mn10300/unit-asb2364/include/unit/irq.h new file mode 100644 index 00000000000..786148e4656 --- /dev/null +++ b/arch/mn10300/unit-asb2364/include/unit/irq.h @@ -0,0 +1,35 @@ +/* ASB2364 FPGA irq numbers + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#ifndef _UNIT_IRQ_H +#define _UNIT_IRQ_H + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_SMP +#define NR_CPU_IRQS GxICR_NUM_EXT_IRQS +#else +#define NR_CPU_IRQS GxICR_NUM_IRQS +#endif + +enum { + FPGA_LAN_IRQ = NR_CPU_IRQS, + FPGA_UART_IRQ, + FPGA_I2C_IRQ, + FPGA_USB_IRQ, + FPGA_RESERVED_IRQ, + FPGA_FPGA_IRQ, + NR_IRQS +}; + +extern void __init irq_fpga_init(void); + +#endif /* !__ASSEMBLY__ */ +#endif /* _UNIT_IRQ_H */ diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c new file mode 100644 index 00000000000..fcf29754e4d --- /dev/null +++ b/arch/mn10300/unit-asb2364/irq-fpga.c @@ -0,0 +1,96 @@ +/* ASB2364 FPGA interrupt multiplexing + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <unit/fpga-regs.h> + +/* + * FPGA PIC operations + */ +static void asb2364_fpga_mask(unsigned int irq) +{ + ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001; + SyncExBus(); +} + +static void asb2364_fpga_ack(unsigned int irq) +{ + ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001; + SyncExBus(); +} + +static void asb2364_fpga_mask_ack(unsigned int irq) +{ + ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001; + SyncExBus(); + ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001; + SyncExBus(); +} + +static void asb2364_fpga_unmask(unsigned int irq) +{ + ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000; + SyncExBus(); +} + +static struct irq_chip asb2364_fpga_pic = { + .name = "fpga", + .ack = asb2364_fpga_ack, + .mask = asb2364_fpga_mask, + .mask_ack = asb2364_fpga_mask_ack, + .unmask = asb2364_fpga_unmask, +}; + +/* + * FPGA PIC interrupt handler + */ +static irqreturn_t fpga_interrupt(int irq, void *_mask) +{ + if ((ASB2364_FPGA_REG_IRQ_LAN & 0x0001) != 0x0001) + generic_handle_irq(FPGA_LAN_IRQ); + if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) != 0x0001) + generic_handle_irq(FPGA_UART_IRQ); + if ((ASB2364_FPGA_REG_IRQ_I2C & 0x0001) != 0x0001) + generic_handle_irq(FPGA_I2C_IRQ); + if ((ASB2364_FPGA_REG_IRQ_USB & 0x0001) != 0x0001) + generic_handle_irq(FPGA_USB_IRQ); + if ((ASB2364_FPGA_REG_IRQ_FPGA & 0x0001) != 0x0001) + generic_handle_irq(FPGA_FPGA_IRQ); + + return IRQ_HANDLED; +} + +/* + * Define an interrupt action for each FPGA PIC output + */ +static struct irqaction fpga_irq[] = { + [0] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "fpga", + }, +}; + +/* + * Initialise the FPGA's PIC + */ +void __init irq_fpga_init(void) +{ + int irq; + + for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++) + set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq); + + /* the FPGA drives the XIRQ1 input on the CPU PIC */ + setup_irq(XIRQ1, &fpga_irq[0]); +} diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c index a3fc09b43f8..11440803db1 100644 --- a/arch/mn10300/unit-asb2364/unit-init.c +++ b/arch/mn10300/unit-asb2364/unit-init.c @@ -20,6 +20,7 @@ #include <asm/processor.h> #include <asm/irq.h> #include <asm/intctl-regs.h> +#include <unit/fpga-regs.h> /* * initialise some of the unit hardware before gdbstub is set up @@ -82,4 +83,6 @@ void __init unit_init_IRQ(void) #define IRQCTL __SYSREG(0xd5000090, u32) IRQCTL |= 0x02; + + irq_fpga_init(); } |