diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/plat-samsung/irq-uart.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/plat-samsung/irq-uart.c')
-rw-r--r-- | arch/arm/plat-samsung/irq-uart.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c new file mode 100644 index 00000000000..3014c7226bd --- /dev/null +++ b/arch/arm/plat-samsung/irq-uart.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* arch/arm/plat-samsung/irq-uart.c | ||
2 | * originally part of arch/arm/plat-s3c64xx/irq.c | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * Samsung- UART Interrupt handling | ||
10 | * | ||
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. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/serial_core.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <asm/mach/irq.h> | ||
23 | |||
24 | #include <mach/map.h> | ||
25 | #include <plat/irq-uart.h> | ||
26 | #include <plat/regs-serial.h> | ||
27 | #include <plat/cpu.h> | ||
28 | |||
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. | ||
31 | */ | ||
32 | static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) | ||
33 | { | ||
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; | ||
38 | |||
39 | chained_irq_enter(chip, desc); | ||
40 | |||
41 | if (pend & (1 << 0)) | ||
42 | generic_handle_irq(base); | ||
43 | if (pend & (1 << 1)) | ||
44 | generic_handle_irq(base + 1); | ||
45 | if (pend & (1 << 2)) | ||
46 | generic_handle_irq(base + 2); | ||
47 | if (pend & (1 << 3)) | ||
48 | generic_handle_irq(base + 3); | ||
49 | |||
50 | chained_irq_exit(chip, desc); | ||
51 | } | ||
52 | |||
53 | static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) | ||
54 | { | ||
55 | void __iomem *reg_base = uirq->regs; | ||
56 | struct irq_chip_generic *gc; | ||
57 | struct irq_chip_type *ct; | ||
58 | |||
59 | /* mask all interrupts at the start. */ | ||
60 | __raw_writel(0xf, reg_base + S3C64XX_UINTM); | ||
61 | |||
62 | gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base, | ||
63 | handle_level_irq); | ||
64 | |||
65 | if (!gc) { | ||
66 | pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", | ||
67 | __func__, uirq->base_irq); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | ct = gc->chip_types; | ||
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); | ||
79 | |||
80 | irq_set_handler_data(uirq->parent_irq, uirq); | ||
81 | irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); | ||
82 | } | ||
83 | |||
84 | /** | ||
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. | ||
88 | * | ||
89 | * Register the UART interrupts specified by @irq including the demuxing | ||
90 | * routines. This supports the S3C6400 and newer style of devices. | ||
91 | */ | ||
92 | void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs) | ||
93 | { | ||
94 | for (; nr_irqs > 0; nr_irqs--, irq++) | ||
95 | s3c_init_uart_irq(irq); | ||
96 | } | ||