diff options
author | Paul Burton <paul.burton@imgtec.com> | 2017-06-02 22:29:57 +0300 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2017-06-28 13:22:41 +0300 |
commit | fbdc674ba33c3791b315a546019e570e3e94e599 (patch) | |
tree | e12c887a9d58020db9f7bc27f6ed6c4c1401aba4 /arch/mips/generic/board-sead3.c | |
parent | 032a469b1e6ef02209308a5b107c10beb4b12fb6 (diff) | |
download | linux-fbdc674ba33c3791b315a546019e570e3e94e599.tar.xz |
MIPS: SEAD-3: Set interrupt-parent per-device, not at root node
The SEAD-3 board may be configured with or without a MIPS Global
Interrupt Controller (GIC). Because of this we have a device tree with a
default case of a GIC present, and code to fixup the device tree based
upon a configuration register that indicates the presence of the GIC.
In order to keep this DT fixup code simple, the interrupt-parent
property was specified at the root node of the SEAD-3 DT, allowing the
fixup code to simply change this property to the phandle of the CPU
interrupt controller if a GIC is not present & affect all
interrupt-using devices at once. This however causes a problem if we do
have a GIC & the device tree is used as-is, because the interrupt-parent
property of the root node applies to the CPU interrupt controller node.
This causes a cycle when of_irq_init() attempts to probe interrupt
controllers in order and boots fail due to a lack of configured
interrupts, with this message printed on the kernel console:
[ 0.000000] OF: of_irq_init: children remain, but no parents
Fix this by removing the interrupt-parent property from the DT root node
& instead setting it for each device which uses interrupts, ensuring
that the CPU interrupt controller node has no interrupt-parent &
allowing of_irq_init() to identify it as the root interrupt controller.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Reported-by: Keng Koh <keng.koh@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16187/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/generic/board-sead3.c')
-rw-r--r-- | arch/mips/generic/board-sead3.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/arch/mips/generic/board-sead3.c b/arch/mips/generic/board-sead3.c index 39e11bd249cf..f109a6b9fdd0 100644 --- a/arch/mips/generic/board-sead3.c +++ b/arch/mips/generic/board-sead3.c @@ -87,14 +87,16 @@ static __init int remove_gic(void *fdt) return -EINVAL; } - err = fdt_setprop_u32(fdt, 0, "interrupt-parent", cpu_phandle); - if (err) { - pr_err("unable to set root interrupt-parent: %d\n", err); - return err; - } - uart_off = fdt_node_offset_by_compatible(fdt, -1, "ns16550a"); while (uart_off >= 0) { + err = fdt_setprop_u32(fdt, uart_off, "interrupt-parent", + cpu_phandle); + if (err) { + pr_warn("unable to set UART interrupt-parent: %d\n", + err); + return err; + } + err = fdt_setprop_u32(fdt, uart_off, "interrupts", cpu_uart_int); if (err) { @@ -117,6 +119,12 @@ static __init int remove_gic(void *fdt) return eth_off; } + err = fdt_setprop_u32(fdt, eth_off, "interrupt-parent", cpu_phandle); + if (err) { + pr_err("unable to set ethernet interrupt-parent: %d\n", err); + return err; + } + err = fdt_setprop_u32(fdt, eth_off, "interrupts", cpu_eth_int); if (err) { pr_err("unable to set ethernet interrupts property: %d\n", err); @@ -129,6 +137,12 @@ static __init int remove_gic(void *fdt) return ehci_off; } + err = fdt_setprop_u32(fdt, ehci_off, "interrupt-parent", cpu_phandle); + if (err) { + pr_err("unable to set EHCI interrupt-parent: %d\n", err); + return err; + } + err = fdt_setprop_u32(fdt, ehci_off, "interrupts", cpu_ehci_int); if (err) { pr_err("unable to set EHCI interrupts property: %d\n", err); |