#define S3C2410_CPUIRQ_OFFSET (16) #define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET) #define IRQ_UART0 S3C2410_IRQ(28) /* 44 */ #define S3C2410_IRQSUB(x) S3C2410_IRQ((x)+54) #define IRQ_S3CUART_RX0 S3C2410_IRQSUB(0) /* 70 */ #define IRQ_S3CUART_TX0 S3C2410_IRQSUB(1) #define IRQ_S3CUART_ERR0 S3C2410_IRQSUB(2) void __init s3c24xx_init_irq(void) { set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); } /* uart demux entry points */ static void s3c_irq_demux_uart0(unsigned int irq, struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX0); } static void s3c_irq_demux_uart(unsigned int start) { unsigned int subsrc, submsk; unsigned int offset = start - IRQ_S3CUART_RX0; /* 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) { if (subsrc & 1) //重新计算子中断号 generic_handle_irq(start); //generic_handle_irq调用注册的回调 if (subsrc & 2) generic_handle_irq(start+1); if (subsrc & 4) generic_handle_irq(start+2); } } //下面是驱动函数中的代码 //注册两个子中断 static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { [0] = { .port = { .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), .iotype = UPIO_MEM, .irq = IRQ_S3CUART_RX0, .uartclk = 0, .fifosize = 16, .ops = &s3c24xx_serial_ops, .flags = UPF_BOOT_AUTOCONF, .line = 0, } }, } /* s3c24xx_serial_init_port * * initialise a single serial port from the platform device given */ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, struct s3c24xx_uart_info *info, struct platform_device *platdev) { struct uart_port *port = &ourport->port; struct s3c2410_uartcfg *cfg; struct resource *res; int ret; port->mapbase = res->start; port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); ret = platform_get_irq(platdev, 0); if (ret < 0) port->irq = 0; else { port->irq = ret; ourport->rx_irq = ret; ourport->tx_irq = ret + 1; } return 0; } static int s3c24xx_serial_startup(struct uart_port *port) { struct s3c24xx_uart_port *ourport = to_ourport(port); int ret; ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0, s3c24xx_serial_portname(port), ourport); ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0, s3c24xx_serial_portname(port), ourport); /* the port reset code should have done the correct * register setup for the port controls */ if (port->line == 2) { s3c2410_gpio_cfgpin(S3C2410_GPH(6), S3C2410_GPH6_TXD2); s3c2410_gpio_pullup(S3C2410_GPH(6), 1); s3c2410_gpio_cfgpin(S3C2410_GPH(7), S3C2410_GPH7_RXD2); s3c2410_gpio_pullup(S3C2410_GPH(7), 1); } return ret; }
Mini2440 串口子中断程序
最新推荐文章于 2014-10-09 23:27:00 发布