From 6044cf1d9426dfd5cdc1e7b9cf8eaed6418e1ff6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 27 Oct 2010 17:28:58 +0100 Subject: 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 --- arch/mn10300/unit-asb2364/Makefile | 2 +- arch/mn10300/unit-asb2364/include/unit/fpga-regs.h | 24 +++--- arch/mn10300/unit-asb2364/include/unit/irq.h | 35 ++++++++ arch/mn10300/unit-asb2364/irq-fpga.c | 96 ++++++++++++++++++++++ arch/mn10300/unit-asb2364/unit-init.c | 3 + 5 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 arch/mn10300/unit-asb2364/include/unit/irq.h create mode 100644 arch/mn10300/unit-asb2364/irq-fpga.c (limited to 'arch/mn10300/unit-asb2364') diff --git a/arch/mn10300/unit-asb2364/Makefile b/arch/mn10300/unit-asb2364/Makefile index 6dd27d65877a..e9d9b90ef6da 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 a039a50c91db..7cf12054db65 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 000000000000..786148e46565 --- /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 000000000000..fcf29754e4d1 --- /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 +#include +#include +#include + +/* + * 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 a3fc09b43f84..11440803db10 100644 --- a/arch/mn10300/unit-asb2364/unit-init.c +++ b/arch/mn10300/unit-asb2364/unit-init.c @@ -20,6 +20,7 @@ #include #include #include +#include /* * 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(); } -- cgit