1 /*
2  * linux/arch/arm/mach-omap2/irq.c
3  *
4  * Interrupt handler for OMAP2 boards.
5  *
6  * Copyright (C) 2005 Nokia Corporation
7  * Author: Paul Mundt <paul.mundt@nokia.com>
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License. See the file "COPYING" in the main directory of this archive
11  * for more details.
12  */
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
17 #include <linux/io.h>
18 
19 #include <asm/exception.h>
20 #include <linux/irqdomain.h>
21 #include <linux/of.h>
22 #include <linux/of_address.h>
23 #include <linux/of_irq.h>
24 
25 #include "irqchip.h"
26 
27 /* Define these here for now until we drop all board-files */
28 #define OMAP24XX_IC_BASE	0x480fe000
29 #define OMAP34XX_IC_BASE	0x48200000
30 
31 /* selected INTC register offsets */
32 
33 #define INTC_REVISION		0x0000
34 #define INTC_SYSCONFIG		0x0010
35 #define INTC_SYSSTATUS		0x0014
36 #define INTC_SIR		0x0040
37 #define INTC_CONTROL		0x0048
38 #define INTC_PROTECTION		0x004C
39 #define INTC_IDLE		0x0050
40 #define INTC_THRESHOLD		0x0068
41 #define INTC_MIR0		0x0084
42 #define INTC_MIR_CLEAR0		0x0088
43 #define INTC_MIR_SET0		0x008c
44 #define INTC_PENDING_IRQ0	0x0098
45 #define INTC_PENDING_IRQ1	0x00b8
46 #define INTC_PENDING_IRQ2	0x00d8
47 #define INTC_PENDING_IRQ3	0x00f8
48 #define INTC_ILR0		0x0100
49 
50 #define ACTIVEIRQ_MASK		0x7f	/* omap2/3 active interrupt bits */
51 #define INTCPS_NR_ILR_REGS	128
52 #define INTCPS_NR_MIR_REGS	3
53 
54 #define INTC_IDLE_FUNCIDLE	(1 << 0)
55 #define INTC_IDLE_TURBO		(1 << 1)
56 
57 #define INTC_PROTECTION_ENABLE	(1 << 0)
58 
59 /*
60  * OMAP2 has a number of different interrupt controllers, each interrupt
61  * controller is identified as its own "bank". Register definitions are
62  * fairly consistent for each bank, but not all registers are implemented
63  * for each bank.. when in doubt, consult the TRM.
64  */
65 
66 /* Structure to save interrupt controller context */
67 struct omap_intc_regs {
68 	u32 sysconfig;
69 	u32 protection;
70 	u32 idle;
71 	u32 threshold;
72 	u32 ilr[INTCPS_NR_ILR_REGS];
73 	u32 mir[INTCPS_NR_MIR_REGS];
74 };
75 static struct omap_intc_regs intc_context;
76 
77 static struct irq_domain *domain;
78 static void __iomem *omap_irq_base;
79 static int omap_nr_pending = 3;
80 static int omap_nr_irqs = 96;
81 
82 /* INTC bank register get/set */
83 static void intc_writel(u32 reg, u32 val)
84 {
85 	writel_relaxed(val, omap_irq_base + reg);
86 }
87 
88 static u32 intc_readl(u32 reg)
89 {
90 	return readl_relaxed(omap_irq_base + reg);
91 }
92 
93 void omap_intc_save_context(void)
94 {
95 	int i;
96 
97 	intc_context.sysconfig =
98 		intc_readl(INTC_SYSCONFIG);
99 	intc_context.protection =
100 		intc_readl(INTC_PROTECTION);
101 	intc_context.idle =
102 		intc_readl(INTC_IDLE);
103 	intc_context.threshold =
104 		intc_readl(INTC_THRESHOLD);
105 
106 	for (i = 0; i < omap_nr_irqs; i++)
107 		intc_context.ilr[i] =
108 			intc_readl((INTC_ILR0 + 0x4 * i));
109 	for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
110 		intc_context.mir[i] =
111 			intc_readl(INTC_MIR0 + (0x20 * i));
112 }
113 
114 void omap_intc_restore_context(void)
115 {
116 	int i;
117 
118 	intc_writel(INTC_SYSCONFIG, intc_context.sysconfig);
119 	intc_writel(INTC_PROTECTION, intc_context.protection);
120 	intc_writel(INTC_IDLE, intc_context.idle);
121 	intc_writel(INTC_THRESHOLD, intc_context.threshold);
122 
123 	for (i = 0; i < omap_nr_irqs; i++)
124 		intc_writel(INTC_ILR0 + 0x4 * i,
125 				intc_context.ilr[i]);
126 
127 	for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
128 		intc_writel(INTC_MIR0 + 0x20 * i,
129 			intc_context.mir[i]);
130 	/* MIRs are saved and restore with other PRCM registers */
131 }
132 
133 void omap3_intc_prepare_idle(void)
134 {
135 	/*
136 	 * Disable autoidle as it can stall interrupt controller,
137 	 * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
138 	 */
139 	intc_writel(INTC_SYSCONFIG, 0);
140 	intc_writel(INTC_IDLE, INTC_IDLE_TURBO);
141 }
142 
143 void omap3_intc_resume_idle(void)
144 {
145 	/* Re-enable autoidle */
146 	intc_writel(INTC_SYSCONFIG, 1);
147 	intc_writel(INTC_IDLE, 0);
148 }
149 
150 /* XXX: FIQ and additional INTC support (only MPU at the moment) */
151 static void omap_ack_irq(struct irq_data *d)
152 {
153 	intc_writel(INTC_CONTROL, 0x1);
154 }
155 
156 static void omap_mask_ack_irq(struct irq_data *d)
157 {
158 	irq_gc_mask_disable_reg(d);
159 	omap_ack_irq(d);
160 }
161 
162 static void __init omap_irq_soft_reset(void)
163 {
164 	unsigned long tmp;
165 
166 	tmp = intc_readl(INTC_REVISION) & 0xff;
167 
168 	pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n",
169 		omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs);
170 
171 	tmp = intc_readl(INTC_SYSCONFIG);
172 	tmp |= 1 << 1;	/* soft reset */
173 	intc_writel(INTC_SYSCONFIG, tmp);
174 
175 	while (!(intc_readl(INTC_SYSSTATUS) & 0x1))
176 		/* Wait for reset to complete */;
177 
178 	/* Enable autoidle */
179 	intc_writel(INTC_SYSCONFIG, 1 << 0);
180 }
181 
182 int omap_irq_pending(void)
183 {
184 	int i;
185 
186 	for (i = 0; i < omap_nr_pending; i++)
187 		if (intc_readl(INTC_PENDING_IRQ0 + (0x20 * i)))
188 			return 1;
189 	return 0;
190 }
191 
192 void omap3_intc_suspend(void)
193 {
194 	/* A pending interrupt would prevent OMAP from entering suspend */
195 	omap_ack_irq(NULL);
196 }
197 
198 static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base)
199 {
200 	int ret;
201 	int i;
202 
203 	ret = irq_alloc_domain_generic_chips(d, 32, 1, "INTC",
204 			handle_level_irq, IRQ_NOREQUEST | IRQ_NOPROBE,
205 			IRQ_LEVEL, 0);
206 	if (ret) {
207 		pr_warn("Failed to allocate irq chips\n");
208 		return ret;
209 	}
210 
211 	for (i = 0; i < omap_nr_pending; i++) {
212 		struct irq_chip_generic *gc;
213 		struct irq_chip_type *ct;
214 
215 		gc = irq_get_domain_generic_chip(d, 32 * i);
216 		gc->reg_base = base;
217 		ct = gc->chip_types;
218 
219 		ct->type = IRQ_TYPE_LEVEL_MASK;
220 		ct->handler = handle_level_irq;
221 
222 		ct->chip.irq_ack = omap_mask_ack_irq;
223 		ct->chip.irq_mask = irq_gc_mask_disable_reg;
224 		ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
225 
226 		ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
227 
228 		ct->regs.enable = INTC_MIR_CLEAR0 + 32 * i;
229 		ct->regs.disable = INTC_MIR_SET0 + 32 * i;
230 	}
231 
232 	return 0;
233 }
234 
235 static void __init omap_alloc_gc_legacy(void __iomem *base,
236 		unsigned int irq_start, unsigned int num)
237 {
238 	struct irq_chip_generic *gc;
239 	struct irq_chip_type *ct;
240 
241 	gc = irq_alloc_generic_chip("INTC", 1, irq_start, base,
242 			handle_level_irq);
243 	ct = gc->chip_types;
244 	ct->chip.irq_ack = omap_mask_ack_irq;
245 	ct->chip.irq_mask = irq_gc_mask_disable_reg;
246 	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
247 	ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
248 
249 	ct->regs.enable = INTC_MIR_CLEAR0;
250 	ct->regs.disable = INTC_MIR_SET0;
251 	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
252 			IRQ_NOREQUEST | IRQ_NOPROBE, 0);
253 }
254 
255 static int __init omap_init_irq_of(struct device_node *node)
256 {
257 	int ret;
258 
259 	omap_irq_base = of_iomap(node, 0);
260 	if (WARN_ON(!omap_irq_base))
261 		return -ENOMEM;
262 
263 	domain = irq_domain_add_linear(node, omap_nr_irqs,
264 			&irq_generic_chip_ops, NULL);
265 
266 	omap_irq_soft_reset();
267 
268 	ret = omap_alloc_gc_of(domain, omap_irq_base);
269 	if (ret < 0)
270 		irq_domain_remove(domain);
271 
272 	return ret;
273 }
274 
275 static int __init omap_init_irq_legacy(u32 base)
276 {
277 	int j, irq_base;
278 
279 	omap_irq_base = ioremap(base, SZ_4K);
280 	if (WARN_ON(!omap_irq_base))
281 		return -ENOMEM;
282 
283 	irq_base = irq_alloc_descs(-1, 0, omap_nr_irqs, 0);
284 	if (irq_base < 0) {
285 		pr_warn("Couldn't allocate IRQ numbers\n");
286 		irq_base = 0;
287 	}
288 
289 	domain = irq_domain_add_legacy(NULL, omap_nr_irqs, irq_base, 0,
290 			&irq_domain_simple_ops, NULL);
291 
292 	omap_irq_soft_reset();
293 
294 	for (j = 0; j < omap_nr_irqs; j += 32)
295 		omap_alloc_gc_legacy(omap_irq_base + j, j + irq_base, 32);
296 
297 	return 0;
298 }
299 
300 static void __init omap_irq_enable_protection(void)
301 {
302 	u32 reg;
303 
304 	reg = intc_readl(INTC_PROTECTION);
305 	reg |= INTC_PROTECTION_ENABLE;
306 	intc_writel(INTC_PROTECTION, reg);
307 }
308 
309 static int __init omap_init_irq(u32 base, struct device_node *node)
310 {
311 	int ret;
312 
313 	if (node)
314 		ret = omap_init_irq_of(node);
315 	else
316 		ret = omap_init_irq_legacy(base);
317 
318 	if (ret == 0)
319 		omap_irq_enable_protection();
320 
321 	return ret;
322 }
323 
324 static asmlinkage void __exception_irq_entry
325 omap_intc_handle_irq(struct pt_regs *regs)
326 {
327 	u32 irqnr = 0;
328 	int handled_irq = 0;
329 	int i;
330 
331 	do {
332 		for (i = 0; i < omap_nr_pending; i++) {
333 			irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i));
334 			if (irqnr)
335 				goto out;
336 		}
337 
338 out:
339 		if (!irqnr)
340 			break;
341 
342 		irqnr = intc_readl(INTC_SIR);
343 		irqnr &= ACTIVEIRQ_MASK;
344 
345 		if (irqnr) {
346 			irqnr = irq_find_mapping(domain, irqnr);
347 			handle_IRQ(irqnr, regs);
348 			handled_irq = 1;
349 		}
350 	} while (irqnr);
351 
352 	/*
353 	 * If an irq is masked or deasserted while active, we will
354 	 * keep ending up here with no irq handled. So remove it from
355 	 * the INTC with an ack.
356 	 */
357 	if (!handled_irq)
358 		omap_ack_irq(NULL);
359 }
360 
361 void __init omap2_init_irq(void)
362 {
363 	omap_nr_irqs = 96;
364 	omap_nr_pending = 3;
365 	omap_init_irq(OMAP24XX_IC_BASE, NULL);
366 	set_handle_irq(omap_intc_handle_irq);
367 }
368 
369 void __init omap3_init_irq(void)
370 {
371 	omap_nr_irqs = 96;
372 	omap_nr_pending = 3;
373 	omap_init_irq(OMAP34XX_IC_BASE, NULL);
374 	set_handle_irq(omap_intc_handle_irq);
375 }
376 
377 void __init ti81xx_init_irq(void)
378 {
379 	omap_nr_irqs = 96;
380 	omap_nr_pending = 4;
381 	omap_init_irq(OMAP34XX_IC_BASE, NULL);
382 	set_handle_irq(omap_intc_handle_irq);
383 }
384 
385 static int __init intc_of_init(struct device_node *node,
386 			     struct device_node *parent)
387 {
388 	int ret;
389 
390 	omap_nr_pending = 3;
391 	omap_nr_irqs = 96;
392 
393 	if (WARN_ON(!node))
394 		return -ENODEV;
395 
396 	if (of_device_is_compatible(node, "ti,am33xx-intc")) {
397 		omap_nr_irqs = 128;
398 		omap_nr_pending = 4;
399 	}
400 
401 	ret = omap_init_irq(-1, of_node_get(node));
402 	if (ret < 0)
403 		return ret;
404 
405 	set_handle_irq(omap_intc_handle_irq);
406 
407 	return 0;
408 }
409 
410 IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init);
411 IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init);
412 IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init);
413