[PATCH 1/2] versatile: sic: add device tree bindings
From: Grant Likely <hidden>
Date: 2012-01-13 02:29:32
Also in:
linux-devicetree
On Fri, Jan 13, 2012 at 12:44:00AM +0000, Jamie Iles wrote:
quoted hunk
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.txtdiff --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
My plan is to select this from CONFIG_ARM, and that is what is in the irqdomain/next branch.
quoted hunk
bool config PLAT_VERSATILE_LEDSdiff --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); }
fpga_irq_handle() also needs to be modified to call irq_find_mapping() to translate from the hwirq to the linux number. There should be no references to irq_start after migrating to use irq_domain.
quoted hunk
@@ -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) } } }
There is a loop in fpga_irq_init() that sets up all the irqs, but with the introduction of the full irq_domain, that can be moved out to the .map irq_domain ops function. The irq_domain will call it to set up each irq when it is requested.
quoted hunk
+ +#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