📄 irq.c
字号:
/* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * arch/mips/ddb5xxx/ddb5477/irq.c * The irq setup and misc routines for DDB5476. * * 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. */#include <linux/config.h>#include <linux/init.h>#include <linux/irq.h>#include <linux/types.h>#include <linux/ptrace.h>#include <asm/system.h>#include <asm/mipsregs.h>#include <asm/ddb5xxx/ddb5xxx.h>/* [jsun] sooner or later we should move this debug stuff to MIPS common */#include <asm/ddb5xxx/debug.h>/* * IRQ mapping * * 0-7: 8 CPU interrupts * 0 - software interrupt 0 * 1 - software interrupt 1 * 2 - most Vrc5477 interrupts are routed to this pin * 3 - (optional) some other interrupts routed to this pin for debugg * 4 - not used * 5 - not used * 6 - not used * 7 - cpu timer (used by default) * * 8-39: 32 Vrc5477 interrupt sources * (refer to the Vrc5477 manual) */#define PCI0 DDB_INTPPES0#define PCI1 DDB_INTPPES1#define ACTIVE_LOW 1#define ACTIVE_HIGH 0#define LEVEL_SENSE 2#define EDGE_TRIGGER 0#define INTA 0#define INTB 1#define INTC 2#define INTD 3#define INTE 4static inline void set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger){ u32 reg_value; u32 reg_bitmask; reg_value = ddb_in32(pci); reg_bitmask = 0x3 << (intn * 2); reg_value &= ~reg_bitmask; reg_value |= (active | trigger) << (intn * 2); ddb_out32(pci, reg_value);}extern void vrc5477_irq_init(u32 base);extern void mips_cpu_irq_init(u32 base);extern asmlinkage void ddb5477_handle_int(void);voidddb5477_irq_setup(void){ MIPS_DEBUG(printk("ddb5477_irq_setup invoked.\n")); /* by default, we disable all interrupts and route all vrc5477 * interrupts to pin 0 (irq 2) */ ddb_out32(DDB_INTCTRL0, 0); ddb_out32(DDB_INTCTRL1, 0); ddb_out32(DDB_INTCTRL2, 0); ddb_out32(DDB_INTCTRL3, 0); clear_cp0_status(0xff00); set_cp0_status(0x0400); /* setup PCI interrupt attributes */ set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI1, INTA, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI1, INTB, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI1, INTC, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE); /* * for debugging purpose, we enable several error interrupts * and route them to pin 1. (IP3) */ /* cpu parity check - 0 */ ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0); /* cpu no-target decode - 1 */ ll_vrc5477_irq_route(1, 1); ll_vrc5477_irq_enable(1); /* local bus read time-out - 7 */ ll_vrc5477_irq_route(7, 1); ll_vrc5477_irq_enable(7); /* PCI SERR# - 14 */ ll_vrc5477_irq_route(14, 1); ll_vrc5477_irq_enable(14); /* PCI internal error - 15 */ ll_vrc5477_irq_route(15, 1); ll_vrc5477_irq_enable(15); /* IOPCI SERR# - 30 */ ll_vrc5477_irq_route(30, 1); ll_vrc5477_irq_enable(30); /* IOPCI internal error - 31 */ ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31); /* init all controllers */ mips_cpu_irq_init(0); vrc5477_irq_init(8); /* hook up the first-level interrupt handler */ set_except_vector(0, ddb5477_handle_int);}/* * the first level int-handler will jump here if it is a vrc5477 irq */#define NUM_5477_IRQS 32asmlinkage voidvrc5477_irq_dispatch(struct pt_regs *regs){ extern unsigned int do_IRQ(int irq, struct pt_regs *regs); u32 intStatus; u32 bitmask; u32 i; MIPS_ASSERT(ddb_in32(DDB_INT2STAT) == 0); MIPS_ASSERT(ddb_in32(DDB_INT3STAT) == 0); MIPS_ASSERT(ddb_in32(DDB_INT4STAT) == 0); MIPS_ASSERT(ddb_in32(DDB_NMISTAT) == 0); if (ddb_in32(DDB_INT1STAT) != 0) {#if defined(CONFIG_LL_DEBUG) vrc5477_show_int_regs();#endif panic("error interrupt has happened.\n"); } intStatus = ddb_in32(DDB_INT0STAT); for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) { /* do we need to "and" with the int mask? */ if (intStatus & bitmask) { do_IRQ(8 + i, regs); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -