[PATCH 1/2] versatile: sic: add device tree bindings
Jamie Iles
jamie at jamieiles.com
Thu Jan 12 19:44:00 EST 2012
Add a device tree binding for the FPGA SIC on versatile platforms. This
also requires the addition of irq domain support for mapping to Linux
IRQs.
Cc: Grant Likely <grant.likely at secretlab.ca>
Cc: Rob Herring <rob.herring at calxeda.com>
Cc: Russell King <linux at arm.linux.org.uk>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
.../devicetree/bindings/arm/versatile-sic.txt | 27 ++++++++++
arch/arm/plat-versatile/Kconfig | 1 +
arch/arm/plat-versatile/fpga-irq.c | 51 +++++++++++++++++++-
arch/arm/plat-versatile/include/plat/fpga-irq.h | 6 ++
4 files changed, 83 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/versatile-sic.txt
diff --git a/Documentation/devicetree/bindings/arm/versatile-sic.txt b/Documentation/devicetree/bindings/arm/versatile-sic.txt
new file mode 100644
index 0000000..971a42e
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/versatile-sic.txt
@@ -0,0 +1,27 @@
+* ARM Versatile FPGA Secondary Interrupt Controller
+
+The SIC is an interrupt controller embedded in an FPGA found on ARM versatile
+platforms.
+
+Required properties:
+
+- compatible : "arm,versatile-sic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : The number of cells to define the interrupts. Must be 1 as
+ the SIC has no configuration options for interrupt sources. The cell is a u32
+ and defines the interrupt number.
+- reg : The register bank for the VIC.
+- interrupt-parent : The interrupt controller that IRQ's are cascaded to.
+- interrupts : Interrupt source for the interrupt that SIC IRQs are routed to
+ in the primary interrupt controller.
+
+Example:
+
+ sic: intc at 10003000 {
+ compatible = "arm,versatile-sic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x10003000 0x1000>;
+ interrupt-parent = <&vic>;
+ interrupts = <31>;
+ };
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index 52353be..a07ffe5 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -4,6 +4,7 @@ config PLAT_VERSATILE_CLCD
bool
config PLAT_VERSATILE_FPGA_IRQ
+ select IRQ_DOMAIN
bool
config PLAT_VERSATILE_LEDS
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c
index f0cc8e1..fd87b06 100644
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ b/arch/arm/plat-versatile/fpga-irq.c
@@ -2,7 +2,13 @@
* Support for Versatile FPGA-based IRQ controllers
*/
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
#include <asm/mach/irq.h>
#include <plat/fpga-irq.h>
@@ -15,7 +21,7 @@
static void fpga_irq_mask(struct irq_data *d)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- u32 mask = 1 << (d->irq - f->irq_start);
+ u32 mask = 1 << d->hwirq;
writel(mask, f->base + IRQ_ENABLE_CLEAR);
}
@@ -23,7 +29,7 @@ static void fpga_irq_mask(struct irq_data *d)
static void fpga_irq_unmask(struct irq_data *d)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- u32 mask = 1 << (d->irq - f->irq_start);
+ u32 mask = 1 << d->hwirq;
writel(mask, f->base + IRQ_ENABLE_SET);
}
@@ -53,6 +59,10 @@ void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
f->chip.irq_ack = fpga_irq_mask;
f->chip.irq_mask = fpga_irq_mask;
f->chip.irq_unmask = fpga_irq_unmask;
+ f->domain.irq_base = f->irq_start;
+ f->domain.nr_irq = 32;
+ f->domain.ops = &irq_domain_simple_ops;
+ irq_domain_add(&f->domain);
if (parent_irq != -1) {
irq_set_handler_data(parent_irq, f);
@@ -70,3 +80,40 @@ void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
}
}
}
+
+#ifdef CONFIG_OF
+int __init sic_of_init(struct device_node *np, struct device_node *parent)
+{
+ struct fpga_irq_data *sic_data = kzalloc(sizeof(*sic_data), GFP_KERNEL);
+ int err = -ENOMEM, irq;
+
+ if (WARN_ON(!sic_data))
+ return err;
+
+ sic_data->base = of_iomap(np, 0);
+ if (WARN_ON(!sic_data->base))
+ goto out_free_data;
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq < 0)
+ goto out_free_data;
+
+ sic_data->irq_start = irq_alloc_descs(-1, 0, 32, numa_node_id());
+ if (WARN_ON(sic_data->irq_start < 0)) {
+ err = sic_data->irq_start;
+ goto out_unmap;
+ }
+ sic_data->domain.of_node = of_node_get(np);
+
+ fpga_irq_init(irq, ~0, sic_data);
+
+ return 0;
+
+out_unmap:
+ iounmap(sic_data->base);
+out_free_data:
+ kfree(sic_data);
+
+ return err;
+}
+#endif /* CONFIG_OF */
diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h
index 627fafd..a1391f3 100644
--- a/arch/arm/plat-versatile/include/plat/fpga-irq.h
+++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h
@@ -1,12 +1,18 @@
#ifndef PLAT_FPGA_IRQ_H
#define PLAT_FPGA_IRQ_H
+#include <linux/irqdomain.h>
+
+struct device_node;
+
struct fpga_irq_data {
void __iomem *base;
unsigned int irq_start;
struct irq_chip chip;
+ struct irq_domain domain;
};
void fpga_irq_init(int, u32, struct fpga_irq_data *);
+int sic_of_init(struct device_node *np, struct device_node *parent);
#endif
--
1.7.5.4
More information about the linux-arm-kernel
mailing list