void __init lpc32xx_init_irq(void)
{
unsigned int i, vloc;
/* Setup MIC */
vloc = io_p2v(MIC_BASE);
__raw_writel(0, (vloc + INTC_MASK));
__raw_writel(MIC_APR_DEFAULT, (vloc + INTC_POLAR));
__raw_writel(MIC_ATR_DEFAULT, (vloc + INTC_ACT_TYPE));
/* Setup SIC1 */
vloc = io_p2v(SIC1_BASE);
__raw_writel(0, (vloc + INTC_MASK));
__raw_writel(SIC1_APR_DEFAULT, (vloc + INTC_POLAR));
__raw_writel(SIC1_ATR_DEFAULT, (vloc + INTC_ACT_TYPE));
/* Setup SIC2 */
vloc = io_p2v(SIC2_BASE);
__raw_writel(0, (vloc + INTC_MASK));
__raw_writel(SIC2_APR_DEFAULT, (vloc + INTC_POLAR));
__raw_writel(SIC2_ATR_DEFAULT, (vloc + INTC_ACT_TYPE));
/* Configure supported IRQ's */
for (i = 0; i < NR_IRQS; i++) {
set_irq_flags(i, IRQF_VALID);
set_irq_chip(i, &lpc32xx_irq_chip); //set_irq_chip
}
/* Set default mappings */
lpc32xx_set_default_mappings(io_p2v(MIC_BASE), MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
lpc32xx_set_default_mappings(io_p2v(SIC1_BASE), SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, INTC_SIC1_OFFS);
lpc32xx_set_default_mappings(io_p2v(SIC2_BASE), SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, INTC_SIC2_OFFS);
/* mask all interrupts except SUBIRQA and SUBFIQ */
__raw_writel((1 << IRQ_SUB1IRQ) | (1 << IRQ_SUB2IRQ) |
(1 << IRQ_SUB1FIQ) | (1 << IRQ_SUB2FIQ),
(io_p2v(MIC_BASE) + INTC_MASK));
__raw_writel(0, (io_p2v(SIC1_BASE) + INTC_MASK));
__raw_writel(0, (io_p2v(SIC2_BASE) + INTC_MASK));
}
lpc32xx_irq_chip
在lpc32xx_init_irq中调用set_irq_chip,其中一个参数是lpc32xx_irq_chip,在其中实现了mask、unmask、set_type等方法。
static struct irq_chip lpc32xx_irq_chip = {
.ack = lpc32xx_mask_ack_irq,
.mask = lpc32xx_mask_irq,
.unmask = lpc32xx_unmask_irq,
.set_type = lpc32xx_set_irq_type,
};
LPC3250中断处理程序
中断处理完毕,需要清除对应中断的中断标志,然后才能返回。
键盘中断范例:
/* Clear IRQ */
__raw_writel(1, KS_IRQ(kscandat->kscan_base))
对于没有特别中断控制器的中断源,因为没有中断寄存器,则需要直接清除对应MIC或者SIC的对应位,如GPIO作为中断输入,则中断服务程序需要清除SIC的对应位。