1 /* arch/arm/plat-samsung/irq-uart.c
2 * originally part of arch/arm/plat-s3c64xx/irq.c
4 * Copyright 2008 Openmoko, Inc.
5 * Copyright 2008 Simtec Electronics
6 * Ben Dooks <ben@simtec.co.uk>
7 * http://armlinux.simtec.co.uk/
9 * Samsung- UART Interrupt handling
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
16 #include <linux/kernel.h>
17 #include <linux/interrupt.h>
18 #include <linux/serial_core.h>
19 #include <linux/irq.h>
22 #include <asm/mach/irq.h>
25 #include <plat/irq-uart.h>
26 #include <plat/regs-serial.h>
29 /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
30 * are consecutive when looking up the interrupt in the demux routines.
32 static void s3c_irq_demux_uart(unsigned int irq
, struct irq_desc
*desc
)
34 struct s3c_uart_irq
*uirq
= desc
->irq_data
.handler_data
;
35 struct irq_chip
*chip
= irq_get_chip(irq
);
36 u32 pend
= __raw_readl(uirq
->regs
+ S3C64XX_UINTP
);
37 int base
= uirq
->base_irq
;
39 chained_irq_enter(chip
, desc
);
42 generic_handle_irq(base
);
44 generic_handle_irq(base
+ 1);
46 generic_handle_irq(base
+ 2);
48 generic_handle_irq(base
+ 3);
50 chained_irq_exit(chip
, desc
);
53 static void __init
s3c_init_uart_irq(struct s3c_uart_irq
*uirq
)
55 void __iomem
*reg_base
= uirq
->regs
;
56 struct irq_chip_generic
*gc
;
57 struct irq_chip_type
*ct
;
59 /* mask all interrupts at the start. */
60 __raw_writel(0xf, reg_base
+ S3C64XX_UINTM
);
62 gc
= irq_alloc_generic_chip("s3c-uart", 1, uirq
->base_irq
, reg_base
,
66 pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n",
67 __func__
, uirq
->base_irq
);
72 ct
->chip
.irq_ack
= irq_gc_ack_set_bit
;
73 ct
->chip
.irq_mask
= irq_gc_mask_set_bit
;
74 ct
->chip
.irq_unmask
= irq_gc_mask_clr_bit
;
75 ct
->regs
.ack
= S3C64XX_UINTP
;
76 ct
->regs
.mask
= S3C64XX_UINTM
;
77 irq_setup_generic_chip(gc
, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE
,
78 IRQ_NOREQUEST
| IRQ_NOPROBE
, 0);
80 irq_set_handler_data(uirq
->parent_irq
, uirq
);
81 irq_set_chained_handler(uirq
->parent_irq
, s3c_irq_demux_uart
);
85 * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing
86 * @irq: The interrupt data for registering
87 * @nr_irqs: The number of interrupt descriptions in @irq.
89 * Register the UART interrupts specified by @irq including the demuxing
90 * routines. This supports the S3C6400 and newer style of devices.
92 void __init
s3c_init_uart_irqs(struct s3c_uart_irq
*irq
, unsigned int nr_irqs
)
94 for (; nr_irqs
> 0; nr_irqs
--, irq
++)
95 s3c_init_uart_irq(irq
);