[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/Makefile b/src/kernel/linux/v4.14/arch/mips/mti-malta/Makefile
new file mode 100644
index 0000000..63940bd
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/Makefile
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# Copyright (C) 2008 Wind River Systems, Inc.
+#   written by Ralf Baechle <ralf@linux-mips.org>
+#
+obj-y				+= malta-display.o
+obj-y				+= malta-dt.o
+obj-y				+= malta-dtshim.o
+obj-y				+= malta-init.o
+obj-y				+= malta-int.o
+obj-y				+= malta-memory.o
+obj-y				+= malta-platform.o
+obj-y				+= malta-reset.o
+obj-y				+= malta-setup.o
+obj-y				+= malta-time.o
+
+obj-$(CONFIG_MIPS_CMP)		+= malta-amon.o
+obj-$(CONFIG_MIPS_MALTA_PM)	+= malta-pm.o
+
+CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/Platform b/src/kernel/linux/v4.14/arch/mips/mti-malta/Platform
new file mode 100644
index 0000000..2cc72c9
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/Platform
@@ -0,0 +1,11 @@
+#
+# MIPS Malta board
+#
+platform-$(CONFIG_MIPS_MALTA)	+= mti-malta/
+cflags-$(CONFIG_MIPS_MALTA)	+= -I$(srctree)/arch/mips/include/asm/mach-malta
+ifdef CONFIG_KVM_GUEST
+    load-$(CONFIG_MIPS_MALTA)	+= 0x0000000040100000
+else
+    load-$(CONFIG_MIPS_MALTA)	+= 0xffffffff80100000
+endif
+all-$(CONFIG_MIPS_MALTA)	:= $(COMPRESSION_FNAME).bin
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-amon.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-amon.c
new file mode 100644
index 0000000..84ac523
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-amon.c
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * Arbitrary Monitor Interface
+ */
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/addrspace.h>
+#include <asm/mipsmtregs.h>
+#include <asm/mips-boards/launch.h>
+#include <asm/vpe.h>
+
+int amon_cpu_avail(int cpu)
+{
+	struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
+
+	if (cpu < 0 || cpu >= NCPULAUNCH) {
+		pr_debug("avail: cpu%d is out of range\n", cpu);
+		return 0;
+	}
+
+	launch += cpu;
+	if (!(launch->flags & LAUNCH_FREADY)) {
+		pr_debug("avail: cpu%d is not ready\n", cpu);
+		return 0;
+	}
+	if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
+		pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
+		return 0;
+	}
+
+	return 1;
+}
+
+int amon_cpu_start(int cpu,
+		    unsigned long pc, unsigned long sp,
+		    unsigned long gp, unsigned long a0)
+{
+	volatile struct cpulaunch *launch =
+		(struct cpulaunch  *)CKSEG0ADDR(CPULAUNCH);
+
+	if (!amon_cpu_avail(cpu))
+		return -1;
+	if (cpu == smp_processor_id()) {
+		pr_debug("launch: I am cpu%d!\n", cpu);
+		return -1;
+	}
+	launch += cpu;
+
+	pr_debug("launch: starting cpu%d\n", cpu);
+
+	launch->pc = pc;
+	launch->gp = gp;
+	launch->sp = sp;
+	launch->a0 = a0;
+
+	smp_wmb();		/* Target must see parameters before go */
+	launch->flags |= LAUNCH_FGO;
+	smp_wmb();		/* Target must see go before we poll  */
+
+	while ((launch->flags & LAUNCH_FGONE) == 0)
+		;
+	smp_rmb();	/* Target will be updating flags soon */
+	pr_debug("launch: cpu%d gone!\n", cpu);
+
+	return 0;
+}
+
+#ifdef CONFIG_MIPS_VPE_LOADER_CMP
+int vpe_run(struct vpe *v)
+{
+	struct vpe_notifications *n;
+
+	if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
+		return -1;
+
+	list_for_each_entry(n, &v->notify, list)
+		n->start(VPE_MODULE_MINOR);
+
+	return 0;
+}
+#endif
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-display.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-display.c
new file mode 100644
index 0000000..d4f8071
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-display.c
@@ -0,0 +1,56 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Display routines for display messages in MIPS boards ascii display.
+ *
+ * Copyright (C) 1999,2000,2012  MIPS Technologies, Inc.
+ * All rights reserved.
+ * Authors: Carsten Langgaard <carstenl@mips.com>
+ *          Steven J. Hill <sjhill@mips.com>
+ */
+#include <linux/compiler.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+
+#include <asm/mips-boards/generic.h>
+
+extern const char display_string[];
+static unsigned int display_count;
+static unsigned int max_display_count;
+
+void mips_display_message(const char *str)
+{
+	static unsigned int __iomem *display = NULL;
+	int i;
+
+	if (unlikely(display == NULL))
+		display = ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int));
+
+	for (i = 0; i <= 14; i += 2) {
+		if (*str)
+			__raw_writel(*str++, display + i);
+		else
+			__raw_writel(' ', display + i);
+	}
+}
+
+static void scroll_display_message(unsigned long data);
+static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
+
+static void scroll_display_message(unsigned long data)
+{
+	mips_display_message(&display_string[display_count++]);
+	if (display_count == max_display_count)
+		display_count = 0;
+
+	mod_timer(&mips_scroll_timer, jiffies + HZ);
+}
+
+void mips_scroll_message(void)
+{
+	del_timer_sync(&mips_scroll_timer);
+	max_display_count = strlen(display_string) + 1 - 8;
+	mod_timer(&mips_scroll_timer, jiffies + 1);
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-dt.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-dt.c
new file mode 100644
index 0000000..b397117
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-dt.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@mips.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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+void __init device_tree_init(void)
+{
+	unflatten_and_copy_device_tree();
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-dtshim.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-dtshim.c
new file mode 100644
index 0000000..7859b6e
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-dtshim.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@mips.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.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/sizes.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-cps.h>
+#include <asm/page.h>
+
+#define ROCIT_REG_BASE			0x1f403000
+#define ROCIT_CONFIG_GEN1		(ROCIT_REG_BASE + 0x04)
+#define  ROCIT_CONFIG_GEN1_MEMMAP_SHIFT	8
+#define  ROCIT_CONFIG_GEN1_MEMMAP_MASK	(0xf << 8)
+
+static unsigned char fdt_buf[16 << 10] __initdata;
+
+/* determined physical memory size, not overridden by command line args	 */
+extern unsigned long physical_memsize;
+
+enum mem_map {
+	MEM_MAP_V1 = 0,
+	MEM_MAP_V2,
+};
+
+#define MAX_MEM_ARRAY_ENTRIES 2
+
+static __init int malta_scon(void)
+{
+	int scon = MIPS_REVISION_SCONID;
+
+	if (scon != MIPS_REVISION_SCON_OTHER)
+		return scon;
+
+	switch (MIPS_REVISION_CORID) {
+	case MIPS_REVISION_CORID_QED_RM5261:
+	case MIPS_REVISION_CORID_CORE_LV:
+	case MIPS_REVISION_CORID_CORE_FPGA:
+	case MIPS_REVISION_CORID_CORE_FPGAR2:
+		return MIPS_REVISION_SCON_GT64120;
+
+	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+	case MIPS_REVISION_CORID_BONITO64:
+	case MIPS_REVISION_CORID_CORE_20K:
+		return MIPS_REVISION_SCON_BONITO;
+
+	case MIPS_REVISION_CORID_CORE_MSC:
+	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_24K:
+		return MIPS_REVISION_SCON_SOCIT;
+
+	case MIPS_REVISION_CORID_CORE_FPGA3:
+	case MIPS_REVISION_CORID_CORE_FPGA4:
+	case MIPS_REVISION_CORID_CORE_FPGA5:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	default:
+		return MIPS_REVISION_SCON_ROCIT;
+	}
+}
+
+static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size,
+					 enum mem_map map)
+{
+	unsigned long size_preio;
+	unsigned entries;
+
+	entries = 1;
+	mem_array[0] = cpu_to_be32(PHYS_OFFSET);
+	if (IS_ENABLED(CONFIG_EVA)) {
+		/*
+		 * The current Malta EVA configuration is "special" in that it
+		 * always makes use of addresses in the upper half of the 32 bit
+		 * physical address map, which gives it a contiguous region of
+		 * DDR but limits it to 2GB.
+		 */
+		mem_array[1] = cpu_to_be32(size);
+		goto done;
+	}
+
+	size_preio = min_t(unsigned long, size, SZ_256M);
+	mem_array[1] = cpu_to_be32(size_preio);
+	size -= size_preio;
+	if (!size)
+		goto done;
+
+	if (map == MEM_MAP_V2) {
+		/*
+		 * We have a flat 32 bit physical memory map with DDR filling
+		 * all 4GB of the memory map, apart from the I/O region which
+		 * obscures 256MB from 0x10000000-0x1fffffff.
+		 *
+		 * Therefore we discard the 256MB behind the I/O region.
+		 */
+		if (size <= SZ_256M)
+			goto done;
+		size -= SZ_256M;
+
+		/* Make use of the memory following the I/O region */
+		entries++;
+		mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_512M);
+		mem_array[3] = cpu_to_be32(size);
+	} else {
+		/*
+		 * We have a 32 bit physical memory map with a 2GB DDR region
+		 * aliased in the upper & lower halves of it. The I/O region
+		 * obscures 256MB from 0x10000000-0x1fffffff in the low alias
+		 * but the DDR it obscures is accessible via the high alias.
+		 *
+		 * Simply access everything beyond the lowest 256MB of DDR using
+		 * the high alias.
+		 */
+		entries++;
+		mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_2G + SZ_256M);
+		mem_array[3] = cpu_to_be32(size);
+	}
+
+done:
+	BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
+	return entries;
+}
+
+static void __init append_memory(void *fdt, int root_off)
+{
+	__be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
+	unsigned long memsize;
+	unsigned mem_entries;
+	int i, err, mem_off;
+	enum mem_map mem_map;
+	u32 config;
+	char *var, param_name[10], *var_names[] = {
+		"ememsize", "memsize",
+	};
+
+	/* if a memory node already exists, leave it alone */
+	mem_off = fdt_path_offset(fdt, "/memory");
+	if (mem_off >= 0)
+		return;
+
+	/* find memory size from the bootloader environment */
+	for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+		var = fw_getenv(var_names[i]);
+		if (!var)
+			continue;
+
+		err = kstrtoul(var, 0, &physical_memsize);
+		if (!err)
+			break;
+
+		pr_warn("Failed to read the '%s' env variable '%s'\n",
+			var_names[i], var);
+	}
+
+	if (!physical_memsize) {
+		pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
+		physical_memsize = 32 << 20;
+	}
+
+	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
+		/*
+		 * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
+		 * the last word of physical memory.
+		 */
+		physical_memsize -= PAGE_SIZE;
+	}
+
+	/* default to using all available RAM */
+	memsize = physical_memsize;
+
+	/* allow the user to override the usable memory */
+	for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+		snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
+		var = strstr(arcs_cmdline, param_name);
+		if (!var)
+			continue;
+
+		memsize = memparse(var + strlen(param_name), NULL);
+	}
+
+	/* if the user says there's more RAM than we thought, believe them */
+	physical_memsize = max_t(unsigned long, physical_memsize, memsize);
+
+	/* detect the memory map in use */
+	if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
+		/* ROCit has a register indicating the memory map in use */
+		config = readl((void __iomem *)CKSEG1ADDR(ROCIT_CONFIG_GEN1));
+		mem_map = config & ROCIT_CONFIG_GEN1_MEMMAP_MASK;
+		mem_map >>= ROCIT_CONFIG_GEN1_MEMMAP_SHIFT;
+	} else {
+		/* if not using ROCit, presume the v1 memory map */
+		mem_map = MEM_MAP_V1;
+	}
+	if (mem_map > MEM_MAP_V2)
+		panic("Unsupported physical memory map v%u detected",
+		      (unsigned int)mem_map);
+
+	/* append memory to the DT */
+	mem_off = fdt_add_subnode(fdt, root_off, "memory");
+	if (mem_off < 0)
+		panic("Unable to add memory node to DT: %d", mem_off);
+
+	err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
+	if (err)
+		panic("Unable to set memory node device_type: %d", err);
+
+	mem_entries = gen_fdt_mem_array(mem_array, physical_memsize, mem_map);
+	err = fdt_setprop(fdt, mem_off, "reg", mem_array,
+			  mem_entries * 2 * sizeof(mem_array[0]));
+	if (err)
+		panic("Unable to set memory regs property: %d", err);
+
+	mem_entries = gen_fdt_mem_array(mem_array, memsize, mem_map);
+	err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
+			  mem_entries * 2 * sizeof(mem_array[0]));
+	if (err)
+		panic("Unable to set linux,usable-memory property: %d", err);
+}
+
+static void __init remove_gic(void *fdt)
+{
+	int err, gic_off, i8259_off, cpu_off;
+	void __iomem *biu_base;
+	uint32_t cpu_phandle, sc_cfg;
+
+	/* if we have a CM which reports a GIC is present, leave the DT alone */
+	err = mips_cm_probe();
+	if (!err && (read_gcr_gic_status() & CM_GCR_GIC_STATUS_EX))
+		return;
+
+	if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
+		/*
+		 * On systems using the RocIT system controller a GIC may be
+		 * present without a CM. Detect whether that is the case.
+		 */
+		biu_base = ioremap_nocache(MSC01_BIU_REG_BASE,
+				MSC01_BIU_ADDRSPACE_SZ);
+		sc_cfg = __raw_readl(biu_base + MSC01_SC_CFG_OFS);
+		if (sc_cfg & MSC01_SC_CFG_GICPRES_MSK) {
+			/* enable the GIC at the system controller level */
+			sc_cfg |= BIT(MSC01_SC_CFG_GICENA_SHF);
+			__raw_writel(sc_cfg, biu_base + MSC01_SC_CFG_OFS);
+			return;
+		}
+	}
+
+	gic_off = fdt_node_offset_by_compatible(fdt, -1, "mti,gic");
+	if (gic_off < 0) {
+		pr_warn("malta-dtshim: unable to find DT GIC node: %d\n",
+			gic_off);
+		return;
+	}
+
+	err = fdt_nop_node(fdt, gic_off);
+	if (err)
+		pr_warn("malta-dtshim: unable to nop GIC node\n");
+
+	i8259_off = fdt_node_offset_by_compatible(fdt, -1, "intel,i8259");
+	if (i8259_off < 0) {
+		pr_warn("malta-dtshim: unable to find DT i8259 node: %d\n",
+			i8259_off);
+		return;
+	}
+
+	cpu_off = fdt_node_offset_by_compatible(fdt, -1,
+			"mti,cpu-interrupt-controller");
+	if (cpu_off < 0) {
+		pr_warn("malta-dtshim: unable to find CPU intc node: %d\n",
+			cpu_off);
+		return;
+	}
+
+	cpu_phandle = fdt_get_phandle(fdt, cpu_off);
+	if (!cpu_phandle) {
+		pr_warn("malta-dtshim: unable to get CPU intc phandle\n");
+		return;
+	}
+
+	err = fdt_setprop_u32(fdt, i8259_off, "interrupt-parent", cpu_phandle);
+	if (err) {
+		pr_warn("malta-dtshim: unable to set i8259 interrupt-parent: %d\n",
+			err);
+		return;
+	}
+
+	err = fdt_setprop_u32(fdt, i8259_off, "interrupts", 2);
+	if (err) {
+		pr_warn("malta-dtshim: unable to set i8259 interrupts: %d\n",
+			err);
+		return;
+	}
+}
+
+void __init *malta_dt_shim(void *fdt)
+{
+	int root_off, len, err;
+	const char *compat;
+
+	if (fdt_check_header(fdt))
+		panic("Corrupt DT");
+
+	err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
+	if (err)
+		panic("Unable to open FDT: %d", err);
+
+	root_off = fdt_path_offset(fdt_buf, "/");
+	if (root_off < 0)
+		panic("No / node in DT");
+
+	compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
+	if (!compat)
+		panic("No root compatible property in DT: %d", len);
+
+	/* if this isn't Malta, leave the DT alone */
+	if (strncmp(compat, "mti,malta", len))
+		return fdt;
+
+	append_memory(fdt_buf, root_off);
+	remove_gic(fdt_buf);
+
+	err = fdt_pack(fdt_buf);
+	if (err)
+		panic("Unable to pack FDT: %d\n", err);
+
+	return fdt_buf;
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-init.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-init.c
new file mode 100644
index 0000000..009f291
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-init.c
@@ -0,0 +1,301 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * PROM library initialisation code.
+ *
+ * Copyright (C) 1999,2000,2004,2005,2012  MIPS Technologies, Inc.
+ * All rights reserved.
+ * Authors: Carsten Langgaard <carstenl@mips.com>
+ *         Maciej W. Rozycki <macro@mips.com>
+ *          Steven J. Hill <sjhill@mips.com>
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/pci_regs.h>
+#include <linux/serial_core.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp-ops.h>
+#include <asm/traps.h>
+#include <asm/fw/fw.h>
+#include <asm/mips-cps.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/malta.h>
+
+static int mips_revision_corid;
+int mips_revision_sconid;
+
+/* Bonito64 system controller register base. */
+unsigned long _pcictrl_bonito;
+unsigned long _pcictrl_bonito_pcicfg;
+
+/* GT64120 system controller register base */
+unsigned long _pcictrl_gt64120;
+
+/* MIPS System controller register base */
+unsigned long _pcictrl_msc;
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void __init console_config(void)
+{
+	char console_string[40];
+	int baud = 0;
+	char parity = '\0', bits = '\0', flow = '\0';
+	char *s;
+
+	s = fw_getenv("modetty0");
+	if (s) {
+		while (*s >= '0' && *s <= '9')
+			baud = baud*10 + *s++ - '0';
+		if (*s == ',')
+			s++;
+		if (*s)
+			parity = *s++;
+		if (*s == ',')
+			s++;
+		if (*s)
+			bits = *s++;
+		if (*s == ',')
+			s++;
+		if (*s == 'h')
+			flow = 'r';
+	}
+	if (baud == 0)
+		baud = 38400;
+	if (parity != 'n' && parity != 'o' && parity != 'e')
+		parity = 'n';
+	if (bits != '7' && bits != '8')
+		bits = '8';
+	if (flow == '\0')
+		flow = 'r';
+
+	if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
+		sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
+			parity, bits);
+		setup_earlycon(console_string);
+	}
+
+	if ((strstr(fw_getcmdline(), "console=")) == NULL) {
+		sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+			parity, bits, flow);
+		strcat(fw_getcmdline(), console_string);
+		pr_info("Config serial console:%s\n", console_string);
+	}
+}
+#endif
+
+static void __init mips_nmi_setup(void)
+{
+	void *base;
+	extern char except_vec_nmi;
+
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa80) :
+		(void *)(CAC_BASE + 0x380);
+	memcpy(base, &except_vec_nmi, 0x80);
+	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+static void __init mips_ejtag_setup(void)
+{
+	void *base;
+	extern char except_vec_ejtag_debug;
+
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa00) :
+		(void *)(CAC_BASE + 0x300);
+	memcpy(base, &except_vec_ejtag_debug, 0x80);
+	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+phys_addr_t mips_cpc_default_phys_base(void)
+{
+	return CPC_BASE_ADDR;
+}
+
+void __init prom_init(void)
+{
+	mips_display_message("LINUX");
+
+	/*
+	 * early setup of _pcictrl_bonito so that we can determine
+	 * the system controller on a CORE_EMUL board
+	 */
+	_pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
+
+	mips_revision_corid = MIPS_REVISION_CORID;
+
+	if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
+		if (BONITO_PCIDID == 0x0001df53 ||
+		    BONITO_PCIDID == 0x0003df53)
+			mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
+		else
+			mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
+	}
+
+	mips_revision_sconid = MIPS_REVISION_SCONID;
+	if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {
+		switch (mips_revision_corid) {
+		case MIPS_REVISION_CORID_QED_RM5261:
+		case MIPS_REVISION_CORID_CORE_LV:
+		case MIPS_REVISION_CORID_CORE_FPGA:
+		case MIPS_REVISION_CORID_CORE_FPGAR2:
+			mips_revision_sconid = MIPS_REVISION_SCON_GT64120;
+			break;
+		case MIPS_REVISION_CORID_CORE_EMUL_BON:
+		case MIPS_REVISION_CORID_BONITO64:
+		case MIPS_REVISION_CORID_CORE_20K:
+			mips_revision_sconid = MIPS_REVISION_SCON_BONITO;
+			break;
+		case MIPS_REVISION_CORID_CORE_MSC:
+		case MIPS_REVISION_CORID_CORE_FPGA2:
+		case MIPS_REVISION_CORID_CORE_24K:
+			/*
+			 * SOCit/ROCit support is essentially identical
+			 * but make an attempt to distinguish them
+			 */
+			mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
+			break;
+		case MIPS_REVISION_CORID_CORE_FPGA3:
+		case MIPS_REVISION_CORID_CORE_FPGA4:
+		case MIPS_REVISION_CORID_CORE_FPGA5:
+		case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+		default:
+			/* See above */
+			mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;
+			break;
+		}
+	}
+
+	switch (mips_revision_sconid) {
+		u32 start, map, mask, data;
+
+	case MIPS_REVISION_SCON_GT64120:
+		/*
+		 * Setup the North bridge to do Master byte-lane swapping
+		 * when running in bigendian.
+		 */
+		_pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+		GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
+			 GT_PCI0_CMD_SBYTESWAP_BIT);
+#else
+		GT_WRITE(GT_PCI0_CMD_OFS, 0);
+#endif
+		/* Fix up PCI I/O mapping if necessary (for Atlas).  */
+		start = GT_READ(GT_PCI0IOLD_OFS);
+		map = GT_READ(GT_PCI0IOREMAP_OFS);
+		if ((start & map) != 0) {
+			map &= ~start;
+			GT_WRITE(GT_PCI0IOREMAP_OFS, map);
+		}
+
+		set_io_port_base(MALTA_GT_PORT_BASE);
+		break;
+
+	case MIPS_REVISION_SCON_BONITO:
+		_pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
+
+		/*
+		 * Disable Bonito IOBC.
+		 */
+		BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+			~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+			  BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+
+		/*
+		 * Setup the North bridge to do Master byte-lane swapping
+		 * when running in bigendian.
+		 */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+		BONITO_BONGENCFG = BONITO_BONGENCFG &
+			~(BONITO_BONGENCFG_MSTRBYTESWAP |
+			  BONITO_BONGENCFG_BYTESWAP);
+#else
+		BONITO_BONGENCFG = BONITO_BONGENCFG |
+			BONITO_BONGENCFG_MSTRBYTESWAP |
+			BONITO_BONGENCFG_BYTESWAP;
+#endif
+
+		set_io_port_base(MALTA_BONITO_PORT_BASE);
+		break;
+
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+		_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
+mips_pci_controller:
+		mb();
+		MSC_READ(MSC01_PCI_CFG, data);
+		MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);
+		wmb();
+
+		/* Fix up lane swapping.  */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+		MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
+#else
+		MSC_WRITE(MSC01_PCI_SWAP,
+			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |
+			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
+			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
+#endif
+
+		/*
+		 * Setup the Malta max (2GB) memory for PCI DMA in host bridge
+		 * in transparent addressing mode.
+		 */
+		mask = PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_PREFETCH;
+		MSC_WRITE(MSC01_PCI_BAR0, mask);
+		MSC_WRITE(MSC01_PCI_HEAD4, mask);
+
+		mask &= MSC01_PCI_BAR0_SIZE_MSK;
+		MSC_WRITE(MSC01_PCI_P2SCMSKL, mask);
+		MSC_WRITE(MSC01_PCI_P2SCMAPL, mask);
+
+		/* Don't handle target retries indefinitely.  */
+		if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==
+		    MSC01_PCI_CFG_MAXRTRY_MSK)
+			data = (data & ~(MSC01_PCI_CFG_MAXRTRY_MSK <<
+					 MSC01_PCI_CFG_MAXRTRY_SHF)) |
+			       ((MSC01_PCI_CFG_MAXRTRY_MSK - 1) <<
+				MSC01_PCI_CFG_MAXRTRY_SHF);
+
+		wmb();
+		MSC_WRITE(MSC01_PCI_CFG, data);
+		mb();
+
+		set_io_port_base(MALTA_MSC_PORT_BASE);
+		break;
+
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
+		_pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000);
+		goto mips_pci_controller;
+
+	default:
+		/* Unknown system controller */
+		mips_display_message("SC Error");
+		while (1);	/* We die here... */
+	}
+	board_nmi_handler_setup = mips_nmi_setup;
+	board_ejtag_handler_setup = mips_ejtag_setup;
+
+	fw_init_cmdline();
+	fw_meminit();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+	console_config();
+#endif
+	/* Early detection of CMP support */
+	mips_cpc_probe();
+
+	if (!register_cps_smp_ops())
+		return;
+	if (!register_cmp_smp_ops())
+		return;
+	if (!register_vsmp_smp_ops())
+		return;
+	register_up_smp_ops();
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-int.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-int.c
new file mode 100644
index 0000000..a840e0c
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-int.c
@@ -0,0 +1,227 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Malta board. The interrupt controller is located in the South Bridge
+ * a PIIX4 device with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+
+#include <asm/traps.h>
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+#include <asm/irq_regs.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mips-cps.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/msc01_pci.h>
+#include <asm/msc01_ic.h>
+#include <asm/setup.h>
+#include <asm/rtlx.h>
+
+static inline int mips_pcibios_iack(void)
+{
+	int irq;
+
+	/*
+	 * Determine highest priority pending interrupt by performing
+	 * a PCI Interrupt Acknowledge cycle.
+	 */
+	switch (mips_revision_sconid) {
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
+		MSC_READ(MSC01_PCI_IACK, irq);
+		irq &= 0xff;
+		break;
+	case MIPS_REVISION_SCON_GT64120:
+		irq = GT_READ(GT_PCI0_IACK_OFS);
+		irq &= 0xff;
+		break;
+	case MIPS_REVISION_SCON_BONITO:
+		/* The following will generate a PCI IACK cycle on the
+		 * Bonito controller. It's a little bit kludgy, but it
+		 * was the easiest way to implement it in hardware at
+		 * the given time.
+		 */
+		BONITO_PCIMAP_CFG = 0x20000;
+
+		/* Flush Bonito register block */
+		(void) BONITO_PCIMAP_CFG;
+		iob();	  /* sync */
+
+		irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
+		iob();	  /* sync */
+		irq &= 0xff;
+		BONITO_PCIMAP_CFG = 0;
+		break;
+	default:
+		pr_emerg("Unknown system controller.\n");
+		return -1;
+	}
+	return irq;
+}
+
+static void corehi_irqdispatch(void)
+{
+	unsigned int intedge, intsteer, pcicmd, pcibadaddr;
+	unsigned int pcimstat, intisr, inten, intpol;
+	unsigned int intrcause, datalo, datahi;
+	struct pt_regs *regs = get_irq_regs();
+
+	pr_emerg("CoreHI interrupt, shouldn't happen, we die here!\n");
+	pr_emerg("epc	 : %08lx\nStatus: %08lx\n"
+		 "Cause : %08lx\nbadVaddr : %08lx\n",
+		 regs->cp0_epc, regs->cp0_status,
+		 regs->cp0_cause, regs->cp0_badvaddr);
+
+	/* Read all the registers and then print them as there is a
+	   problem with interspersed printk's upsetting the Bonito controller.
+	   Do it for the others too.
+	*/
+
+	switch (mips_revision_sconid) {
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
+		ll_msc_irq();
+		break;
+	case MIPS_REVISION_SCON_GT64120:
+		intrcause = GT_READ(GT_INTRCAUSE_OFS);
+		datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
+		datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
+		pr_emerg("GT_INTRCAUSE = %08x\n", intrcause);
+		pr_emerg("GT_CPUERR_ADDR = %02x%08x\n",
+				datahi, datalo);
+		break;
+	case MIPS_REVISION_SCON_BONITO:
+		pcibadaddr = BONITO_PCIBADADDR;
+		pcimstat = BONITO_PCIMSTAT;
+		intisr = BONITO_INTISR;
+		inten = BONITO_INTEN;
+		intpol = BONITO_INTPOL;
+		intedge = BONITO_INTEDGE;
+		intsteer = BONITO_INTSTEER;
+		pcicmd = BONITO_PCICMD;
+		pr_emerg("BONITO_INTISR = %08x\n", intisr);
+		pr_emerg("BONITO_INTEN = %08x\n", inten);
+		pr_emerg("BONITO_INTPOL = %08x\n", intpol);
+		pr_emerg("BONITO_INTEDGE = %08x\n", intedge);
+		pr_emerg("BONITO_INTSTEER = %08x\n", intsteer);
+		pr_emerg("BONITO_PCICMD = %08x\n", pcicmd);
+		pr_emerg("BONITO_PCIBADADDR = %08x\n", pcibadaddr);
+		pr_emerg("BONITO_PCIMSTAT = %08x\n", pcimstat);
+		break;
+	}
+
+	die("CoreHi interrupt", regs);
+}
+
+static irqreturn_t corehi_handler(int irq, void *dev_id)
+{
+	corehi_irqdispatch();
+	return IRQ_HANDLED;
+}
+
+static struct irqaction corehi_irqaction = {
+	.handler = corehi_handler,
+	.name = "CoreHi",
+	.flags = IRQF_NO_THREAD,
+};
+
+static msc_irqmap_t msc_irqmap[] __initdata = {
+	{MSC01C_INT_TMR,		MSC01_IRQ_EDGE, 0},
+	{MSC01C_INT_PCI,		MSC01_IRQ_LEVEL, 0},
+};
+static int msc_nr_irqs __initdata = ARRAY_SIZE(msc_irqmap);
+
+static msc_irqmap_t msc_eicirqmap[] __initdata = {
+	{MSC01E_INT_SW0,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_SW1,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_I8259A,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_SMI,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_COREHI,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_CORELO,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_TMR,		MSC01_IRQ_EDGE, 0},
+	{MSC01E_INT_PCI,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_PERFCTR,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_CPUCTR,		MSC01_IRQ_LEVEL, 0}
+};
+
+static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
+
+void __init arch_init_irq(void)
+{
+	int corehi_irq;
+
+	/*
+	 * Preallocate the i8259's expected virq's here. Since irqchip_init()
+	 * will probe the irqchips in hierarchial order, i8259 is probed last.
+	 * If anything allocates a virq before the i8259 is probed, it will
+	 * be given one of the i8259's expected range and consequently setup
+	 * of the i8259 will fail.
+	 */
+	WARN(irq_alloc_descs(I8259A_IRQ_BASE, I8259A_IRQ_BASE,
+			    16, numa_node_id()) < 0,
+		"Cannot reserve i8259 virqs at IRQ%d\n", I8259A_IRQ_BASE);
+
+	i8259_set_poll(mips_pcibios_iack);
+	irqchip_init();
+
+	switch (mips_revision_sconid) {
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+		if (cpu_has_veic)
+			init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
+					MSC01E_INT_BASE, msc_eicirqmap,
+					msc_nr_eicirqs);
+		else
+			init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
+					MSC01C_INT_BASE, msc_irqmap,
+					msc_nr_irqs);
+		break;
+
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
+		if (cpu_has_veic)
+			init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
+					MSC01E_INT_BASE, msc_eicirqmap,
+					msc_nr_eicirqs);
+		else
+			init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
+					MSC01C_INT_BASE, msc_irqmap,
+					msc_nr_irqs);
+	}
+
+	if (mips_gic_present()) {
+		corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
+	} else if (cpu_has_veic) {
+		set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
+		corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
+	} else {
+		corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
+	}
+
+	setup_irq(corehi_irq, &corehi_irqaction);
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-memory.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-memory.c
new file mode 100644
index 0000000..a475567
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-memory.c
@@ -0,0 +1,59 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * PROM library functions for acquiring/using memory descriptors given to
+ * us from the YAMON.
+ *
+ * Copyright (C) 1999,2000,2012  MIPS Technologies, Inc.
+ * All rights reserved.
+ * Authors: Carsten Langgaard <carstenl@mips.com>
+ *          Steven J. Hill <sjhill@mips.com>
+ */
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cdmm.h>
+#include <asm/maar.h>
+#include <asm/sections.h>
+#include <asm/fw/fw.h>
+
+/* determined physical memory size, not overridden by command line args	 */
+unsigned long physical_memsize = 0L;
+
+static void free_init_pages_eva_malta(void *begin, void *end)
+{
+	free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
+			__pa_symbol((unsigned long *)end));
+}
+
+void __init fw_meminit(void)
+{
+	bool eva = IS_ENABLED(CONFIG_EVA);
+
+	free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
+}
+
+void __init prom_free_prom_memory(void)
+{
+	unsigned long addr;
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		free_init_pages("YAMON memory",
+				addr, addr + boot_mem_map.map[i].size);
+	}
+}
+
+phys_addr_t mips_cdmm_phys_base(void)
+{
+	/* This address is "typically unused" */
+	return 0x1fc10000;
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-platform.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-platform.c
new file mode 100644
index 0000000..11e9527
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-platform.c
@@ -0,0 +1,75 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006, 07 MIPS Technologies, Inc.
+ *   written by Ralf Baechle (ralf@linux-mips.org)
+ *     written by Ralf Baechle <ralf@linux-mips.org>
+ *
+ * Copyright (C) 2008 Wind River Systems, Inc.
+ *   updated by Tiejun Chen <tiejun.chen@windriver.com>
+ *
+ * 1. Probe driver for the Malta's UART ports:
+ *
+ *   o 2 ports in the SMC SuperIO
+ *   o 1 port in the CBUS UART, a discrete 16550 which normally is only used
+ *     for bringups.
+ *
+ * We don't use 8250_platform.c on Malta as it would result in the CBUS
+ * UART becoming ttyS0.
+ *
+ * 2. Register RTC-CMOS platform device on Malta.
+ */
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <asm/mips-boards/maltaint.h>
+
+#define SMC_PORT(base, int)						\
+{									\
+	.iobase		= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_PORT,					\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,		\
+	.regshift	= 0,						\
+}
+
+#define CBUS_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+	SMC_PORT(0x3F8, 4),
+	SMC_PORT(0x2F8, 3),
+#ifndef CONFIG_MIPS_CMP
+	{
+		.mapbase	= 0x1f000900,	/* The CBUS UART */
+		.irq		= MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
+		.uartclk	= 3686400,	/* Twice the usual clk! */
+		.iotype		= UPIO_MEM32,
+		.flags		= CBUS_UART_FLAGS,
+		.regshift	= 3,
+	},
+#endif
+	{ },
+};
+
+static struct platform_device malta_uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static struct platform_device *malta_devices[] __initdata = {
+	&malta_uart8250_device,
+};
+
+static int __init malta_add_devices(void)
+{
+	return platform_add_devices(malta_devices, ARRAY_SIZE(malta_devices));
+}
+
+device_initcall(malta_add_devices);
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-pm.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-pm.c
new file mode 100644
index 0000000..efbd659
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-pm.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@mips.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+
+#include <asm/mach-malta/malta-pm.h>
+
+static struct pci_bus *pm_pci_bus;
+static resource_size_t pm_io_offset;
+
+int mips_pm_suspend(unsigned state)
+{
+	int spec_devid;
+	u16 sts;
+
+	if (!pm_pci_bus || !pm_io_offset)
+		return -ENODEV;
+
+	/* Ensure the power button status is clear */
+	while (1) {
+		sts = inw(pm_io_offset + PIIX4_FUNC3IO_PMSTS);
+		if (!(sts & PIIX4_FUNC3IO_PMSTS_PWRBTN_STS))
+			break;
+		outw(sts, pm_io_offset + PIIX4_FUNC3IO_PMSTS);
+	}
+
+	/* Enable entry to suspend */
+	outw(state | PIIX4_FUNC3IO_PMCNTRL_SUS_EN,
+	     pm_io_offset + PIIX4_FUNC3IO_PMCNTRL);
+
+	/* If the special cycle occurs too soon this doesn't work... */
+	mdelay(10);
+
+	/*
+	 * The PIIX4 will enter the suspend state only after seeing a special
+	 * cycle with the correct magic data on the PCI bus. Generate that
+	 * cycle now.
+	 */
+	spec_devid = PCI_DEVID(0, PCI_DEVFN(0x1f, 0x7));
+	pci_bus_write_config_dword(pm_pci_bus, spec_devid, 0,
+				   PIIX4_SUSPEND_MAGIC);
+
+	/* Give the system some time to power down */
+	mdelay(1000);
+
+	return 0;
+}
+
+static int __init malta_pm_setup(void)
+{
+	struct pci_dev *dev;
+	int res, io_region = PCI_BRIDGE_RESOURCES;
+
+	/* Find a reference to the PCI bus */
+	pm_pci_bus = pci_find_next_bus(NULL);
+	if (!pm_pci_bus) {
+		pr_warn("malta-pm: failed to find reference to PCI bus\n");
+		return -ENODEV;
+	}
+
+	/* Find the PIIX4 PM device */
+	dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+			     PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
+			     PCI_ANY_ID, NULL);
+	if (!dev) {
+		pr_warn("malta-pm: failed to find PIIX4 PM\n");
+		return -ENODEV;
+	}
+
+	/* Request access to the PIIX4 PM IO registers */
+	res = pci_request_region(dev, io_region, "PIIX4 PM IO registers");
+	if (res) {
+		pr_warn("malta-pm: failed to request PM IO registers (%d)\n",
+			res);
+		pci_dev_put(dev);
+		return -ENODEV;
+	}
+
+	/* Find the offset to the PIIX4 PM IO registers */
+	pm_io_offset = pci_resource_start(dev, io_region);
+
+	pci_dev_put(dev);
+	return 0;
+}
+
+late_initcall(malta_pm_setup);
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-reset.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-reset.c
new file mode 100644
index 0000000..dd6f62a
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-reset.c
@@ -0,0 +1,30 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ */
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/reboot.h>
+
+#include <asm/reboot.h>
+#include <asm/mach-malta/malta-pm.h>
+
+static void mips_machine_power_off(void)
+{
+	mips_pm_suspend(PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF);
+
+	pr_info("Failed to power down, resetting\n");
+	machine_restart(NULL);
+}
+
+static int __init mips_reboot_setup(void)
+{
+	pm_power_off = mips_machine_power_off;
+
+	return 0;
+}
+arch_initcall(mips_reboot_setup);
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-setup.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-setup.c
new file mode 100644
index 0000000..de34adb
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-setup.c
@@ -0,0 +1,301 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2008 Dmitri Vorobiev
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/of_fdt.h>
+#include <linux/pci.h>
+#include <linux/screen_info.h>
+#include <linux/time.h>
+
+#include <asm/fw/fw.h>
+#include <asm/mach-malta/malta-dtshim.h>
+#include <asm/mips-cps.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/dma.h>
+#include <asm/prom.h>
+#include <asm/traps.h>
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#endif
+
+#define ROCIT_CONFIG_GEN0		0x1f403000
+#define  ROCIT_CONFIG_GEN0_PCI_IOCU	BIT(7)
+
+static struct resource standard_io_resources[] = {
+	{
+		.name = "dma1",
+		.start = 0x00,
+		.end = 0x1f,
+		.flags = IORESOURCE_BUSY
+	},
+	{
+		.name = "timer",
+		.start = 0x40,
+		.end = 0x5f,
+		.flags = IORESOURCE_BUSY
+	},
+	{
+		.name = "keyboard",
+		.start = 0x60,
+		.end = 0x6f,
+		.flags = IORESOURCE_BUSY
+	},
+	{
+		.name = "dma page reg",
+		.start = 0x80,
+		.end = 0x8f,
+		.flags = IORESOURCE_BUSY
+	},
+	{
+		.name = "dma2",
+		.start = 0xc0,
+		.end = 0xdf,
+		.flags = IORESOURCE_BUSY
+	},
+};
+
+const char *get_system_type(void)
+{
+	return "MIPS Malta";
+}
+
+const char display_string[] = "	       LINUX ON MALTA	    ";
+
+#ifdef CONFIG_BLK_DEV_FD
+static void __init fd_activate(void)
+{
+	/*
+	 * Activate Floppy Controller in the SMSC FDC37M817 Super I/O
+	 * Controller.
+	 * Done by YAMON 2.00 onwards
+	 */
+	/* Entering config state. */
+	SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG);
+
+	/* Activate floppy controller. */
+	SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
+	SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
+	SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
+	SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
+
+	/* Exit config state. */
+	SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
+}
+#endif
+
+static int __init plat_enable_iocoherency(void)
+{
+	int supported = 0;
+	u32 cfg;
+
+	if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
+		if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
+			BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
+			pr_info("Enabled Bonito CPU coherency\n");
+			supported = 1;
+		}
+		if (strstr(fw_getcmdline(), "iobcuncached")) {
+			BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
+			BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+				~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+				  BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+			pr_info("Disabled Bonito IOBC coherency\n");
+		} else {
+			BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
+			BONITO_PCIMEMBASECFG |=
+				(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+				 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+			pr_info("Enabled Bonito IOBC coherency\n");
+		}
+	} else if (mips_cps_numiocu(0) != 0) {
+		/* Nothing special needs to be done to enable coherency */
+		pr_info("CMP IOCU detected\n");
+		cfg = __raw_readl((u32 *)CKSEG1ADDR(ROCIT_CONFIG_GEN0));
+		if (!(cfg & ROCIT_CONFIG_GEN0_PCI_IOCU)) {
+			pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n");
+			return 0;
+		}
+		supported = 1;
+	}
+	hw_coherentio = supported;
+	return supported;
+}
+
+static void __init plat_setup_iocoherency(void)
+{
+#ifdef CONFIG_DMA_NONCOHERENT
+	/*
+	 * Kernel has been configured with software coherency
+	 * but we might choose to turn it off and use hardware
+	 * coherency instead.
+	 */
+	if (plat_enable_iocoherency()) {
+		if (coherentio == IO_COHERENCE_DISABLED)
+			pr_info("Hardware DMA cache coherency disabled\n");
+		else
+			pr_info("Hardware DMA cache coherency enabled\n");
+	} else {
+		if (coherentio == IO_COHERENCE_ENABLED)
+			pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
+		else
+			pr_info("Software DMA cache coherency enabled\n");
+	}
+#else
+	if (!plat_enable_iocoherency())
+		panic("Hardware DMA cache coherency not supported!");
+#endif
+}
+
+static void __init pci_clock_check(void)
+{
+	unsigned int __iomem *jmpr_p =
+		(unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int));
+	int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07;
+	static const int pciclocks[] __initconst = {
+		33, 20, 25, 30, 12, 16, 37, 10
+	};
+	int pciclock = pciclocks[jmpr];
+	char *optptr, *argptr = fw_getcmdline();
+
+	/*
+	 * If user passed a pci_clock= option, don't tack on another one
+	 */
+	optptr = strstr(argptr, "pci_clock=");
+	if (optptr && (optptr == argptr || optptr[-1] == ' '))
+		return;
+
+	if (pciclock != 33) {
+		pr_warn("WARNING: PCI clock is %dMHz, setting pci_clock\n",
+			pciclock);
+		argptr += strlen(argptr);
+		sprintf(argptr, " pci_clock=%d", pciclock);
+		if (pciclock < 20 || pciclock > 66)
+			pr_warn("WARNING: IDE timing calculations will be "
+			        "incorrect\n");
+	}
+}
+
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
+static void __init screen_info_setup(void)
+{
+	screen_info = (struct screen_info) {
+		.orig_x = 0,
+		.orig_y = 25,
+		.ext_mem_k = 0,
+		.orig_video_page = 0,
+		.orig_video_mode = 0,
+		.orig_video_cols = 80,
+		.unused2 = 0,
+		.orig_video_ega_bx = 0,
+		.unused3 = 0,
+		.orig_video_lines = 25,
+		.orig_video_isVGA = VIDEO_TYPE_VGAC,
+		.orig_video_points = 16
+	};
+}
+#endif
+
+static void __init bonito_quirks_setup(void)
+{
+	char *argptr;
+
+	argptr = fw_getcmdline();
+	if (strstr(argptr, "debug")) {
+		BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE;
+		pr_info("Enabled Bonito debug mode\n");
+	} else
+		BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE;
+
+#ifdef CONFIG_DMA_COHERENT
+	if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
+		BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
+		pr_info("Enabled Bonito CPU coherency\n");
+
+		argptr = fw_getcmdline();
+		if (strstr(argptr, "iobcuncached")) {
+			BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
+			BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+				~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+					BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+			pr_info("Disabled Bonito IOBC coherency\n");
+		} else {
+			BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
+			BONITO_PCIMEMBASECFG |=
+				(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+					BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+			pr_info("Enabled Bonito IOBC coherency\n");
+		}
+	} else
+		panic("Hardware DMA cache coherency not supported");
+#endif
+}
+
+void __init *plat_get_fdt(void)
+{
+	return (void *)__dtb_start;
+}
+
+void __init plat_mem_setup(void)
+{
+	unsigned int i;
+	void *fdt = plat_get_fdt();
+
+	fdt = malta_dt_shim(fdt);
+	__dt_setup_arch(fdt);
+
+	if (IS_ENABLED(CONFIG_EVA))
+		/* EVA has already been configured in mach-malta/kernel-init.h */
+		pr_info("Enhanced Virtual Addressing (EVA) activated\n");
+
+	mips_pcibios_init();
+
+	/* Request I/O space for devices used on the Malta board. */
+	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+		request_resource(&ioport_resource, standard_io_resources+i);
+
+	/*
+	 * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge.
+	 */
+	enable_dma(4);
+
+#ifdef CONFIG_DMA_COHERENT
+	if (mips_revision_sconid != MIPS_REVISION_SCON_BONITO)
+		panic("Hardware DMA cache coherency not supported");
+#endif
+
+	if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO)
+		bonito_quirks_setup();
+
+	plat_setup_iocoherency();
+
+	pci_clock_check();
+
+#ifdef CONFIG_BLK_DEV_FD
+	fd_activate();
+#endif
+
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
+	screen_info_setup();
+#endif
+}
diff --git a/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-time.c b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-time.c
new file mode 100644
index 0000000..66c8667
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/mti-malta/malta-time.c
@@ -0,0 +1,270 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+#include <linux/types.h>
+#include <linux/i8253.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/libfdt.h>
+#include <linux/math64.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+#include <asm/setup.h>
+#include <asm/time.h>
+#include <asm/mc146818-time.h>
+#include <asm/msc01_ic.h>
+#include <asm/mips-cps.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/maltaint.h>
+
+static int mips_cpu_timer_irq;
+static int mips_cpu_perf_irq;
+extern int cp0_perfcount_irq;
+
+static unsigned int gic_frequency;
+
+static void mips_timer_dispatch(void)
+{
+	do_IRQ(mips_cpu_timer_irq);
+}
+
+static void mips_perf_dispatch(void)
+{
+	do_IRQ(mips_cpu_perf_irq);
+}
+
+static unsigned int freqround(unsigned int freq, unsigned int amount)
+{
+	freq += amount;
+	freq -= freq % (amount*2);
+	return freq;
+}
+
+/*
+ * Estimate CPU and GIC frequencies.
+ */
+static void __init estimate_frequencies(void)
+{
+	unsigned long flags;
+	unsigned int count, start;
+	unsigned char secs1, secs2, ctrl;
+	int secs;
+	u64 giccount = 0, gicstart = 0;
+
+#if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
+	mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000;
+	return;
+#endif
+
+	local_irq_save(flags);
+
+	if (mips_gic_present())
+		clear_gic_config(GIC_CONFIG_COUNTSTOP);
+
+	/*
+	 * Read counters exactly on rising edge of update flag.
+	 * This helps get an accurate reading under virtualisation.
+	 */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+	start = read_c0_count();
+	if (mips_gic_present())
+		gicstart = read_gic_counter();
+
+	/* Wait for falling edge before reading RTC. */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	secs1 = CMOS_READ(RTC_SECONDS);
+
+	/* Read counters again exactly on rising edge of update flag. */
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+	count = read_c0_count();
+	if (mips_gic_present())
+		giccount = read_gic_counter();
+
+	/* Wait for falling edge before reading RTC again. */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	secs2 = CMOS_READ(RTC_SECONDS);
+
+	ctrl = CMOS_READ(RTC_CONTROL);
+
+	local_irq_restore(flags);
+
+	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		secs1 = bcd2bin(secs1);
+		secs2 = bcd2bin(secs2);
+	}
+	secs = secs2 - secs1;
+	if (secs < 1)
+		secs += 60;
+
+	count -= start;
+	count /= secs;
+	mips_hpt_frequency = count;
+
+	if (mips_gic_present()) {
+		giccount = div_u64(giccount - gicstart, secs);
+		gic_frequency = giccount;
+	}
+}
+
+void read_persistent_clock(struct timespec *ts)
+{
+	ts->tv_sec = mc146818_get_cmos_time();
+	ts->tv_nsec = 0;
+}
+
+int get_c0_fdc_int(void)
+{
+	/*
+	 * Some cores claim the FDC is routable through the GIC, but it doesn't
+	 * actually seem to be connected for those Malta bitstreams.
+	 */
+	switch (current_cpu_type()) {
+	case CPU_INTERAPTIV:
+	case CPU_PROAPTIV:
+		return -1;
+	};
+
+	if (cpu_has_veic)
+		return -1;
+	else if (mips_gic_present())
+		return gic_get_c0_fdc_int();
+	else if (cp0_fdc_irq >= 0)
+		return MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
+	else
+		return -1;
+}
+
+int get_c0_perfcount_int(void)
+{
+	if (cpu_has_veic) {
+		set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
+		mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
+	} else if (mips_gic_present()) {
+		mips_cpu_perf_irq = gic_get_c0_perfcount_int();
+	} else if (cp0_perfcount_irq >= 0) {
+		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+	} else {
+		mips_cpu_perf_irq = -1;
+	}
+
+	return mips_cpu_perf_irq;
+}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
+
+unsigned int get_c0_compare_int(void)
+{
+	if (cpu_has_veic) {
+		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
+	} else if (mips_gic_present()) {
+		mips_cpu_timer_irq = gic_get_c0_compare_int();
+	} else {
+		mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+	}
+
+	return mips_cpu_timer_irq;
+}
+
+static void __init init_rtc(void)
+{
+	unsigned char freq, ctrl;
+
+	/* Set 32KHz time base if not already set */
+	freq = CMOS_READ(RTC_FREQ_SELECT);
+	if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ)
+		CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
+
+	/* Ensure SET bit is clear so RTC can run */
+	ctrl = CMOS_READ(RTC_CONTROL);
+	if (ctrl & RTC_SET)
+		CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL);
+}
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+static u32 gic_frequency_dt;
+
+static struct property gic_frequency_prop = {
+	.name = "clock-frequency",
+	.length = sizeof(u32),
+	.value = &gic_frequency_dt,
+};
+
+static void update_gic_frequency_dt(void)
+{
+	struct device_node *node;
+
+	gic_frequency_dt = cpu_to_be32(gic_frequency);
+
+	node = of_find_compatible_node(NULL, NULL, "mti,gic-timer");
+	if (!node) {
+		pr_err("mti,gic-timer device node not found\n");
+		return;
+	}
+
+	if (of_update_property(node, &gic_frequency_prop) < 0)
+		pr_err("error updating gic frequency property\n");
+}
+
+#endif
+
+void __init plat_time_init(void)
+{
+	unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
+	unsigned int freq;
+
+	init_rtc();
+	estimate_frequencies();
+
+	freq = mips_hpt_frequency;
+	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		freq *= 2;
+	freq = freqround(freq, 5000);
+	printk("CPU frequency %d.%02d MHz\n", freq/1000000,
+	       (freq%1000000)*100/1000000);
+
+	mips_scroll_message();
+
+#ifdef CONFIG_I8253
+	/* Only Malta has a PIT. */
+	setup_pit_timer();
+#endif
+
+	if (mips_gic_present()) {
+		freq = freqround(gic_frequency, 5000);
+		printk("GIC frequency %d.%02d MHz\n", freq/1000000,
+		       (freq%1000000)*100/1000000);
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+		update_gic_frequency_dt();
+		timer_probe();
+#endif
+	}
+}