Commit | Line | Data |
---|---|---|
7c6337e2 KH |
1 | /* |
2 | * Interrupt handler for DaVinci boards. | |
3 | * | |
4 | * Copyright (C) 2006 Texas Instruments. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | * | |
20 | */ | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/init.h> | |
23 | #include <linux/interrupt.h> | |
24 | #include <linux/irq.h> | |
fced80c7 | 25 | #include <linux/io.h> |
7c6337e2 | 26 | |
a09e64fb | 27 | #include <mach/hardware.h> |
9e16469c | 28 | #include <mach/cputype.h> |
673dd36f | 29 | #include <mach/common.h> |
7c6337e2 KH |
30 | #include <asm/mach/irq.h> |
31 | ||
7c6337e2 KH |
32 | #define FIQ_REG0_OFFSET 0x0000 |
33 | #define FIQ_REG1_OFFSET 0x0004 | |
34 | #define IRQ_REG0_OFFSET 0x0008 | |
35 | #define IRQ_REG1_OFFSET 0x000C | |
36 | #define IRQ_ENT_REG0_OFFSET 0x0018 | |
37 | #define IRQ_ENT_REG1_OFFSET 0x001C | |
38 | #define IRQ_INCTL_REG_OFFSET 0x0020 | |
39 | #define IRQ_EABASE_REG_OFFSET 0x0024 | |
40 | #define IRQ_INTPRI0_REG_OFFSET 0x0030 | |
41 | #define IRQ_INTPRI7_REG_OFFSET 0x004C | |
42 | ||
7c6337e2 KH |
43 | static inline void davinci_irq_writel(unsigned long value, int offset) |
44 | { | |
673dd36f | 45 | __raw_writel(value, davinci_intc_base + offset); |
7c6337e2 KH |
46 | } |
47 | ||
aac4dd1d TG |
48 | static __init void |
49 | davinci_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | |
7c6337e2 | 50 | { |
aac4dd1d TG |
51 | struct irq_chip_generic *gc; |
52 | struct irq_chip_type *ct; | |
53 | ||
54 | gc = irq_alloc_generic_chip("AINTC", 1, irq_start, base, handle_edge_irq); | |
33e1e5e3 TP |
55 | if (!gc) { |
56 | pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", | |
57 | __func__, irq_start); | |
58 | return; | |
59 | } | |
60 | ||
aac4dd1d | 61 | ct = gc->chip_types; |
659fb32d | 62 | ct->chip.irq_ack = irq_gc_ack_set_bit; |
aac4dd1d TG |
63 | ct->chip.irq_mask = irq_gc_mask_clr_bit; |
64 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | |
65 | ||
66 | ct->regs.ack = IRQ_REG0_OFFSET; | |
67 | ct->regs.mask = IRQ_ENT_REG0_OFFSET; | |
68 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | |
69 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | |
7c6337e2 KH |
70 | } |
71 | ||
7c6337e2 KH |
72 | /* ARM Interrupt Controller Initialization */ |
73 | void __init davinci_irq_init(void) | |
74 | { | |
aac4dd1d | 75 | unsigned i, j; |
673dd36f | 76 | const u8 *davinci_def_priorities = davinci_soc_info.intc_irq_prios; |
7c6337e2 | 77 | |
bd808947 CC |
78 | davinci_intc_type = DAVINCI_INTC_TYPE_AINTC; |
79 | davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_4K); | |
80 | if (WARN_ON(!davinci_intc_base)) | |
81 | return; | |
82 | ||
7c6337e2 KH |
83 | /* Clear all interrupt requests */ |
84 | davinci_irq_writel(~0x0, FIQ_REG0_OFFSET); | |
85 | davinci_irq_writel(~0x0, FIQ_REG1_OFFSET); | |
86 | davinci_irq_writel(~0x0, IRQ_REG0_OFFSET); | |
87 | davinci_irq_writel(~0x0, IRQ_REG1_OFFSET); | |
88 | ||
89 | /* Disable all interrupts */ | |
90 | davinci_irq_writel(0x0, IRQ_ENT_REG0_OFFSET); | |
91 | davinci_irq_writel(0x0, IRQ_ENT_REG1_OFFSET); | |
92 | ||
93 | /* Interrupts disabled immediately, IRQ entry reflects all */ | |
94 | davinci_irq_writel(0x0, IRQ_INCTL_REG_OFFSET); | |
95 | ||
96 | /* we don't use the hardware vector table, just its entry addresses */ | |
97 | davinci_irq_writel(0, IRQ_EABASE_REG_OFFSET); | |
98 | ||
99 | /* Clear all interrupt requests */ | |
100 | davinci_irq_writel(~0x0, FIQ_REG0_OFFSET); | |
101 | davinci_irq_writel(~0x0, FIQ_REG1_OFFSET); | |
102 | davinci_irq_writel(~0x0, IRQ_REG0_OFFSET); | |
103 | davinci_irq_writel(~0x0, IRQ_REG1_OFFSET); | |
104 | ||
105 | for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) { | |
7c6337e2 KH |
106 | u32 pri; |
107 | ||
9e16469c SR |
108 | for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++) |
109 | pri |= (*davinci_def_priorities & 0x07) << j; | |
7c6337e2 KH |
110 | davinci_irq_writel(pri, i); |
111 | } | |
112 | ||
aac4dd1d TG |
113 | for (i = 0, j = 0; i < davinci_soc_info.intc_irq_num; i += 32, j += 0x04) |
114 | davinci_alloc_gc(davinci_intc_base + j, i, 32); | |
115 | ||
116 | irq_set_handler(IRQ_TINT1_TINT34, handle_level_irq); | |
7c6337e2 | 117 | } |