Skip to content

Commit a493f33

Browse files
anholtKAGA-KOKO
authored andcommitted
irqchip/bcm2835: Add support for being used as a second level controller
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 <[email protected]> Acked-by: Stephen Warren <[email protected]> Cc: [email protected] Cc: Lee Jones <[email protected]> Cc: Jason Cooper <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent de58e52 commit a493f33

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ The BCM2835 contains a custom top-level interrupt controller, which supports
55
controller, or the HW block containing it, is referred to occasionally
66
as "armctrl" in the SoC documentation, hence naming of this binding.
77

8+
The BCM2836 contains the same interrupt controller with the same
9+
interrupts, but the per-CPU interrupt controller is the root, and an
10+
interrupt there indicates that the ARMCTRL has an interrupt to handle.
11+
812
Required properties:
913

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

28+
Additional required properties for brcm,bcm2836-armctrl-ic:
29+
- interrupt-parent : Specifies the parent interrupt controller when this
30+
controller is the second level.
31+
- interrupts : Specifies the interrupt on the parent for this interrupt
32+
controller to handle.
33+
2334
The interrupt sources are as follows:
2435

2536
Bank 0:
@@ -102,9 +113,21 @@ Bank 2:
102113

103114
Example:
104115

116+
/* BCM2835, first level */
105117
intc: interrupt-controller {
106118
compatible = "brcm,bcm2835-armctrl-ic";
107119
reg = <0x7e00b200 0x200>;
108120
interrupt-controller;
109121
#interrupt-cells = <2>;
110122
};
123+
124+
/* BCM2836, second level */
125+
intc: interrupt-controller {
126+
compatible = "brcm,bcm2836-armctrl-ic";
127+
reg = <0x7e00b200 0x200>;
128+
interrupt-controller;
129+
#interrupt-cells = <2>;
130+
131+
interrupt-parent = <&local_intc>;
132+
interrupts = <8>;
133+
};

drivers/irqchip/irq-bcm2835.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct armctrl_ic {
9696
static struct armctrl_ic intc __read_mostly;
9797
static void __exception_irq_entry bcm2835_handle_irq(
9898
struct pt_regs *regs);
99+
static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc);
99100

100101
static void armctrl_mask_irq(struct irq_data *d)
101102
{
@@ -139,7 +140,8 @@ static const struct irq_domain_ops armctrl_ops = {
139140
};
140141

141142
static int __init armctrl_of_init(struct device_node *node,
142-
struct device_node *parent)
143+
struct device_node *parent,
144+
bool is_2836)
143145
{
144146
void __iomem *base;
145147
int irq, b, i;
@@ -168,10 +170,34 @@ static int __init armctrl_of_init(struct device_node *node,
168170
}
169171
}
170172

171-
set_handle_irq(bcm2835_handle_irq);
173+
if (is_2836) {
174+
int parent_irq = irq_of_parse_and_map(node, 0);
175+
176+
if (!parent_irq) {
177+
panic("%s: unable to get parent interrupt.\n",
178+
node->full_name);
179+
}
180+
irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq);
181+
} else {
182+
set_handle_irq(bcm2835_handle_irq);
183+
}
184+
172185
return 0;
173186
}
174187

188+
static int __init bcm2835_armctrl_of_init(struct device_node *node,
189+
struct device_node *parent)
190+
{
191+
return armctrl_of_init(node, parent, false);
192+
}
193+
194+
static int __init bcm2836_armctrl_of_init(struct device_node *node,
195+
struct device_node *parent)
196+
{
197+
return armctrl_of_init(node, parent, true);
198+
}
199+
200+
175201
/*
176202
* Handle each interrupt across the entire interrupt controller. This reads the
177203
* status register before handling each interrupt, which is necessary given that
@@ -219,4 +245,15 @@ static void __exception_irq_entry bcm2835_handle_irq(
219245
handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
220246
}
221247

222-
IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);
248+
static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc)
249+
{
250+
u32 hwirq;
251+
252+
while ((hwirq = get_next_armctrl_hwirq()) != ~0)
253+
generic_handle_irq(irq_linear_revmap(intc.domain, hwirq));
254+
}
255+
256+
IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic",
257+
bcm2835_armctrl_of_init);
258+
IRQCHIP_DECLARE(bcm2836_armctrl_ic, "brcm,bcm2836-armctrl-ic",
259+
bcm2836_armctrl_of_init);

0 commit comments

Comments
 (0)