aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Iles <jamie@jamieiles.com>2011-09-27 06:00:46 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2011-11-15 13:14:02 -0500
commitf9b28ccbc7139af656147dcbba9c5425d5706b7d (patch)
treea10608259acc0487938f30b4669a2c4b678f91c3
parent08d33b27f7063ba2b4a29f9e3a2dcb65f30dec0b (diff)
ARM: vic: device tree binding
This adds a device tree binding for the VIC based on the of_irq_init() support. This adds an irqdomain to the vic and always registers all vics in the static vic array rather than for pm only to keep track of the irq domain. struct irq_data::hwirq is used where appropriate rather than runtime masking. v3: - include linux/export.h for THIS_MODULE v2: - use irq_domain_simple_ops - remove stub implementation of vic_of_init for !CONFIG_OF - Make VIC select IRQ_DOMAIN Reviewed-by: Rob Herring <robherring2@gmail.com> Reviewed-by: Grant Likely <grant.likely@secretlab.ca> Tested-by: Thomas Abraham <thomas.abraham@linaro.org> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
-rw-r--r--Documentation/devicetree/bindings/arm/vic.txt29
-rw-r--r--arch/arm/common/Kconfig1
-rw-r--r--arch/arm/common/vic.c107
-rw-r--r--arch/arm/include/asm/hardware/vic.h7
4 files changed, 115 insertions, 29 deletions
diff --git a/Documentation/devicetree/bindings/arm/vic.txt b/Documentation/devicetree/bindings/arm/vic.txt
new file mode 100644
index 000000000000..266716b23437
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vic.txt
@@ -0,0 +1,29 @@
1* ARM Vectored Interrupt Controller
2
3One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM
4system for interrupt routing. For multiple controllers they can either be
5nested or have the outputs wire-OR'd together.
6
7Required properties:
8
9- compatible : should be one of
10 "arm,pl190-vic"
11 "arm,pl192-vic"
12- interrupt-controller : Identifies the node as an interrupt controller
13- #interrupt-cells : The number of cells to define the interrupts. Must be 1 as
14 the VIC has no configuration options for interrupt sources. The cell is a u32
15 and defines the interrupt number.
16- reg : The register bank for the VIC.
17
18Optional properties:
19
20- interrupts : Interrupt source for parent controllers if the VIC is nested.
21
22Example:
23
24 vic0: interrupt-controller@60000 {
25 compatible = "arm,pl192-vic";
26 interrupt-controller;
27 #interrupt-cells = <1>;
28 reg = <0x60000 0x1000>;
29 };
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index a11cee523cd4..10ca9749e94d 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -7,6 +7,7 @@ config GIC_NON_BANKED
7 bool 7 bool
8 8
9config ARM_VIC 9config ARM_VIC
10 select IRQ_DOMAIN
10 bool 11 bool
11 12
12config ARM_VIC_NR 13config ARM_VIC_NR
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 01f18a421b17..a227a7d53700 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -19,9 +19,14 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#include <linux/export.h>
22#include <linux/init.h> 23#include <linux/init.h>
23#include <linux/list.h> 24#include <linux/list.h>
24#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/irqdomain.h>
27#include <linux/of.h>
28#include <linux/of_address.h>
29#include <linux/of_irq.h>
25#include <linux/syscore_ops.h> 30#include <linux/syscore_ops.h>
26#include <linux/device.h> 31#include <linux/device.h>
27#include <linux/amba/bus.h> 32#include <linux/amba/bus.h>
@@ -29,7 +34,6 @@
29#include <asm/mach/irq.h> 34#include <asm/mach/irq.h>
30#include <asm/hardware/vic.h> 35#include <asm/hardware/vic.h>
31 36
32#ifdef CONFIG_PM
33/** 37/**
34 * struct vic_device - VIC PM device 38 * struct vic_device - VIC PM device
35 * @irq: The IRQ number for the base of the VIC. 39 * @irq: The IRQ number for the base of the VIC.
@@ -40,6 +44,7 @@
40 * @int_enable: Save for VIC_INT_ENABLE. 44 * @int_enable: Save for VIC_INT_ENABLE.
41 * @soft_int: Save for VIC_INT_SOFT. 45 * @soft_int: Save for VIC_INT_SOFT.
42 * @protect: Save for VIC_PROTECT. 46 * @protect: Save for VIC_PROTECT.
47 * @domain: The IRQ domain for the VIC.
43 */ 48 */
44struct vic_device { 49struct vic_device {
45 void __iomem *base; 50 void __iomem *base;
@@ -50,13 +55,13 @@ struct vic_device {
50 u32 int_enable; 55 u32 int_enable;
51 u32 soft_int; 56 u32 soft_int;
52 u32 protect; 57 u32 protect;
58 struct irq_domain domain;
53}; 59};
54 60
55/* we cannot allocate memory when VICs are initially registered */ 61/* we cannot allocate memory when VICs are initially registered */
56static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; 62static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
57 63
58static int vic_id; 64static int vic_id;
59#endif /* CONFIG_PM */
60 65
61/** 66/**
62 * vic_init2 - common initialisation code 67 * vic_init2 - common initialisation code
@@ -156,39 +161,50 @@ static int __init vic_pm_init(void)
156 return 0; 161 return 0;
157} 162}
158late_initcall(vic_pm_init); 163late_initcall(vic_pm_init);
164#endif /* CONFIG_PM */
159 165
160/** 166/**
161 * vic_pm_register - Register a VIC for later power management control 167 * vic_register() - Register a VIC.
162 * @base: The base address of the VIC. 168 * @base: The base address of the VIC.
163 * @irq: The base IRQ for the VIC. 169 * @irq: The base IRQ for the VIC.
164 * @resume_sources: bitmask of interrupts allowed for resume sources. 170 * @resume_sources: bitmask of interrupts allowed for resume sources.
171 * @node: The device tree node associated with the VIC.
165 * 172 *
166 * Register the VIC with the system device tree so that it can be notified 173 * Register the VIC with the system device tree so that it can be notified
167 * of suspend and resume requests and ensure that the correct actions are 174 * of suspend and resume requests and ensure that the correct actions are
168 * taken to re-instate the settings on resume. 175 * taken to re-instate the settings on resume.
176 *
177 * This also configures the IRQ domain for the VIC.
169 */ 178 */
170static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources) 179static void __init vic_register(void __iomem *base, unsigned int irq,
180 u32 resume_sources, struct device_node *node)
171{ 181{
172 struct vic_device *v; 182 struct vic_device *v;
173 183
174 if (vic_id >= ARRAY_SIZE(vic_devices)) 184 if (vic_id >= ARRAY_SIZE(vic_devices)) {
175 printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); 185 printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
176 else { 186 return;
177 v = &vic_devices[vic_id];
178 v->base = base;
179 v->resume_sources = resume_sources;
180 v->irq = irq;
181 vic_id++;
182 } 187 }
188
189 v = &vic_devices[vic_id];
190 v->base = base;
191 v->resume_sources = resume_sources;
192 v->irq = irq;
193 vic_id++;
194
195 v->domain.irq_base = irq;
196 v->domain.nr_irq = 32;
197#ifdef CONFIG_OF_IRQ
198 v->domain.of_node = of_node_get(node);
199 v->domain.ops = &irq_domain_simple_ops;
200#endif /* CONFIG_OF */
201 irq_domain_add(&v->domain);
183} 202}
184#else
185static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
186#endif /* CONFIG_PM */
187 203
188static void vic_ack_irq(struct irq_data *d) 204static void vic_ack_irq(struct irq_data *d)
189{ 205{
190 void __iomem *base = irq_data_get_irq_chip_data(d); 206 void __iomem *base = irq_data_get_irq_chip_data(d);
191 unsigned int irq = d->irq & 31; 207 unsigned int irq = d->hwirq;
192 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); 208 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
193 /* moreover, clear the soft-triggered, in case it was the reason */ 209 /* moreover, clear the soft-triggered, in case it was the reason */
194 writel(1 << irq, base + VIC_INT_SOFT_CLEAR); 210 writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
@@ -197,14 +213,14 @@ static void vic_ack_irq(struct irq_data *d)
197static void vic_mask_irq(struct irq_data *d) 213static void vic_mask_irq(struct irq_data *d)
198{ 214{
199 void __iomem *base = irq_data_get_irq_chip_data(d); 215 void __iomem *base = irq_data_get_irq_chip_data(d);
200 unsigned int irq = d->irq & 31; 216 unsigned int irq = d->hwirq;
201 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); 217 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
202} 218}
203 219
204static void vic_unmask_irq(struct irq_data *d) 220static void vic_unmask_irq(struct irq_data *d)
205{ 221{
206 void __iomem *base = irq_data_get_irq_chip_data(d); 222 void __iomem *base = irq_data_get_irq_chip_data(d);
207 unsigned int irq = d->irq & 31; 223 unsigned int irq = d->hwirq;
208 writel(1 << irq, base + VIC_INT_ENABLE); 224 writel(1 << irq, base + VIC_INT_ENABLE);
209} 225}
210 226
@@ -226,7 +242,7 @@ static struct vic_device *vic_from_irq(unsigned int irq)
226static int vic_set_wake(struct irq_data *d, unsigned int on) 242static int vic_set_wake(struct irq_data *d, unsigned int on)
227{ 243{
228 struct vic_device *v = vic_from_irq(d->irq); 244 struct vic_device *v = vic_from_irq(d->irq);
229 unsigned int off = d->irq & 31; 245 unsigned int off = d->hwirq;
230 u32 bit = 1 << off; 246 u32 bit = 1 << off;
231 247
232 if (!v) 248 if (!v)
@@ -330,15 +346,9 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
330 vic_set_irq_sources(base, irq_start, vic_sources); 346 vic_set_irq_sources(base, irq_start, vic_sources);
331} 347}
332 348
333/** 349static void __init __vic_init(void __iomem *base, unsigned int irq_start,
334 * vic_init - initialise a vectored interrupt controller 350 u32 vic_sources, u32 resume_sources,
335 * @base: iomem base address 351 struct device_node *node)
336 * @irq_start: starting interrupt number, must be muliple of 32
337 * @vic_sources: bitmask of interrupt sources to allow
338 * @resume_sources: bitmask of interrupt sources to allow for resume
339 */
340void __init vic_init(void __iomem *base, unsigned int irq_start,
341 u32 vic_sources, u32 resume_sources)
342{ 352{
343 unsigned int i; 353 unsigned int i;
344 u32 cellid = 0; 354 u32 cellid = 0;
@@ -375,5 +385,46 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
375 385
376 vic_set_irq_sources(base, irq_start, vic_sources); 386 vic_set_irq_sources(base, irq_start, vic_sources);
377 387
378 vic_pm_register(base, irq_start, resume_sources); 388 vic_register(base, irq_start, resume_sources, node);
389}
390
391/**
392 * vic_init() - initialise a vectored interrupt controller
393 * @base: iomem base address
394 * @irq_start: starting interrupt number, must be muliple of 32
395 * @vic_sources: bitmask of interrupt sources to allow
396 * @resume_sources: bitmask of interrupt sources to allow for resume
397 */
398void __init vic_init(void __iomem *base, unsigned int irq_start,
399 u32 vic_sources, u32 resume_sources)
400{
401 __vic_init(base, irq_start, vic_sources, resume_sources, NULL);
402}
403
404#ifdef CONFIG_OF
405int __init vic_of_init(struct device_node *node, struct device_node *parent)
406{
407 void __iomem *regs;
408 int irq_base;
409
410 if (WARN(parent, "non-root VICs are not supported"))
411 return -EINVAL;
412
413 regs = of_iomap(node, 0);
414 if (WARN_ON(!regs))
415 return -EIO;
416
417 irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
418 if (WARN_ON(irq_base < 0))
419 goto out_unmap;
420
421 __vic_init(regs, irq_base, ~0, ~0, node);
422
423 return 0;
424
425 out_unmap:
426 iounmap(regs);
427
428 return -EIO;
379} 429}
430#endif /* CONFIG OF */
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index 5d72550a8097..b348a545de23 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -41,7 +41,12 @@
41#define VIC_PL192_VECT_ADDR 0xF00 41#define VIC_PL192_VECT_ADDR 0xF00
42 42
43#ifndef __ASSEMBLY__ 43#ifndef __ASSEMBLY__
44#include <linux/compiler.h>
45#include <linux/types.h>
46
47struct device_node;
44void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); 48void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
45#endif 49int vic_of_init(struct device_node *node, struct device_node *parent);
46 50
51#endif /* __ASSEMBLY__ */
47#endif 52#endif