core.c
来自「linux2.6.16版本」· C语言 代码 · 共 533 行 · 第 1/2 页
C
533 行
/************************************************************************* * GPIO helpers *************************************************************************/static unsigned long GPIO_IRQ_falling_edge;static unsigned long GPIO_IRQ_rising_edge;static unsigned long GPIO_IRQ_level_low;static unsigned long GPIO_IRQ_level_high;static void update_gpio_int_csrs(void){ ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge); ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge); ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low); ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);}void gpio_line_config(int line, int direction){ unsigned long flags; local_irq_save(flags); if (direction == GPIO_OUT) { irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0; /* if it's an output, it ain't an interrupt anymore */ GPIO_IRQ_falling_edge &= ~(1 << line); GPIO_IRQ_rising_edge &= ~(1 << line); GPIO_IRQ_level_low &= ~(1 << line); GPIO_IRQ_level_high &= ~(1 << line); update_gpio_int_csrs(); ixp2000_reg_wrb(IXP2000_GPIO_PDSR, 1 << line); } else if (direction == GPIO_IN) { ixp2000_reg_wrb(IXP2000_GPIO_PDCR, 1 << line); } local_irq_restore(flags);}/************************************************************************* * IRQ handling IXP2000 *************************************************************************/static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){ int i; unsigned long status = *IXP2000_GPIO_INST; for (i = 0; i <= 7; i++) { if (status & (1<<i)) { desc = irq_desc + i + IRQ_IXP2000_GPIO0; desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs); } }}static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type){ int line = irq - IRQ_IXP2000_GPIO0; /* * First, configure this GPIO line as an input. */ ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line); /* * Then, set the proper trigger type. */ if (type & IRQT_FALLING) GPIO_IRQ_falling_edge |= 1 << line; else GPIO_IRQ_falling_edge &= ~(1 << line); if (type & IRQT_RISING) GPIO_IRQ_rising_edge |= 1 << line; else GPIO_IRQ_rising_edge &= ~(1 << line); if (type & IRQT_LOW) GPIO_IRQ_level_low |= 1 << line; else GPIO_IRQ_level_low &= ~(1 << line); if (type & IRQT_HIGH) GPIO_IRQ_level_high |= 1 << line; else GPIO_IRQ_level_high &= ~(1 << line); update_gpio_int_csrs(); /* * Finally, mark the corresponding IRQ as valid. */ irq_desc[irq].valid = 1; return 0;}static void ixp2000_GPIO_irq_mask_ack(unsigned int irq){ ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0))); ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0))); ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0))); ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));}static void ixp2000_GPIO_irq_mask(unsigned int irq){ ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));}static void ixp2000_GPIO_irq_unmask(unsigned int irq){ ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));}static struct irqchip ixp2000_GPIO_irq_chip = { .ack = ixp2000_GPIO_irq_mask_ack, .mask = ixp2000_GPIO_irq_mask, .unmask = ixp2000_GPIO_irq_unmask, .set_type = ixp2000_GPIO_irq_type,};static void ixp2000_pci_irq_mask(unsigned int irq){ unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE; if (irq == IRQ_IXP2000_PCIA) ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26))); else if (irq == IRQ_IXP2000_PCIB) ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));}static void ixp2000_pci_irq_unmask(unsigned int irq){ unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE; if (irq == IRQ_IXP2000_PCIA) ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26))); else if (irq == IRQ_IXP2000_PCIB) ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));}/* * Error interrupts. These are used extensively by the microengine drivers */static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){ int i; unsigned long status = *IXP2000_IRQ_ERR_STATUS; for(i = 31; i >= 0; i--) { if(status & (1 << i)) { desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs); } }}static void ixp2000_err_irq_mask(unsigned int irq){ ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR, (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));}static void ixp2000_err_irq_unmask(unsigned int irq){ ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET, (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));}static struct irqchip ixp2000_err_irq_chip = { .ack = ixp2000_err_irq_mask, .mask = ixp2000_err_irq_mask, .unmask = ixp2000_err_irq_unmask};static struct irqchip ixp2000_pci_irq_chip = { .ack = ixp2000_pci_irq_mask, .mask = ixp2000_pci_irq_mask, .unmask = ixp2000_pci_irq_unmask};static void ixp2000_irq_mask(unsigned int irq){ ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << irq));}static void ixp2000_irq_unmask(unsigned int irq){ ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));}static struct irqchip ixp2000_irq_chip = { .ack = ixp2000_irq_mask, .mask = ixp2000_irq_mask, .unmask = ixp2000_irq_unmask};void __init ixp2000_init_irq(void){ int irq; /* * Mask all sources */ ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff); ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff); /* clear all GPIO edge/level detects */ ixp2000_reg_write(IXP2000_GPIO_REDR, 0); ixp2000_reg_write(IXP2000_GPIO_FEDR, 0); ixp2000_reg_write(IXP2000_GPIO_LSHR, 0); ixp2000_reg_write(IXP2000_GPIO_LSLR, 0); ixp2000_reg_write(IXP2000_GPIO_INCR, -1); /* clear PCI interrupt sources */ ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, 0); /* * Certain bits in the IRQ status register of the * IXP2000 are reserved. Instead of trying to map * things non 1:1 from bit position to IRQ number, * we mark the reserved IRQs as invalid. This makes * our mask/unmask code much simpler. */ for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { if ((1 << irq) & IXP2000_VALID_IRQ_MASK) { set_irq_chip(irq, &ixp2000_irq_chip); set_irq_handler(irq, do_level_IRQ); set_irq_flags(irq, IRQF_VALID); } else set_irq_flags(irq, 0); } for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) { if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) & IXP2000_VALID_ERR_IRQ_MASK) { set_irq_chip(irq, &ixp2000_err_irq_chip); set_irq_handler(irq, do_level_IRQ); set_irq_flags(irq, IRQF_VALID); } else set_irq_flags(irq, 0); } set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler); /* * GPIO IRQs are invalid until someone sets the interrupt mode * by calling set_irq_type(). */ for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { set_irq_chip(irq, &ixp2000_GPIO_irq_chip); set_irq_handler(irq, do_level_IRQ); set_irq_flags(irq, 0); } set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler); /* * Enable PCI irqs. The actual PCI[AB] decoding is done in * entry-macro.S, so we don't need a chained handler for the * PCI interrupt source. */ ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI)); for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) { set_irq_chip(irq, &ixp2000_pci_irq_chip); set_irq_handler(irq, do_level_IRQ); set_irq_flags(irq, IRQF_VALID); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?