From 6be3809614db2d52724eb4b5193c27d2466142be Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:47:48 +0200 Subject: [PATCH 050/114] BCM2708: armctrl: Add IRQ Device Tree support Add Device Tree IRQ support for BCM2708. Usage is the same as for irq-bcm2835. See binding document: brcm,bcm2835-armctrl-ic.txt A bank 3 is added to handle GPIO interrupts. This is done because armctrl also handles GPIO interrupts. Signed-off-by: Noralf Tronnes BCM2708: armctrl: remove irq bank 3 irq bank 3 was needed by the pinctrl-bcm2708 and bcm2708_gpio combination. It is no longer required. Signed-off-by: Noralf Tronnes --- arch/arm/boot/dts/bcm2708.dtsi | 9 ++++ arch/arm/mach-bcm2708/armctrl.c | 96 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) --- a/arch/arm/boot/dts/bcm2708.dtsi +++ b/arch/arm/boot/dts/bcm2708.dtsi @@ -4,6 +4,8 @@ compatible = "brcm,bcm2708"; model = "BCM2708"; + interrupt-parent = <&intc>; + chosen { /* bootargs must be 1024 characters long because the @@ -17,6 +19,13 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x7e000000 0x20000000 0x02000000>; + + intc: interrupt-controller { + compatible = "brcm,bcm2708-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <2>; + }; }; clocks { --- a/arch/arm/mach-bcm2708/armctrl.c +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -79,6 +81,99 @@ static void armctrl_unmask_irq(struct ir } } +#ifdef CONFIG_OF + +#define NR_IRQS_BANK0 21 +#define NR_BANKS 3 +#define IRQS_PER_BANK 32 + +/* from drivers/irqchip/irq-bcm2835.c */ +static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize != 2)) + return -EINVAL; + + if (WARN_ON(intspec[0] >= NR_BANKS)) + return -EINVAL; + + if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) + return -EINVAL; + + if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) + return -EINVAL; + + if (intspec[0] == 0) + *out_hwirq = ARM_IRQ0_BASE + intspec[1]; + else if (intspec[0] == 1) + *out_hwirq = ARM_IRQ1_BASE + intspec[1]; + else + *out_hwirq = ARM_IRQ2_BASE + intspec[1]; + + /* reverse remap_irqs[] */ + switch (*out_hwirq) { + case INTERRUPT_VC_JPEG: + *out_hwirq = INTERRUPT_JPEG; + break; + case INTERRUPT_VC_USB: + *out_hwirq = INTERRUPT_USB; + break; + case INTERRUPT_VC_3D: + *out_hwirq = INTERRUPT_3D; + break; + case INTERRUPT_VC_DMA2: + *out_hwirq = INTERRUPT_DMA2; + break; + case INTERRUPT_VC_DMA3: + *out_hwirq = INTERRUPT_DMA3; + break; + case INTERRUPT_VC_I2C: + *out_hwirq = INTERRUPT_I2C; + break; + case INTERRUPT_VC_SPI: + *out_hwirq = INTERRUPT_SPI; + break; + case INTERRUPT_VC_I2SPCM: + *out_hwirq = INTERRUPT_I2SPCM; + break; + case INTERRUPT_VC_SDIO: + *out_hwirq = INTERRUPT_SDIO; + break; + case INTERRUPT_VC_UART: + *out_hwirq = INTERRUPT_UART; + break; + case INTERRUPT_VC_ARASANSDIO: + *out_hwirq = INTERRUPT_ARASANSDIO; + break; + } + + *out_type = IRQ_TYPE_NONE; + return 0; +} + +static struct irq_domain_ops armctrl_ops = { + .xlate = armctrl_xlate +}; + +void __init armctrl_dt_init(void) +{ + struct device_node *np; + struct irq_domain *domain; + + np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); + if (!np) + return; + + domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, + IRQ_ARMCTRL_START, 0, + &armctrl_ops, NULL); + WARN_ON(!domain); +} +#else +void __init armctrl_dt_init(void) { } +#endif /* CONFIG_OF */ + #if defined(CONFIG_PM) /* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ @@ -215,5 +310,6 @@ int __init armctrl_init(void __iomem * b armctrl_pm_register(base, irq_start, resume_sources); init_FIQ(FIQ_START); + armctrl_dt_init(); return 0; }