aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt48
-rw-r--r--drivers/irqchip/Kconfig5
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-orion.c192
4 files changed, 246 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt
new file mode 100644
index 000000000000..2c11ac76fac9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt
@@ -0,0 +1,48 @@
1Marvell Orion SoC interrupt controllers
2
3* Main interrupt controller
4
5Required properties:
6- compatible: shall be "marvell,orion-intc"
7- reg: base address(es) of interrupt registers starting with CAUSE register
8- interrupt-controller: identifies the node as an interrupt controller
9- #interrupt-cells: number of cells to encode an interrupt source, shall be 1
10
11The interrupt sources map to the corresponding bits in the interrupt
12registers, i.e.
13- 0 maps to bit 0 of first base address,
14- 1 maps to bit 1 of first base address,
15- 32 maps to bit 0 of second base address, and so on.
16
17Example:
18 intc: interrupt-controller {
19 compatible = "marvell,orion-intc";
20 interrupt-controller;
21 #interrupt-cells = <1>;
22 /* Dove has 64 first level interrupts */
23 reg = <0x20200 0x10>, <0x20210 0x10>;
24 };
25
26* Bridge interrupt controller
27
28Required properties:
29- compatible: shall be "marvell,orion-bridge-intc"
30- reg: base address of bridge interrupt registers starting with CAUSE register
31- interrupts: bridge interrupt of the main interrupt controller
32- interrupt-controller: identifies the node as an interrupt controller
33- #interrupt-cells: number of cells to encode an interrupt source, shall be 1
34
35Optional properties:
36- marvell,#interrupts: number of interrupts provided by bridge interrupt
37 controller, defaults to 32 if not set
38
39Example:
40 bridge_intc: interrupt-controller {
41 compatible = "marvell,orion-bridge-intc";
42 interrupt-controller;
43 #interrupt-cells = <1>;
44 reg = <0x20110 0x8>;
45 interrupts = <0>;
46 /* Dove bridge provides 5 interrupts */
47 marvell,#interrupts = <5>;
48 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4a33351c25dc..68c31071968d 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -25,6 +25,11 @@ config ARM_VIC_NR
25 The maximum number of VICs available in the system, for 25 The maximum number of VICs available in the system, for
26 power management. 26 power management.
27 27
28config ORION_IRQCHIP
29 bool
30 select IRQ_DOMAIN
31 select MULTI_IRQ_HANDLER
32
28config RENESAS_INTC_IRQPIN 33config RENESAS_INTC_IRQPIN
29 bool 34 bool
30 select IRQ_DOMAIN 35 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index cda4cb5f7327..55df3bdf804d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARCH_MXS) += irq-mxs.o
7obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o 7obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
8obj-$(CONFIG_METAG) += irq-metag-ext.o 8obj-$(CONFIG_METAG) += irq-metag-ext.o
9obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o 9obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
10obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
10obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o 11obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
11obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o 12obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
12obj-$(CONFIG_ARM_GIC) += irq-gic.o 13obj-$(CONFIG_ARM_GIC) += irq-gic.o
diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c
new file mode 100644
index 000000000000..e51d40031884
--- /dev/null
+++ b/drivers/irqchip/irq-orion.c
@@ -0,0 +1,192 @@
1/*
2 * Marvell Orion SoCs IRQ chip driver.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/io.h>
12#include <linux/irq.h>
13#include <linux/of.h>
14#include <linux/of_address.h>
15#include <linux/of_irq.h>
16#include <asm/exception.h>
17#include <asm/mach/irq.h>
18
19#include "irqchip.h"
20
21/*
22 * Orion SoC main interrupt controller
23 */
24#define ORION_IRQS_PER_CHIP 32
25
26#define ORION_IRQ_CAUSE 0x00
27#define ORION_IRQ_MASK 0x04
28#define ORION_IRQ_FIQ_MASK 0x08
29#define ORION_IRQ_ENDP_MASK 0x0c
30
31static struct irq_domain *orion_irq_domain;
32
33static asmlinkage void
34__exception_irq_entry orion_handle_irq(struct pt_regs *regs)
35{
36 struct irq_domain_chip_generic *dgc = orion_irq_domain->gc;
37 int n, base = 0;
38
39 for (n = 0; n < dgc->num_chips; n++, base += ORION_IRQS_PER_CHIP) {
40 struct irq_chip_generic *gc =
41 irq_get_domain_generic_chip(orion_irq_domain, base);
42 u32 stat = readl_relaxed(gc->reg_base + ORION_IRQ_CAUSE) &
43 gc->mask_cache;
44 while (stat) {
45 u32 hwirq = ffs(stat) - 1;
46 u32 irq = irq_find_mapping(orion_irq_domain,
47 gc->irq_base + hwirq);
48 handle_IRQ(irq, regs);
49 stat &= ~(1 << hwirq);
50 }
51 }
52}
53
54static int __init orion_irq_init(struct device_node *np,
55 struct device_node *parent)
56{
57 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
58 int n, ret, base, num_chips = 0;
59 struct resource r;
60
61 /* count number of irq chips by valid reg addresses */
62 while (of_address_to_resource(np, num_chips, &r) == 0)
63 num_chips++;
64
65 orion_irq_domain = irq_domain_add_linear(np,
66 num_chips * ORION_IRQS_PER_CHIP,
67 &irq_generic_chip_ops, NULL);
68 if (!orion_irq_domain)
69 panic("%s: unable to add irq domain\n", np->name);
70
71 ret = irq_alloc_domain_generic_chips(orion_irq_domain,
72 ORION_IRQS_PER_CHIP, 1, np->name,
73 handle_level_irq, clr, 0,
74 IRQ_GC_INIT_MASK_CACHE);
75 if (ret)
76 panic("%s: unable to alloc irq domain gc\n", np->name);
77
78 for (n = 0, base = 0; n < num_chips; n++, base += ORION_IRQS_PER_CHIP) {
79 struct irq_chip_generic *gc =
80 irq_get_domain_generic_chip(orion_irq_domain, base);
81
82 of_address_to_resource(np, n, &r);
83
84 if (!request_mem_region(r.start, resource_size(&r), np->name))
85 panic("%s: unable to request mem region %d",
86 np->name, n);
87
88 gc->reg_base = ioremap(r.start, resource_size(&r));
89 if (!gc->reg_base)
90 panic("%s: unable to map resource %d", np->name, n);
91
92 gc->chip_types[0].regs.mask = ORION_IRQ_MASK;
93 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
94 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
95
96 /* mask all interrupts */
97 writel(0, gc->reg_base + ORION_IRQ_MASK);
98 }
99
100 set_handle_irq(orion_handle_irq);
101 return 0;
102}
103IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init);
104
105/*
106 * Orion SoC bridge interrupt controller
107 */