Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6d5e47e authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle
Browse files

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: default avatarPaul 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 0a152736
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -4,10 +4,13 @@
/memreserve/ 0x00001000 0x000ef000;	// ROM data
/memreserve/ 0x000f0000 0x004cc000;	// reserved

#include <dt-bindings/interrupt-controller/mips-gic.h>

/ {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "mti,sead-3";
	interrupt-parent = <&gic>;

	cpus {
		cpu@0 {
@@ -19,4 +22,32 @@
		device_type = "memory";
		reg = <0x0 0x08000000>;
	};

	cpu_intc: interrupt-controller {
		compatible = "mti,cpu-interrupt-controller";

		interrupt-controller;
		#interrupt-cells = <1>;
	};

	gic: interrupt-controller@1b1c0000 {
		compatible = "mti,gic";
		reg = <0x1b1c0000 0x20000>;

		interrupt-controller;
		#interrupt-cells = <3>;

		/*
		 * Declare the interrupt-parent even though the mti,gic
		 * binding doesn't require it, such that the kernel can
		 * figure out that cpu_intc is the root interrupt
		 * controller & should be probed first.
		 */
		interrupt-parent = <&cpu_intc>;

		timer {
			compatible = "mti,gic-timer";
			interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
		};
	};
};
+29 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef __MIPS_SEAD3_DTSHIM_H__
#define __MIPS_SEAD3_DTSHIM_H__

#include <linux/init.h>

#ifdef CONFIG_MIPS_SEAD3

extern void __init *sead3_dt_shim(void *fdt);

#else /* !CONFIG_MIPS_SEAD3 */

static inline void *sead3_dt_shim(void *fdt)
{
	return fdt;
}

#endif /* !CONFIG_MIPS_SEAD3 */

#endif /* __MIPS_SEAD3_DTSHIM_H__ */
+0 −5
Original line number Diff line number Diff line
@@ -12,12 +12,7 @@

#include <linux/irqchip/mips-gic.h>

/* SEAD-3 GIC address space definitions. */
#define GIC_BASE_ADDR		0x1b1c0000
#define GIC_ADDRSPACE_SZ	(128 * 1024)

/* CPU interrupt offsets */
#define CPU_INT_GIC		2
#define CPU_INT_EHCI		2
#define CPU_INT_UART0		4
#define CPU_INT_UART1		4
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#
obj-y := sead3-lcd.o
obj-y += sead3-display.o
obj-y += sead3-dtshim.o
obj-y += sead3-init.o
obj-y += sead3-int.o
obj-y += sead3-platform.o
+92 −0
Original line number Diff line number Diff line
/*
 * 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;
}
Loading