📄 irq.c
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * arch/sh64/kernel/irq_cayman.c * * SH-5 Cayman Interrupt Support * * This file handles the board specific parts of the Cayman interrupt system * * Copyright (C) 2002 Stuart Menefy */#include <linux/config.h>#include <asm/irq.h>#include <asm/page.h>#include <asm/io.h>#include <linux/irq.h>#include <linux/interrupt.h>#include <linux/signal.h>#include <asm/cayman.h>unsigned long epld_virt;#define EPLD_BASE 0x04002000#define EPLD_STATUS_BASE (epld_virt + 0x10)#define EPLD_MASK_BASE (epld_virt + 0x20)/* Note the SMSC SuperIO chip and SMSC LAN chip interrupts are all muxed onto the same SH-5 interrupt */static irqreturn_t cayman_interrupt_smsc(int irq, void *dev_id, struct pt_regs *regs){ printk(KERN_INFO "CAYMAN: spurious SMSC interrupt\n"); return IRQ_NONE;}static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id, struct pt_regs *regs){ printk(KERN_INFO "CAYMAN: spurious PCI interrupt, IRQ %d\n", irq); return IRQ_NONE;}static struct irqaction cayman_action_smsc = { .name = "Cayman SMSC Mux", .handler = cayman_interrupt_smsc, .flags = SA_INTERRUPT,};static struct irqaction cayman_action_pci2 = { .name = "Cayman PCI2 Mux", .handler = cayman_interrupt_pci2, .flags = SA_INTERRUPT,};static void enable_cayman_irq(unsigned int irq){ unsigned long flags; unsigned long mask; unsigned int reg; unsigned char bit; irq -= START_EXT_IRQS; reg = EPLD_MASK_BASE + ((irq / 8) << 2); bit = 1<<(irq % 8); local_irq_save(flags); mask = ctrl_inl(reg); mask |= bit; ctrl_outl(mask, reg); local_irq_restore(flags);}void disable_cayman_irq(unsigned int irq){ unsigned long flags; unsigned long mask; unsigned int reg; unsigned char bit; irq -= START_EXT_IRQS; reg = EPLD_MASK_BASE + ((irq / 8) << 2); bit = 1<<(irq % 8); local_irq_save(flags); mask = ctrl_inl(reg); mask &= ~bit; ctrl_outl(mask, reg); local_irq_restore(flags);}static void ack_cayman_irq(unsigned int irq){ disable_cayman_irq(irq);}static void end_cayman_irq(unsigned int irq){ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_cayman_irq(irq);}static unsigned int startup_cayman_irq(unsigned int irq){ enable_cayman_irq(irq); return 0; /* never anything pending */}static void shutdown_cayman_irq(unsigned int irq){ disable_cayman_irq(irq);}struct hw_interrupt_type cayman_irq_type = { .typename = "Cayman-IRQ", .startup = startup_cayman_irq, .shutdown = shutdown_cayman_irq, .enable = enable_cayman_irq, .disable = disable_cayman_irq, .ack = ack_cayman_irq, .end = end_cayman_irq,};int cayman_irq_demux(int evt){ int irq = intc_evt_to_irq[evt]; if (irq == SMSC_IRQ) { unsigned long status; int i; status = ctrl_inl(EPLD_STATUS_BASE) & ctrl_inl(EPLD_MASK_BASE) & 0xff; if (status == 0) { irq = -1; } else { for (i=0; i<8; i++) { if (status & (1<<i)) break; } irq = START_EXT_IRQS + i; } } if (irq == PCI2_IRQ) { unsigned long status; int i; status = ctrl_inl(EPLD_STATUS_BASE + 3 * sizeof(u32)) & ctrl_inl(EPLD_MASK_BASE + 3 * sizeof(u32)) & 0xff; if (status == 0) { irq = -1; } else { for (i=0; i<8; i++) { if (status & (1<<i)) break; } irq = START_EXT_IRQS + (3 * 8) + i; } } return irq;}#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)int cayman_irq_describe(char* p, int irq){ if (irq < NR_INTC_IRQS) { return intc_irq_describe(p, irq); } else if (irq < NR_INTC_IRQS + 8) { return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS); } else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) { return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24)); } return 0;}#endifvoid init_cayman_irq(void){ int i; epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD"); if (!epld_virt) { printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n"); return; } for (i=0; i<NR_EXT_IRQS; i++) { irq_desc[START_EXT_IRQS + i].handler = &cayman_irq_type; } /* Setup the SMSC interrupt */ setup_irq(SMSC_IRQ, &cayman_action_smsc); setup_irq(PCI2_IRQ, &cayman_action_pci2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -