summaryrefslogtreecommitdiffstats
path: root/arch/mips/mti-sead3/sead3-dtshim.c
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2016-08-26 15:17:34 +0100
committerRalf Baechle <ralf@linux-mips.org>2016-10-05 01:31:20 +0200
commitb6d5e47e67292542a41c3fe367bacb364eb4e601 (patch)
tree009d252825c827993b2b6fb67b21827cb1fc20a4 /arch/mips/mti-sead3/sead3-dtshim.c
parent0a15273666aa18a45985e6419afa05ec24ecfeb4 (diff)
downloadblackbird-obmc-linux-b6d5e47e67292542a41c3fe367bacb364eb4e601.tar.gz
blackbird-obmc-linux-b6d5e47e67292542a41c3fe367bacb364eb4e601.zip
MIPS: SEAD3: Probe interrupt controllers using DT
Probe the CPU interrupt controller & optional Global Interrupt Controller (GIC) using devicetree rather than platform code. Because the bootloader on SEAD3 does not provide a device tree to the kernel & the device tree is always built in, we patch out the GIC node during boot if we detect that a GIC is not present in the system. The appropriate IRQ domain is discovered by platform code setting up device IRQ numbers temporarily. It will be removed by further patches which move the devices towards being probed via device tree. No behavioural change is intended by this patch. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: Matt Redfearn <matt.redfearn@imgtec.com> Cc: Kefeng Wang <wangkefeng.wang@huawei.com> Cc: Jacek Anaszewski <j.anaszewski@samsung.com> Cc: Rob Herring <robh+dt@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14047/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mti-sead3/sead3-dtshim.c')
-rw-r--r--arch/mips/mti-sead3/sead3-dtshim.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/arch/mips/mti-sead3/sead3-dtshim.c b/arch/mips/mti-sead3/sead3-dtshim.c
new file mode 100644
index 000000000000..3283a7e19a88
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-dtshim.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) "sead3-dtshim: " fmt
+
+#include <linux/errno.h>
+#include <linux/libfdt.h>
+#include <linux/printk.h>
+
+#include <asm/io.h>
+
+#define SEAD_CONFIG CKSEG1ADDR(0x1b100110)
+#define SEAD_CONFIG_GIC_PRESENT BIT(1)
+
+static unsigned char fdt_buf[16 << 10] __initdata;
+
+static int remove_gic(void *fdt)
+{
+ int gic_off, cpu_off, err;
+ uint32_t cfg, cpu_phandle;
+
+ /* leave the GIC node intact if a GIC is present */
+ cfg = __raw_readl((uint32_t *)SEAD_CONFIG);
+ if (cfg & SEAD_CONFIG_GIC_PRESENT)
+ return 0;
+
+ gic_off = fdt_node_offset_by_compatible(fdt, -1, "mti,gic");
+ if (gic_off < 0) {
+ pr_err("unable to find DT GIC node: %d\n", gic_off);
+ return gic_off;
+ }
+
+ err = fdt_nop_node(fdt, gic_off);
+ if (err) {
+ pr_err("unable to nop GIC node\n");
+ return err;
+ }
+
+ cpu_off = fdt_node_offset_by_compatible(fdt, -1,
+ "mti,cpu-interrupt-controller");
+ if (cpu_off < 0) {
+ pr_err("unable to find CPU intc node: %d\n", cpu_off);
+ return cpu_off;
+ }
+
+ cpu_phandle = fdt_get_phandle(fdt, cpu_off);
+ if (!cpu_phandle) {
+ pr_err("unable to get CPU intc phandle\n");
+ 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;
+ }
+
+ return 0;
+}
+
+void __init *sead3_dt_shim(void *fdt)
+{
+ int err;
+
+ if (fdt_check_header(fdt))
+ panic("Corrupt DT");
+
+ /* if this isn't SEAD3, leave the DT alone */
+ if (fdt_node_check_compatible(fdt, 0, "mti,sead-3"))
+ return fdt;
+
+ err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
+ if (err)
+ panic("Unable to open FDT: %d", err);
+
+ err = remove_gic(fdt_buf);
+ if (err)
+ panic("Unable to patch FDT: %d", err);
+
+ err = fdt_pack(fdt_buf);
+ if (err)
+ panic("Unable to pack FDT: %d\n", err);
+
+ return fdt_buf;
+}
OpenPOWER on IntegriCloud