[PATCH 1/2] versatile: sic: add device tree bindings

Subsystems: arm port, open firmware and flattened device tree bindings, the rest

STALE5319d

2 messages, 2 authors, 2012-01-13 · open the first message on its own page

[PATCH 1/2] versatile: sic: add device tree bindings

From: Jamie Iles <hidden>
Date: 2012-01-13 00:44:00

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 <redacted>
Cc: Rob Herring <redacted>
Cc: Russell King <redacted>
Signed-off-by: Jamie Iles <redacted>
---
 .../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

Re: [PATCH 1/2] versatile: sic: add device tree bindings

From: Russell King - ARM Linux <hidden>
Date: 2012-01-13 10:48:42

On Fri, Jan 13, 2012 at 12:44:00AM +0000, Jamie Iles wrote:
+#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);
I notice that you completely ignore the validity mask, and initialize all
32 interrupts.  This is wrong.  You don't think I put the validity mask
there just to obfuscate the code?

And this shouldn't be called 'sic' at all.  It may be the secondary
interrupt controller on the Versatile, but it's also the PIC, SIC and
CIC on Integrator platforms.  Calling anything in this file (which is
entirely separate of any platform) 'sic' is _wrong_.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help