Merge branch 'master' of git://git.denx.de/u-boot-sh
diff --git a/Makefile b/Makefile
index 73a080c..1d7d5f2 100644
--- a/Makefile
+++ b/Makefile
@@ -1074,7 +1074,10 @@
 else
 ifneq ($(CONFIG_SPL_FIT_GENERATOR),"")
 U_BOOT_ITS := u-boot.its
-$(U_BOOT_ITS): FORCE
+ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-rockchip/make_fit_atf.py")
+U_BOOT_ITS_DEPS += u-boot
+endif
+$(U_BOOT_ITS): $(U_BOOT_ITS_DEPS) FORCE
 	$(srctree)/$(CONFIG_SPL_FIT_GENERATOR) \
 	$(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@
 endif
diff --git a/arch/Kconfig b/arch/Kconfig
index 9b4bcbf..c988c17 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -60,8 +60,20 @@
 	select SYS_BOOT_GET_KBD
 
 config RISCV
-	bool "riscv architecture"
+	bool "RISC-V architecture"
 	select SUPPORT_OF_CONTROL
+	select OF_CONTROL
+	select DM
+	imply DM_SERIAL
+	imply DM_ETH
+	imply DM_MMC
+	imply DM_SPI
+	imply DM_SPI_FLASH
+	imply BLK
+	imply CLK
+	imply MTD
+	imply TIMER
+	imply CMD_DM
 
 config SANDBOX
 	bool "Sandbox"
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index d59aa3a..b24593e 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -157,6 +157,10 @@
 config TARGET_HSDK
 	bool "Support Synpsys HS DevelopmentKit board"
 
+config TARGET_IOT_DEVKIT
+	bool "Synopsys Brite IoT Development kit"
+	select CPU_ARCEM6
+
 endchoice
 
 source "board/abilis/tb100/Kconfig"
@@ -164,5 +168,6 @@
 source "board/synopsys/axs10x/Kconfig"
 source "board/synopsys/emdk/Kconfig"
 source "board/synopsys/hsdk/Kconfig"
+source "board/synopsys/iot_devkit/Kconfig"
 
 endmenu
diff --git a/arch/arc/config.mk b/arch/arc/config.mk
index 169e5d7..d255c90 100644
--- a/arch/arc/config.mk
+++ b/arch/arc/config.mk
@@ -9,21 +9,15 @@
 endif
 
 ifdef CONFIG_SYS_LITTLE_ENDIAN
-ARC_CROSS_COMPILE := arc-linux-
 PLATFORM_LDFLAGS += -EL
 PLATFORM_CPPFLAGS += -mlittle-endian
 endif
 
 ifdef CONFIG_SYS_BIG_ENDIAN
-ARC_CROSS_COMPILE := arceb-linux-
 PLATFORM_LDFLAGS += -EB
 PLATFORM_CPPFLAGS += -mbig-endian
 endif
 
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := $(ARC_CROSS_COMPILE)
-endif
-
 ifdef CONFIG_ARC_MMU_VER
 CONFIG_MMU = 1
 endif
diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile
index 491a4f4..17e1405 100644
--- a/arch/arc/dts/Makefile
+++ b/arch/arc/dts/Makefile
@@ -6,6 +6,7 @@
 dtb-$(CONFIG_TARGET_TB100) +=  abilis_tb100.dtb
 dtb-$(CONFIG_TARGET_EMDK) +=  emdk.dtb
 dtb-$(CONFIG_TARGET_HSDK) +=  hsdk.dtb
+dtb-$(CONFIG_TARGET_IOT_DEVKIT) +=  iot_devkit.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/arc/dts/abilis_tb100.dts b/arch/arc/dts/abilis_tb100.dts
index de3e57d..19e45b9 100644
--- a/arch/arc/dts/abilis_tb100.dts
+++ b/arch/arc/dts/abilis_tb100.dts
@@ -7,6 +7,8 @@
 #include "skeleton.dtsi"
 
 / {
+	model = "abilis,tb100";
+
 	aliases {
 		console = &uart0;
 	};
diff --git a/arch/arc/dts/axs101.dts b/arch/arc/dts/axs101.dts
index 13873be..fc9fa93 100644
--- a/arch/arc/dts/axs101.dts
+++ b/arch/arc/dts/axs101.dts
@@ -9,6 +9,8 @@
 
 
 / {
+	model = "snps,axs101";
+
 	chosen {
 		stdout-path = &uart0;
 	};
diff --git a/arch/arc/dts/axs103.dts b/arch/arc/dts/axs103.dts
index 81778c8..6e2dd00 100644
--- a/arch/arc/dts/axs103.dts
+++ b/arch/arc/dts/axs103.dts
@@ -9,6 +9,8 @@
 
 
 / {
+	model = "snps,axs103";
+
 	chosen {
 		stdout-path = &uart0;
 	};
diff --git a/arch/arc/dts/emdk.dts b/arch/arc/dts/emdk.dts
index 5e853e3..ebe538d 100644
--- a/arch/arc/dts/emdk.dts
+++ b/arch/arc/dts/emdk.dts
@@ -7,6 +7,8 @@
 #include "skeleton.dtsi"
 
 / {
+	model = "snps,emdk";
+
 	#address-cells = <1>;
 	#size-cells = <1>;
 
diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts
index 673bc5b..f024b96 100644
--- a/arch/arc/dts/hsdk.dts
+++ b/arch/arc/dts/hsdk.dts
@@ -8,6 +8,8 @@
 #include "dt-bindings/clock/snps,hsdk-cgu.h"
 
 / {
+	model = "snps,hsdk";
+
 	#address-cells = <1>;
 	#size-cells = <1>;
 
diff --git a/arch/arc/dts/iot_devkit.dts b/arch/arc/dts/iot_devkit.dts
new file mode 100644
index 0000000..ebf5a95
--- /dev/null
+++ b/arch/arc/dts/iot_devkit.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		console = &uart0;
+	};
+
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <144000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	uart0: serial0@80014000 {
+		compatible = "snps,dw-apb-uart";
+		clock-frequency = <16000000>;
+		reg = <0x80014000 0x1000>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+	usb: usb@f0040000 {
+		compatible = "snps,dwc2";
+		reg = <0xf0040000 0x10000>;
+		phys = <&usbphy>;
+		phy-names = "usb2-phy";
+	};
+
+	usbphy: phy {
+		compatible = "nop-phy";
+		#phy-cells = <0>;
+	};
+};
diff --git a/arch/arc/dts/nsim.dts b/arch/arc/dts/nsim.dts
index 9c1c7aa..243ecb1 100644
--- a/arch/arc/dts/nsim.dts
+++ b/arch/arc/dts/nsim.dts
@@ -7,6 +7,8 @@
 #include "skeleton.dtsi"
 
 / {
+	model = "snps,nsim";
+
 	aliases {
 		console = &arcuart0;
 	};
diff --git a/arch/arc/lib/cpu.c b/arch/arc/lib/cpu.c
index cb95e06..50cd7cd 100644
--- a/arch/arc/lib/cpu.c
+++ b/arch/arc/lib/cpu.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ * Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved.
  */
 
 #include <common.h>
@@ -33,3 +33,36 @@
 {
 	return 0;
 }
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+const char *decode_identity(void)
+{
+	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
+
+	switch (arcver) {
+	/* ARCompact cores */
+	case 0x32: return "ARC 700 v4.4-4.5";
+	case 0x33: return "ARC 700 v4.6-v4.9";
+	case 0x34: return "ARC 700 v4.10";
+	case 0x35: return "ARC 700 v4.11";
+
+	/* ARCv2 cores */
+	case 0x41: return "ARC EM v1.1a";
+	case 0x42: return "ARC EM v3.0";
+	case 0x43: return "ARC EM v4.0";
+	case 0x50: return "ARC HS v1.0";
+	case 0x51: return "ARC EM v2.0";
+	case 0x52: return "ARC EM v2.1";
+	case 0x53: return "ARC HS v3.0";
+	case 0x54: return "ARC HS v4.0";
+
+	default: return "Unknown ARC core";
+	}
+}
+
+int print_cpuinfo(void)
+{
+	printf("CPU:   %s\n", decode_identity());
+	return 0;
+}
+#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/dts/rk3188-radxarock-u-boot.dtsi b/arch/arm/dts/rk3188-radxarock-u-boot.dtsi
index 013535a..1bb5408 100644
--- a/arch/arm/dts/rk3188-radxarock-u-boot.dtsi
+++ b/arch/arm/dts/rk3188-radxarock-u-boot.dtsi
@@ -11,6 +11,21 @@
 	u-boot,dm-spl;
 };
 
+&mmc0 {
+	fifo-mode;
+	max-frequency = <16000000>;
+};
+
+&mmc1 {
+	fifo-mode;
+	max-frequency = <16000000>;
+};
+
+&emmc {
+	fifo-mode;
+	max-frequency = <16000000>;
+};
+
 &uart2 {
 	status = "okay";
 	u-boot,dm-spl;
diff --git a/arch/arm/dts/rk3188-radxarock.dts b/arch/arm/dts/rk3188-radxarock.dts
index ac931e1..6136712 100644
--- a/arch/arm/dts/rk3188-radxarock.dts
+++ b/arch/arm/dts/rk3188-radxarock.dts
@@ -104,6 +104,8 @@
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 		gpio = <&gpio3 1 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwr>;
 		startup-delay-us = <100000>;
 		vin-supply = <&vcc_io>;
 	};
@@ -334,6 +336,12 @@
 		};
 	};
 
+	sd0 {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <RK_GPIO3 1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	usb {
 		host_vbus_drv: host-vbus-drv {
 			rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
diff --git a/arch/arm/mach-rockchip/fit_spl_optee.its b/arch/arm/mach-rockchip/fit_spl_optee.its
new file mode 100644
index 0000000..9be4b3c
--- /dev/null
+++ b/arch/arm/mach-rockchip/fit_spl_optee.its
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 Rockchip Electronic Co.,Ltd
+ *
+ * Simple U-boot fit source file containing U-Boot, dtb and optee
+ */
+
+/dts-v1/;
+
+/ {
+	description = "Simple image with OP-TEE support";
+	#address-cells = <1>;
+
+	images {
+		uboot@1 {
+			description = "U-Boot";
+			data = /incbin/("../../../u-boot-nodtb.bin");
+			type = "standalone";
+			os = "U-Boot";
+			arch = "arm";
+			compression = "none";
+			load = <0x61000000>;
+		};
+		optee@1 {
+			description = "OP-TEE";
+			data = /incbin/("../../../tee.bin");
+			type = "firmware";
+			arch = "arm";
+			os = "tee";
+			compression = "none";
+			load = <0x68400000>;
+			entry = <0x68400000>;
+		};
+		fdt@1 {
+			description = "dtb";
+			data = /incbin/("../../../u-boot.dtb");
+			type = "flat_dt";
+			compression = "none";
+		};
+	};
+
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			description = "Rockchip armv7 with OP-TEE";
+			firmware = "optee@1";
+			loadables = "uboot@1";
+			fdt = "fdt@1";
+		};
+	};
+};
diff --git a/arch/arm/mach-rockchip/make_fit_atf.py b/arch/arm/mach-rockchip/make_fit_atf.py
index 6b3d920..d1faff1 100755
--- a/arch/arm/mach-rockchip/make_fit_atf.py
+++ b/arch/arm/mach-rockchip/make_fit_atf.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
 """
 A script to generate FIT image source for rockchip boards
 with ARM Trusted Firmware
@@ -34,7 +34,7 @@
 	#address-cells = <1>;
 
 	images {
-		uboot@1 {
+		uboot {
 			description = "U-Boot (64-bit)";
 			data = /incbin/("u-boot-nodtb.bin");
 			type = "standalone";
@@ -43,6 +43,7 @@
 			compression = "none";
 			load = <0x%08x>;
 		};
+
 """
 
 DT_IMAGES_NODE_END="""
@@ -53,23 +54,23 @@
 };
 """
 
-def append_atf_node(file, atf_index, phy_addr):
+def append_atf_node(file, atf_index, phy_addr, elf_entry):
     """
     Append ATF DT node to input FIT dts file.
     """
     data = 'bl31_0x%08x.bin' % phy_addr
-    print >> file, '\t\tatf@%d {' % atf_index
-    print >> file, '\t\t\tdescription = \"ARM Trusted Firmware\";'
-    print >> file, '\t\t\tdata = /incbin/("%s");' % data
-    print >> file, '\t\t\ttype = "firmware";'
-    print >> file, '\t\t\tarch = "arm64";'
-    print >> file, '\t\t\tos = "arm-trusted-firmware";'
-    print >> file, '\t\t\tcompression = "none";'
-    print >> file, '\t\t\tload = <0x%08x>;' % phy_addr
+    file.write('\t\tatf_%d {\n' % atf_index)
+    file.write('\t\t\tdescription = \"ARM Trusted Firmware\";\n')
+    file.write('\t\t\tdata = /incbin/("%s");\n' % data)
+    file.write('\t\t\ttype = "firmware";\n')
+    file.write('\t\t\tarch = "arm64";\n')
+    file.write('\t\t\tos = "arm-trusted-firmware";\n')
+    file.write('\t\t\tcompression = "none";\n')
+    file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
     if atf_index == 1:
-        print >> file, '\t\t\tentry = <0x%08x>;' % phy_addr
-    print >> file, '\t\t};'
-    print >> file, ''
+        file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
+    file.write('\t\t};\n')
+    file.write('\n')
 
 def append_fdt_node(file, dtbs):
     """
@@ -78,43 +79,43 @@
     cnt = 1
     for dtb in dtbs:
         dtname = os.path.basename(dtb)
-        print >> file, '\t\tfdt@%d {' % cnt
-        print >> file, '\t\t\tdescription = "%s";' % dtname
-        print >> file, '\t\t\tdata = /incbin/("%s");' % dtb
-        print >> file, '\t\t\ttype = "flat_dt";'
-        print >> file, '\t\t\tcompression = "none";'
-        print >> file, '\t\t};'
-        print >> file, ''
+        file.write('\t\tfdt_%d {\n' % cnt)
+        file.write('\t\t\tdescription = "%s";\n' % dtname)
+        file.write('\t\t\tdata = /incbin/("%s");\n' % dtb)
+        file.write('\t\t\ttype = "flat_dt";\n')
+        file.write('\t\t\tcompression = "none";\n')
+        file.write('\t\t};\n')
+        file.write('\n')
         cnt = cnt + 1
 
 def append_conf_section(file, cnt, dtname, atf_cnt):
-    print >> file, '\t\tconfig@%d {' % cnt
-    print >> file, '\t\t\tdescription = "%s";' % dtname
-    print >> file, '\t\t\tfirmware = "atf@1";'
-    print >> file, '\t\t\tloadables = "uboot@1",',
+    file.write('\t\tconfig_%d {\n' % cnt)
+    file.write('\t\t\tdescription = "%s";\n' % dtname)
+    file.write('\t\t\tfirmware = "atf_1";\n')
+    file.write('\t\t\tloadables = "uboot",')
     for i in range(1, atf_cnt):
-        print >> file, '"atf@%d"' % (i+1),
+        file.write('"atf_%d"' % (i+1))
         if i != (atf_cnt - 1):
-            print >> file, ',',
+            file.write(',')
         else:
-            print >> file, ';'
-    print >> file, '\t\t\tfdt = "fdt@1";'
-    print >> file, '\t\t};'
-    print >> file, ''
+            file.write(';\n')
+    file.write('\t\t\tfdt = "fdt_1";\n')
+    file.write('\t\t};\n')
+    file.write('\n')
 
 def append_conf_node(file, dtbs, atf_cnt):
     """
     Append configeration nodes.
     """
     cnt = 1
-    print >> file, '\tconfigurations {'
-    print >> file, '\t\tdefault = "config@1";'
+    file.write('\tconfigurations {\n')
+    file.write('\t\tdefault = "config_1";\n')
     for dtb in dtbs:
         dtname = os.path.basename(dtb)
         append_conf_section(file, cnt, dtname, atf_cnt)
         cnt = cnt + 1
-    print >> file, '\t};'
-    print >> file, ''
+    file.write('\t};\n')
+    file.write('\n')
 
 def generate_atf_fit_dts(fit_file_name, bl31_file_name, uboot_file_name, dtbs_file_name):
     """
@@ -127,7 +128,7 @@
 
     num_load_seg = 0
     p_paddr = 0xFFFFFFFF
-    with open(uboot_file_name) as uboot_file:
+    with open(uboot_file_name, 'rb') as uboot_file:
         uboot = ELFFile(uboot_file)
         for i in range(uboot.num_segments()):
             seg = uboot.get_segment(i)
@@ -137,27 +138,28 @@
 
     assert (p_paddr != 0xFFFFFFFF and num_load_seg == 1)
 
-    print >> fit_file, DT_HEADER % p_paddr
+    fit_file.write(DT_HEADER % p_paddr)
 
-    with open(bl31_file_name) as bl31_file:
+    with open(bl31_file_name, 'rb') as bl31_file:
         bl31 = ELFFile(bl31_file)
+        elf_entry = bl31.header['e_entry']
         for i in range(bl31.num_segments()):
             seg = bl31.get_segment(i)
             if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)):
                 paddr = seg.__getitem__(ELF_SEG_P_PADDR)
                 p= seg.__getitem__(ELF_SEG_P_PADDR)
-                append_atf_node(fit_file, i+1, paddr)
+                append_atf_node(fit_file, i+1, paddr, elf_entry)
     atf_cnt = i+1
     append_fdt_node(fit_file, dtbs_file_name)
-    print >> fit_file, '%s' % DT_IMAGES_NODE_END
+    fit_file.write('%s\n' % DT_IMAGES_NODE_END)
     append_conf_node(fit_file, dtbs_file_name, atf_cnt)
-    print >> fit_file, '%s' % DT_END
+    fit_file.write('%s\n' % DT_END)
 
     if fit_file_name != sys.stdout:
         fit_file.close()
 
 def generate_atf_binary(bl31_file_name):
-    with open(bl31_file_name) as bl31_file:
+    with open(bl31_file_name, 'rb') as bl31_file:
         bl31 = ELFFile(bl31_file)
 
         num = bl31.num_segments()
@@ -178,17 +180,17 @@
         bl31 = ELFFile(bl31_file)
 
         num = bl31.num_segments()
-        print 'Number of Segments : %d' % bl31.num_segments()
+        print('Number of Segments : %d' % bl31.num_segments())
         for i in range(num):
-            print 'Segment %d' % i
+            print('Segment %d' % i)
             seg = bl31.get_segment(i)
             ptype = seg[ELF_SEG_P_TYPE]
             poffset = seg[ELF_SEG_P_OFFSET]
             pmemsz = seg[ELF_SEG_P_MEMSZ]
             pfilesz = seg[ELF_SEG_P_FILESZ]
-            print 'type: %s\nfilesz: %08x\nmemsz: %08x\noffset: %08x' % (ptype, pfilesz, pmemsz, poffset)
+            print('type: %s\nfilesz: %08x\nmemsz: %08x\noffset: %08x' % (ptype, pfilesz, pmemsz, poffset))
             paddr = seg[ELF_SEG_P_PADDR]
-            print 'paddr: %08x' % paddr
+            print('paddr: %08x' % paddr)
 
 def main():
     uboot_elf="./u-boot"
@@ -204,7 +206,7 @@
         elif opt == "-b":
             bl31_elf=val
         elif opt == "-h":
-            print __doc__
+            print(__doc__)
             sys.exit(2)
 
     dtbs = args
diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_s10.h b/arch/arm/mach-socfpga/include/mach/reset_manager_s10.h
index 6182d5f..31b73ed 100644
--- a/arch/arm/mach-socfpga/include/mach/reset_manager_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/reset_manager_s10.h
@@ -108,8 +108,6 @@
 #define RSTMGR_GPIO1		RSTMGR_DEFINE(2, 25)
 #define RSTMGR_SDR		RSTMGR_DEFINE(3, 6)
 
-void socfpga_emac_manage_reset(const unsigned int of_reset_id, u32 state);
-
 /* Create a human-readable reference to SoCFPGA reset. */
 #define SOCFPGA_RESET(_name)	RSTMGR_##_name
 
diff --git a/arch/arm/mach-socfpga/misc_s10.c b/arch/arm/mach-socfpga/misc_s10.c
index 918baac..e599362 100644
--- a/arch/arm/mach-socfpga/misc_s10.c
+++ b/arch/arm/mach-socfpga/misc_s10.c
@@ -36,7 +36,8 @@
 	if (!phymode)
 		return -EINVAL;
 
-	if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii"))
+	if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii") ||
+	    !strcmp(phymode, "sgmii"))
 		modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
 	else if (!strcmp(phymode, "rgmii"))
 		modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
@@ -58,7 +59,7 @@
 	struct fdtdec_phandle_args args;
 	const char *phy_mode;
 	u32 gmac_index;
-	int nodes[2];	/* Max. 3 GMACs */
+	int nodes[3];	/* Max. 3 GMACs */
 	int ret, count;
 	int i, node;
 
diff --git a/arch/arm/mach-socfpga/reset_manager_s10.c b/arch/arm/mach-socfpga/reset_manager_s10.c
index 5cc8336..f176c38 100644
--- a/arch/arm/mach-socfpga/reset_manager_s10.c
+++ b/arch/arm/mach-socfpga/reset_manager_s10.c
@@ -93,41 +93,6 @@
 	}
 }
 
-/* of_reset_id: emac reset id
- * state: 0 - disable reset, !0 - enable reset
- */
-void socfpga_emac_manage_reset(const unsigned int of_reset_id, u32 state)
-{
-	u32 reset_emac;
-	u32 reset_emacocp;
-
-	/* hardcode this now */
-	switch (of_reset_id) {
-	case EMAC0_RESET:
-		reset_emac = SOCFPGA_RESET(EMAC0);
-		reset_emacocp = SOCFPGA_RESET(EMAC0_OCP);
-		break;
-	case EMAC1_RESET:
-		reset_emac = SOCFPGA_RESET(EMAC1);
-		reset_emacocp = SOCFPGA_RESET(EMAC1_OCP);
-		break;
-	case EMAC2_RESET:
-		reset_emac = SOCFPGA_RESET(EMAC2);
-		reset_emacocp = SOCFPGA_RESET(EMAC2_OCP);
-		break;
-	default:
-		printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id);
-		hang();
-		break;
-	}
-
-	/* Reset ECC OCP first */
-	socfpga_per_reset(reset_emacocp, state);
-
-	/* Release the EMAC controller from reset */
-	socfpga_per_reset(reset_emac, state);
-}
-
 /*
  * Release peripherals from reset based on handoff
  */
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 20a43d8..168ca3d 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -1,4 +1,4 @@
-menu "RISCV architecture"
+menu "RISC-V architecture"
 	depends on RISCV
 
 config SYS_ARCH
@@ -11,22 +11,26 @@
 config TARGET_AX25_AE350
 	bool "Support ax25-ae350"
 
+config TARGET_QEMU_VIRT
+	bool "Support QEMU Virt Board"
+
 endchoice
 
 source "board/AndesTech/ax25-ae350/Kconfig"
+source "board/emulation/qemu-riscv/Kconfig"
 
 choice
 	prompt "CPU selection"
 	default CPU_RISCV_32
 
 config CPU_RISCV_32
-	bool "RISCV 32 bit"
+	bool "RISC-V 32-bit"
 	select 32BIT
 	help
 	  Choose this option to build an U-Boot for RISCV32 architecture.
 
 config CPU_RISCV_64
-	bool "RISCV 64 bit"
+	bool "RISC-V 64-bit"
 	select 64BIT
 	help
 	  Choose this option to build an U-Boot for RISCV64 architecture.
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 084888a..8fb6a88 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -3,7 +3,8 @@
 # Copyright (C) 2017 Andes Technology Corporation.
 # Rick Chen, Andes Technology Corporation <rick@andestech.com>
 
-head-y := arch/riscv/cpu/$(CPU)/start.o
+head-y := arch/riscv/cpu/start.o
 
+libs-y += arch/riscv/cpu/
 libs-y += arch/riscv/cpu/$(CPU)/
 libs-y += arch/riscv/lib/
diff --git a/arch/riscv/config.mk b/arch/riscv/config.mk
index c0b3858..ed9eb0c 100644
--- a/arch/riscv/config.mk
+++ b/arch/riscv/config.mk
@@ -10,20 +10,20 @@
 # Rick Chen, Andes Technology Corporation <rick@andestech.com>
 #
 
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := riscv32-unknown-linux-gnu-
-endif
-
 32bit-emul		:= elf32lriscv
 64bit-emul		:= elf64lriscv
 
 ifdef CONFIG_32BIT
+PLATFORM_CPPFLAGS	+= -march=rv32ima -mabi=ilp32
 PLATFORM_LDFLAGS	+= -m $(32bit-emul)
+CFLAGS_EFI		+= -march=rv32ima -mabi=ilp32
 EFI_LDS			:= elf_riscv32_efi.lds
 endif
 
 ifdef CONFIG_64BIT
+PLATFORM_CPPFLAGS	+= -march=rv64ima -mabi=lp64
 PLATFORM_LDFLAGS	+= -m $(64bit-emul)
+CFLAGS_EFI		+= -march=rv64ima -mabi=lp64
 EFI_LDS			:= elf_riscv64_efi.lds
 endif
 
@@ -31,8 +31,8 @@
 			      -T $(srctree)/examples/standalone/riscv.lds
 
 PLATFORM_CPPFLAGS	+= -ffixed-gp -fpic
-PLATFORM_RELFLAGS += -fno-common -gdwarf-2 -ffunction-sections
-LDFLAGS_u-boot += --gc-sections -static -pie
+PLATFORM_RELFLAGS	+= -fno-common -gdwarf-2 -ffunction-sections
+LDFLAGS_u-boot		+= --gc-sections -static -pie
 
 EFI_CRT0		:= crt0_riscv_efi.o
 EFI_RELOC		:= reloc_riscv_efi.o
diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile
new file mode 100644
index 0000000..2cc6757
--- /dev/null
+++ b/arch/riscv/cpu/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+
+extra-y = start.o
+
+obj-y += cpu.o
diff --git a/arch/riscv/cpu/ax25/Makefile b/arch/riscv/cpu/ax25/Makefile
index c3f164c..2ab0342 100644
--- a/arch/riscv/cpu/ax25/Makefile
+++ b/arch/riscv/cpu/ax25/Makefile
@@ -3,6 +3,4 @@
 # Copyright (C) 2017 Andes Technology Corporation
 # Rick Chen, Andes Technology Corporation <rick@andestech.com>
 
-extra-y	= start.o
-
 obj-y	:= cpu.o
diff --git a/arch/riscv/cpu/ax25/cpu.c b/arch/riscv/cpu/ax25/cpu.c
index ab05b57..fddcc15 100644
--- a/arch/riscv/cpu/ax25/cpu.c
+++ b/arch/riscv/cpu/ax25/cpu.c
@@ -6,9 +6,6 @@
 
 /* CPU specific code */
 #include <common.h>
-#include <command.h>
-#include <watchdog.h>
-#include <asm/cache.h>
 
 /*
  * cleanup_before_linux() is called just before we call linux
@@ -24,9 +21,3 @@
 
 	return 0;
 }
-
-int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	disable_interrupts();
-	panic("ax25-ae350 wdt not support yet.\n");
-}
diff --git a/arch/riscv/cpu/ax25/u-boot.lds b/arch/riscv/cpu/ax25/u-boot.lds
deleted file mode 100644
index c50b964..0000000
--- a/arch/riscv/cpu/ax25/u-boot.lds
+++ /dev/null
@@ -1,90 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2017 Andes Technology Corporation
- * Rick Chen, Andes Technology Corporation <rick@andestech.com>
- */
-OUTPUT_ARCH("riscv")
-ENTRY(_start)
-
-SECTIONS
-{
-	. = ALIGN(4);
-	.text :
-	{
-		arch/riscv/cpu/ax25/start.o	(.text)
-	}
-
-	/* This needs to come before *(.text*) */
-	.efi_runtime : {
-                __efi_runtime_start = .;
-		*(.text.efi_runtime*)
-		*(.rodata.efi_runtime*)
-		*(.data.efi_runtime*)
-                __efi_runtime_stop = .;
-	}
-
-	.text_rest :
-	{
-		*(.text*)
-	}
-
-	. = ALIGN(4);
-	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
-
-	. = ALIGN(4);
-	.data : {
-		__global_pointer$ = . + 0x800;
-		*(.data*)
-	}
-	. = ALIGN(4);
-
-	.got : {
-	   __got_start = .;
-	   *(.got.plt) *(.got)
-	   __got_end = .;
-    }
-
-	. = ALIGN(4);
-
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
-	}
-
-    . = ALIGN(4);
-
-	.efi_runtime_rel : {
-                __efi_runtime_rel_start = .;
-		*(.rel*.efi_runtime)
-		*(.rel*.efi_runtime.*)
-                __efi_runtime_rel_stop = .;
-	}
-
-    . = ALIGN(4);
-
-    /DISCARD/ : { *(.rela.plt*) }
-    .rela.dyn : {
-        __rel_dyn_start = .;
-        *(.rela*)
-        __rel_dyn_end = .;
-    }
-
-    . = ALIGN(4);
-
-    .dynsym : {
-        __dyn_sym_start = .;
-        *(.dynsym)
-        __dyn_sym_end = .;
-    }
-
-    . = ALIGN(4);
-
-	_end = .;
-
-	.bss : {
-        __bss_start = .;
-        *(.bss*)
-		. = ALIGN(4);
-		__bss_end = .;
-	}
-
-}
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
new file mode 100644
index 0000000..ae57fb8
--- /dev/null
+++ b/arch/riscv/cpu/cpu.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/csr.h>
+
+enum {
+	ISA_INVALID = 0,
+	ISA_32BIT,
+	ISA_64BIT,
+	ISA_128BIT
+};
+
+static const char * const isa_bits[] = {
+	[ISA_INVALID] = NULL,
+	[ISA_32BIT]   = "32",
+	[ISA_64BIT]   = "64",
+	[ISA_128BIT]  = "128"
+};
+
+static inline bool supports_extension(char ext)
+{
+	return csr_read(misa) & (1 << (ext - 'a'));
+}
+
+int print_cpuinfo(void)
+{
+	char name[32];
+	char *s = name;
+	int bit;
+
+	s += sprintf(name, "rv");
+	bit = csr_read(misa) >> (sizeof(long) * 8 - 2);
+	s += sprintf(s, isa_bits[bit]);
+
+	supports_extension('i') ? *s++ = 'i' : 'r';
+	supports_extension('m') ? *s++ = 'm' : 'i';
+	supports_extension('a') ? *s++ = 'a' : 's';
+	supports_extension('f') ? *s++ = 'f' : 'c';
+	supports_extension('d') ? *s++ = 'd' : '-';
+	supports_extension('c') ? *s++ = 'c' : 'v';
+	*s++ = '\0';
+
+	printf("CPU:   %s\n", name);
+
+	return 0;
+}
diff --git a/arch/riscv/cpu/qemu/Makefile b/arch/riscv/cpu/qemu/Makefile
new file mode 100644
index 0000000..258e462
--- /dev/null
+++ b/arch/riscv/cpu/qemu/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+
+obj-y += dram.o
+obj-y += cpu.o
diff --git a/arch/riscv/cpu/qemu/cpu.c b/arch/riscv/cpu/qemu/cpu.c
new file mode 100644
index 0000000..6c7a327
--- /dev/null
+++ b/arch/riscv/cpu/qemu/cpu.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+
+/*
+ * cleanup_before_linux() is called just before we call linux
+ * it prepares the processor for linux
+ *
+ * we disable interrupt and caches.
+ */
+int cleanup_before_linux(void)
+{
+	disable_interrupts();
+
+	/* turn off I/D-cache */
+
+	return 0;
+}
diff --git a/arch/riscv/cpu/qemu/dram.c b/arch/riscv/cpu/qemu/dram.c
new file mode 100644
index 0000000..84d87d2
--- /dev/null
+++ b/arch/riscv/cpu/qemu/dram.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+
+int dram_init(void)
+{
+	return fdtdec_setup_mem_size_base();
+}
+
+int dram_init_banksize(void)
+{
+	return fdtdec_setup_memory_banksize();
+}
diff --git a/arch/riscv/cpu/ax25/start.S b/arch/riscv/cpu/start.S
similarity index 100%
rename from arch/riscv/cpu/ax25/start.S
rename to arch/riscv/cpu/start.S
diff --git a/arch/riscv/cpu/u-boot.lds b/arch/riscv/cpu/u-boot.lds
new file mode 100644
index 0000000..11bc4a7
--- /dev/null
+++ b/arch/riscv/cpu/u-boot.lds
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ */
+
+OUTPUT_ARCH("riscv")
+ENTRY(_start)
+
+SECTIONS
+{
+	. = ALIGN(4);
+	.text : {
+		arch/riscv/cpu/start.o	(.text)
+	}
+
+	/* This needs to come before *(.text*) */
+	.efi_runtime : {
+		__efi_runtime_start = .;
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+		__efi_runtime_stop = .;
+	}
+
+	.text_rest : {
+		*(.text*)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		__global_pointer$ = . + 0x800;
+		*(.data*)
+	}
+	. = ALIGN(4);
+
+	.got : {
+		__got_start = .;
+		*(.got.plt) *(.got)
+		__got_end = .;
+	}
+
+	. = ALIGN(4);
+
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	. = ALIGN(4);
+
+	.efi_runtime_rel : {
+		__efi_runtime_rel_start = .;
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
+		__efi_runtime_rel_stop = .;
+	}
+
+	. = ALIGN(4);
+
+	/DISCARD/ : { *(.rela.plt*) }
+	.rela.dyn : {
+		__rel_dyn_start = .;
+		*(.rela*)
+		__rel_dyn_end = .;
+	}
+
+	. = ALIGN(4);
+
+	.dynsym : {
+		__dyn_sym_start = .;
+		*(.dynsym)
+		__dyn_sym_end = .;
+	}
+
+	. = ALIGN(4);
+
+	_end = .;
+
+	.bss : {
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	}
+}
diff --git a/arch/riscv/dts/ae350.dts b/arch/riscv/dts/ae350.dts
index 2927e41..4717ae8 100644
--- a/arch/riscv/dts/ae350.dts
+++ b/arch/riscv/dts/ae350.dts
@@ -1,144 +1,147 @@
 /dts-v1/;
 
 / {
-  #address-cells = <2>;
-  #size-cells = <2>;
-  compatible = "andestech,ax25";
-  model = "andestech,ax25";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	compatible = "andestech,ax25";
+	model = "andestech,ax25";
 
 	aliases {
 		uart0 = &serial0;
 		spi0 = &spi;
-	} ;
+	};
 
 	chosen {
 		bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
 		stdout-path = "uart0:38400n8";
-  };
+	};
 
-  cpus {
-    #address-cells = <1>;
-    #size-cells = <0>;
-    timebase-frequency = <10000000>;
-    CPU0: cpu@0 {
-      device_type = "cpu";
-      reg = <0>;
-      status = "okay";
-      compatible = "riscv";
-      riscv,isa = "rv64imafdc";
-      mmu-type = "riscv,sv39";
-      clock-frequency = <60000000>;
-      CPU0_intc: interrupt-controller {
-        #interrupt-cells = <1>;
-        interrupt-controller;
-        compatible = "riscv,cpu-intc";
-      };
-    };
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		timebase-frequency = <10000000>;
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv64imafdc";
+			mmu-type = "riscv,sv39";
+			clock-frequency = <60000000>;
+
+			CPU0_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
 	};
 
 	memory@0 {
 		device_type = "memory";
-    reg = <0x0 0x00000000 0x0 0x40000000>;
+		reg = <0x0 0x00000000 0x0 0x40000000>;
 	};
 
-  soc {
-    #address-cells = <2>;
-    #size-cells = <2>;
-    compatible = "andestech,riscv-ae350-soc";
-    ranges;
+	soc {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "andestech,riscv-ae350-soc";
+		ranges;
 	};
 
-  plmt0@e6000000 {
-    compatible = "riscv,plmt0";
-    interrupts-extended = <&CPU0_intc 7>;
-    reg = <0x0 0xe6000000 0x0 0x100000>;
-		};
-
-  plic0: interrupt-controller@e4000000 {
-    compatible = "riscv,plic0";
-    #address-cells = <2>;
-    #interrupt-cells = <2>;
-    interrupt-controller;
-    reg = <0x0 0xe4000000 0x0 0x2000000>;
-    riscv,ndev=<31>;
-    interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+	plmt0@e6000000 {
+		compatible = "riscv,plmt0";
+		interrupts-extended = <&CPU0_intc 7>;
+		reg = <0x0 0xe6000000 0x0 0x100000>;
 	};
 
-  plic1: interrupt-controller@e6400000 {
-    compatible = "riscv,plic1";
-    #address-cells = <2>;
-    #interrupt-cells = <2>;
+	plic0: interrupt-controller@e4000000 {
+		compatible = "riscv,plic0";
+		#address-cells = <2>;
+		#interrupt-cells = <2>;
 		interrupt-controller;
-    reg = <0x0 0xe6400000 0x0 0x400000>;
-    riscv,ndev=<1>;
-    interrupts-extended = <&CPU0_intc 3>;
-  };
+		reg = <0x0 0xe4000000 0x0 0x2000000>;
+		riscv,ndev=<31>;
+		interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+	};
 
-  spiclk: virt_100mhz {
-    #clock-cells = <0>;
-    compatible = "fixed-clock";
-    clock-frequency = <100000000>;
-  };
+	plic1: interrupt-controller@e6400000 {
+		compatible = "riscv,plic1";
+		#address-cells = <2>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0x0 0xe6400000 0x0 0x400000>;
+		riscv,ndev=<1>;
+		interrupts-extended = <&CPU0_intc 3>;
+	};
 
-  timer0: timer@f0400000 {
-    compatible = "andestech,atcpit100";
-    reg = <0x0 0xf0400000 0x0 0x1000>;
-    clock-frequency = <40000000>;
-    interrupts = <3 4>;
-    interrupt-parent = <&plic0>;
+	spiclk: virt_100mhz {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <100000000>;
+	};
+
+	timer0: timer@f0400000 {
+		compatible = "andestech,atcpit100";
+		reg = <0x0 0xf0400000 0x0 0x1000>;
+		clock-frequency = <40000000>;
+		interrupts = <3 4>;
+		interrupt-parent = <&plic0>;
 	};
 
 	serial0: serial@f0300000 {
 		compatible = "andestech,uart16550", "ns16550a";
-    reg = <0x0 0xf0300000 0x0 0x1000>;
-    interrupts = <9 4>;
+		reg = <0x0 0xf0300000 0x0 0x1000>;
+		interrupts = <9 4>;
 		clock-frequency = <19660800>;
 		reg-shift = <2>;
 		reg-offset = <32>;
 		no-loopback-test = <1>;
-    interrupt-parent = <&plic0>;
+		interrupt-parent = <&plic0>;
 	};
 
 	mac0: mac@e0100000 {
 		compatible = "andestech,atmac100";
-    reg = <0x0 0xe0100000 0x0 0x1000>;
-    interrupts = <19 4>;
-    interrupt-parent = <&plic0>;
+		reg = <0x0 0xe0100000 0x0 0x1000>;
+		interrupts = <19 4>;
+		interrupt-parent = <&plic0>;
 	};
 
 	mmc0: mmc@f0e00000 {
-    compatible = "andestech,atfsdc010";
+		compatible = "andestech,atfsdc010";
 		max-frequency = <100000000>;
-    clock-freq-min-max = <400000 100000000>;
+		clock-freq-min-max = <400000 100000000>;
 		fifo-depth = <0x10>;
-    reg = <0x0 0xf0e00000 0x0 0x1000>;
-    interrupts = <18 4>;
+		reg = <0x0 0xf0e00000 0x0 0x1000>;
+		interrupts = <18 4>;
 		cap-sd-highspeed;
-    interrupt-parent = <&plic0>;
+		interrupt-parent = <&plic0>;
 	};
 
-  smc0: smc@e0400000 {
-    compatible = "andestech,atfsmc020";
-    reg = <0x0 0xe0400000 0x0 0x1000>;
-  };
+	smc0: smc@e0400000 {
+		compatible = "andestech,atfsmc020";
+		reg = <0x0 0xe0400000 0x0 0x1000>;
+	};
 
-  nor@0,0 {
-    compatible = "cfi-flash";
-    reg = <0x0 0x88000000 0x0 0x1000>;
-    bank-width = <2>;
-    device-width = <1>;
-  };
+	nor@0,0 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x88000000 0x0 0x1000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
 
 	spi: spi@f0b00000 {
 		compatible = "andestech,atcspi200";
-    reg = <0x0 0xf0b00000 0x0 0x1000>;
+		reg = <0x0 0xf0b00000 0x0 0x1000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		num-cs = <1>;
 		clocks = <&spiclk>;
 		interrupts = <3 4>;
-    interrupt-parent = <&plic0>;
-			flash@0 {
+		interrupt-parent = <&plic0>;
+
+		flash@0 {
 			compatible = "spi-flash";
 			spi-max-frequency = <50000000>;
 			reg = <0>;
diff --git a/arch/riscv/include/asm/bootm.h b/arch/riscv/include/asm/bootm.h
deleted file mode 100644
index 6786345..0000000
--- a/arch/riscv/include/asm/bootm.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 2013, Google Inc.
- *
- * Copyright (C) 2011
- * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
- */
-#ifndef NDS32_BOOTM_H
-#define NDS32_BOOTM_H
-
-#include <asm/setup.h>
-
-#endif
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
new file mode 100644
index 0000000..50fccea
--- /dev/null
+++ b/arch/riscv/include/asm/csr.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015 Regents of the University of California
+ *
+ * Taken from Linux arch/riscv/include/asm/csr.h
+ */
+
+#ifndef _ASM_RISCV_CSR_H
+#define _ASM_RISCV_CSR_H
+
+/* Status register flags */
+#define SR_SIE		_AC(0x00000002, UL) /* Supervisor Interrupt Enable */
+#define SR_SPIE		_AC(0x00000020, UL) /* Previous Supervisor IE */
+#define SR_SPP		_AC(0x00000100, UL) /* Previously Supervisor */
+#define SR_SUM		_AC(0x00040000, UL) /* Supervisor access User Memory */
+
+#define SR_FS		_AC(0x00006000, UL) /* Floating-point Status */
+#define SR_FS_OFF	_AC(0x00000000, UL)
+#define SR_FS_INITIAL	_AC(0x00002000, UL)
+#define SR_FS_CLEAN	_AC(0x00004000, UL)
+#define SR_FS_DIRTY	_AC(0x00006000, UL)
+
+#define SR_XS		_AC(0x00018000, UL) /* Extension Status */
+#define SR_XS_OFF	_AC(0x00000000, UL)
+#define SR_XS_INITIAL	_AC(0x00008000, UL)
+#define SR_XS_CLEAN	_AC(0x00010000, UL)
+#define SR_XS_DIRTY	_AC(0x00018000, UL)
+
+#ifndef CONFIG_64BIT
+#define SR_SD		_AC(0x80000000, UL) /* FS/XS dirty */
+#else
+#define SR_SD		_AC(0x8000000000000000, UL) /* FS/XS dirty */
+#endif
+
+/* SATP flags */
+#if __riscv_xlen == 32
+#define SATP_PPN	_AC(0x003FFFFF, UL)
+#define SATP_MODE_32	_AC(0x80000000, UL)
+#define SATP_MODE	SATP_MODE_32
+#else
+#define SATP_PPN	_AC(0x00000FFFFFFFFFFF, UL)
+#define SATP_MODE_39	_AC(0x8000000000000000, UL)
+#define SATP_MODE	SATP_MODE_39
+#endif
+
+/* Interrupt Enable and Interrupt Pending flags */
+#define SIE_SSIE	_AC(0x00000002, UL) /* Software Interrupt Enable */
+#define SIE_STIE	_AC(0x00000020, UL) /* Timer Interrupt Enable */
+
+#define EXC_INST_MISALIGNED	0
+#define EXC_INST_ACCESS		1
+#define EXC_BREAKPOINT		3
+#define EXC_LOAD_ACCESS		5
+#define EXC_STORE_ACCESS	7
+#define EXC_SYSCALL		8
+#define EXC_INST_PAGE_FAULT	12
+#define EXC_LOAD_PAGE_FAULT	13
+#define EXC_STORE_PAGE_FAULT	15
+
+#ifndef __ASSEMBLY__
+
+#define csr_swap(csr, val)					\
+({								\
+	unsigned long __v = (unsigned long)(val);		\
+	__asm__ __volatile__ ("csrrw %0, " #csr ", %1"		\
+			      : "=r" (__v) : "rK" (__v)		\
+			      : "memory");			\
+	__v;							\
+})
+
+#define csr_read(csr)						\
+({								\
+	register unsigned long __v;				\
+	__asm__ __volatile__ ("csrr %0, " #csr			\
+			      : "=r" (__v) :			\
+			      : "memory");			\
+	__v;							\
+})
+
+#define csr_write(csr, val)					\
+({								\
+	unsigned long __v = (unsigned long)(val);		\
+	__asm__ __volatile__ ("csrw " #csr ", %0"		\
+			      : : "rK" (__v)			\
+			      : "memory");			\
+})
+
+#define csr_read_set(csr, val)					\
+({								\
+	unsigned long __v = (unsigned long)(val);		\
+	__asm__ __volatile__ ("csrrs %0, " #csr ", %1"		\
+			      : "=r" (__v) : "rK" (__v)		\
+			      : "memory");			\
+	__v;							\
+})
+
+#define csr_set(csr, val)					\
+({								\
+	unsigned long __v = (unsigned long)(val);		\
+	__asm__ __volatile__ ("csrs " #csr ", %0"		\
+			      : : "rK" (__v)			\
+			      : "memory");			\
+})
+
+#define csr_read_clear(csr, val)				\
+({								\
+	unsigned long __v = (unsigned long)(val);		\
+	__asm__ __volatile__ ("csrrc %0, " #csr ", %1"		\
+			      : "=r" (__v) : "rK" (__v)		\
+			      : "memory");			\
+	__v;							\
+})
+
+#define csr_clear(csr, val)					\
+({								\
+	unsigned long __v = (unsigned long)(val);		\
+	__asm__ __volatile__ ("csrc " #csr ", %0"		\
+			      : : "rK" (__v)			\
+			      : "memory");			\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_RISCV_CSR_H */
diff --git a/arch/riscv/include/asm/encoding.h b/arch/riscv/include/asm/encoding.h
index f237a72..9ea50ce 100644
--- a/arch/riscv/include/asm/encoding.h
+++ b/arch/riscv/include/asm/encoding.h
@@ -128,6 +128,7 @@
 	((SUPERVISOR) ? PTE_SR(PTE) : PTE_UR(PTE)))
 
 #ifdef __riscv
+
 #ifdef CONFIG_64BIT
 # define MSTATUS_SD MSTATUS64_SD
 # define SSTATUS_SD SSTATUS64_SD
@@ -141,53 +142,10 @@
 # define MCAUSE_INT MCAUSE32_INT
 # define MCAUSE_CAUSE MCAUSE32_CAUSE
 #endif
+
 #define RISCV_PGSHIFT 12
 #define RISCV_PGSIZE BIT(RISCV_PGSHIFT)
 
-#ifndef __ASSEMBLER__
+#endif /* __riscv */
 
-#ifdef __GNUC__
-
-#define read_csr(reg) ({ unsigned long __tmp; \
-	asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
-	__tmp; })
-
-#define write_csr(reg, _val) ({ \
-typeof(_val) (val) = (_val); \
-if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
-	asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
-else \
-	asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
-
-#define swap_csr(reg, _val) ({ unsigned long __tmp; \
-typeof(_val) (val) = (_val); \
-if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
-	asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \
-else \
-	asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
-	__tmp; })
-
-#define set_csr(reg, _bit) ({ unsigned long __tmp; \
-typeof(_bit) (bit) = (_bit); \
-if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
-	asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
-else \
-	asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
-	__tmp; })
-
-#define clear_csr(reg, _bit) ({ unsigned long __tmp; \
-typeof(_bit) (bit) = (_bit); \
-if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
-	asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
-else \
-	asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
-	__tmp; })
-
-#define rdtime() read_csr(time)
-#define rdcycle() read_csr(cycle)
-#define rdinstret() read_csr(instret)
-
-#endif
-#endif
-#endif
-#endif
+#endif /* RISCV_CSR_ENCODING_H */
diff --git a/arch/riscv/include/asm/mach-types.h b/arch/riscv/include/asm/mach-types.h
deleted file mode 100644
index f219ced..0000000
--- a/arch/riscv/include/asm/mach-types.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2017 Andes Technology Corporation
- * Rick Chen, Andes Technology Corporation <rick@andestech.com>
- */
-
-#ifndef __ASM_RISCV_MACH_TYPE_H
-#define __ASM_RISCV_MACH_TYPE_H
-
-#ifndef __ASSEMBLY__
-/* The type of machine we're running on */
-extern unsigned int __machine_arch_type;
-#endif
-
-#define MACH_TYPE_AE350		1
-
-#ifdef CONFIG_ARCH_AE350
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type __machine_arch_type
-# else
-#  define machine_arch_type MACH_TYPE_AE350
-# endif
-# define machine_is_ae350() (machine_arch_type == MACH_TYPE_AE350)
-#else
-# define machine_is_ae350() (1)
-#endif
-
-#endif /* __ASM_RISCV_MACH_TYPE_H */
diff --git a/arch/riscv/include/asm/setup.h b/arch/riscv/include/asm/setup.h
deleted file mode 100644
index ff8de16..0000000
--- a/arch/riscv/include/asm/setup.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *  linux/arch/nds32/include/asm/setup.h
- *
- * Copyright (C) 1997-1999 Russell King
- * Copyright (C) 2008 Andes Technology Corporation
- * Copyright (C) 2013 Ken Kuo (ken_kuo@andestech.com)
- * Copyright (C) 2017 Rick Chen (rick@andestech.com)
- *
- *  Structure passed to kernel to tell it about the
- *  hardware it's running on.  See Documentation/arm/Setup
- *  for more info.
- */
-#ifndef __RISCV_SETUP_H
-#define __RISCV_SETUP_H
-
-#define COMMAND_LINE_SIZE 256
-
-/* The list ends with an ATAG_NONE node. */
-#define ATAG_NONE	0x00000000
-
-struct tag_header {
-	u32 size;
-	u32 tag;
-};
-
-/* The list must start with an ATAG_CORE node */
-#define ATAG_CORE	0x54410001
-
-struct tag_core {
-	u32 flags;		/* bit 0 = read-only */
-	u32 pagesize;
-	u32 rootdev;
-};
-
-/* it is allowed to have multiple ATAG_MEM nodes */
-#define ATAG_MEM	0x54410002
-
-struct tag_mem32 {
-	u32	size;
-	u32	start;	/* physical start address */
-};
-
-/* VGA text type displays */
-#define ATAG_VIDEOTEXT	0x54410003
-
-struct tag_videotext {
-	u8		x;
-	u8		y;
-	u16		video_page;
-	u8		video_mode;
-	u8		video_cols;
-	u16		video_ega_bx;
-	u8		video_lines;
-	u8		video_isvga;
-	u16		video_points;
-};
-
-/* describes how the ramdisk will be used in kernel */
-#define ATAG_RAMDISK	0x54410004
-
-struct tag_ramdisk {
-	u32 flags;	/* bit 0 = load, bit 1 = prompt */
-	u32 size;	/* decompressed ramdisk size in _kilo_ bytes */
-	u32 start;	/* starting block of floppy-based RAM disk image */
-};
-
-/*
- * this one accidentally used virtual addresses - as such,
- * it's deprecated.
- * describes where the compressed ramdisk image lives (virtual address)
- */
-#define ATAG_INITRD		0x54410005
-
-/* describes where the compressed ramdisk image lives (physical address) */
-#define ATAG_INITRD2	0x54420005
-
-struct tag_initrd {
-	u32 start;	/* physical start address */
-	u32 size;	/* size of compressed ramdisk image in bytes */
-};
-
-/* board serial number. "64 bits should be enough for everybody" */
-#define ATAG_SERIAL		0x54410006
-
-struct tag_serialnr {
-	u32 low;
-	u32 high;
-};
-
-/* board revision */
-#define ATAG_REVISION	0x54410007
-
-struct tag_revision {
-	u32 rev;
-};
-
-/* initial values for vesafb-type framebuffers. see struct screen_info
- * in include/linux/tty.h
- */
-#define ATAG_VIDEOLFB	0x54410008
-
-struct tag_videolfb {
-	u16		lfb_width;
-	u16		lfb_height;
-	u16		lfb_depth;
-	u16		lfb_linelength;
-	u32		lfb_base;
-	u32		lfb_size;
-	u8		red_size;
-	u8		red_pos;
-	u8		green_size;
-	u8		green_pos;
-	u8		blue_size;
-	u8		blue_pos;
-	u8		rsvd_size;
-	u8		rsvd_pos;
-};
-
-/* command line: \0 terminated string */
-#define ATAG_CMDLINE	0x54410009
-
-struct tag_cmdline {
-	char	cmdline[COMMAND_LINE_SIZE];
-};
-
-struct tag {
-	struct tag_header hdr;
-	union {
-		struct tag_core		core;
-		struct tag_mem32	mem;
-		struct tag_videotext	videotext;
-		struct tag_ramdisk	ramdisk;
-		struct tag_initrd	initrd;
-		struct tag_serialnr	serialnr;
-		struct tag_revision	revision;
-		struct tag_videolfb	videolfb;
-		struct tag_cmdline	cmdline;
-	} u;
-};
-
-struct tagtable {
-	u32 tag;
-	int (*parse)(const struct tag *);
-};
-
-#define tag_member_present(_tag, member)				\
-	typeof(_tag) (tag) = (_tag); \
-	((unsigned long)(&((struct tag *)0L)->member + 1)	\
-		<= (tag)->hdr.size * 4)
-
-#define tag_next(_t)	\
-	typeof(_t) (t) = (_t); \
-	((struct tag *)((u32 *)(t) + (t)->hdr.size))
-#define tag_size(type)	((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
-
-#define for_each_tag(_t, base) \
-	typeof(_t) (t) = (_t); \
-	for (t = base; t->hdr.size; t = tag_next(t))
-
-#ifdef __KERNEL__
-
-#define __tag __used __attribute__((__section__(".taglist")))
-#define __tagtable(tag, fn) \
-static struct tagtable __tagtable_##fn __tag = { tag, fn }
-
-/*
- * Memory map description
- */
-#define NR_BANKS 8
-
-struct meminfo {
-	int nr_banks;
-	struct {
-		unsigned long start;
-		unsigned long size;
-		int           node;
-	} bank[NR_BANKS];
-};
-
-/*
- * Early command line parameters.
- */
-struct early_params {
-	const char *arg;
-	void (*fn)(char **p);
-};
-
-#define __early_param(name, fn)					\
-static struct early_params __early_##fn __used	\
-__attribute__((__section__("__early_param"))) = { name, fn }
-
-#endif
-#endif
diff --git a/arch/riscv/include/asm/u-boot.h b/arch/riscv/include/asm/u-boot.h
index 9e5b32d..3186835 100644
--- a/arch/riscv/include/asm/u-boot.h
+++ b/arch/riscv/include/asm/u-boot.h
@@ -23,7 +23,6 @@
 #include <environment.h>
 
 typedef struct bd_info {
-	unsigned long	bi_arch_number;	/* unique id for this board */
 	unsigned long	bi_boot_params;	/* where this board expects params */
 	unsigned long	bi_memstart;	/* start of DRAM memory */
 	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index cc562f9..b58db89 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -10,6 +10,7 @@
 obj-$(CONFIG_CMD_GO) += boot.o
 obj-y	+= cache.o
 obj-y	+= interrupts.o
+obj-y	+= reset.o
 obj-y   += setjmp.o
 
 # For building EFI apps
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index 2610a57..a7a9fb9 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -11,7 +11,7 @@
 #include <image.h>
 #include <u-boot/zlib.h>
 #include <asm/byteorder.h>
-#include <asm/bootm.h>
+#include <asm/csr.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -26,10 +26,7 @@
 
 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
 {
-	bd_t	*bd = gd->bd;
-	char	*s;
-	int	machid = bd->bi_arch_number;
-	void	(*theKernel)(int arch, uint params);
+	void	(*kernel)(ulong hart, void *dtb);
 
 	/*
 	 * allow the PREP bootm subcommand, it is required for bootm to work
@@ -40,18 +37,12 @@
 	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
 		return 1;
 
-	theKernel = (void (*)(int, uint))images->ep;
-
-	s = env_get("machid");
-	if (s) {
-		machid = simple_strtoul(s, NULL, 16);
-		printf("Using machid 0x%x from environment\n", machid);
-	}
+	kernel = (void (*)(ulong, void *))images->ep;
 
 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 
 	debug("## Transferring control to Linux (at address %08lx) ...\n",
-	       (ulong)theKernel);
+	       (ulong)kernel);
 
 	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
 #ifdef CONFIG_OF_LIBFDT
@@ -67,8 +58,9 @@
 	printf("\nStarting kernel ...\n\n");
 
 	cleanup_before_linux();
+
 	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
-		theKernel(machid, (unsigned long)images->ft_addr);
+		kernel(csr_read(mhartid), images->ft_addr);
 
 	/* does not return */
 
diff --git a/arch/riscv/lib/reset.c b/arch/riscv/lib/reset.c
new file mode 100644
index 0000000..b8cecb3
--- /dev/null
+++ b/arch/riscv/lib/reset.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	printf("resetting ...\n");
+
+	printf("reset not supported yet\n");
+	hang();
+
+	return 0;
+}
diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c
index fd5aaa1..5f4ca0f 100644
--- a/board/AndesTech/ax25-ae350/ax25-ae350.c
+++ b/board/AndesTech/ax25-ae350/ax25-ae350.c
@@ -4,7 +4,6 @@
  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
  */
 
-#include <asm/mach-types.h>
 #include <common.h>
 #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
 #include <netdev.h>
@@ -21,7 +20,6 @@
 
 int board_init(void)
 {
-	gd->bd->bi_arch_number = MACH_TYPE_AE350;
 	gd->bd->bi_boot_params = PHYS_SDRAM_0 + 0x400;
 
 	return 0;
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
new file mode 100644
index 0000000..af23363
--- /dev/null
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -0,0 +1,22 @@
+if TARGET_QEMU_VIRT
+
+config SYS_BOARD
+	default "qemu-riscv"
+
+config SYS_VENDOR
+	default "emulation"
+
+config SYS_CPU
+	default "qemu"
+
+config SYS_CONFIG_NAME
+	default "qemu-riscv"
+
+config SYS_TEXT_BASE
+	default 0x80000000
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	imply SYS_NS16550
+
+endif
diff --git a/board/emulation/qemu-riscv/MAINTAINERS b/board/emulation/qemu-riscv/MAINTAINERS
new file mode 100644
index 0000000..3c6eb4f
--- /dev/null
+++ b/board/emulation/qemu-riscv/MAINTAINERS
@@ -0,0 +1,7 @@
+QEMU RISC-V 'VIRT' BOARD
+M:	Bin Meng <bmeng.cn@gmail.com>
+S:	Maintained
+F:	board/emulation/qemu-riscv/
+F:	include/configs/qemu-riscv.h
+F:	configs/qemu-riscv32_defconfig
+F:	configs/qemu-riscv64_defconfig
diff --git a/board/emulation/qemu-riscv/Makefile b/board/emulation/qemu-riscv/Makefile
new file mode 100644
index 0000000..3f29b90
--- /dev/null
+++ b/board/emulation/qemu-riscv/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+
+obj-y	+= qemu-riscv.o
diff --git a/board/emulation/qemu-riscv/qemu-riscv.c b/board/emulation/qemu-riscv/qemu-riscv.c
new file mode 100644
index 0000000..041e716
--- /dev/null
+++ b/board/emulation/qemu-riscv/qemu-riscv.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+
+#define MROM_FDT_ADDR	0x1020
+
+int board_init(void)
+{
+	return 0;
+}
+
+void *board_fdt_blob_setup(void)
+{
+	/*
+	 * QEMU loads a generated DTB for us immediately
+	 * after the reset vectors in the MROM
+	 */
+	return (void *)MROM_FDT_ADDR;
+}
diff --git a/board/synopsys/iot_devkit/Kconfig b/board/synopsys/iot_devkit/Kconfig
new file mode 100644
index 0000000..ad956b2
--- /dev/null
+++ b/board/synopsys/iot_devkit/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_IOT_DEVKIT
+
+config SYS_BOARD
+	default "iot_devkit"
+
+config SYS_VENDOR
+	default "synopsys"
+
+config SYS_CONFIG_NAME
+	default "iot_devkit"
+
+endif
diff --git a/board/synopsys/iot_devkit/MAINTAINERS b/board/synopsys/iot_devkit/MAINTAINERS
new file mode 100644
index 0000000..06457cf
--- /dev/null
+++ b/board/synopsys/iot_devkit/MAINTAINERS
@@ -0,0 +1,5 @@
+IOT DEVKIT BOARD
+M:	Alexey Brodkin <abrodkin@synopsys.com>
+S:	Maintained
+F:	board/synopsys/iot_devkit/
+F:	configs/iot_devkit_defconfig
diff --git a/board/synopsys/iot_devkit/Makefile b/board/synopsys/iot_devkit/Makefile
new file mode 100644
index 0000000..1616024
--- /dev/null
+++ b/board/synopsys/iot_devkit/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= iot_devkit.o
diff --git a/board/synopsys/iot_devkit/config.mk b/board/synopsys/iot_devkit/config.mk
new file mode 100644
index 0000000..1207335
--- /dev/null
+++ b/board/synopsys/iot_devkit/config.mk
@@ -0,0 +1,2 @@
+PLATFORM_CPPFLAGS += -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter
+LDSCRIPT = $(srctree)/board/synopsys/iot_devkit/u-boot.lds
diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c
new file mode 100644
index 0000000..c185d5c
--- /dev/null
+++ b/board/synopsys/iot_devkit/iot_devkit.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dwmmc.h>
+#include <linux/libfdt.h>
+#include <fdtdec.h>
+
+#include <asm/arcregs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SYSCON_BASE	0xf000a000
+#define AHBCKDIV	(void *)(SYSCON_BASE + 0x04)
+#define APBCKDIV	(void *)(SYSCON_BASE + 0x08)
+#define APBCKEN		(void *)(SYSCON_BASE + 0x0C)
+#define CLKSEL		(void *)(SYSCON_BASE + 0x24)
+#define CLKSTAT		(void *)(SYSCON_BASE + 0x28)
+#define PLLCON		(void *)(SYSCON_BASE + 0x2C)
+#define APBCKSEL	(void *)(SYSCON_BASE + 0x30)
+#define AHBCKEN		(void *)(SYSCON_BASE + 0x34)
+#define USBPHY_PLL	(void *)(SYSCON_BASE + 0x78)
+#define USBCFG		(void *)(SYSCON_BASE + 0x7c)
+
+#define PLL_MASK_0	0xffcfffff
+#define PLL_MASK_1	0xffcfff00
+#define PLL_MASK_2	0xfbcfff00
+
+#define CLKSEL_DEFAULT	0x5a690000
+
+static int set_cpu_freq(unsigned int clk)
+{
+	clk /= 1000000;
+
+	/* Set clk to ext Xtal (LSN value 0) */
+	writel(CLKSEL_DEFAULT, CLKSEL);
+
+	switch (clk) {
+	case 16:
+		/* Bypass mode */
+		return 0;
+
+	case 50:
+		writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+		/* pll_off=1, M=25, N=1, OD=3, PLL_OUT_CLK=50M */
+		writel((readl(PLLCON) & PLL_MASK_1) | 0x300191, PLLCON);
+		/* pll_off=0, M=25, N=1, OD=3, PLL_OUT_CLK=50M */
+		writel((readl(PLLCON) & PLL_MASK_2) | 0x300191, PLLCON);
+		break;
+
+	case 72:
+		writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+		/* pll_off=1, M=18, N=1, OD=2, PLL_OUT_CLK=72M */
+		writel((readl(PLLCON) & PLL_MASK_1) | 0x200121, PLLCON);
+		/* pll_off=0, M=18, N=1, OD=2, PLL_OUT_CLK=72M */
+		writel((readl(PLLCON) & PLL_MASK_2) | 0x200121, PLLCON);
+		break;
+
+	case 100:
+		writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+		/* pll_off=1,M=25, N=1, OD=2, PLL_OUT_CLK=100M */
+		writel((readl(PLLCON) & PLL_MASK_1) | 0x200191, PLLCON);
+		/* pll_off=0,M=25, N=1, OD=2, PLL_OUT_CLK=100M */
+		writel((readl(PLLCON) & PLL_MASK_2) | 0x200191, PLLCON);
+		break;
+
+	case 144:
+		writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+		/* pll_off=1, M=18, N=1, OD=1, PLL_OUT_CLK=144M */
+		writel((readl(PLLCON) & PLL_MASK_1) | 0x100121, PLLCON);
+		/* pll_off=0, M=18, N=1, OD=1, PLL_OUT_CLK=144M */
+		writel((readl(PLLCON) & PLL_MASK_2) | 0x100121, PLLCON);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	while (!(readl(CLKSTAT) & 0x4))
+		;
+
+	/* Set clk from PLL on bus (LSN = 1) */
+	writel(CLKSEL_DEFAULT | BIT(0), CLKSEL);
+
+	return 0;
+}
+
+extern u8 __rom_end[];
+extern u8 __ram_start[];
+extern u8 __ram_end[];
+
+/*
+ * Use mach_cpu_init() for .data section copy as board_early_init_f() will be
+ * too late: initf_dm() will use a value of "av_" variable from not yet
+ * initialized (by copy) area.
+ */
+int mach_cpu_init(void)
+{
+	int offset, freq;
+
+	/* Don't relocate U-Boot */
+	gd->flags |= GD_FLG_SKIP_RELOC;
+
+	/* Copy data from ROM to RAM */
+	u8 *src = __rom_end;
+	u8 *dst = __ram_start;
+
+	while (dst < __ram_end)
+		*dst++ = *src++;
+
+	/* Enable debug uart */
+#define DEBUG_UART_BASE		0x80014000
+#define DEBUG_UART_DLF_OFFSET	0xc0
+	write_aux_reg(DEBUG_UART_BASE + DEBUG_UART_DLF_OFFSET, 1);
+
+	offset = fdt_path_offset(gd->fdt_blob, "/cpu_card/core_clk");
+	if (offset < 0)
+		return offset;
+
+	freq = fdtdec_get_int(gd->fdt_blob, offset, "clock-frequency", 0);
+	if (!freq)
+		return -EINVAL;
+
+	/* If CPU freq > 100 MHz, divide eFLASH clock by 2 */
+	if (freq > 100000000) {
+		u32 reg = readl(AHBCKDIV);
+
+		reg &= ~(0xF << 8);
+		reg |= 2 << 8;
+		writel(reg, AHBCKDIV);
+	}
+
+	return set_cpu_freq(freq);
+}
+
+#define ARC_PERIPHERAL_BASE	0xF0000000
+#define SDIO_BASE		(ARC_PERIPHERAL_BASE + 0xB000)
+
+int board_mmc_init(bd_t *bis)
+{
+	struct dwmci_host *host = NULL;
+
+	host = malloc(sizeof(struct dwmci_host));
+	if (!host) {
+		printf("dwmci_host malloc fail!\n");
+		return -ENOMEM;
+	}
+
+	memset(host, 0, sizeof(struct dwmci_host));
+	host->name = "Synopsys Mobile storage";
+	host->ioaddr = (void *)SDIO_BASE;
+	host->buswidth = 4;
+	host->dev_index = 0;
+	host->bus_hz = 50000000;
+
+	add_dwmci(host, host->bus_hz / 2, 400000);
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: Synopsys IoT Development Kit\n");
+	return 0;
+};
diff --git a/board/synopsys/iot_devkit/u-boot.lds b/board/synopsys/iot_devkit/u-boot.lds
new file mode 100644
index 0000000..d083168
--- /dev/null
+++ b/board/synopsys/iot_devkit/u-boot.lds
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+
+MEMORY {
+	ROM : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE
+	RAM : ORIGIN = RAM_DATA_BASE, LENGTH = RAM_DATA_SIZE
+}
+
+OUTPUT_FORMAT("elf32-littlearc", "elf32-littlearc", "elf32-littlearc")
+OUTPUT_ARCH(arc)
+ENTRY(_start)
+SECTIONS
+{
+	. = CONFIG_SYS_MONITOR_BASE;
+	__image_copy_start = .;
+	.ivt :
+	{
+		__ivt_start = .;
+		KEEP(*(.ivt));
+		__ivt_end = .;
+	} > ROM
+
+	. = ALIGN(1024);
+	.text :	{
+		__text_start = .;
+		arch/arc/lib/start.o (.text*)
+		*(.text*)
+		__text_end = .;
+	} > ROM
+
+	. = ALIGN(4);
+	.rodata : {
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+	} > ROM
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+
+		/* Mark RAM's LMA */
+		. = ALIGN(4);
+		__rom_end = .;
+	} > ROM
+
+	.data : {
+		/* Mark RAM's VMA */
+		. = ALIGN(4);
+
+		/*
+		 * Everything between __ram_start and __ram_start will be
+		 * copied from ROM to RAM in board_early_init_f().
+		 */
+		__ram_start = .;
+
+		*(.data*)
+
+		__ram_end = .;
+	} > RAM AT > ROM
+
+	.bss : {
+		. = ALIGN(1024);
+		__bss_start = .;
+		*(.bss*)
+		__bss_end = .;
+	} > RAM
+
+	/* Keep relocation-related symbols to make linker happy */
+	__rel_dyn_start = .;
+	__rel_dyn_end = .;
+	__image_copy_end = .;
+	__init_end = .;
+}
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 397dd15..60b4387 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -424,9 +424,10 @@
 {
 	bd_t *bd = gd->bd;
 
-	print_num("arch_number", bd->bi_arch_number);
 	print_bi_boot_params(bd);
 	print_bi_dram(bd);
+	print_num("relocaddr", gd->relocaddr);
+	print_num("reloc off", gd->reloc_off);
 	print_eth_ip_addr();
 	print_baudrate();
 
diff --git a/common/Kconfig b/common/Kconfig
index 41f27a1..d7300c2 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -573,7 +573,7 @@
 
 config DISPLAY_CPUINFO
 	bool "Display information about the CPU during start up"
-	default y if ARM || NIOS2 || X86 || XTENSA || M68K
+	default y if ARC|| ARM || NIOS2 || X86 || XTENSA || M68K
 	help
 	  Display information about the CPU that U-Boot is running on
 	  when U-Boot starts up. The function print_cpuinfo() is called
@@ -581,7 +581,7 @@
 
 config DISPLAY_BOARDINFO
 	bool "Display information about the board during early start up"
-	default y if ARM || M68K || MIPS || PPC || SANDBOX || XTENSA
+	default y if ARC || ARM || M68K || MIPS || PPC || SANDBOX || XTENSA
 	help
 	  Display information about the board that U-Boot is running on
 	  when U-Boot starts up. The board function checkboard() is called
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 18dbc23..d056462 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -832,6 +832,13 @@
 	  Enable access to the AM33xx RTC and select the external 32kHz clock
 	  source.
 
+config SPL_OPTEE
+	bool "Support OP-TEE Trusted OS"
+	depends on ARM
+	help
+	  OP-TEE is an open source Trusted OS  which is loaded by SPL.
+	  More detail at: https://github.com/OP-TEE/optee_os
+
 config TPL
 	bool
 	depends on SUPPORT_TPL
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 814081f..a130a5b 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_$(SPL_TPL_)NET_SUPPORT) += spl_net.o
 obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += spl_mmc.o
 obj-$(CONFIG_$(SPL_TPL_)ATF) += spl_atf.o
+obj-$(CONFIG_$(SPL_TPL_)OPTEE) += spl_optee.o
 obj-$(CONFIG_$(SPL_TPL_)USB_SUPPORT) += spl_usb.o
 obj-$(CONFIG_$(SPL_TPL_)FAT_SUPPORT) += spl_fat.o
 obj-$(CONFIG_$(SPL_TPL_)EXT_SUPPORT) += spl_ext.o
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 038f2b0..292e659 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -536,6 +536,13 @@
 		spl_invoke_atf(&spl_image);
 		break;
 #endif
+#if CONFIG_IS_ENABLED(OPTEE)
+	case IH_OS_TEE:
+		debug("Jumping to U-Boot via OP-TEE\n");
+		spl_optee_entry(NULL, NULL, spl_image.fdt_addr,
+				(void *)spl_image.entry_point);
+		break;
+#endif
 #ifdef CONFIG_SPL_OS_BOOT
 	case IH_OS_LINUX:
 		debug("Jumping to Linux\n");
diff --git a/common/spl/spl_optee.S b/common/spl/spl_optee.S
new file mode 100644
index 0000000..8bd1949
--- /dev/null
+++ b/common/spl/spl_optee.S
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017 Rockchip Electronic Co.,Ltd
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(spl_optee_entry)
+	ldr lr, =CONFIG_SYS_TEXT_BASE
+	mov pc, r3
+ENDPROC(spl_optee_entry)
diff --git a/configs/ax25-ae350_defconfig b/configs/ax25-ae350_defconfig
index d64f078..614ef15 100644
--- a/configs/ax25-ae350_defconfig
+++ b/configs/ax25-ae350_defconfig
@@ -15,30 +15,20 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_BOOTP_PREFER_SERVERIP=y
 CONFIG_CMD_CACHE=y
-CONFIG_OF_CONTROL=y
 CONFIG_OF_BOARD=y
 CONFIG_DEFAULT_DEVICE_TREE="ae350"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_DM=y
-CONFIG_CLK=y
 CONFIG_MMC=y
-CONFIG_DM_MMC=y
 CONFIG_FTSDC010=y
 CONFIG_FTSDC010_SDIO=y
-CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=y
-CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
-CONFIG_DM_ETH=y
 CONFIG_FTMAC100=y
 CONFIG_BAUDRATE=38400
-CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
-CONFIG_DM_SPI=y
 CONFIG_ATCSPI200_SPI=y
-CONFIG_TIMER=y
 CONFIG_ATCPIT100_TIMER=y
diff --git a/configs/iot_devkit_defconfig b/configs/iot_devkit_defconfig
new file mode 100644
index 0000000..1f0f9c3
--- /dev/null
+++ b/configs/iot_devkit_defconfig
@@ -0,0 +1,38 @@
+CONFIG_ARC=y
+CONFIG_ISA_ARCV2=y
+CONFIG_CPU_ARCEM6=y
+CONFIG_SYS_ICACHE_OFF=y
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_TARGET_IOT_DEVKIT=y
+CONFIG_SYS_TEXT_BASE=0x20000000
+CONFIG_SYS_CLK_FREQ=16000000
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_SYS_PROMPT="IoTDK# "
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_BOOTM is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_NET is not set
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_EMBED=y
+CONFIG_DEFAULT_DEVICE_TREE="iot_devkit"
+CONFIG_ENV_IS_IN_FAT=y
+CONFIG_ENV_FAT_INTERFACE="mmc"
+CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
+CONFIG_DM=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_BUFFER_SIZE=16
+CONFIG_USB_STORAGE=y
+CONFIG_FS_FAT_MAX_CLUSTSIZE=4096
diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig
new file mode 100644
index 0000000..ff1fb1f
--- /dev/null
+++ b/configs/qemu-riscv32_defconfig
@@ -0,0 +1,6 @@
+CONFIG_RISCV=y
+CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_OF_BOARD=y
diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig
new file mode 100644
index 0000000..d6c1a5d
--- /dev/null
+++ b/configs/qemu-riscv64_defconfig
@@ -0,0 +1,7 @@
+CONFIG_RISCV=y
+CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_CPU_RISCV_64=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_OF_BOARD=y
diff --git a/doc/README.qemu-riscv b/doc/README.qemu-riscv
new file mode 100644
index 0000000..e2e4804
--- /dev/null
+++ b/doc/README.qemu-riscv
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+
+U-Boot on QEMU's 'virt' machine on RISC-V
+=========================================
+
+QEMU for RISC-V supports a special 'virt' machine designed for emulation and
+virtualization purposes. This document describes how to run U-Boot under it.
+Both 32-bit 64-bit targets are supported.
+
+The QEMU virt machine models a generic RISC-V virtual machine with support for
+the VirtIO standard networking and block storage devices. It has CLINT, PLIC,
+16550A UART devices in addition to VirtIO and it also uses device-tree to pass
+configuration information to guest software. It implements RISC-V privileged
+architecture spec v1.10.
+
+Building U-Boot
+---------------
+Set the CROSS_COMPILE environment variable as usual, and run:
+
+- For 32-bit RISC-V:
+    make qemu-riscv32_defconfig
+    make
+
+- For 64-bit RISC-V:
+    make qemu-riscv64_defconfig
+    make
+
+Running U-Boot
+--------------
+The minimal QEMU command line to get U-Boot up and running is:
+
+- For 32-bit RISC-V:
+    qemu-system-riscv32 -nographic -machine virt -kernel u-boot
+
+- For 64-bit RISC-V:
+    qemu-system-riscv64 -nographic -machine virt -kernel u-boot
+
+The commands above create targets with 128MiB memory by default.
+A freely configurable amount of RAM can be created via the '-m'
+parameter. For example, '-m 2G' creates 2GiB memory for the target,
+and the memory node in the embedded DTB created by QEMU reflects
+the new setting.
+
+These have been tested in QEMU 3.0.0.
diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c
index 0f6574d..68836a7 100644
--- a/drivers/gpio/dwapb_gpio.c
+++ b/drivers/gpio/dwapb_gpio.c
@@ -171,8 +171,7 @@
 		if (!fdtdec_get_bool(blob, node, "gpio-controller"))
 			continue;
 
-		plat = NULL;
-		plat = calloc(1, sizeof(*plat));
+		plat = devm_kcalloc(dev, 1, sizeof(*plat), GFP_KERNEL);
 		if (!plat)
 			return -ENOMEM;
 
@@ -181,23 +180,17 @@
 		plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0);
 		plat->name = fdt_stringlist_get(blob, node, "bank-name", 0,
 						NULL);
-		if (ret)
-			goto err;
 
 		ret = device_bind(dev, dev->driver, plat->name,
 				  plat, -1, &subdev);
 		if (ret)
-			goto err;
+			return ret;
 
 		dev_set_of_offset(subdev, node);
 		bank++;
 	}
 
 	return 0;
-
-err:
-	free(plat);
-	return ret;
 }
 
 static int gpio_dwapb_remove(struct udevice *dev)
diff --git a/drivers/i2c/i2c-versatile.c b/drivers/i2c/i2c-versatile.c
new file mode 100644
index 0000000..f523844
--- /dev/null
+++ b/drivers/i2c/i2c-versatile.c
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Arm Ltd.
+ * Author: Liviu Dudau <liviu.dudau@foss.arm.com>
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <linux/io.h>
+
+#define I2C_CONTROL_REG		0x00
+#define I2C_SET_REG		0x00
+#define I2C_CLEAR_REG		0x04
+
+#define SCL	BIT(0)
+#define SDA	BIT(1)
+
+struct versatile_i2c_priv {
+	phys_addr_t base;
+	u32 delay;
+};
+
+static inline void versatile_sda_set(struct versatile_i2c_priv *priv, u8 state)
+{
+	writel(SDA, priv->base + (state ? I2C_SET_REG : I2C_CLEAR_REG));
+	udelay(priv->delay);
+}
+
+static inline int versatile_sda_get(struct versatile_i2c_priv *priv)
+{
+	int v = !!(readl(priv->base + I2C_CONTROL_REG) & SDA);
+
+	udelay(priv->delay);
+	return v;
+}
+
+static inline void versatile_scl_set(struct versatile_i2c_priv *priv, u8 state)
+{
+	writel(SCL, priv->base + (state ? I2C_SET_REG : I2C_CLEAR_REG));
+	udelay(priv->delay);
+}
+
+static inline int versatile_scl_get(struct versatile_i2c_priv *priv)
+{
+	int v = !!(readl(priv->base + I2C_CONTROL_REG) & SCL);
+
+	udelay(priv->delay);
+	return v;
+}
+
+/* start: SDA goes from high to low while SCL is high */
+static void versatile_i2c_start(struct versatile_i2c_priv *priv)
+{
+	udelay(priv->delay);
+	versatile_sda_set(priv, 1);
+	versatile_scl_set(priv, 1);
+	versatile_sda_set(priv, 0);
+}
+
+/* stop: SDA goes from low to high while SCL is high */
+static void versatile_i2c_stop(struct versatile_i2c_priv *priv)
+{
+	versatile_scl_set(priv, 0);
+	versatile_sda_set(priv, 0);
+	versatile_scl_set(priv, 1);
+	versatile_sda_set(priv, 1);
+}
+
+/* read a bit from the SDA line (data or ACK/NACK) */
+static u8 versatile_i2c_read_bit(struct versatile_i2c_priv *priv)
+{
+	versatile_scl_set(priv, 0);
+	versatile_sda_set(priv, 1);
+	versatile_scl_set(priv, 1);
+	udelay(priv->delay);
+	return (u8)versatile_sda_get(priv);
+}
+
+/* write a bit on the SDA line */
+static void versatile_i2c_write_bit(struct versatile_i2c_priv *priv, u8 bit)
+{
+	versatile_scl_set(priv, 0);
+	versatile_sda_set(priv, bit);
+	versatile_scl_set(priv, 1);
+	udelay(priv->delay);
+}
+
+/* send a reset sequence of 9 clocks with SDA high */
+static void versatile_i2c_reset_bus(struct versatile_i2c_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < 9; i++)
+		versatile_i2c_write_bit(priv, 1);
+
+	versatile_i2c_stop(priv);
+}
+
+/* write byte without start/stop sequence */
+static int versatile_i2c_write_byte(struct versatile_i2c_priv *priv, u8 byte)
+{
+	u8 nak, i;
+
+	for (i = 0; i < 8; i++) {
+		versatile_i2c_write_bit(priv, byte & 0x80);
+		byte <<= 1;
+	}
+
+	/* read ACK */
+	nak = versatile_i2c_read_bit(priv);
+	versatile_scl_set(priv, 0);
+
+	return nak;	/* not a nack is an ack */
+}
+
+static int versatile_i2c_read_byte(struct versatile_i2c_priv *priv,
+				   u8 *byte, u8 ack)
+{
+	u8 i;
+
+	*byte = 0;
+	for (i = 0; i < 8; i++) {
+		*byte <<= 1;
+		*byte |= versatile_i2c_read_bit(priv);
+	}
+	/* write the nack */
+	versatile_i2c_write_bit(priv, ack);
+
+	return 0;
+}
+
+static int versatile_i2c_send_slave_addr(struct versatile_i2c_priv *priv,
+					 struct i2c_msg *msg)
+{
+	u8 addr;
+	int ret;
+
+	if (msg->flags & I2C_M_TEN) {
+		/* 10-bit address, send extended address code first */
+		addr = 0xf0 | ((msg->addr >> 7) & 0x06);
+		ret = versatile_i2c_write_byte(priv, addr);
+		if (ret) {
+			versatile_i2c_stop(priv);
+			return -EIO;
+		}
+
+		/* remaining bits */
+		ret = versatile_i2c_write_byte(priv, msg->addr & 0xff);
+		if (ret) {
+			versatile_i2c_stop(priv);
+			return -EIO;
+		}
+		/* reads need to resend the addr */
+		if (msg->flags & I2C_M_RD) {
+			versatile_i2c_start(priv);
+			addr |= 1;
+			ret = versatile_i2c_write_byte(priv, addr);
+			if (ret) {
+				versatile_i2c_stop(priv);
+				return -EIO;
+			}
+		}
+	} else {
+		/* normal 7-bit address */
+		addr = msg->addr << 1;
+		if (msg->flags & I2C_M_RD)
+			addr |= 1;
+		ret = versatile_i2c_write_byte(priv, addr);
+		if (ret) {
+			versatile_i2c_stop(priv);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int versatile_i2c_message_xfer(struct versatile_i2c_priv *priv,
+				      struct i2c_msg *msg)
+{
+	int i, ret;
+	u8 ack;
+
+	versatile_i2c_start(priv);
+	if (versatile_i2c_send_slave_addr(priv, msg))
+		return -EIO;
+
+	for (i = 0; i < msg->len; i++) {
+		if (msg->flags & I2C_M_RD) {
+			ack = (msg->len - i - 1) == 0 ? 1 : 0;
+			ret = versatile_i2c_read_byte(priv, &msg->buf[i], ack);
+		} else {
+			ret = versatile_i2c_write_byte(priv, msg->buf[i]);
+		}
+
+		if (ret)
+			break;
+	}
+
+	versatile_i2c_stop(priv);
+
+	return ret;
+}
+
+static int versatile_i2c_xfer(struct udevice *bus,
+			      struct i2c_msg *msg, int nmsgs)
+{
+	struct versatile_i2c_priv *priv = dev_get_priv(bus);
+	int ret;
+
+	for ( ; nmsgs > 0; nmsgs--, msg++) {
+		ret = versatile_i2c_message_xfer(priv, msg);
+		if (ret)
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int versatile_i2c_chip_probe(struct udevice *bus,
+				    uint chip, uint chip_flags)
+{
+	/* probe the presence of a slave by writing a 0-size message */
+	struct i2c_msg msg = { .addr = chip, .flags = chip_flags,
+			       .len = 0, .buf = NULL };
+	struct versatile_i2c_priv *priv = dev_get_priv(bus);
+
+	return versatile_i2c_message_xfer(priv, &msg);
+}
+
+static int versatile_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	struct versatile_i2c_priv *priv = dev_get_priv(bus);
+
+	priv->delay = 1000000 / (speed << 2);
+
+	versatile_i2c_reset_bus(priv);
+
+	return 0;
+}
+
+static int versatile_i2c_probe(struct udevice *dev)
+{
+	struct versatile_i2c_priv *priv = dev_get_priv(dev);
+
+	priv->base = (phys_addr_t)dev_read_addr(dev);
+	priv->delay = 25;	/* 25us * 4 = 100kHz */
+	/*
+	 * U-Boot still doesn't assign automatically
+	 * sequence numbers to devices
+	 */
+	dev->req_seq = 1;
+
+	return 0;
+}
+
+static const struct dm_i2c_ops versatile_i2c_ops = {
+	.xfer = versatile_i2c_xfer,
+	.probe_chip = versatile_i2c_chip_probe,
+	.set_bus_speed = versatile_i2c_set_bus_speed,
+};
+
+static const struct udevice_id versatile_i2c_of_match[] = {
+	{ .compatible = "arm,versatile-i2c" },
+	{ }
+};
+
+U_BOOT_DRIVER(versatile_i2c) = {
+	.name = "i2c-bus-versatile",
+	.id = UCLASS_I2C,
+	.of_match = versatile_i2c_of_match,
+	.probe = versatile_i2c_probe,
+	.priv_auto_alloc_size = sizeof(struct versatile_i2c_priv),
+	.ops = &versatile_i2c_ops,
+};
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 13180fc..3c702b3 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -92,6 +92,24 @@
 	dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
 }
 
+static int dwmci_fifo_ready(struct dwmci_host *host, u32 bit, u32 *len)
+{
+	u32 timeout = 20000;
+
+	*len = dwmci_readl(host, DWMCI_STATUS);
+	while (--timeout && (*len & bit)) {
+		udelay(200);
+		*len = dwmci_readl(host, DWMCI_STATUS);
+	}
+
+	if (!timeout) {
+		debug("%s: FIFO underflow timeout\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
 {
 	int ret = 0;
@@ -122,7 +140,12 @@
 			if (data->flags == MMC_DATA_READ &&
 			    (mask & DWMCI_INTMSK_RXDR)) {
 				while (size) {
-					len = dwmci_readl(host, DWMCI_STATUS);
+					ret = dwmci_fifo_ready(host,
+							DWMCI_FIFO_EMPTY,
+							&len);
+					if (ret < 0)
+						break;
+
 					len = (len >> DWMCI_FIFO_SHIFT) &
 						    DWMCI_FIFO_MASK;
 					len = min(size, len);
@@ -136,7 +159,12 @@
 			} else if (data->flags == MMC_DATA_WRITE &&
 				   (mask & DWMCI_INTMSK_TXDR)) {
 				while (size) {
-					len = dwmci_readl(host, DWMCI_STATUS);
+					ret = dwmci_fifo_ready(host,
+							DWMCI_FIFO_FULL,
+							&len);
+					if (ret < 0)
+						break;
+
 					len = fifo_depth - ((len >>
 						   DWMCI_FIFO_SHIFT) &
 						   DWMCI_FIFO_MASK);
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index f54d95a..bf2d83a 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -156,6 +156,7 @@
 }
 
 static const struct udevice_id rockchip_dwmmc_ids[] = {
+	{ .compatible = "rockchip,rk2928-dw-mshc" },
 	{ .compatible = "rockchip,rk3288-dw-mshc" },
 	{ }
 };
diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
index a66edd9..dd6baca 100644
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
-spinand-objs := core.o macronix.o micron.o winbond.o
+spinand-objs := core.o gigadevice.o macronix.o micron.o winbond.o
 obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 362d104..cb8ffa3 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -830,6 +830,7 @@
 };
 
 static const struct spinand_manufacturer *spinand_manufacturers[] = {
+	&gigadevice_spinand_manufacturer,
 	&macronix_spinand_manufacturer,
 	&micron_spinand_manufacturer,
 	&winbond_spinand_manufacturer,
diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
new file mode 100644
index 0000000..0bade20
--- /dev/null
+++ b/drivers/mtd/nand/spi/gigadevice.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ *
+ * Derived from drivers/mtd/nand/spi/micron.c
+ *   Copyright (c) 2016-2017 Micron Technology, Inc.
+ */
+
+#ifndef __UBOOT__
+#include <linux/device.h>
+#include <linux/kernel.h>
+#endif
+#include <linux/mtd/spinand.h>
+
+#define SPINAND_MFR_GIGADEVICE			0xc8
+
+#define GIGADEVICE_STATUS_ECC_MASK		GENMASK(5, 4)
+#define GIGADEVICE_STATUS_ECC_NO_BITFLIPS	(0 << 4)
+#define GIGADEVICE_STATUS_ECC_1TO7_BITFLIPS	(1 << 4)
+#define GIGADEVICE_STATUS_ECC_8_BITFLIPS	(3 << 4)
+
+static SPINAND_OP_VARIANTS(read_cache_variants,
+		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants,
+		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants,
+		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+		SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+static int gd5f1gq4u_ooblayout_ecc(struct mtd_info *mtd, int section,
+				   struct mtd_oob_region *region)
+{
+	if (section)
+		return -ERANGE;
+
+	region->offset = 64;
+	region->length = 64;
+
+	return 0;
+}
+
+static int gd5f1gq4u_ooblayout_free(struct mtd_info *mtd, int section,
+				    struct mtd_oob_region *region)
+{
+	if (section)
+		return -ERANGE;
+
+	/* Reserve 2 bytes for the BBM. */
+	region->offset = 2;
+	region->length = 62;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops gd5f1gq4u_ooblayout = {
+	.ecc = gd5f1gq4u_ooblayout_ecc,
+	.free = gd5f1gq4u_ooblayout_free,
+};
+
+static int gd5f1gq4u_ecc_get_status(struct spinand_device *spinand,
+				    u8 status)
+{
+	if (status)
+		debug("%s (%d): status=%02x\n", __func__, __LINE__, status);
+
+	switch (status & GIGADEVICE_STATUS_ECC_MASK) {
+	case STATUS_ECC_NO_BITFLIPS:
+		return 0;
+
+	case GIGADEVICE_STATUS_ECC_1TO7_BITFLIPS:
+		return 7;
+
+	case GIGADEVICE_STATUS_ECC_8_BITFLIPS:
+		return 8;
+
+	case STATUS_ECC_UNCOR_ERROR:
+		return -EBADMSG;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static const struct spinand_info gigadevice_spinand_table[] = {
+	SPINAND_INFO("GD5F1GQ4UC", 0xd1,
+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+		     NAND_ECCREQ(8, 2048),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     0,
+		     SPINAND_ECCINFO(&gd5f1gq4u_ooblayout,
+				     gd5f1gq4u_ecc_get_status)),
+};
+
+static int gigadevice_spinand_detect(struct spinand_device *spinand)
+{
+	u8 *id = spinand->id.data;
+	int ret;
+
+	/*
+	 * Gigadevice SPI NAND read ID need a dummy byte,
+	 * so the first byte in raw_id is dummy.
+	 */
+	if (id[1] != SPINAND_MFR_GIGADEVICE)
+		return 0;
+
+	ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
+				     ARRAY_SIZE(gigadevice_spinand_table),
+				     id[2]);
+	if (ret)
+		return ret;
+
+	return 1;
+}
+
+static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
+	.detect = gigadevice_spinand_detect,
+};
+
+const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
+	.id = SPINAND_MFR_GIGADEVICE,
+	.name = "GigaDevice",
+	.ops = &gigadevice_spinand_manuf_ops,
+};
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 98485b1..76d5a1d1 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -96,6 +96,12 @@
 	help
 	  Add support for various Winbond SPI flash chips (W25xxx)
 
+config SPI_FLASH_XMC
+	bool "XMC SPI flash support"
+	help
+	  Add support for various XMC (Wuhan Xinxin Semiconductor
+	  Manufacturing Corp.) SPI flash chips (XM25xxx)
+
 endif
 
 config SPI_FLASH_USE_4K_SECTORS
diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c
index e662e4b..ad0a0c8 100644
--- a/drivers/mtd/spi/spi_flash_ids.c
+++ b/drivers/mtd/spi/spi_flash_ids.c
@@ -189,6 +189,10 @@
 	{"w25q256fw",	   INFO(0xef6019, 0x0,	64 * 1024,   512, RD_FULL | WR_QPP | SECT_4K) },
 	{"w25q256jw",	   INFO(0xef7019, 0x0,	64 * 1024,   512, RD_FULL | WR_QPP | SECT_4K) },
 #endif
+#ifdef CONFIG_SPI_FLASH_XMC /* Wuhan Xinxin Semiconductor Manufacturing Corp */
+	{ "xm25qh64a",	   INFO(0x207017, 0x0, 64 * 1024,    128, SECT_4K | RD_DUAL | RD_QUAD) },
+	{ "xm25qh128a",	   INFO(0x207018, 0x0, 64 * 1024,    256, SECT_4K | RD_DUAL | RD_QUAD) },
+#endif
 	{},	/* Empty entry to terminate the list */
 	/*
 	 * Note:
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 30a24d1..c01ae75 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -24,6 +24,11 @@
 #include <dt-bindings/clock/rk3288-cru.h>
 #include "designware.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+#define DELAY_ENABLE(soc, tx, rx) \
+	(((tx) ? soc##_TXCLK_DLY_ENA_GMAC_ENABLE : soc##_TXCLK_DLY_ENA_GMAC_DISABLE) | \
+	((rx) ? soc##_RXCLK_DLY_ENA_GMAC_ENABLE : soc##_RXCLK_DLY_ENA_GMAC_DISABLE))
+
 /*
  * Platform data for the gmac
  *
@@ -286,8 +291,7 @@
 		     RK3228_RXCLK_DLY_ENA_GMAC_MASK |
 		     RK3228_TXCLK_DLY_ENA_GMAC_MASK,
 		     RK3228_GMAC_PHY_INTF_SEL_RGMII |
-		     RK3228_RXCLK_DLY_ENA_GMAC_ENABLE |
-		     RK3228_TXCLK_DLY_ENA_GMAC_ENABLE);
+		     DELAY_ENABLE(RK3228, pdata->tx_delay, pdata->rx_delay));
 
 	rk_clrsetreg(&grf->mac_con[0],
 		     RK3228_CLK_RX_DL_CFG_GMAC_MASK |
@@ -310,8 +314,7 @@
 		     RK3288_TXCLK_DLY_ENA_GMAC_MASK |
 		     RK3288_CLK_RX_DL_CFG_GMAC_MASK |
 		     RK3288_CLK_TX_DL_CFG_GMAC_MASK,
-		     RK3288_RXCLK_DLY_ENA_GMAC_ENABLE |
-		     RK3288_TXCLK_DLY_ENA_GMAC_ENABLE |
+		     DELAY_ENABLE(RK3288, pdata->rx_delay, pdata->tx_delay) |
 		     pdata->rx_delay << RK3288_CLK_RX_DL_CFG_GMAC_SHIFT |
 		     pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT);
 }
@@ -350,8 +353,7 @@
 		     RK3328_RXCLK_DLY_ENA_GMAC_MASK |
 		     RK3328_TXCLK_DLY_ENA_GMAC_MASK,
 		     RK3328_GMAC_PHY_INTF_SEL_RGMII |
-		     RK3328_RXCLK_DLY_ENA_GMAC_MASK |
-		     RK3328_TXCLK_DLY_ENA_GMAC_ENABLE);
+		     DELAY_ENABLE(RK3328, pdata->tx_delay, pdata->rx_delay));
 
 	rk_clrsetreg(&grf->mac_con[0],
 		     RK3328_CLK_RX_DL_CFG_GMAC_MASK |
@@ -392,8 +394,7 @@
 		     RK3368_TXCLK_DLY_ENA_GMAC_MASK |
 		     RK3368_CLK_RX_DL_CFG_GMAC_MASK |
 		     RK3368_CLK_TX_DL_CFG_GMAC_MASK,
-		     RK3368_RXCLK_DLY_ENA_GMAC_ENABLE |
-		     RK3368_TXCLK_DLY_ENA_GMAC_ENABLE |
+		     DELAY_ENABLE(RK3368, pdata->tx_delay, pdata->rx_delay) |
 		     pdata->rx_delay << RK3368_CLK_RX_DL_CFG_GMAC_SHIFT |
 		     pdata->tx_delay << RK3368_CLK_TX_DL_CFG_GMAC_SHIFT);
 }
@@ -413,8 +414,7 @@
 		     RK3399_TXCLK_DLY_ENA_GMAC_MASK |
 		     RK3399_CLK_RX_DL_CFG_GMAC_MASK |
 		     RK3399_CLK_TX_DL_CFG_GMAC_MASK,
-		     RK3399_RXCLK_DLY_ENA_GMAC_ENABLE |
-		     RK3399_TXCLK_DLY_ENA_GMAC_ENABLE |
+		     DELAY_ENABLE(RK3399, pdata->tx_delay, pdata->rx_delay) |
 		     pdata->rx_delay << RK3399_CLK_RX_DL_CFG_GMAC_SHIFT |
 		     pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT);
 }
@@ -451,40 +451,86 @@
 
 	switch (eth_pdata->phy_interface) {
 	case PHY_INTERFACE_MODE_RGMII:
-		/*
-		 * If the gmac clock is from internal pll, need to set and
-		 * check the return value for gmac clock at RGMII mode. If
-		 * the gmac clock is from external source, the clock rate
-		 * is not set, because of it is bypassed.
-		 */
-		if (!pdata->clock_input) {
-			rate = clk_set_rate(&clk, 125000000);
-			if (rate != 125000000)
-				return -EINVAL;
-		}
-
 		/* Set to RGMII mode */
 		if (ops->set_to_rgmii)
 			ops->set_to_rgmii(pdata);
 		else
 			return -EPERM;
 
-		break;
-	case PHY_INTERFACE_MODE_RMII:
-		/* The commet is the same as RGMII mode */
+		/*
+		 * If the gmac clock is from internal pll, need to set and
+		 * check the return value for gmac clock at RGMII mode. If
+		 * the gmac clock is from external source, the clock rate
+		 * is not set, because of it is bypassed.
+		 */
+
 		if (!pdata->clock_input) {
-			rate = clk_set_rate(&clk, 50000000);
-			if (rate != 50000000)
+			rate = clk_set_rate(&clk, 125000000);
+			if (rate != 125000000)
 				return -EINVAL;
 		}
+		break;
 
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		/* Set to RGMII mode */
+		if (ops->set_to_rgmii) {
+			pdata->tx_delay = 0;
+			pdata->rx_delay = 0;
+			ops->set_to_rgmii(pdata);
+		} else
+			return -EPERM;
+
+		if (!pdata->clock_input) {
+			rate = clk_set_rate(&clk, 125000000);
+			if (rate != 125000000)
+				return -EINVAL;
+		}
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
 		/* Set to RMII mode */
 		if (ops->set_to_rmii)
 			ops->set_to_rmii(pdata);
 		else
 			return -EPERM;
 
+		if (!pdata->clock_input) {
+			rate = clk_set_rate(&clk, 50000000);
+			if (rate != 50000000)
+				return -EINVAL;
+		}
 		break;
+
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+		 /* Set to RGMII_RXID mode */
+		if (ops->set_to_rgmii) {
+			pdata->tx_delay = 0;
+			ops->set_to_rgmii(pdata);
+		} else
+			return -EPERM;
+
+		if (!pdata->clock_input) {
+			rate = clk_set_rate(&clk, 125000000);
+			if (rate != 125000000)
+				return -EINVAL;
+		}
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		/* Set to RGMII_TXID mode */
+		if (ops->set_to_rgmii) {
+			pdata->rx_delay = 0;
+			ops->set_to_rgmii(pdata);
+		} else
+			return -EPERM;
+
+		if (!pdata->clock_input) {
+			rate = clk_set_rate(&clk, 125000000);
+			if (rate != 125000000)
+				return -EINVAL;
+		}
+		break;
+
 	default:
 		debug("NO interface defined!\n");
 		return -ENXIO;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 196767a..1df6876 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -116,6 +116,14 @@
 	  access the SPI NOR flash on platforms embedding this Intel
 	  ICH IP core.
 
+config MT7621_SPI
+	bool "MediaTek MT7621 SPI driver"
+	depends on ARCH_MT7620
+	help
+	  Enable the MT7621 SPI driver. This driver can be used to access
+	  the SPI NOR flash on platforms embedding this Ralink / MediaTek
+	  SPI core, like MT7621/7628/7688.
+
 config MVEBU_A3700_SPI
 	bool "Marvell Armada 3700 SPI driver"
 	select CLK_ARMADA_3720
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ee99508..7242ea7 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -33,6 +33,7 @@
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
 obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
 obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
diff --git a/drivers/spi/mt7621_spi.c b/drivers/spi/mt7621_spi.c
new file mode 100644
index 0000000..107e58f
--- /dev/null
+++ b/drivers/spi/mt7621_spi.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ *
+ * Derived from the Linux driver version drivers/spi/spi-mt7621.c
+ *   Copyright (C) 2011 Sergiy <piratfm@gmail.com>
+ *   Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
+ *   Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi.h>
+#include <wait_bit.h>
+#include <linux/io.h>
+
+#define SPI_MSG_SIZE_MAX	32	/* SPI message chunk size */
+/* Enough for SPI NAND page read / write with page size 2048 bytes */
+#define SPI_MSG_SIZE_OVERALL	(2048 + 16)
+
+#define MT7621_SPI_TRANS	0x00
+#define MT7621_SPI_TRANS_START	BIT(8)
+#define MT7621_SPI_TRANS_BUSY	BIT(16)
+
+#define MT7621_SPI_OPCODE	0x04
+#define MT7621_SPI_DATA0	0x08
+#define MT7621_SPI_DATA4	0x18
+#define MT7621_SPI_MASTER	0x28
+#define MT7621_SPI_MOREBUF	0x2c
+#define MT7621_SPI_POLAR	0x38
+
+#define MT7621_LSB_FIRST	BIT(3)
+#define MT7621_CPOL		BIT(4)
+#define MT7621_CPHA		BIT(5)
+
+#define MASTER_MORE_BUFMODE	BIT(2)
+#define MASTER_RS_CLK_SEL	GENMASK(27, 16)
+#define MASTER_RS_CLK_SEL_SHIFT	16
+#define MASTER_RS_SLAVE_SEL	GENMASK(31, 29)
+
+struct mt7621_spi {
+	void __iomem *base;
+	unsigned int sys_freq;
+	u32 data[(SPI_MSG_SIZE_OVERALL / 4) + 1];
+	int tx_len;
+};
+
+static void mt7621_spi_reset(struct mt7621_spi *rs, int duplex)
+{
+	setbits_le32(rs->base + MT7621_SPI_MASTER,
+		     MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE);
+}
+
+static void mt7621_spi_set_cs(struct mt7621_spi *rs, int cs, int enable)
+{
+	u32 val = 0;
+
+	debug("%s: cs#%d -> %s\n", __func__, cs, enable ? "enable" : "disable");
+	if (enable)
+		val = BIT(cs);
+	iowrite32(val, rs->base + MT7621_SPI_POLAR);
+}
+
+static int mt7621_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mt7621_spi *rs = dev_get_priv(bus);
+	u32 reg;
+
+	debug("%s: mode=0x%08x\n", __func__, mode);
+	reg = ioread32(rs->base + MT7621_SPI_MASTER);
+
+	reg &= ~MT7621_LSB_FIRST;
+	if (mode & SPI_LSB_FIRST)
+		reg |= MT7621_LSB_FIRST;
+
+	reg &= ~(MT7621_CPHA | MT7621_CPOL);
+	switch (mode & (SPI_CPOL | SPI_CPHA)) {
+	case SPI_MODE_0:
+		break;
+	case SPI_MODE_1:
+		reg |= MT7621_CPHA;
+		break;
+	case SPI_MODE_2:
+		reg |= MT7621_CPOL;
+		break;
+	case SPI_MODE_3:
+		reg |= MT7621_CPOL | MT7621_CPHA;
+		break;
+	}
+	iowrite32(reg, rs->base + MT7621_SPI_MASTER);
+
+	return 0;
+}
+
+static int mt7621_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct mt7621_spi *rs = dev_get_priv(bus);
+	u32 rate;
+	u32 reg;
+
+	debug("%s: speed=%d\n", __func__, speed);
+	rate = DIV_ROUND_UP(rs->sys_freq, speed);
+	debug("rate:%u\n", rate);
+
+	if (rate > 4097)
+		return -EINVAL;
+
+	if (rate < 2)
+		rate = 2;
+
+	reg = ioread32(rs->base + MT7621_SPI_MASTER);
+	reg &= ~MASTER_RS_CLK_SEL;
+	reg |= (rate - 2) << MASTER_RS_CLK_SEL_SHIFT;
+	iowrite32(reg, rs->base + MT7621_SPI_MASTER);
+
+	return 0;
+}
+
+static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
+{
+	int ret;
+
+	ret =  wait_for_bit_le32(rs->base + MT7621_SPI_TRANS,
+				 MT7621_SPI_TRANS_BUSY, 0, 10, 0);
+	if (ret)
+		pr_err("Timeout in %s!\n", __func__);
+
+	return ret;
+}
+
+static int mt7621_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			   const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mt7621_spi *rs = dev_get_priv(bus);
+	const u8 *tx_buf = dout;
+	u8 *ptr = (u8 *)dout;
+	u8 *rx_buf = din;
+	int total_size = bitlen >> 3;
+	int chunk_size;
+	int rx_len = 0;
+	u32 data[(SPI_MSG_SIZE_MAX / 4) + 1] = { 0 };
+	u32 val;
+	int i;
+
+	debug("%s: dout=%p, din=%p, len=%x, flags=%lx\n", __func__, dout, din,
+	      total_size, flags);
+
+	/*
+	 * This driver only supports half-duplex, so complain and bail out
+	 * upon full-duplex messages
+	 */
+	if (dout && din) {
+		printf("Only half-duplex SPI transfer supported\n");
+		return -EIO;
+	}
+
+	if (dout) {
+		debug("TX-DATA: ");
+		for (i = 0; i < total_size; i++)
+			debug("%02x ", *ptr++);
+		debug("\n");
+	}
+
+	mt7621_spi_wait_till_ready(rs);
+
+	/*
+	 * Set CS active upon start of SPI message. This message can
+	 * be split upon multiple calls to this xfer function
+	 */
+	if (flags & SPI_XFER_BEGIN)
+		mt7621_spi_set_cs(rs, spi_chip_select(dev), 1);
+
+	while (total_size > 0) {
+		/* Don't exceed the max xfer size */
+		chunk_size = min_t(int, total_size, SPI_MSG_SIZE_MAX);
+
+		/*
+		 * We might have some TX data buffered from the last xfer
+		 * message. Make sure, that this does not exceed the max
+		 * xfer size
+		 */
+		if (rs->tx_len > 4)
+			chunk_size -= rs->tx_len;
+		if (din)
+			rx_len = chunk_size;
+
+		if (tx_buf) {
+			/* Check if this message does not exceed the buffer */
+			if ((chunk_size + rs->tx_len) > SPI_MSG_SIZE_OVERALL) {
+				printf("TX message size too big (%d)\n",
+				       chunk_size + rs->tx_len);
+				return -EMSGSIZE;
+			}
+
+			/*
+			 * Write all TX data into internal buffer to collect
+			 * all TX messages into one buffer (might be split into
+			 * multiple calls to this function)
+			 */
+			for (i = 0; i < chunk_size; i++, rs->tx_len++) {
+				rs->data[rs->tx_len / 4] |=
+					tx_buf[i] << (8 * (rs->tx_len & 3));
+			}
+		}
+
+		if (flags & SPI_XFER_END) {
+			/* Write TX data into controller */
+			if (rs->tx_len) {
+				rs->data[0] = swab32(rs->data[0]);
+				if (rs->tx_len < 4)
+					rs->data[0] >>= (4 - rs->tx_len) * 8;
+
+				for (i = 0; i < rs->tx_len; i += 4) {
+					iowrite32(rs->data[i / 4], rs->base +
+						  MT7621_SPI_OPCODE + i);
+				}
+			}
+
+			/* Write length into controller */
+			val = (min_t(int, rs->tx_len, 4) * 8) << 24;
+			if (rs->tx_len > 4)
+				val |= (rs->tx_len - 4) * 8;
+			val |= (rx_len * 8) << 12;
+			iowrite32(val, rs->base + MT7621_SPI_MOREBUF);
+
+			/* Start the xfer */
+			setbits_le32(rs->base + MT7621_SPI_TRANS,
+				     MT7621_SPI_TRANS_START);
+
+			/* Wait until xfer is finished on bus */
+			mt7621_spi_wait_till_ready(rs);
+
+			/* Reset TX length and TX buffer for next xfer */
+			rs->tx_len = 0;
+			memset(rs->data, 0, sizeof(rs->data));
+		}
+
+		for (i = 0; i < rx_len; i += 4)
+			data[i / 4] = ioread32(rs->base + MT7621_SPI_DATA0 + i);
+
+		if (rx_len) {
+			debug("RX-DATA: ");
+			for (i = 0; i < rx_len; i++) {
+				rx_buf[i] = data[i / 4] >> (8 * (i & 3));
+				debug("%02x ", rx_buf[i]);
+			}
+			debug("\n");
+		}
+
+		if (tx_buf)
+			tx_buf += chunk_size;
+		if (rx_buf)
+			rx_buf += chunk_size;
+		total_size -= chunk_size;
+	}
+
+	/* Wait until xfer is finished on bus and de-assert CS */
+	mt7621_spi_wait_till_ready(rs);
+	if (flags & SPI_XFER_END)
+		mt7621_spi_set_cs(rs, spi_chip_select(dev), 0);
+
+	return 0;
+}
+
+static int mt7621_spi_probe(struct udevice *dev)
+{
+	struct mt7621_spi *rs = dev_get_priv(dev);
+
+	rs->base = dev_remap_addr(dev);
+	if (!rs->base)
+		return -EINVAL;
+
+	/*
+	 * Read input clock via DT for now. At some point this should be
+	 * replaced by implementing a clock driver for this SoC and getting
+	 * the SPI frequency via this clock driver.
+	 */
+	rs->sys_freq = dev_read_u32_default(dev, "clock-frequency", 0);
+	if (!rs->sys_freq) {
+		printf("Please provide clock-frequency!\n");
+		return -EINVAL;
+	}
+
+	mt7621_spi_reset(rs, 0);
+
+	return 0;
+}
+
+static const struct dm_spi_ops mt7621_spi_ops = {
+	.set_mode = mt7621_spi_set_mode,
+	.set_speed = mt7621_spi_set_speed,
+	.xfer = mt7621_spi_xfer,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static const struct udevice_id mt7621_spi_ids[] = {
+	{ .compatible = "ralink,mt7621-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mt7621_spi) = {
+	.name = "mt7621_spi",
+	.id = UCLASS_SPI,
+	.of_match = mt7621_spi_ids,
+	.ops = &mt7621_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct mt7621_spi),
+	.probe = mt7621_spi_probe,
+};
diff --git a/include/configs/iot_devkit.h b/include/configs/iot_devkit.h
new file mode 100644
index 0000000..4ffe114
--- /dev/null
+++ b/include/configs/iot_devkit.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef _CONFIG_IOT_DEVKIT_H_
+#define _CONFIG_IOT_DEVKIT_H_
+
+#include <linux/sizes.h>
+
+/*
+ *                         MEMORY MAP
+ *
+ * eFlash: 0x0000_0000 - 0x0008_0000 (512K)
+ *   ICCM: 0x2000_0000 - 0x2004_0000 (256K)
+ *   SRAM: 0x3000_0000 - 0x3002_0000 (128K)
+ *   DCCM: 0x8000_0000 - 0x8002_0000 (128K)
+ *     Note: only data goes here, as IFQ cannot fetch instructions from DCCM
+ *
+ *
+ *                         RAM PARTITIONING
+ *
+ *   +-----------+----------+---------------------+-------------+
+ *   | <-- Stack |  .data   | Malloc              | Environment |
+ *   +-----------+----------+---------------------+-------------+
+ *   :           :          :                     :\___________/
+ *   :           :          :                     :      |
+ *   :           :          :                     :     CONFIG_ENV_SIZE
+ *   :           :           \____________________/
+ *   :           :                     |
+ *   :           :                    CONFIG_SYS_MALLOC_LEN
+ *   :           :
+ *   :          Specified explicitly by CONFIG_SYS_INIT_SP_ADDR
+ *   :
+ *  Specified explicitly by CONFIG_SYS_SDRAM_BASE
+ *
+ *  NOTES:
+ *    - Stack starts from CONFIG_SYS_INIT_SP_ADDR and grows down,
+ *      i.e. towards CONFIG_SYS_SDRAM_BASE but nothing stops it from crossing
+ *      that CONFIG_SYS_SDRAM_BASE in which case data won't be really saved on
+ *      stack any longer and values popped from stack will contain garbage
+ *      leading to unexpected behavior, typically but not limited to:
+ *        - "Returning" back to bogus caller function
+ *        - Reading data from weird addresses
+ */
+
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+
+#define SRAM_BASE			0x30000000
+#define SRAM_SIZE			SZ_128K
+
+#define DCCM_BASE			0x80000000
+#define DCCM_SIZE			SZ_128K
+
+#define CONFIG_SYS_SDRAM_BASE		DCCM_BASE
+#define CONFIG_SYS_SDRAM_SIZE		DCCM_SIZE
+
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_32K)
+
+#define CONFIG_SYS_MALLOC_LEN		SZ_64K
+#define CONFIG_SYS_BOOTM_LEN		SZ_128K
+#define CONFIG_SYS_LOAD_ADDR		SRAM_BASE
+
+#define ROM_BASE			CONFIG_SYS_MONITOR_BASE
+#define ROM_SIZE			SZ_256K
+
+#define RAM_DATA_BASE			CONFIG_SYS_INIT_SP_ADDR
+#define RAM_DATA_SIZE			CONFIG_SYS_SDRAM_SIZE - \
+					(CONFIG_SYS_INIT_SP_ADDR - \
+					CONFIG_SYS_SDRAM_BASE) - \
+					CONFIG_SYS_MALLOC_LEN - \
+					CONFIG_ENV_SIZE
+
+/* Required by DW MMC driver */
+#define CONFIG_BOUNCE_BUFFER
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_SIZE			SZ_4K
+#define CONFIG_BOOTFILE			"app.bin"
+#define CONFIG_LOADADDR			CONFIG_SYS_LOAD_ADDR
+
+#endif /* _CONFIG_IOT_DEVKIT_H_ */
diff --git a/include/configs/qemu-riscv.h b/include/configs/qemu-riscv.h
new file mode 100644
index 0000000..d279c23
--- /dev/null
+++ b/include/configs/qemu-riscv.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_2M)
+
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_2M)
+
+#define CONFIG_SYS_MALLOC_LEN		SZ_8M
+
+/* Environment options */
+#define CONFIG_ENV_SIZE			SZ_4K
+
+#endif /* __CONFIG_H */
diff --git a/include/dwmmc.h b/include/dwmmc.h
index bc1d6e3..0f9d51b 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -103,6 +103,8 @@
 #define DWMCI_CTYPE_8BIT	(1 << 16)
 
 /* Status Register */
+#define DWMCI_FIFO_EMPTY	(1 << 2)
+#define DWMCI_FIFO_FULL		(1 << 3)
 #define DWMCI_BUSY		(1 << 9)
 #define DWMCI_FIFO_MASK		0x1fff
 #define DWMCI_FIFO_SHIFT	17
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 8c9c756..be01e1e 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -201,6 +201,7 @@
 };
 
 /* SPI NAND manufacturers */
+extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
 extern const struct spinand_manufacturer macronix_spinand_manufacturer;
 extern const struct spinand_manufacturer micron_spinand_manufacturer;
 extern const struct spinand_manufacturer winbond_spinand_manufacturer;
diff --git a/include/spl.h b/include/spl.h
index b42683c..9a439f4 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -289,6 +289,19 @@
 void spl_invoke_atf(struct spl_image_info *spl_image);
 
 /**
+ * spl_optee_entry - entry function for optee
+ *
+ * args defind in op-tee project
+ * https://github.com/OP-TEE/optee_os/
+ * core/arch/arm/kernel/generic_entry_a32.S
+ * @arg0: pagestore
+ * @arg1: (ARMv7 standard bootarg #1)
+ * @arg2: device tree address, (ARMv7 standard bootarg #2)
+ * @arg3: non-secure entry address (ARMv7 bootarg #0)
+ */
+void spl_optee_entry(void *arg0, void *arg1, void *arg2, void *arg3);
+
+/**
  * board_return_to_bootrom - allow for boards to continue with the boot ROM
  *
  * If a board (e.g. the Rockchip RK3368 boards) provide some
diff --git a/tools/rkimage.c b/tools/rkimage.c
index a0a3185..ae50de5 100644
--- a/tools/rkimage.c
+++ b/tools/rkimage.c
@@ -15,8 +15,7 @@
 static void rkimage_set_header(void *buf, struct stat *sbuf, int ifd,
 			       struct image_tool_params *params)
 {
-	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
-	       RK_SPL_HDR_SIZE);
+	memcpy(buf, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
 
 	if (rkcommon_need_rc4_spl(params))
 		rkcommon_rc4_encode_spl(buf, 4, params->file_size);
@@ -36,7 +35,7 @@
 U_BOOT_IMAGE_TYPE(
 	rkimage,
 	"Rockchip Boot Image support",
-	4,
+	0,
 	&header,
 	rkcommon_check_params,
 	NULL,
diff --git a/tools/socfpgaimage.c b/tools/socfpgaimage.c
index 390c9bb..72d8b96 100644
--- a/tools/socfpgaimage.c
+++ b/tools/socfpgaimage.c
@@ -191,6 +191,7 @@
 	if (hdr_csum != sfp_csum)
 		return -EINVAL;
 
+	*ver = header_v0.version;
 	return img_len;
 }