aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-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
3 files changed, 86 insertions, 29 deletions
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