diff --git a/Makefile b/Makefile
index 8013cbd9f9..1e18a37913 100644
--- a/Makefile
+++ b/Makefile
@@ -895,6 +895,7 @@ ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb-tegra.bin
 endif
 
 ALL-$(CONFIG_ARCH_MEDIATEK) += u-boot-mtk.bin
+ALL-$(CONFIG_ARCH_MTMIPS) += u-boot-mtmips.bin
 
 # Add optional build target if defined in board/cpu/soc headers
 ifneq ($(CONFIG_BUILD_TARGET),)
@@ -1664,6 +1665,14 @@ u-boot-mtk.bin: u-boot.bin FORCE
 	$(call if_changed,mkimage)
 endif
 
+ifeq ($(CONFIG_SPL),y)
+u-boot-mtmips.bin: u-boot.dtb u-boot-lzma.img spl/u-boot-spl.bin FORCE
+	$(call if_changed,binman)
+else
+u-boot-mtmips.bin: u-boot.bin FORCE
+	$(call if_changed,copy)
+endif
+
 ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
 
 # Rule to link u-boot
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 5f82caf8be..5f74f549b5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -98,6 +98,9 @@ config ARCH_MTMIPS
 	select SUPPORTS_CPU_MIPS32_R2
 	select SUPPORTS_LITTLE_ENDIAN
 	select SYSRESET
+	select SUPPORT_SPL
+	select SPL_LZMA
+	select BINMAN
 
 config ARCH_JZ47XX
 	bool "Support Ingenic JZ47xx"
diff --git a/arch/mips/dts/mt7628-u-boot.dtsi b/arch/mips/dts/mt7628-u-boot.dtsi
new file mode 100644
index 0000000000..213959105f
--- /dev/null
+++ b/arch/mips/dts/mt7628-u-boot.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Weijie Gao <weijie.gao at mediatek.com>
+ */
+
+/ {
+	binman {
+		filename = "u-boot-mtmips.bin";
+		pad-byte = <0xff>;
+
+#ifdef CONFIG_SPL
+		u-boot-spl {
+		};
+
+		u-boot-lzma-img {
+		};
+#else
+		u-boot {
+		};
+#endif
+	};
+};
diff --git a/arch/mips/mach-mtmips/Kconfig b/arch/mips/mach-mtmips/Kconfig
index 3f25de8b85..9b42d5b581 100644
--- a/arch/mips/mach-mtmips/Kconfig
+++ b/arch/mips/mach-mtmips/Kconfig
@@ -20,8 +20,16 @@ config SYS_ICACHE_LINE_SIZE
 	default 32
 
 config SYS_TEXT_BASE
+	default 0x9c000000 if !SPL
+	default 0x80200000 if SPL
+
+config SPL_TEXT_BASE
 	default 0x9c000000
 
+config SPL_LOADER_SUPPORT
+	bool
+	default y
+
 choice
 	prompt "MediaTek MIPS SoC select"
 
@@ -34,6 +42,14 @@ config SOC_MT7628
 	select PINCTRL_MT7628
 	select MTK_SERIAL
 	select SYSRESET_RESETCTL
+	select SPL_SEPARATE_BSS if SPL
+	select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
+	select SPL_OF_CONTROL if SPL_DM
+	select SPL_SIMPLE_BUS if SPL_DM
+	select SPL_DM_SERIAL if SPL_DM
+	select SPL_CLK if SPL_DM && SPL_SERIAL_SUPPORT
+	select SPL_SYSRESET if SPL_DM
+	select SPL_OF_LIBFDT if SPL_OF_CONTROL
 	help
 	  This supports MediaTek MT7628/MT7688.
 
@@ -88,6 +104,14 @@ endchoice
 config SUPPORTS_BOOT_RAM
 	bool
 
+config SPL_UART2_SPIS_PINMUX
+	bool "Use alternative pinmux for UART2 in SPL stage"
+	depends on SPL_SERIAL_SUPPORT
+	default n
+	help
+	  Select this if the UART2 of your board is connected to GPIO 16/17
+	  (shared with SPIS) rather than the usual GPIO 20/21.
+
 source "board/gardena/smart-gateway-mt7688/Kconfig"
 source "board/seeed/linkit-smart-7688/Kconfig"
 
diff --git a/arch/mips/mach-mtmips/Makefile b/arch/mips/mach-mtmips/Makefile
index 72f0369030..08d2a236d0 100644
--- a/arch/mips/mach-mtmips/Makefile
+++ b/arch/mips/mach-mtmips/Makefile
@@ -3,5 +3,6 @@
 obj-y += cpu.o
 obj-y += ddr_init.o
 obj-y += ddr_cal.o
+obj-$(CONFIG_SPL_BUILD) += spl.o spl_load.o
 
 obj-$(CONFIG_SOC_MT7628) += mt7628/
diff --git a/arch/mips/mach-mtmips/include/mach/serial.h b/arch/mips/mach-mtmips/include/mach/serial.h
new file mode 100644
index 0000000000..bfa246b428
--- /dev/null
+++ b/arch/mips/mach-mtmips/include/mach/serial.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author:  Weijie Gao <weijie.gao at mediatek.com>
+ */
+
+#ifndef _MTMIPS_SERIAL_H_
+#define _MTMIPS_SERIAL_H_
+
+void mtmips_spl_serial_init(void);
+
+#endif /* _MTMIPS_SERIAL_H_ */
diff --git a/arch/mips/mach-mtmips/include/mach/spl.h b/arch/mips/mach-mtmips/include/mach/spl.h
new file mode 100644
index 0000000000..5674dd533e
--- /dev/null
+++ b/arch/mips/mach-mtmips/include/mach/spl.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao at mediatek.com>
+ */
+#ifndef	_MACH_MTMIPS_SPL_H_
+#define	_MACH_MTMIPS_SPL_H_
+
+#include <asm/spl.h>
+
+#define BOOT_DEVICE_MTMIPS_NOR	(BOOT_DEVICE_BOOTROM + 0x100)
+
+#endif /* _MACH_MTMIPS_SPL_H_ */
diff --git a/arch/mips/mach-mtmips/mt7628/Makefile b/arch/mips/mach-mtmips/mt7628/Makefile
index db62e90d77..7e139d5adf 100644
--- a/arch/mips/mach-mtmips/mt7628/Makefile
+++ b/arch/mips/mach-mtmips/mt7628/Makefile
@@ -3,3 +3,4 @@
 obj-y += lowlevel_init.o
 obj-y += init.o
 obj-y += ddr.o
+obj-$(CONFIG_SPL_BUILD) += serial.o
diff --git a/arch/mips/mach-mtmips/mt7628/serial.c b/arch/mips/mach-mtmips/mt7628/serial.c
new file mode 100644
index 0000000000..a7d324792d
--- /dev/null
+++ b/arch/mips/mach-mtmips/mt7628/serial.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author:  Weijie Gao <weijie.gao at mediatek.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include "mt7628.h"
+
+void mtmips_spl_serial_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+	void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+
+#if CONFIG_CONS_INDEX == 1
+	clrbits_32(base + SYSCTL_GPIO_MODE1_REG, UART0_MODE_M);
+#elif CONFIG_CONS_INDEX == 2
+	clrbits_32(base + SYSCTL_GPIO_MODE1_REG, UART1_MODE_M);
+#elif CONFIG_CONS_INDEX == 3
+	setbits_32(base + SYSCTL_AGPIO_CFG_REG, EPHY_GPIO_AIO_EN_M);
+#ifdef CONFIG_SPL_UART2_SPIS_PINMUX
+	setbits_32(base + SYSCTL_GPIO_MODE1_REG, SPIS_MODE_M);
+	clrsetbits_32(base + SYSCTL_GPIO_MODE1_REG, UART2_MODE_M,
+		      1 << UART2_MODE_S);
+#else
+	clrbits_32(base + SYSCTL_GPIO_MODE1_REG, UART2_MODE_M);
+	clrsetbits_32(base + SYSCTL_GPIO_MODE1_REG, SPIS_MODE_M,
+		      1 << SPIS_MODE_S);
+#endif /* CONFIG_SPL_UART2_SPIS_PINMUX */
+#endif /* CONFIG_CONS_INDEX */
+#endif /* CONFIG_SPL_SERIAL_SUPPORT */
+}
diff --git a/arch/mips/mach-mtmips/spl.c b/arch/mips/mach-mtmips/spl.c
new file mode 100644
index 0000000000..f12fb70d75
--- /dev/null
+++ b/arch/mips/mach-mtmips/spl.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao at mediatek.com>
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <linux/sizes.h>
+#include <mach/serial.h>
+#include <mach/spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void __noreturn board_init_f(ulong dummy)
+{
+	spl_init();
+
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+	mtmips_spl_serial_init();
+	preloader_console_init();
+#endif
+
+	board_init_r(NULL, 0);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	spl_boot_list[0] = BOOT_DEVICE_MTMIPS_NOR;
+}
diff --git a/arch/mips/mach-mtmips/spl_load.c b/arch/mips/mach-mtmips/spl_load.c
new file mode 100644
index 0000000000..95dd491baa
--- /dev/null
+++ b/arch/mips/mach-mtmips/spl_load.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao at mediatek.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <asm/sections.h>
+#include <linux/compiler.h>
+#include <linux/sizes.h>
+#include <mach/spl.h>
+#include <spl.h>
+
+#ifdef CONFIG_SPL_LZMA
+#include <lzma/LzmaTypes.h>
+#include <lzma/LzmaDec.h>
+#include <lzma/LzmaTools.h>
+#endif /* CONFIG_SPL_LZMA */
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && defined(CONFIG_OF_SEPARATE)
+#include <fdt.h>
+#endif
+
+static ulong spl_dtb_size(void)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	void *fdt = __image_copy_end;
+
+	if (fdt_magic(fdt) == FDT_MAGIC)
+		return fdt_totalsize(fdt);
+#endif
+
+	return 0;
+}
+
+static int spl_try_load_image(struct spl_image_info *spl_image,
+			      void *image_addr)
+{
+	int ret;
+	uintptr_t dataptr;
+	struct image_header hdr;
+	size_t __maybe_unused lzma_len;
+
+	memcpy(&hdr, (const void *)image_addr, sizeof(hdr));
+
+	ret = spl_parse_image_header(spl_image, &hdr);
+	if (ret)
+		return ret;
+
+	if (!spl_image->entry_point)
+		spl_image->entry_point = spl_image->load_addr;
+
+	dataptr = (uintptr_t)image_addr + sizeof(hdr);
+
+	switch (hdr.ih_comp) {
+	case IH_COMP_NONE:
+		/*
+		 * Load real U-Boot from its location to its defined location
+		 * in SDRAM
+		 */
+		if (spl_image->load_addr != dataptr) {
+			memmove((void *)spl_image->load_addr, (void *)dataptr,
+				spl_image->size);
+		}
+		break;
+#ifdef CONFIG_SPL_LZMA
+	case IH_COMP_LZMA:
+		/*
+		 * Uncompress real U-Boot to its defined location in SDRAM
+		 */
+		lzma_len = SZ_8M;
+
+		ret = lzmaBuffToBuffDecompress((u8 *)spl_image->load_addr,
+					       &lzma_len, (u8 *)dataptr,
+					       spl_image->size);
+
+		if (ret) {
+			printf("Error: LZMA uncompression error: %d\n", ret);
+			return ret;
+		}
+
+		spl_image->size = lzma_len;
+		break;
+#endif /* CONFIG_SPL_LZMA */
+	default:
+		debug("Warning: Unsupported compression method found in image "
+		      "header at offset 0x%p\n", image_addr);
+		return -EINVAL;
+	}
+
+	flush_cache((unsigned long)spl_image->load_addr, spl_image->size);
+
+	return 0;
+}
+
+static int spl_mtk_nor_load_image(struct spl_image_info *spl_image,
+				  struct spl_boot_device *bootdev)
+{
+	ulong offset = spl_dtb_size();
+
+	/*
+	 * Loading of the payload to SDRAM is done with skipping of
+	 * the mkimage header
+	 */
+	spl_image->flags |= SPL_COPY_PAYLOAD_ONLY;
+
+	/* Try to boot without padding */
+	if (!spl_try_load_image(spl_image, (u8 *)__image_copy_end + offset))
+		return 0;
+
+#ifdef CONFIG_SYS_UBOOT_BASE
+	/* Try user defined offset */
+	if (!spl_try_load_image(spl_image, (void *)CONFIG_SYS_UBOOT_BASE))
+		return 0;
+#endif
+
+	return -EINVAL;
+}
+SPL_LOAD_IMAGE_METHOD("NOR", 0, BOOT_DEVICE_MTMIPS_NOR, spl_mtk_nor_load_image);
