From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- arch/mips/au1000/common/irq.c | 654 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 654 insertions(+) create mode 100644 arch/mips/au1000/common/irq.c (limited to 'arch/mips/au1000/common/irq.c') diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c new file mode 100644 index 000000000000..d1eb5a4a9a19 --- /dev/null +++ b/arch/mips/au1000/common/irq.c @@ -0,0 +1,654 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1000 interrupt routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_MIPS_PB1000 +#include +#endif + +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +/* note: prints function name for you */ +#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define EXT_INTC0_REQ0 2 /* IP 2 */ +#define EXT_INTC0_REQ1 3 /* IP 3 */ +#define EXT_INTC1_REQ0 4 /* IP 4 */ +#define EXT_INTC1_REQ1 5 /* IP 5 */ +#define MIPS_TIMER_IP 7 /* IP 7 */ + +extern asmlinkage void au1000_IRQ(void); +extern void set_debug_traps(void); +extern irq_cpustat_t irq_stat [NR_CPUS]; + +static void setup_local_irq(unsigned int irq, int type, int int_req); +static unsigned int startup_irq(unsigned int irq); +static void end_irq(unsigned int irq_nr); +static inline void mask_and_ack_level_irq(unsigned int irq_nr); +static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr); +static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr); +static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr); +inline void local_enable_irq(unsigned int irq_nr); +inline void local_disable_irq(unsigned int irq_nr); + +void (*board_init_irq)(void); + +#ifdef CONFIG_PM +extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); +#endif + +static DEFINE_SPINLOCK(irq_lock); + + +static unsigned int startup_irq(unsigned int irq_nr) +{ + local_enable_irq(irq_nr); + return 0; +} + + +static void shutdown_irq(unsigned int irq_nr) +{ + local_disable_irq(irq_nr); + return; +} + + +inline void local_enable_irq(unsigned int irq_nr) +{ + if (irq_nr > AU1000_LAST_INTC0_INT) { + au_writel(1<<(irq_nr-32), IC1_MASKSET); + au_writel(1<<(irq_nr-32), IC1_WAKESET); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_WAKECLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { + au_writel(1<<(irq_nr-32), IC1_RISINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { + au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1< AU1000_LAST_INTC0_INT) { + au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); + au_writel(1<<(irq_nr-32), IC1_RISINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1< AU1000_MAX_INTR) return; + /* Config2[n], Config1[n], Config0[n] */ + if (irq_nr > AU1000_LAST_INTC0_INT) { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + irq_desc[irq_nr].handler = &rise_edge_irq_type; + break; + case INTC_INT_FALL_EDGE: /* 0:1:0 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + irq_desc[irq_nr].handler = &fall_edge_irq_type; + break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + irq_desc[irq_nr].handler = &either_edge_irq_type; + break; + case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2SET); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + irq_desc[irq_nr].handler = &level_irq_type; + break; + case INTC_INT_LOW_LEVEL: /* 1:1:0 */ + au_writel(1<<(irq_nr-32), IC1_CFG2SET); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + irq_desc[irq_nr].handler = &level_irq_type; + break; + case INTC_INT_DISABLED: /* 0:0:0 */ + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + break; + default: /* disable the interrupt */ + printk("unexpected int type %d (irq %d)\n", type, irq_nr); + au_writel(1<<(irq_nr-32), IC1_CFG0CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1CLR); + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + return; + } + if (int_req) /* assign to interrupt request 1 */ + au_writel(1<<(irq_nr-32), IC1_ASSIGNCLR); + else /* assign to interrupt request 0 */ + au_writel(1<<(irq_nr-32), IC1_ASSIGNSET); + au_writel(1<<(irq_nr-32), IC1_SRCSET); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + au_writel(1<<(irq_nr-32), IC1_WAKECLR); + } + else { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1<im_irq, imp->im_type, imp->im_request); + imp++; + } + + /* Now set up the irq mapping for the board. + */ + imp = au1xxx_irq_map; + for (i=0; iim_irq, imp->im_type, imp->im_request); + imp++; + } + + set_c0_status(ALLINTS); + + /* Board specific IRQ initialization. + */ + if (board_init_irq) + (*board_init_irq)(); +} + + +/* + * Interrupts are nested. Even if an interrupt handler is registered + * as "fast", we might get another interrupt before we return from + * intcX_reqX_irqdispatch(). + */ + +void intc0_req0_irqdispatch(struct pt_regs *regs) +{ + int irq = 0; + static unsigned long intc0_req0 = 0; + + intc0_req0 |= au_readl(IC0_REQ0INT); + + if (!intc0_req0) return; + + /* + * Because of the tight timing of SETUP token to reply + * transactions, the USB devices-side packet complete + * interrupt needs the highest priority. + */ + if ((intc0_req0 & (1<