diff mbox

[3/6] ARM: plat-versatile: add DT support to FPGA IRQ controller

Message ID 1345119357-22702-1-git-send-email-linus.walleij@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Linus Walleij Aug. 16, 2012, 12:15 p.m. UTC
This adds Device Tree probing support to the Versatile FPGA
IRQ controller.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 .../devicetree/bindings/arm/versatile-fpga-irq.txt | 35 ++++++++++++++++++
 arch/arm/plat-versatile/fpga-irq.c                 | 41 ++++++++++++++++++++++
 arch/arm/plat-versatile/include/plat/fpga-irq.h    |  2 ++
 3 files changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt

Comments

Arnd Bergmann Aug. 16, 2012, 1:50 p.m. UTC | #1
On Thursday 16 August 2012, Linus Walleij wrote:
> +- irq-start: the u32 hardware IRQ number of the first interrupt handled by
> +  this FPGA IRQ instance - since there may be many FPGA IRQ controller
> +  instances, each will have its unique hardware offset number.

The irq-start value is a Linux specific invention, the hardware doesn't
know anything about these. As long as you depend on specific IRQ numbers
to get assigned, I would use something like auxdata to find the
start number. When all devices get their IRQ numbers from the device
tree, you can move to linear IRQ domains instead of legacy, and let
the irq domain code pick the numbers.

	Arnd
Linus Walleij Sept. 1, 2012, 1:14 a.m. UTC | #2
On Thu, Aug 16, 2012 at 3:50 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 16 August 2012, Linus Walleij wrote:
>> +- irq-start: the u32 hardware IRQ number of the first interrupt handled by
>> +  this FPGA IRQ instance - since there may be many FPGA IRQ controller
>> +  instances, each will have its unique hardware offset number.
>
> The irq-start value is a Linux specific invention, the hardware doesn't
> know anything about these. As long as you depend on specific IRQ numbers
> to get assigned, I would use something like auxdata to find the
> start number.

Sorry that does not work. Auxdata is not used with IRQ controllers,
only with devices.

of_irq_init() will dereference the .data field of struct of_device_id
and use as a callback function to initialize the IRQ controller, no
chance to pass any other data that way.

> When all devices get their IRQ numbers from the device
> tree, you can move to linear IRQ domains instead of legacy, and let
> the irq domain code pick the numbers.

It seems I have no other choice here than to move directly to
linear numbers or atleast dynamically allocated descriptors.

Yours,
Linus Walleij
Arnd Bergmann Sept. 1, 2012, 7:11 a.m. UTC | #3
On Saturday 01 September 2012, Linus Walleij wrote:
> > When all devices get their IRQ numbers from the device
> > tree, you can move to linear IRQ domains instead of legacy, and let
> > the irq domain code pick the numbers.
> 
> It seems I have no other choice here than to move directly to
> linear numbers or atleast dynamically allocated descriptors.

You could also do a hack and keep the number hardcoded, or dependent
on the "compatible" value of the root node, but moving to linear
domains would be nicer because then you don't have to change this code
again.

	Arnd
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt b/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt
new file mode 100644
index 0000000..d20242a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt
@@ -0,0 +1,35 @@ 
+* ARM Versatile FPGA interrupt controller
+
+One or more FPGA IRQ controllers can be synthesized in an ARM reference board
+such as the Integrator or Versatile family. The output of these different
+controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
+instance can handle up to 32 interrupts.
+
+Required properties:
+- compatible: "arm,versatile-fpga-irq"
+- interrupt-controller: Identifies the node as an interrupt controller
+- #interrupt-cells: The number of cells to define the interrupts.  Must be 1
+  as the FPGA IRQ controller has no configuration options for interrupt
+  sources.  The cell is a u32 and defines the interrupt number.
+- reg: The register bank for the FPGA interrupt controller.
+- irq-start: the u32 hardware IRQ number of the first interrupt handled by
+  this FPGA IRQ instance - since there may be many FPGA IRQ controller
+  instances, each will have its unique hardware offset number.
+- clear-mask: a u32 number representing the mask written to clear all IRQs
+  on the controller at boot for example.
+- valid-mask: a u32 number representing a bit mask determining which of
+  the interrupts are valid. Unconnected/unused lines are set to 0, and
+  the system till not make it possible for devices to request these
+  interrupts.
+
+Example:
+
+pic: pic@14000000 {
+        compatible = "arm,versatile-fpga-irq";
+        #interrupt-cells = <1>;
+        interrupt-controller;
+        reg = <0x14000000 0x100>;
+        irq-start = <1>;
+        clear-mask = <0xffffffff>;
+        valid-mask = <0x003fffff>;
+};
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c
index 6e70d03..379ff53 100644
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ b/arch/arm/plat-versatile/fpga-irq.c
@@ -5,6 +5,8 @@ 
 #include <linux/io.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
@@ -14,6 +16,13 @@ 
 #define IRQ_RAW_STATUS		0x04
 #define IRQ_ENABLE_SET		0x08
 #define IRQ_ENABLE_CLEAR	0x0c
+#define INT_SOFT_SET		0x10
+#define INT_SOFT_CLEAR		0x14
+#define FIQ_STATUS		0x20
+#define FIQ_RAW_STATUS		0x24
+#define FIQ_ENABLE		0x28
+#define FIQ_ENABLE_SET		0x28
+#define FIQ_ENABLE_CLEAR	0x2C
 
 /**
  * struct fpga_irq_data - irq data container for the FPGA IRQ controller
@@ -156,3 +165,35 @@  void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
 
 	fpga_irq_id++;
 }
+
+#ifdef CONFIG_OF
+int __init fpga_irq_of_init(struct device_node *node,
+			    struct device_node *parent)
+{
+	void __iomem *base;
+	u32 irq_start;
+	u32 clear_mask;
+	u32 valid_mask;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	base = of_iomap(node, 0);
+	WARN(!base, "unable to map fpga irq registers\n");
+
+	if (of_property_read_u32(node, "irq-start", &irq_start))
+		irq_start = 0;
+
+	if (of_property_read_u32(node, "clear-mask", &clear_mask))
+		clear_mask = 0;
+
+	if (of_property_read_u32(node, "valid-mask", &valid_mask))
+		valid_mask = 0;
+
+	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
+	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
+	fpga_irq_init(base, node->name, irq_start, -1, valid_mask, node);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h
index 91bcfb6..1fac965 100644
--- a/arch/arm/plat-versatile/include/plat/fpga-irq.h
+++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h
@@ -7,5 +7,7 @@  struct pt_regs;
 void fpga_handle_irq(struct pt_regs *regs);
 void fpga_irq_init(void __iomem *, const char *, int, int, u32,
 		struct device_node *node);
+int fpga_irq_of_init(struct device_node *node,
+		     struct device_node *parent);
 
 #endif