?? irq.c
字號:
}static inline voids3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit){ unsigned long mask; unsigned long submask; submask = __raw_readl(S3C2410_INTSUBMSK); mask = __raw_readl(S3C2410_INTMSK); submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0)); mask &= ~parentbit; /* write back masks */ __raw_writel(submask, S3C2410_INTSUBMSK); __raw_writel(mask, S3C2410_INTMSK);}static inline voids3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group){ unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0); s3c_irqsub_mask(irqno, parentmask, group); __raw_writel(bit, S3C2410_SUBSRCPND); /* only ack parent if we've got all the irqs (seems we must * ack, all and hope that the irq system retriggers ok when * the interrupt goes off again) */ if (1) { __raw_writel(parentmask, S3C2410_SRCPND); __raw_writel(parentmask, S3C2410_INTPND); }}/* UART0 */static voids3c_irq_uart0_mask(unsigned int irqno){ s3c_irqsub_mask(irqno, INTMSK_UART0, 7);}static voids3c_irq_uart0_unmask(unsigned int irqno){ s3c_irqsub_unmask(irqno, INTMSK_UART0);}static voids3c_irq_uart0_ack(unsigned int irqno){ s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);}static struct irqchip s3c_irq_uart0 = { .mask = s3c_irq_uart0_mask, .unmask = s3c_irq_uart0_unmask, .ack = s3c_irq_uart0_ack,};/* UART1 */static voids3c_irq_uart1_mask(unsigned int irqno){ s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);}static voids3c_irq_uart1_unmask(unsigned int irqno){ s3c_irqsub_unmask(irqno, INTMSK_UART1);}static voids3c_irq_uart1_ack(unsigned int irqno){ s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);}static struct irqchip s3c_irq_uart1 = { .mask = s3c_irq_uart1_mask, .unmask = s3c_irq_uart1_unmask, .ack = s3c_irq_uart1_ack,};/* UART2 */static voids3c_irq_uart2_mask(unsigned int irqno){ s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);}static voids3c_irq_uart2_unmask(unsigned int irqno){ s3c_irqsub_unmask(irqno, INTMSK_UART2);}static voids3c_irq_uart2_ack(unsigned int irqno){ s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);}static struct irqchip s3c_irq_uart2 = { .mask = s3c_irq_uart2_mask, .unmask = s3c_irq_uart2_unmask, .ack = s3c_irq_uart2_ack,};/* ADC and Touchscreen */static voids3c_irq_adc_mask(unsigned int irqno){ s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);}static voids3c_irq_adc_unmask(unsigned int irqno){ s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);}static voids3c_irq_adc_ack(unsigned int irqno){ s3c_irqsub_maskack(irqno, INTMSK_ADCPARENT, 3 << 9);}static struct irqchip s3c_irq_adc = { .mask = s3c_irq_adc_mask, .unmask = s3c_irq_adc_unmask, .ack = s3c_irq_adc_ack,};/* irq demux for adc */static void s3c_irq_demux_adc(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){ unsigned int subsrc, submsk; unsigned int offset = 9; struct irqdesc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ subsrc = __raw_readl(S3C2410_SUBSRCPND); submsk = __raw_readl(S3C2410_INTSUBMSK); subsrc &= ~submsk; subsrc >>= offset; subsrc &= 3; if (subsrc != 0) { if (subsrc & 1) { mydesc = irq_desc + IRQ_TC; mydesc->handle( IRQ_TC, mydesc, regs); } if (subsrc & 2) { mydesc = irq_desc + IRQ_ADC; mydesc->handle(IRQ_ADC, mydesc, regs); } }}static void s3c_irq_demux_uart(unsigned int start, struct pt_regs *regs){ unsigned int subsrc, submsk; unsigned int offset = start - IRQ_S3CUART_RX0; struct irqdesc *desc; /* read the current pending interrupts, and the mask * for what it is available */ subsrc = __raw_readl(S3C2410_SUBSRCPND); submsk = __raw_readl(S3C2410_INTSUBMSK); irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n", start, offset, subsrc, submsk); subsrc &= ~submsk; subsrc >>= offset; subsrc &= 7; if (subsrc != 0) { desc = irq_desc + start; if (subsrc & 1) desc->handle(start, desc, regs); desc++; if (subsrc & 2) desc->handle(start+1, desc, regs); desc++; if (subsrc & 4) desc->handle(start+2, desc, regs); }}/* uart demux entry points */static voids3c_irq_demux_uart0(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){ irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX0, regs);}static voids3c_irq_demux_uart1(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){ irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX1, regs);}static voids3c_irq_demux_uart2(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){ irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);}/* s3c24xx_init_irq * * Initialise S3C2410 IRQ system*/void __init s3c24xx_init_irq(void){ unsigned long pend; unsigned long last; int irqno; int i; irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); /* first, clear all interrupts pending... */ last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_EINTPEND); if (pend == 0 || pend == last) break; __raw_writel(pend, S3C2410_EINTPEND); printk("irq: clearing pending ext status %08x\n", (int)pend); last = pend; } last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_INTPND); if (pend == 0 || pend == last) break; __raw_writel(pend, S3C2410_SRCPND); __raw_writel(pend, S3C2410_INTPND); printk("irq: clearing pending status %08x\n", (int)pend); last = pend; } last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_SUBSRCPND); if (pend == 0 || pend == last) break; printk("irq: clearing subpending status %08x\n", (int)pend); __raw_writel(pend, S3C2410_SUBSRCPND); last = pend; } /* register the main interrupts */ irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) { /* set all the s3c2410 internal irqs */ switch (irqno) { /* deal with the special IRQs (cascaded) */ case IRQ_UART0: case IRQ_UART1: case IRQ_UART2: case IRQ_LCD: case IRQ_ADCPARENT: set_irq_chip(irqno, &s3c_irq_level_chip); set_irq_handler(irqno, do_level_IRQ); break; case IRQ_RESERVED6: case IRQ_RESERVED24: /* no IRQ here */ break; default: //irqdbf("registering irq %d (s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_chip); set_irq_handler(irqno, do_edge_IRQ); set_irq_flags(irqno, IRQF_VALID); } } /* setup the cascade irq handlers */ set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); /* external interrupts */ for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { irqdbf("registering irq %d (ext int)\n", irqno); set_irq_chip(irqno, &s3c_irq_eint0t4); set_irq_handler(irqno, do_edge_IRQ); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { irqdbf("registering irq %d (extended s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irqext_chip); set_irq_handler(irqno, do_edge_IRQ); set_irq_flags(irqno, IRQF_VALID); } /* register the uart interrupts */ irqdbf("s3c2410: registering external interrupts\n"); for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart0); set_irq_handler(irqno, do_level_IRQ); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart1); set_irq_handler(irqno, do_level_IRQ); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart2); set_irq_handler(irqno, do_level_IRQ); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { irqdbf("registering irq %d (s3c adc irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_adc); set_irq_handler(irqno, do_edge_IRQ); set_irq_flags(irqno, IRQF_VALID); } irqdbf("s3c2410: registered interrupt handlers\n");}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -