aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2011-09-28 22:27:52 -0400
committerArnd Bergmann <arnd@arndb.de>2011-10-31 09:03:26 -0400
commitb3f7ed0324091e2cb23fe1b3c10570700f614014 (patch)
tree6f9a14a39fc4302276a1560cb48c1ede72fc5dff /arch/arm/common
parent4294f8baaf174c9aa57886e7ed27caf4b02578f6 (diff)
ARM: gic: add OF based initialization
This adds ARM gic interrupt controller initialization using device tree data. The initialization function is intended to be called by of_irq_init function like this: const static struct of_device_id irq_match[] = { { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, {} }; static void __init init_irqs(void) { of_irq_init(irq_match); } Signed-off-by: Rob Herring <rob.herring@calxeda.com> Reviewed-by: Jamie Iles <jamie@jamieiles.com> Tested-by: Thomas Abraham <thomas.abraham@linaro.org> Acked-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/gic.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index ccaa1ab18de7..1333e68b1f96 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -30,6 +30,9 @@
30#include <linux/cpu_pm.h> 30#include <linux/cpu_pm.h>
31#include <linux/cpumask.h> 31#include <linux/cpumask.h>
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/of.h>
34#include <linux/of_address.h>
35#include <linux/of_irq.h>
33#include <linux/irqdomain.h> 36#include <linux/irqdomain.h>
34#include <linux/interrupt.h> 37#include <linux/interrupt.h>
35#include <linux/percpu.h> 38#include <linux/percpu.h>
@@ -530,7 +533,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
530} 533}
531#endif 534#endif
532 535
536#ifdef CONFIG_OF
537static int gic_irq_domain_dt_translate(struct irq_domain *d,
538 struct device_node *controller,
539 const u32 *intspec, unsigned int intsize,
540 unsigned long *out_hwirq, unsigned int *out_type)
541{
542 if (d->of_node != controller)
543 return -EINVAL;
544 if (intsize < 3)
545 return -EINVAL;
546
547 /* Get the interrupt number and add 16 to skip over SGIs */
548 *out_hwirq = intspec[1] + 16;
549
550 /* For SPIs, we need to add 16 more to get the GIC irq ID number */
551 if (!intspec[0])
552 *out_hwirq += 16;
553
554 *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
555 return 0;
556}
557#endif
558
533const struct irq_domain_ops gic_irq_domain_ops = { 559const struct irq_domain_ops gic_irq_domain_ops = {
560#ifdef CONFIG_OF
561 .dt_translate = gic_irq_domain_dt_translate,
562#endif
534}; 563};
535 564
536void __init gic_init(unsigned int gic_nr, unsigned int irq_start, 565void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -608,3 +637,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
608 writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); 637 writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
609} 638}
610#endif 639#endif
640
641#ifdef CONFIG_OF
642static int gic_cnt __initdata = 0;
643
644int __init gic_of_init(struct device_node *node, struct device_node *parent)
645{
646 void __iomem *cpu_base;
647 void __iomem *dist_base;
648 int irq;
649 struct irq_domain *domain = &gic_data[gic_cnt].domain;
650
651 if (WARN_ON(!node))
652 return -ENODEV;
653
654 dist_base = of_iomap(node, 0);
655 WARN(!dist_base, "unable to map gic dist registers\n");
656
657 cpu_base = of_iomap(node, 1);
658 WARN(!cpu_base, "unable to map gic cpu registers\n");
659
660 domain->of_node = of_node_get(node);
661
662 gic_init(gic_cnt, 16, dist_base, cpu_base);
663
664 if (parent) {
665 irq = irq_of_parse_and_map(node, 0);
666 gic_cascade_irq(gic_cnt, irq);
667 }
668 gic_cnt++;
669 return 0;
670}
671#endif