xref: /linux/drivers/irqchip/irq-atmel-aic5.c (revision 3fd6c59042dbba50391e30862beac979491145fe)
1 /*
2  * Atmel AT91 AIC5 (Advanced Interrupt Controller) driver
3  *
4  *  Copyright (C) 2004 SAN People
5  *  Copyright (C) 2004 ATMEL
6  *  Copyright (C) Rick Bronson
7  *  Copyright (C) 2014 Free Electrons
8  *
9  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
10  *
11  * This file is licensed under the terms of the GNU General Public
12  * License version 2.  This program is licensed "as is" without any
13  * warranty of any kind, whether express or implied.
14  */
15 
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/mm.h>
19 #include <linux/bitmap.h>
20 #include <linux/types.h>
21 #include <linux/irq.h>
22 #include <linux/irqchip.h>
23 #include <linux/of.h>
24 #include <linux/of_address.h>
25 #include <linux/of_irq.h>
26 #include <linux/irqdomain.h>
27 #include <linux/err.h>
28 #include <linux/slab.h>
29 #include <linux/io.h>
30 
31 #include <asm/exception.h>
32 #include <asm/mach/irq.h>
33 
34 #include "irq-atmel-aic-common.h"
35 
36 /* Number of irq lines managed by AIC */
37 #define NR_AIC5_IRQS	128
38 
39 #define AT91_AIC5_SSR		0x0
40 #define AT91_AIC5_INTSEL_MSK	(0x7f << 0)
41 
42 #define AT91_AIC5_SMR			0x4
43 
44 #define AT91_AIC5_SVR			0x8
45 #define AT91_AIC5_IVR			0x10
46 #define AT91_AIC5_FVR			0x14
47 #define AT91_AIC5_ISR			0x18
48 
49 #define AT91_AIC5_IPR0			0x20
50 #define AT91_AIC5_IPR1			0x24
51 #define AT91_AIC5_IPR2			0x28
52 #define AT91_AIC5_IPR3			0x2c
53 #define AT91_AIC5_IMR			0x30
54 #define AT91_AIC5_CISR			0x34
55 
56 #define AT91_AIC5_IECR			0x40
57 #define AT91_AIC5_IDCR			0x44
58 #define AT91_AIC5_ICCR			0x48
59 #define AT91_AIC5_ISCR			0x4c
60 #define AT91_AIC5_EOICR			0x38
61 #define AT91_AIC5_SPU			0x3c
62 #define AT91_AIC5_DCR			0x6c
63 
64 #define AT91_AIC5_FFER			0x50
65 #define AT91_AIC5_FFDR			0x54
66 #define AT91_AIC5_FFSR			0x58
67 
68 static struct irq_domain *aic5_domain;
69 
aic5_handle(struct pt_regs * regs)70 static void __exception_irq_entry aic5_handle(struct pt_regs *regs)
71 {
72 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(aic5_domain, 0);
73 	u32 irqnr;
74 	u32 irqstat;
75 
76 	irqnr = irq_reg_readl(bgc, AT91_AIC5_IVR);
77 	irqstat = irq_reg_readl(bgc, AT91_AIC5_ISR);
78 
79 	if (!irqstat)
80 		irq_reg_writel(bgc, 0, AT91_AIC5_EOICR);
81 	else
82 		generic_handle_domain_irq(aic5_domain, irqnr);
83 }
84 
aic5_mask(struct irq_data * d)85 static void aic5_mask(struct irq_data *d)
86 {
87 	struct irq_domain *domain = d->domain;
88 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
89 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
90 
91 	/*
92 	 * Disable interrupt on AIC5. We always take the lock of the
93 	 * first irq chip as all chips share the same registers.
94 	 */
95 	irq_gc_lock(bgc);
96 	irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
97 	irq_reg_writel(gc, 1, AT91_AIC5_IDCR);
98 	gc->mask_cache &= ~d->mask;
99 	irq_gc_unlock(bgc);
100 }
101 
aic5_unmask(struct irq_data * d)102 static void aic5_unmask(struct irq_data *d)
103 {
104 	struct irq_domain *domain = d->domain;
105 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
106 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
107 
108 	/*
109 	 * Enable interrupt on AIC5. We always take the lock of the
110 	 * first irq chip as all chips share the same registers.
111 	 */
112 	irq_gc_lock(bgc);
113 	irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
114 	irq_reg_writel(gc, 1, AT91_AIC5_IECR);
115 	gc->mask_cache |= d->mask;
116 	irq_gc_unlock(bgc);
117 }
118 
aic5_retrigger(struct irq_data * d)119 static int aic5_retrigger(struct irq_data *d)
120 {
121 	struct irq_domain *domain = d->domain;
122 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
123 
124 	/* Enable interrupt on AIC5 */
125 	irq_gc_lock(bgc);
126 	irq_reg_writel(bgc, d->hwirq, AT91_AIC5_SSR);
127 	irq_reg_writel(bgc, 1, AT91_AIC5_ISCR);
128 	irq_gc_unlock(bgc);
129 
130 	return 1;
131 }
132 
aic5_set_type(struct irq_data * d,unsigned type)133 static int aic5_set_type(struct irq_data *d, unsigned type)
134 {
135 	struct irq_domain *domain = d->domain;
136 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
137 	unsigned int smr;
138 	int ret;
139 
140 	irq_gc_lock(bgc);
141 	irq_reg_writel(bgc, d->hwirq, AT91_AIC5_SSR);
142 	smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
143 	ret = aic_common_set_type(d, type, &smr);
144 	if (!ret)
145 		irq_reg_writel(bgc, smr, AT91_AIC5_SMR);
146 	irq_gc_unlock(bgc);
147 
148 	return ret;
149 }
150 
151 #ifdef CONFIG_PM
152 static u32 *smr_cache;
153 
aic5_suspend(struct irq_data * d)154 static void aic5_suspend(struct irq_data *d)
155 {
156 	struct irq_domain *domain = d->domain;
157 	struct irq_domain_chip_generic *dgc = domain->gc;
158 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
159 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
160 	int i;
161 	u32 mask;
162 
163 	if (smr_cache)
164 		for (i = 0; i < domain->revmap_size; i++) {
165 			irq_reg_writel(bgc, i, AT91_AIC5_SSR);
166 			smr_cache[i] = irq_reg_readl(bgc, AT91_AIC5_SMR);
167 		}
168 
169 	irq_gc_lock(bgc);
170 	for (i = 0; i < dgc->irqs_per_chip; i++) {
171 		mask = 1 << i;
172 		if ((mask & gc->mask_cache) == (mask & gc->wake_active))
173 			continue;
174 
175 		irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
176 		if (mask & gc->wake_active)
177 			irq_reg_writel(bgc, 1, AT91_AIC5_IECR);
178 		else
179 			irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
180 	}
181 	irq_gc_unlock(bgc);
182 }
183 
aic5_resume(struct irq_data * d)184 static void aic5_resume(struct irq_data *d)
185 {
186 	struct irq_domain *domain = d->domain;
187 	struct irq_domain_chip_generic *dgc = domain->gc;
188 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
189 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
190 	int i;
191 	u32 mask;
192 
193 	irq_gc_lock(bgc);
194 
195 	if (smr_cache) {
196 		irq_reg_writel(bgc, 0xffffffff, AT91_AIC5_SPU);
197 		for (i = 0; i < domain->revmap_size; i++) {
198 			irq_reg_writel(bgc, i, AT91_AIC5_SSR);
199 			irq_reg_writel(bgc, i, AT91_AIC5_SVR);
200 			irq_reg_writel(bgc, smr_cache[i], AT91_AIC5_SMR);
201 		}
202 	}
203 
204 	for (i = 0; i < dgc->irqs_per_chip; i++) {
205 		mask = 1 << i;
206 
207 		if (!smr_cache &&
208 		    ((mask & gc->mask_cache) == (mask & gc->wake_active)))
209 			continue;
210 
211 		irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
212 		if (mask & gc->mask_cache)
213 			irq_reg_writel(bgc, 1, AT91_AIC5_IECR);
214 		else
215 			irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
216 	}
217 	irq_gc_unlock(bgc);
218 }
219 
aic5_pm_shutdown(struct irq_data * d)220 static void aic5_pm_shutdown(struct irq_data *d)
221 {
222 	struct irq_domain *domain = d->domain;
223 	struct irq_domain_chip_generic *dgc = domain->gc;
224 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
225 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
226 	int i;
227 
228 	irq_gc_lock(bgc);
229 	for (i = 0; i < dgc->irqs_per_chip; i++) {
230 		irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
231 		irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
232 		irq_reg_writel(bgc, 1, AT91_AIC5_ICCR);
233 	}
234 	irq_gc_unlock(bgc);
235 }
236 #else
237 #define aic5_suspend		NULL
238 #define aic5_resume		NULL
239 #define aic5_pm_shutdown	NULL
240 #endif /* CONFIG_PM */
241 
aic5_hw_init(struct irq_domain * domain)242 static void __init aic5_hw_init(struct irq_domain *domain)
243 {
244 	struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
245 	int i;
246 
247 	/*
248 	 * Perform 8 End Of Interrupt Command to make sure AIC
249 	 * will not Lock out nIRQ
250 	 */
251 	for (i = 0; i < 8; i++)
252 		irq_reg_writel(gc, 0, AT91_AIC5_EOICR);
253 
254 	/*
255 	 * Spurious Interrupt ID in Spurious Vector Register.
256 	 * When there is no current interrupt, the IRQ Vector Register
257 	 * reads the value stored in AIC_SPU
258 	 */
259 	irq_reg_writel(gc, 0xffffffff, AT91_AIC5_SPU);
260 
261 	/* No debugging in AIC: Debug (Protect) Control Register */
262 	irq_reg_writel(gc, 0, AT91_AIC5_DCR);
263 
264 	/* Disable and clear all interrupts initially */
265 	for (i = 0; i < domain->revmap_size; i++) {
266 		irq_reg_writel(gc, i, AT91_AIC5_SSR);
267 		irq_reg_writel(gc, i, AT91_AIC5_SVR);
268 		irq_reg_writel(gc, 1, AT91_AIC5_IDCR);
269 		irq_reg_writel(gc, 1, AT91_AIC5_ICCR);
270 	}
271 }
272 
aic5_irq_domain_xlate(struct irq_domain * d,struct device_node * ctrlr,const u32 * intspec,unsigned int intsize,irq_hw_number_t * out_hwirq,unsigned int * out_type)273 static int aic5_irq_domain_xlate(struct irq_domain *d,
274 				 struct device_node *ctrlr,
275 				 const u32 *intspec, unsigned int intsize,
276 				 irq_hw_number_t *out_hwirq,
277 				 unsigned int *out_type)
278 {
279 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(d, 0);
280 	unsigned long flags;
281 	unsigned smr;
282 	int ret;
283 
284 	if (!bgc)
285 		return -EINVAL;
286 
287 	ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
288 					  out_hwirq, out_type);
289 	if (ret)
290 		return ret;
291 
292 	irq_gc_lock_irqsave(bgc, flags);
293 	irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR);
294 	smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
295 	aic_common_set_priority(intspec[2], &smr);
296 	irq_reg_writel(bgc, smr, AT91_AIC5_SMR);
297 	irq_gc_unlock_irqrestore(bgc, flags);
298 
299 	return ret;
300 }
301 
302 static const struct irq_domain_ops aic5_irq_ops = {
303 	.map	= irq_map_generic_chip,
304 	.xlate	= aic5_irq_domain_xlate,
305 };
306 
sama5d3_aic_irq_fixup(void)307 static void __init sama5d3_aic_irq_fixup(void)
308 {
309 	aic_common_rtc_irq_fixup();
310 }
311 
sam9x60_aic_irq_fixup(void)312 static void __init sam9x60_aic_irq_fixup(void)
313 {
314 	aic_common_rtc_irq_fixup();
315 	aic_common_rtt_irq_fixup();
316 }
317 
318 static const struct of_device_id aic5_irq_fixups[] __initconst = {
319 	{ .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
320 	{ .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
321 	{ .compatible = "microchip,sam9x60", .data = sam9x60_aic_irq_fixup },
322 	{ .compatible = "microchip,sam9x7", .data = sam9x60_aic_irq_fixup },
323 	{ /* sentinel */ },
324 };
325 
aic5_of_init(struct device_node * node,struct device_node * parent,int nirqs)326 static int __init aic5_of_init(struct device_node *node,
327 			       struct device_node *parent,
328 			       int nirqs)
329 {
330 	struct irq_chip_generic *gc;
331 	struct irq_domain *domain;
332 	int nchips;
333 	int i;
334 
335 	if (nirqs > NR_AIC5_IRQS)
336 		return -EINVAL;
337 
338 	if (aic5_domain)
339 		return -EEXIST;
340 
341 	domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
342 				    nirqs, aic5_irq_fixups);
343 	if (IS_ERR(domain))
344 		return PTR_ERR(domain);
345 
346 	aic5_domain = domain;
347 	nchips = aic5_domain->revmap_size / 32;
348 	for (i = 0; i < nchips; i++) {
349 		gc = irq_get_domain_generic_chip(domain, i * 32);
350 
351 		gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
352 		gc->chip_types[0].chip.irq_mask = aic5_mask;
353 		gc->chip_types[0].chip.irq_unmask = aic5_unmask;
354 		gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
355 		gc->chip_types[0].chip.irq_set_type = aic5_set_type;
356 		gc->chip_types[0].chip.irq_suspend = aic5_suspend;
357 		gc->chip_types[0].chip.irq_resume = aic5_resume;
358 		gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
359 	}
360 
361 	aic5_hw_init(domain);
362 	set_handle_irq(aic5_handle);
363 
364 	return 0;
365 }
366 
367 #define NR_SAMA5D2_IRQS		77
368 
sama5d2_aic5_of_init(struct device_node * node,struct device_node * parent)369 static int __init sama5d2_aic5_of_init(struct device_node *node,
370 				       struct device_node *parent)
371 {
372 #ifdef CONFIG_PM
373 	smr_cache = kcalloc(DIV_ROUND_UP(NR_SAMA5D2_IRQS, 32) * 32,
374 			    sizeof(*smr_cache), GFP_KERNEL);
375 	if (!smr_cache)
376 		return -ENOMEM;
377 #endif
378 
379 	return aic5_of_init(node, parent, NR_SAMA5D2_IRQS);
380 }
381 IRQCHIP_DECLARE(sama5d2_aic5, "atmel,sama5d2-aic", sama5d2_aic5_of_init);
382 
383 #define NR_SAMA5D3_IRQS		48
384 
sama5d3_aic5_of_init(struct device_node * node,struct device_node * parent)385 static int __init sama5d3_aic5_of_init(struct device_node *node,
386 				       struct device_node *parent)
387 {
388 	return aic5_of_init(node, parent, NR_SAMA5D3_IRQS);
389 }
390 IRQCHIP_DECLARE(sama5d3_aic5, "atmel,sama5d3-aic", sama5d3_aic5_of_init);
391 
392 #define NR_SAMA5D4_IRQS		68
393 
sama5d4_aic5_of_init(struct device_node * node,struct device_node * parent)394 static int __init sama5d4_aic5_of_init(struct device_node *node,
395 				       struct device_node *parent)
396 {
397 	return aic5_of_init(node, parent, NR_SAMA5D4_IRQS);
398 }
399 IRQCHIP_DECLARE(sama5d4_aic5, "atmel,sama5d4-aic", sama5d4_aic5_of_init);
400 
401 #define NR_SAM9X60_IRQS		50
402 
sam9x60_aic5_of_init(struct device_node * node,struct device_node * parent)403 static int __init sam9x60_aic5_of_init(struct device_node *node,
404 				       struct device_node *parent)
405 {
406 	return aic5_of_init(node, parent, NR_SAM9X60_IRQS);
407 }
408 IRQCHIP_DECLARE(sam9x60_aic5, "microchip,sam9x60-aic", sam9x60_aic5_of_init);
409 
410 #define NR_SAM9X7_IRQS		70
411 
sam9x7_aic5_of_init(struct device_node * node,struct device_node * parent)412 static int __init sam9x7_aic5_of_init(struct device_node *node, struct device_node *parent)
413 {
414 	return aic5_of_init(node, parent, NR_SAM9X7_IRQS);
415 }
416 IRQCHIP_DECLARE(sam9x7_aic5, "microchip,sam9x7-aic", sam9x7_aic5_of_init);
417