Skip to content

Commit

Permalink
irqchip/bcm2835: Add support for being used as a second level controller
Browse files Browse the repository at this point in the history
The BCM2836 (Raspberry Pi 2) uses two levels of interrupt handling
with the CPU-local interrupts being the root, so we need to register
ours as chained off of the CPU's local interrupt.

Signed-off-by: Eric Anholt <eric@anholt.net>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Cc: linux-rpi-kernel@lists.infradead.org
Cc: Lee Jones <lee@kernel.org>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/1438902033-31477-3-git-send-email-eric@anholt.net
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Eric Anholt authored and Thomas Gleixner committed Aug 20, 2015
1 parent de58e52 commit a493f33
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ The BCM2835 contains a custom top-level interrupt controller, which supports
controller, or the HW block containing it, is referred to occasionally
as "armctrl" in the SoC documentation, hence naming of this binding.

The BCM2836 contains the same interrupt controller with the same
interrupts, but the per-CPU interrupt controller is the root, and an
interrupt there indicates that the ARMCTRL has an interrupt to handle.

Required properties:

- compatible : should be "brcm,bcm2835-armctrl-ic"
- compatible : should be "brcm,bcm2835-armctrl-ic" or
"brcm,bcm2836-armctrl-ic"
- reg : Specifies base physical address and size of the registers.
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
Expand All @@ -20,6 +25,12 @@ Required properties:
The 2nd cell contains the interrupt number within the bank. Valid values
are 0..7 for bank 0, and 0..31 for bank 1.

Additional required properties for brcm,bcm2836-armctrl-ic:
- interrupt-parent : Specifies the parent interrupt controller when this
controller is the second level.
- interrupts : Specifies the interrupt on the parent for this interrupt
controller to handle.

The interrupt sources are as follows:

Bank 0:
Expand Down Expand Up @@ -102,9 +113,21 @@ Bank 2:

Example:

/* BCM2835, first level */
intc: interrupt-controller {
compatible = "brcm,bcm2835-armctrl-ic";
reg = <0x7e00b200 0x200>;
interrupt-controller;
#interrupt-cells = <2>;
};

/* BCM2836, second level */
intc: interrupt-controller {
compatible = "brcm,bcm2836-armctrl-ic";
reg = <0x7e00b200 0x200>;
interrupt-controller;
#interrupt-cells = <2>;

interrupt-parent = <&local_intc>;
interrupts = <8>;
};
43 changes: 40 additions & 3 deletions drivers/irqchip/irq-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct armctrl_ic {
static struct armctrl_ic intc __read_mostly;
static void __exception_irq_entry bcm2835_handle_irq(
struct pt_regs *regs);
static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc);

static void armctrl_mask_irq(struct irq_data *d)
{
Expand Down Expand Up @@ -139,7 +140,8 @@ static const struct irq_domain_ops armctrl_ops = {
};

static int __init armctrl_of_init(struct device_node *node,
struct device_node *parent)
struct device_node *parent,
bool is_2836)
{
void __iomem *base;
int irq, b, i;
Expand Down Expand Up @@ -168,10 +170,34 @@ static int __init armctrl_of_init(struct device_node *node,
}
}

set_handle_irq(bcm2835_handle_irq);
if (is_2836) {
int parent_irq = irq_of_parse_and_map(node, 0);

if (!parent_irq) {
panic("%s: unable to get parent interrupt.\n",
node->full_name);
}
irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq);
} else {
set_handle_irq(bcm2835_handle_irq);
}

return 0;
}

static int __init bcm2835_armctrl_of_init(struct device_node *node,
struct device_node *parent)
{
return armctrl_of_init(node, parent, false);
}

static int __init bcm2836_armctrl_of_init(struct device_node *node,
struct device_node *parent)
{
return armctrl_of_init(node, parent, true);
}


/*
* Handle each interrupt across the entire interrupt controller. This reads the
* status register before handling each interrupt, which is necessary given that
Expand Down Expand Up @@ -219,4 +245,15 @@ static void __exception_irq_entry bcm2835_handle_irq(
handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
}

IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);
static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc)
{
u32 hwirq;

while ((hwirq = get_next_armctrl_hwirq()) != ~0)
generic_handle_irq(irq_linear_revmap(intc.domain, hwirq));
}

IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic",
bcm2835_armctrl_of_init);
IRQCHIP_DECLARE(bcm2836_armctrl_ic, "brcm,bcm2836-armctrl-ic",
bcm2836_armctrl_of_init);

0 comments on commit a493f33

Please sign in to comment.