[PATCH 1/2] versatile: sic: add device tree bindings
Grant Likely
grant.likely at secretlab.ca
Fri Jan 13 13:29:32 EST 2012
On Fri, Jan 13, 2012 at 12:44:00AM +0000, Jamie Iles wrote:
> 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
My plan is to select this from CONFIG_ARM, and that is what is in the
irqdomain/next branch.
> 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);
> }
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.
> @@ -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.
> +
> +#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 devicetree-discuss
mailing list