]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/irqchip/irq-atmel-aic5.c
Merge tag 'mfd-fixes-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
[karo-tx-linux.git] / drivers / irqchip / irq-atmel-aic5.c
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
70 static asmlinkage void __exception_irq_entry
71 aic5_handle(struct pt_regs *regs)
72 {
73         struct irq_domain_chip_generic *dgc = aic5_domain->gc;
74         struct irq_chip_generic *gc = dgc->gc[0];
75         u32 irqnr;
76         u32 irqstat;
77
78         irqnr = irq_reg_readl(gc, AT91_AIC5_IVR);
79         irqstat = irq_reg_readl(gc, AT91_AIC5_ISR);
80
81         if (!irqstat)
82                 irq_reg_writel(gc, 0, AT91_AIC5_EOICR);
83         else
84                 handle_domain_irq(aic5_domain, irqnr, regs);
85 }
86
87 static void aic5_mask(struct irq_data *d)
88 {
89         struct irq_domain *domain = d->domain;
90         struct irq_domain_chip_generic *dgc = domain->gc;
91         struct irq_chip_generic *bgc = dgc->gc[0];
92         struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
93
94         /*
95          * Disable interrupt on AIC5. We always take the lock of the
96          * first irq chip as all chips share the same registers.
97          */
98         irq_gc_lock(bgc);
99         irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
100         irq_reg_writel(gc, 1, AT91_AIC5_IDCR);
101         gc->mask_cache &= ~d->mask;
102         irq_gc_unlock(bgc);
103 }
104
105 static void aic5_unmask(struct irq_data *d)
106 {
107         struct irq_domain *domain = d->domain;
108         struct irq_domain_chip_generic *dgc = domain->gc;
109         struct irq_chip_generic *bgc = dgc->gc[0];
110         struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
111
112         /*
113          * Enable interrupt on AIC5. We always take the lock of the
114          * first irq chip as all chips share the same registers.
115          */
116         irq_gc_lock(bgc);
117         irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
118         irq_reg_writel(gc, 1, AT91_AIC5_IECR);
119         gc->mask_cache |= d->mask;
120         irq_gc_unlock(bgc);
121 }
122
123 static int aic5_retrigger(struct irq_data *d)
124 {
125         struct irq_domain *domain = d->domain;
126         struct irq_domain_chip_generic *dgc = domain->gc;
127         struct irq_chip_generic *gc = dgc->gc[0];
128
129         /* Enable interrupt on AIC5 */
130         irq_gc_lock(gc);
131         irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
132         irq_reg_writel(gc, 1, AT91_AIC5_ISCR);
133         irq_gc_unlock(gc);
134
135         return 0;
136 }
137
138 static int aic5_set_type(struct irq_data *d, unsigned type)
139 {
140         struct irq_domain *domain = d->domain;
141         struct irq_domain_chip_generic *dgc = domain->gc;
142         struct irq_chip_generic *gc = dgc->gc[0];
143         unsigned int smr;
144         int ret;
145
146         irq_gc_lock(gc);
147         irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
148         smr = irq_reg_readl(gc, AT91_AIC5_SMR);
149         ret = aic_common_set_type(d, type, &smr);
150         if (!ret)
151                 irq_reg_writel(gc, smr, AT91_AIC5_SMR);
152         irq_gc_unlock(gc);
153
154         return ret;
155 }
156
157 #ifdef CONFIG_PM
158 static void aic5_suspend(struct irq_data *d)
159 {
160         struct irq_domain *domain = d->domain;
161         struct irq_domain_chip_generic *dgc = domain->gc;
162         struct irq_chip_generic *bgc = dgc->gc[0];
163         struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
164         int i;
165         u32 mask;
166
167         irq_gc_lock(bgc);
168         for (i = 0; i < dgc->irqs_per_chip; i++) {
169                 mask = 1 << i;
170                 if ((mask & gc->mask_cache) == (mask & gc->wake_active))
171                         continue;
172
173                 irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
174                 if (mask & gc->wake_active)
175                         irq_reg_writel(bgc, 1, AT91_AIC5_IECR);
176                 else
177                         irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
178         }
179         irq_gc_unlock(bgc);
180 }
181
182 static void aic5_resume(struct irq_data *d)
183 {
184         struct irq_domain *domain = d->domain;
185         struct irq_domain_chip_generic *dgc = domain->gc;
186         struct irq_chip_generic *bgc = dgc->gc[0];
187         struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
188         int i;
189         u32 mask;
190
191         irq_gc_lock(bgc);
192         for (i = 0; i < dgc->irqs_per_chip; i++) {
193                 mask = 1 << i;
194                 if ((mask & gc->mask_cache) == (mask & gc->wake_active))
195                         continue;
196
197                 irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
198                 if (mask & gc->mask_cache)
199                         irq_reg_writel(bgc, 1, AT91_AIC5_IECR);
200                 else
201                         irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
202         }
203         irq_gc_unlock(bgc);
204 }
205
206 static void aic5_pm_shutdown(struct irq_data *d)
207 {
208         struct irq_domain *domain = d->domain;
209         struct irq_domain_chip_generic *dgc = domain->gc;
210         struct irq_chip_generic *bgc = dgc->gc[0];
211         struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
212         int i;
213
214         irq_gc_lock(bgc);
215         for (i = 0; i < dgc->irqs_per_chip; i++) {
216                 irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
217                 irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
218                 irq_reg_writel(bgc, 1, AT91_AIC5_ICCR);
219         }
220         irq_gc_unlock(bgc);
221 }
222 #else
223 #define aic5_suspend            NULL
224 #define aic5_resume             NULL
225 #define aic5_pm_shutdown        NULL
226 #endif /* CONFIG_PM */
227
228 static void __init aic5_hw_init(struct irq_domain *domain)
229 {
230         struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
231         int i;
232
233         /*
234          * Perform 8 End Of Interrupt Command to make sure AIC
235          * will not Lock out nIRQ
236          */
237         for (i = 0; i < 8; i++)
238                 irq_reg_writel(gc, 0, AT91_AIC5_EOICR);
239
240         /*
241          * Spurious Interrupt ID in Spurious Vector Register.
242          * When there is no current interrupt, the IRQ Vector Register
243          * reads the value stored in AIC_SPU
244          */
245         irq_reg_writel(gc, 0xffffffff, AT91_AIC5_SPU);
246
247         /* No debugging in AIC: Debug (Protect) Control Register */
248         irq_reg_writel(gc, 0, AT91_AIC5_DCR);
249
250         /* Disable and clear all interrupts initially */
251         for (i = 0; i < domain->revmap_size; i++) {
252                 irq_reg_writel(gc, i, AT91_AIC5_SSR);
253                 irq_reg_writel(gc, i, AT91_AIC5_SVR);
254                 irq_reg_writel(gc, 1, AT91_AIC5_IDCR);
255                 irq_reg_writel(gc, 1, AT91_AIC5_ICCR);
256         }
257 }
258
259 static int aic5_irq_domain_xlate(struct irq_domain *d,
260                                  struct device_node *ctrlr,
261                                  const u32 *intspec, unsigned int intsize,
262                                  irq_hw_number_t *out_hwirq,
263                                  unsigned int *out_type)
264 {
265         struct irq_domain_chip_generic *dgc = d->gc;
266         struct irq_chip_generic *gc;
267         unsigned smr;
268         int ret;
269
270         if (!dgc)
271                 return -EINVAL;
272
273         ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
274                                           out_hwirq, out_type);
275         if (ret)
276                 return ret;
277
278         gc = dgc->gc[0];
279
280         irq_gc_lock(gc);
281         irq_reg_writel(gc, *out_hwirq, AT91_AIC5_SSR);
282         smr = irq_reg_readl(gc, AT91_AIC5_SMR);
283         ret = aic_common_set_priority(intspec[2], &smr);
284         if (!ret)
285                 irq_reg_writel(gc, intspec[2] | smr, AT91_AIC5_SMR);
286         irq_gc_unlock(gc);
287
288         return ret;
289 }
290
291 static const struct irq_domain_ops aic5_irq_ops = {
292         .map    = irq_map_generic_chip,
293         .xlate  = aic5_irq_domain_xlate,
294 };
295
296 static void __init sama5d3_aic_irq_fixup(struct device_node *root)
297 {
298         aic_common_rtc_irq_fixup(root);
299 }
300
301 static const struct of_device_id aic5_irq_fixups[] __initconst = {
302         { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
303         { .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
304         { /* sentinel */ },
305 };
306
307 static int __init aic5_of_init(struct device_node *node,
308                                struct device_node *parent,
309                                int nirqs)
310 {
311         struct irq_chip_generic *gc;
312         struct irq_domain *domain;
313         int nchips;
314         int i;
315
316         if (nirqs > NR_AIC5_IRQS)
317                 return -EINVAL;
318
319         if (aic5_domain)
320                 return -EEXIST;
321
322         domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
323                                     nirqs);
324         if (IS_ERR(domain))
325                 return PTR_ERR(domain);
326
327         aic_common_irq_fixup(aic5_irq_fixups);
328
329         aic5_domain = domain;
330         nchips = aic5_domain->revmap_size / 32;
331         for (i = 0; i < nchips; i++) {
332                 gc = irq_get_domain_generic_chip(domain, i * 32);
333
334                 gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
335                 gc->chip_types[0].chip.irq_mask = aic5_mask;
336                 gc->chip_types[0].chip.irq_unmask = aic5_unmask;
337                 gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
338                 gc->chip_types[0].chip.irq_set_type = aic5_set_type;
339                 gc->chip_types[0].chip.irq_suspend = aic5_suspend;
340                 gc->chip_types[0].chip.irq_resume = aic5_resume;
341                 gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
342         }
343
344         aic5_hw_init(domain);
345         set_handle_irq(aic5_handle);
346
347         return 0;
348 }
349
350 #define NR_SAMA5D2_IRQS         77
351
352 static int __init sama5d2_aic5_of_init(struct device_node *node,
353                                        struct device_node *parent)
354 {
355         return aic5_of_init(node, parent, NR_SAMA5D2_IRQS);
356 }
357 IRQCHIP_DECLARE(sama5d2_aic5, "atmel,sama5d2-aic", sama5d2_aic5_of_init);
358
359 #define NR_SAMA5D3_IRQS         48
360
361 static int __init sama5d3_aic5_of_init(struct device_node *node,
362                                        struct device_node *parent)
363 {
364         return aic5_of_init(node, parent, NR_SAMA5D3_IRQS);
365 }
366 IRQCHIP_DECLARE(sama5d3_aic5, "atmel,sama5d3-aic", sama5d3_aic5_of_init);
367
368 #define NR_SAMA5D4_IRQS         68
369
370 static int __init sama5d4_aic5_of_init(struct device_node *node,
371                                        struct device_node *parent)
372 {
373         return aic5_of_init(node, parent, NR_SAMA5D4_IRQS);
374 }
375 IRQCHIP_DECLARE(sama5d4_aic5, "atmel,sama5d4-aic", sama5d4_aic5_of_init);