ppc4xx_pic.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 259 行
C
259 行
/* * * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * * Module name: ppc4xx_pic.c * * Description: * Interrupt controller driver for PowerPC 4xx-based processors. *//* * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has * 32 possible interrupts, a majority of which are not implemented on * all cores. There are six configurable, external interrupt pins and * there are eight internal interrupts for the on-chip serial port * (SPU), DMA controller, and JTAG controller. * * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32 * possible interrupts as well. There are seven, configurable external * interrupt pins and there are 17 internal interrupts for the on-chip * serial port, DMA controller, on-chip Ethernet controller, PCI, etc. * */#include <linux/init.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/stddef.h>#include <asm/processor.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/ibm4xx.h>#include <asm/ppc4xx_pic.h>/* Global Variables */struct hw_interrupt_type *ppc4xx_pic;/* Six of one, half dozen of the other....#ifdefs, separate files, * other tricks..... * * There are basically two types of interrupt controllers, the 403 AIC * and the "others" with UIC. I just kept them both here separated * with #ifdefs, but it seems to change depending upon how supporting * files (like ppc4xx.h) change. -- Dan. */#ifdef CONFIG_403/* Function Prototypes */static void ppc403_aic_enable(unsigned int irq);static void ppc403_aic_disable(unsigned int irq);static void ppc403_aic_disable_and_ack(unsigned int irq);static struct hw_interrupt_type ppc403_aic = { "403GC AIC", NULL, NULL, ppc403_aic_enable, ppc403_aic_disable, ppc403_aic_disable_and_ack, 0};intppc403_pic_get_irq(struct pt_regs *regs){ int irq; unsigned long bits; /* * Only report the status of those interrupts that are actually * enabled. */ bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); /* * Walk through the interrupts from highest priority to lowest, and * report the first pending interrupt found. * We want PPC, not C bit numbering, so just subtract the ffs() * result from 32. */ irq = 32 - ffs(bits); if (irq == NR_AIC_IRQS) irq = -1; return (irq);}static voidppc403_aic_enable(unsigned int irq){ int bit, word; bit = irq & 0x1f; word = irq >> 5; ppc_cached_irq_mask[word] |= (1 << (31 - bit)); mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);}static voidppc403_aic_disable(unsigned int irq){ int bit, word; bit = irq & 0x1f; word = irq >> 5; ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);}static voidppc403_aic_disable_and_ack(unsigned int irq){ int bit, word; bit = irq & 0x1f; word = irq >> 5; ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); mtdcr(DCRN_EXISR, (1 << (31 - bit)));}#else /* !CONFIG_403 */static voidppc405_uic_enable(unsigned int irq){ int bit, word; bit = irq & 0x1f; word = irq >> 5; ppc_cached_irq_mask[word] |= 1 << (31 - bit); mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]);}static voidppc405_uic_disable(unsigned int irq){ int bit, word; bit = irq & 0x1f; word = irq >> 5; ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]);}static voidppc405_uic_disable_and_ack(unsigned int irq){ int bit, word; bit = irq & 0x1f; word = irq >> 5; ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]); mtdcr(DCRN_UIC0_SR, (1 << (31 - bit)));}static voidppc405_uic_end(unsigned int irq){ int bit, word; unsigned int tr_bits; bit = irq & 0x1f; word = irq >> 5; tr_bits = mfdcr(DCRN_UIC0_TR); if ((tr_bits & (1 << (31 - bit))) == 0) { /* level trigger */ mtdcr(DCRN_UIC0_SR, 1 << (31 - bit)); } if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { ppc_cached_irq_mask[word] |= 1 << (31 - bit); mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]); }}static struct hw_interrupt_type ppc405_uic = {#if defined (CONFIG_405GP) "405GP UIC",#else "NP405 UIC",#endif NULL, NULL, ppc405_uic_enable, ppc405_uic_disable, ppc405_uic_disable_and_ack, ppc405_uic_end, 0};intppc405_pic_get_irq(struct pt_regs *regs){ int irq; unsigned long bits; /* * Only report the status of those interrupts that are actually * enabled. */ bits = mfdcr(DCRN_UIC0_MSR); /* * Walk through the interrupts from highest priority to lowest, and * report the first pending interrupt found. * We want PPC, not C bit numbering, so just subtract the ffs() * result from 32. */ irq = 32 - ffs(bits); if (irq == NR_AIC_IRQS) irq = -1; return (irq);}#endifvoid __initppc4xx_pic_init(void){ /* * Disable all external interrupts until they are * explicity requested. */ ppc_cached_irq_mask[0] = 0;#ifdef CONFIG_403 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]); ppc4xx_pic = &ppc403_aic; ppc_md.get_irq = ppc403_pic_get_irq;#else mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[0]); /* Set all interrupts to non-critical. */ mtdcr(DCRN_UIC0_CR, 0); ppc4xx_pic = &ppc405_uic; ppc_md.get_irq = ppc405_pic_get_irq;#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?