aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.18/0050-BCM2708-armctrl-Add-IRQ-Device-Tree-support.patch
blob: f548d40712704a65c99d7f3c2db44cec27a282fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
From 6be3809614db2d52724eb4b5193c27d2466142be Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Wed, 9 Jul 2014 14:47:48 +0200
Subject: [PATCH 050/114] BCM2708: armctrl: Add IRQ Device Tree support

Add Device Tree IRQ support for BCM2708.
Usage is the same as for irq-bcm2835.
See binding document: brcm,bcm2835-armctrl-ic.txt

A bank 3 is added to handle GPIO interrupts. This is done because
armctrl also handles GPIO interrupts.

Signed-off-by: Noralf Tronnes <notro@tronnes.org>

BCM2708: armctrl: remove irq bank 3

irq bank 3 was needed by the pinctrl-bcm2708 and bcm2708_gpio
combination. It is no longer required.

Signed-off-by: Noralf Tronnes <notro@tronnes.org>
---
 arch/arm/boot/dts/bcm2708.dtsi  |  9 ++++
 arch/arm/mach-bcm2708/armctrl.c | 96 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)

--- a/arch/arm/boot/dts/bcm2708.dtsi
+++ b/arch/arm/boot/dts/bcm2708.dtsi
@@ -4,6 +4,8 @@
 	compatible = "brcm,bcm2708";
 	model = "BCM2708";
 
+	interrupt-parent = <&intc>;
+
 	chosen {
 		/*
 		   bootargs must be 1024 characters long because the
@@ -17,6 +19,13 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x7e000000 0x20000000 0x02000000>;
+
+		intc: interrupt-controller {
+			compatible = "brcm,bcm2708-armctrl-ic";
+			reg = <0x7e00b200 0x200>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 	};
 
 	clocks {
--- a/arch/arm/mach-bcm2708/armctrl.c
+++ b/arch/arm/mach-bcm2708/armctrl.c
@@ -23,6 +23,8 @@
 #include <linux/version.h>
 #include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
 
 #include <asm/mach/irq.h>
 #include <mach/hardware.h>
@@ -79,6 +81,99 @@ static void armctrl_unmask_irq(struct ir
 	}
 }
 
+#ifdef CONFIG_OF
+
+#define NR_IRQS_BANK0           21
+#define NR_BANKS                3
+#define IRQS_PER_BANK           32
+
+/* from drivers/irqchip/irq-bcm2835.c */
+static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr,
+        const u32 *intspec, unsigned int intsize,
+        unsigned long *out_hwirq, unsigned int *out_type)
+{
+        if (WARN_ON(intsize != 2))
+                return -EINVAL;
+
+        if (WARN_ON(intspec[0] >= NR_BANKS))
+                return -EINVAL;
+
+        if (WARN_ON(intspec[1] >= IRQS_PER_BANK))
+                return -EINVAL;
+
+        if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0))
+                return -EINVAL;
+
+	if (intspec[0] == 0)
+		*out_hwirq = ARM_IRQ0_BASE + intspec[1];
+	else if (intspec[0] == 1)
+		*out_hwirq = ARM_IRQ1_BASE + intspec[1];
+	else
+		*out_hwirq = ARM_IRQ2_BASE + intspec[1];
+
+	/* reverse remap_irqs[] */
+	switch (*out_hwirq) {
+	case INTERRUPT_VC_JPEG:
+		*out_hwirq = INTERRUPT_JPEG;
+		break;
+	case INTERRUPT_VC_USB:
+		*out_hwirq = INTERRUPT_USB;
+		break;
+	case INTERRUPT_VC_3D:
+		*out_hwirq = INTERRUPT_3D;
+		break;
+	case INTERRUPT_VC_DMA2:
+		*out_hwirq = INTERRUPT_DMA2;
+		break;
+	case INTERRUPT_VC_DMA3:
+		*out_hwirq = INTERRUPT_DMA3;
+		break;
+	case INTERRUPT_VC_I2C:
+		*out_hwirq = INTERRUPT_I2C;
+		break;
+	case INTERRUPT_VC_SPI:
+		*out_hwirq = INTERRUPT_SPI;
+		break;
+	case INTERRUPT_VC_I2SPCM:
+		*out_hwirq = INTERRUPT_I2SPCM;
+		break;
+	case INTERRUPT_VC_SDIO:
+		*out_hwirq = INTERRUPT_SDIO;
+		break;
+	case INTERRUPT_VC_UART:
+		*out_hwirq = INTERRUPT_UART;
+		break;
+	case INTERRUPT_VC_ARASANSDIO:
+		*out_hwirq = INTERRUPT_ARASANSDIO;
+		break;
+	}
+
+        *out_type = IRQ_TYPE_NONE;
+        return 0;
+}
+
+static struct irq_domain_ops armctrl_ops = {
+        .xlate = armctrl_xlate
+};
+
+void __init armctrl_dt_init(void)
+{
+	struct device_node *np;
+	struct irq_domain *domain;
+
+	np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic");
+	if (!np)
+		return;
+
+	domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS,
+					IRQ_ARMCTRL_START, 0,
+					&armctrl_ops, NULL);
+        WARN_ON(!domain);
+}
+#else
+void __init armctrl_dt_init(void) { }
+#endif /* CONFIG_OF */
+
 #if defined(CONFIG_PM)
 
 /* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */
@@ -215,5 +310,6 @@ int __init armctrl_init(void __iomem * b
 
 	armctrl_pm_register(base, irq_start, resume_sources);
 	init_FIQ(FIQ_START);
+	armctrl_dt_init();
 	return 0;
 }