Kaynağa Gözat

Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-riscv

- Increase stack size to avoid a stack overflow during distro boot.
- Add hifive-unleashed-a00.dts for SIFIVE FU540.
- Add OF_SEPARATE support for SIFIVE FU540.
- Add SPL support for Andes AX25 AE350.
- Improve U-Boot SPL / OpenSBI smp boot flow for RISC-V.
Tom Rini 4 yıl önce
ebeveyn
işleme
520f955902

+ 1 - 1
arch/riscv/Kconfig

@@ -224,7 +224,7 @@ config XIP
 
 config STACK_SIZE_SHIFT
 	int
-	default 13
+	default 14
 
 config SPL_LDSCRIPT
 	default "arch/riscv/cpu/u-boot-spl.lds"

+ 3 - 1
arch/riscv/cpu/ax25/Kconfig

@@ -6,7 +6,9 @@ config RISCV_NDS
 	imply RISCV_TIMER
 	imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
 	imply ANDES_PLMT if (RISCV_MMODE || SPL_RISCV_MMODE)
-	imply V5L2_CACHE
+	imply SPL_CPU_SUPPORT
+	imply SPL_OPENSBI
+	imply SPL_LOAD_FIT
 	help
 	  Run U-Boot on AndeStar V5 platforms and use some specific features
 	  which are provided by Andes Technology AndeStar V5 families.

+ 46 - 14
arch/riscv/cpu/ax25/cache.c

@@ -12,18 +12,46 @@
 #include <asm/csr.h>
 
 #ifdef CONFIG_RISCV_NDS_CACHE
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 /* mcctlcommand */
 #define CCTL_REG_MCCTLCOMMAND_NUM	0x7cc
 
 /* D-cache operation */
 #define CCTL_L1D_WBINVAL_ALL	6
 #endif
+#endif
+
+#ifdef CONFIG_V5L2_CACHE
+static void _cache_enable(void)
+{
+	struct udevice *dev = NULL;
+
+	uclass_find_first_device(UCLASS_CACHE, &dev);
+
+	if (dev)
+		cache_enable(dev);
+}
+
+static void _cache_disable(void)
+{
+	struct udevice *dev = NULL;
+
+	uclass_find_first_device(UCLASS_CACHE, &dev);
+
+	if (dev)
+		cache_disable(dev);
+}
+#endif
 
 void flush_dcache_all(void)
 {
+#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
 #ifdef CONFIG_RISCV_NDS_CACHE
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL);
 #endif
+#endif
+#endif
 }
 
 void flush_dcache_range(unsigned long start, unsigned long end)
@@ -40,6 +68,7 @@ void icache_enable(void)
 {
 #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
 #ifdef CONFIG_RISCV_NDS_CACHE
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	asm volatile (
 		"csrr t1, mcache_ctl\n\t"
 		"ori t0, t1, 0x1\n\t"
@@ -47,12 +76,14 @@ void icache_enable(void)
 	);
 #endif
 #endif
+#endif
 }
 
 void icache_disable(void)
 {
 #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
 #ifdef CONFIG_RISCV_NDS_CACHE
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	asm volatile (
 		"fence.i\n\t"
 		"csrr t1, mcache_ctl\n\t"
@@ -61,24 +92,23 @@ void icache_disable(void)
 	);
 #endif
 #endif
+#endif
 }
 
 void dcache_enable(void)
 {
 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 #ifdef CONFIG_RISCV_NDS_CACHE
-	struct udevice *dev = NULL;
-
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	asm volatile (
 		"csrr t1, mcache_ctl\n\t"
 		"ori t0, t1, 0x2\n\t"
 		"csrw mcache_ctl, t0\n\t"
 	);
-
-	uclass_find_first_device(UCLASS_CACHE, &dev);
-
-	if (dev)
-		cache_enable(dev);
+#endif
+#ifdef CONFIG_V5L2_CACHE
+	_cache_enable();
+#endif
 #endif
 #endif
 }
@@ -87,19 +117,17 @@ void dcache_disable(void)
 {
 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 #ifdef CONFIG_RISCV_NDS_CACHE
-	struct udevice *dev = NULL;
-
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL);
 	asm volatile (
 		"csrr t1, mcache_ctl\n\t"
 		"andi t0, t1, ~0x2\n\t"
 		"csrw mcache_ctl, t0\n\t"
 	);
-
-	uclass_find_first_device(UCLASS_CACHE, &dev);
-
-	if (dev)
-		cache_disable(dev);
+#endif
+#ifdef CONFIG_V5L2_CACHE
+	_cache_disable();
+#endif
 #endif
 #endif
 }
@@ -109,6 +137,7 @@ int icache_status(void)
 	int ret = 0;
 
 #ifdef CONFIG_RISCV_NDS_CACHE
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	asm volatile (
 		"csrr t1, mcache_ctl\n\t"
 		"andi	%0, t1, 0x01\n\t"
@@ -116,6 +145,7 @@ int icache_status(void)
 		:
 		: "memory"
 	);
+#endif
 #endif
 
 	return ret;
@@ -126,6 +156,7 @@ int dcache_status(void)
 	int ret = 0;
 
 #ifdef CONFIG_RISCV_NDS_CACHE
+#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
 	asm volatile (
 		"csrr t1, mcache_ctl\n\t"
 		"andi	%0, t1, 0x02\n\t"
@@ -133,6 +164,7 @@ int dcache_status(void)
 		:
 		: "memory"
 	);
+#endif
 #endif
 
 	return ret;

+ 4 - 2
arch/riscv/cpu/start.S

@@ -174,7 +174,7 @@ spl_clear_bss:
 spl_clear_bss_loop:
 	SREG	zero, 0(t0)
 	addi	t0, t0, REGBYTES
-	bne	t0, t1, spl_clear_bss_loop
+	blt	t0, t1, spl_clear_bss_loop
 
 spl_stack_gd_setup:
 	jal	spl_relocate_stack_gd
@@ -197,6 +197,7 @@ spl_secondary_hart_stack_gd_setup:
 	la	a0, secondary_hart_relocate
 	mv	a1, s0
 	mv	a2, s0
+	mv	a3, zero
 	jal	smp_call_function
 
 	/* hang if relocation of secondary harts has failed */
@@ -324,7 +325,7 @@ clear_bss:
 clbss_l:
 	SREG	zero, 0(t0)		/* clear loop... */
 	addi	t0, t0, REGBYTES
-	bne	t0, t1, clbss_l
+	blt	t0, t1, clbss_l
 
 relocate_secondary_harts:
 #ifdef CONFIG_SMP
@@ -337,6 +338,7 @@ relocate_secondary_harts:
 
 	mv	a1, s2
 	mv	a2, s3
+	mv	a3, zero
 	jal	smp_call_function
 
 	/* hang if relocation of secondary harts has failed */

+ 1 - 1
arch/riscv/cpu/u-boot-spl.lds

@@ -76,7 +76,7 @@ SECTIONS
 	.bss : {
 		__bss_start = .;
 		*(.bss*)
-		. = ALIGN(4);
+		. = ALIGN(8);
 		__bss_end = .;
 	} > .bss_mem
 }

+ 1 - 1
arch/riscv/cpu/u-boot.lds

@@ -82,7 +82,7 @@ SECTIONS
 	.bss : {
 		__bss_start = .;
 		*(.bss*)
-		. = ALIGN(4);
+		. = ALIGN(8);
 		__bss_end = .;
 	}
 }

+ 1 - 0
arch/riscv/dts/Makefile

@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb
+dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb
 
 targets += $(dtb-y)
 

+ 57 - 4
arch/riscv/dts/ae350_32.dts

@@ -62,6 +62,48 @@
 				compatible = "riscv,cpu-intc";
 			};
 		};
+		CPU2: cpu@2 {
+			device_type = "cpu";
+			reg = <2>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv32imafdc";
+			riscv,priv-major = <1>;
+			riscv,priv-minor = <10>;
+			mmu-type = "riscv,sv32";
+			clock-frequency = <60000000>;
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <32>;
+			next-level-cache = <&L2>;
+			CPU2_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
+		CPU3: cpu@3 {
+			device_type = "cpu";
+			reg = <3>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv32imafdc";
+			riscv,priv-major = <1>;
+			riscv,priv-minor = <10>;
+			mmu-type = "riscv,sv32";
+			clock-frequency = <60000000>;
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <32>;
+			next-level-cache = <&L2>;
+			CPU3_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
 	};
 
 	L2: l2-cache@e0500000 {
@@ -94,7 +136,10 @@
 			interrupt-controller;
 			reg = <0xe4000000 0x2000000>;
 			riscv,ndev=<71>;
-			interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>;
+			interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9
+				&CPU1_intc 11 &CPU1_intc 9
+				&CPU2_intc 11 &CPU2_intc 9
+				&CPU3_intc 11 &CPU3_intc 9>;
 		};
 
 		plic1: interrupt-controller@e6400000 {
@@ -104,12 +149,18 @@
 			interrupt-controller;
 			reg = <0xe6400000 0x400000>;
 			riscv,ndev=<2>;
-			interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>;
+			interrupts-extended = <&CPU0_intc 3
+				&CPU1_intc 3
+				&CPU2_intc 3
+				&CPU3_intc 3>;
 		};
 
 		plmt0@e6000000 {
 			compatible = "riscv,plmt0";
-			interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>;
+			interrupts-extended = <&CPU0_intc 7
+				&CPU1_intc 7
+				&CPU2_intc 7
+				&CPU3_intc 7>;
 			reg = <0xe6000000 0x100000>;
 		};
 	};
@@ -245,8 +296,10 @@
 	};
 
 	nor@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
 		compatible = "cfi-flash";
-		reg = <0x88000000 0x1000>;
+		reg = <0x88000000 0x4000000>;
 		bank-width = <2>;
 		device-width = <1>;
 	};

+ 57 - 4
arch/riscv/dts/ae350_64.dts

@@ -62,6 +62,48 @@
 				compatible = "riscv,cpu-intc";
 			};
 		};
+		CPU2: cpu@2 {
+			device_type = "cpu";
+			reg = <2>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv64imafdc";
+			riscv,priv-major = <1>;
+			riscv,priv-minor = <10>;
+			mmu-type = "riscv,sv39";
+			clock-frequency = <60000000>;
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <32>;
+			next-level-cache = <&L2>;
+			CPU2_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
+		CPU3: cpu@3 {
+			device_type = "cpu";
+			reg = <3>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv64imafdc";
+			riscv,priv-major = <1>;
+			riscv,priv-minor = <10>;
+			mmu-type = "riscv,sv39";
+			clock-frequency = <60000000>;
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <32>;
+			next-level-cache = <&L2>;
+			CPU3_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
 	};
 
 	L2: l2-cache@e0500000 {
@@ -94,7 +136,10 @@
 			interrupt-controller;
 			reg = <0x0 0xe4000000 0x0 0x2000000>;
 			riscv,ndev=<71>;
-			interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>;
+			interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9
+				&CPU1_intc 11 &CPU1_intc 9
+				&CPU2_intc 11 &CPU2_intc 9
+				&CPU3_intc 11 &CPU3_intc 9>;
 		};
 
 		plic1: interrupt-controller@e6400000 {
@@ -104,12 +149,18 @@
 			interrupt-controller;
 			reg = <0x0 0xe6400000 0x0 0x400000>;
 			riscv,ndev=<2>;
-			interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>;
+			interrupts-extended = <&CPU0_intc 3
+				&CPU1_intc 3
+				&CPU2_intc 3
+				&CPU3_intc 3>;
 		};
 
 		plmt0@e6000000 {
 			compatible = "riscv,plmt0";
-			interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>;
+			interrupts-extended = <&CPU0_intc 7
+				&CPU1_intc 7
+				&CPU2_intc 7
+				&CPU3_intc 7>;
 			reg = <0x0 0xe6000000 0x0 0x100000>;
 		};
 	};
@@ -245,8 +296,10 @@
 	};
 
 	nor@0,0 {
+		#address-cells = <2>;
+		#size-cells = <2>;
 		compatible = "cfi-flash";
-		reg = <0x0 0x88000000 0x0 0x1000>;
+		reg = <0x0 0x88000000 0x0 0x4000000>;
 		bank-width = <2>;
 		device-width = <1>;
 	};

+ 251 - 0
arch/riscv/dts/fu540-c000.dtsi

@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2018-2019 SiFive, Inc */
+
+/dts-v1/;
+
+#include <dt-bindings/clock/sifive-fu540-prci.h>
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	compatible = "sifive,fu540-c000", "sifive,fu540";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		ethernet0 = &eth0;
+	};
+
+	chosen {
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu0: cpu@0 {
+			compatible = "sifive,e51", "sifive,rocket0", "riscv";
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <128>;
+			i-cache-size = <16384>;
+			reg = <0>;
+			riscv,isa = "rv64imac";
+			status = "disabled";
+			cpu0_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
+		cpu1: cpu@1 {
+			compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			reg = <1>;
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+			cpu1_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
+		cpu2: cpu@2 {
+			compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			reg = <2>;
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+			cpu2_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
+		cpu3: cpu@3 {
+			compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			reg = <3>;
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+			cpu3_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
+		cpu4: cpu@4 {
+			compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			reg = <4>;
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+			cpu4_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
+	};
+	soc {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "sifive,fu540-c000", "sifive,fu540", "simple-bus";
+		ranges;
+		plic0: interrupt-controller@c000000 {
+			#interrupt-cells = <1>;
+			compatible = "sifive,plic-1.0.0";
+			reg = <0x0 0xc000000 0x0 0x4000000>;
+			riscv,ndev = <53>;
+			interrupt-controller;
+			interrupts-extended = <
+				&cpu0_intc 0xffffffff
+				&cpu1_intc 0xffffffff &cpu1_intc 9
+				&cpu2_intc 0xffffffff &cpu2_intc 9
+				&cpu3_intc 0xffffffff &cpu3_intc 9
+				&cpu4_intc 0xffffffff &cpu4_intc 9>;
+		};
+		prci: clock-controller@10000000 {
+			compatible = "sifive,fu540-c000-prci";
+			reg = <0x0 0x10000000 0x0 0x1000>;
+			clocks = <&hfclk>, <&rtcclk>;
+			#clock-cells = <1>;
+		};
+		uart0: serial@10010000 {
+			compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+			reg = <0x0 0x10010000 0x0 0x1000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <4>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			status = "disabled";
+		};
+		uart1: serial@10011000 {
+			compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+			reg = <0x0 0x10011000 0x0 0x1000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <5>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			status = "disabled";
+		};
+		i2c0: i2c@10030000 {
+			compatible = "sifive,fu540-c000-i2c", "sifive,i2c0";
+			reg = <0x0 0x10030000 0x0 0x1000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <50>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			reg-shift = <2>;
+			reg-io-width = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		qspi0: spi@10040000 {
+			compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+			reg = <0x0 0x10040000 0x0 0x1000
+			       0x0 0x20000000 0x0 0x10000000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <51>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		qspi1: spi@10041000 {
+			compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+			reg = <0x0 0x10041000 0x0 0x1000
+			       0x0 0x30000000 0x0 0x10000000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <52>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		qspi2: spi@10050000 {
+			compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+			reg = <0x0 0x10050000 0x0 0x1000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <6>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		eth0: ethernet@10090000 {
+			compatible = "sifive,fu540-c000-gem";
+			interrupt-parent = <&plic0>;
+			interrupts = <53>;
+			reg = <0x0 0x10090000 0x0 0x2000
+			       0x0 0x100a0000 0x0 0x1000>;
+			local-mac-address = [00 00 00 00 00 00];
+			clock-names = "pclk", "hclk";
+			clocks = <&prci PRCI_CLK_GEMGXLPLL>,
+				 <&prci PRCI_CLK_GEMGXLPLL>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		pwm0: pwm@10020000 {
+			compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+			reg = <0x0 0x10020000 0x0 0x1000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <42 43 44 45>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+		pwm1: pwm@10021000 {
+			compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+			reg = <0x0 0x10021000 0x0 0x1000>;
+			interrupt-parent = <&plic0>;
+			interrupts = <46 47 48 49>;
+			clocks = <&prci PRCI_CLK_TLCLK>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+	};
+};

+ 96 - 0
arch/riscv/dts/hifive-unleashed-a00.dts

@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2018-2019 SiFive, Inc */
+
+#include "fu540-c000.dtsi"
+
+/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+#define RTCCLK_FREQ		1000000
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	model = "SiFive HiFive Unleashed A00";
+	compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000";
+
+	chosen {
+		stdout-path = "serial0";
+	};
+
+	cpus {
+		timebase-frequency = <RTCCLK_FREQ>;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x2 0x00000000>;
+	};
+
+	soc {
+	};
+
+	hfclk: hfclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <33333333>;
+		clock-output-names = "hfclk";
+	};
+
+	rtcclk: rtcclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <RTCCLK_FREQ>;
+		clock-output-names = "rtcclk";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&qspi0 {
+	status = "okay";
+	flash@0 {
+		compatible = "issi,is25wp256", "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
+	};
+};
+
+&qspi2 {
+	status = "okay";
+	mmc@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		spi-max-frequency = <20000000>;
+		voltage-ranges = <3300 3300>;
+		disable-wp;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	phy-mode = "gmii";
+	phy-handle = <&phy0>;
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&pwm1 {
+	status = "okay";
+};

+ 2 - 1
arch/riscv/include/asm/smp.h

@@ -46,8 +46,9 @@ void handle_ipi(ulong hart);
  * @addr: Address of function
  * @arg0: First argument of function
  * @arg1: Second argument of function
+ * @wait: Wait for harts to acknowledge request
  * @return 0 if OK, -ve on error
  */
-int smp_call_function(ulong addr, ulong arg0, ulong arg1);
+int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait);
 
 #endif

+ 18 - 4
arch/riscv/lib/andes_plic.c

@@ -19,7 +19,7 @@
 #include <cpu.h>
 
 /* pending register */
-#define PENDING_REG(base, hart)	((ulong)(base) + 0x1000 + (hart) * 8)
+#define PENDING_REG(base, hart)	((ulong)(base) + 0x1000 + ((hart) / 4) * 4)
 /* enable register */
 #define ENABLE_REG(base, hart)	((ulong)(base) + 0x2000 + (hart) * 0x80)
 /* claim register */
@@ -46,7 +46,7 @@ static int init_plic(void);
 
 static int enable_ipi(int hart)
 {
-	int en;
+	unsigned int en;
 
 	en = ENABLE_HART_IPI >> hart;
 	writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, hart));
@@ -94,10 +94,13 @@ static int init_plic(void)
 
 int riscv_send_ipi(int hart)
 {
+	unsigned int ipi;
+
 	PLIC_BASE_GET();
 
-	writel(SEND_IPI_TO_HART(hart),
-	       (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart));
+	ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
+	writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic,
+				gd->arch.boot_hart));
 
 	return 0;
 }
@@ -114,6 +117,17 @@ int riscv_clear_ipi(int hart)
 	return 0;
 }
 
+int riscv_get_ipi(int hart, int *pending)
+{
+	PLIC_BASE_GET();
+
+	*pending = readl((void __iomem *)PENDING_REG(gd->arch.plic,
+						     gd->arch.boot_hart));
+	*pending = !!(*pending & SEND_IPI_TO_HART(hart));
+
+	return 0;
+}
+
 static const struct udevice_id andes_plic_ids[] = {
 	{ .compatible = "riscv,plic1", .data = RISCV_SYSCON_PLIC },
 	{ }

+ 1 - 1
arch/riscv/lib/bootm.c

@@ -99,7 +99,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
 		if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
 #ifdef CONFIG_SMP
 			ret = smp_call_function(images->ep,
-						(ulong)images->ft_addr, 0);
+						(ulong)images->ft_addr, 0, 0);
 			if (ret)
 				hang();
 #endif

+ 11 - 0
arch/riscv/lib/sbi_ipi.c

@@ -23,3 +23,14 @@ int riscv_clear_ipi(int hart)
 
 	return 0;
 }
+
+int riscv_get_ipi(int hart, int *pending)
+{
+	/*
+	 * The SBI does not support reading the IPI status. We always return 0
+	 * to indicate that no IPI is pending.
+	 */
+	*pending = 0;
+
+	return 0;
+}

+ 9 - 0
arch/riscv/lib/sifive_clint.c

@@ -71,6 +71,15 @@ int riscv_clear_ipi(int hart)
 	return 0;
 }
 
+int riscv_get_ipi(int hart, int *pending)
+{
+	CLINT_BASE_GET();
+
+	*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
+
+	return 0;
+}
+
 static const struct udevice_id sifive_clint_ids[] = {
 	{ .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT },
 	{ }

+ 34 - 9
arch/riscv/lib/smp.c

@@ -32,11 +32,23 @@ extern int riscv_send_ipi(int hart);
  */
 extern int riscv_clear_ipi(int hart);
 
-static int send_ipi_many(struct ipi_data *ipi)
+/**
+ * riscv_get_ipi() - Get status of inter-processor interrupt (IPI)
+ *
+ * Platform code must provide this function.
+ *
+ * @hart: Hart ID of hart to be checked
+ * @pending: Pointer to variable with result of the check,
+ *           1 if IPI is pending, 0 otherwise
+ * @return 0 if OK, -ve on error
+ */
+extern int riscv_get_ipi(int hart, int *pending);
+
+static int send_ipi_many(struct ipi_data *ipi, int wait)
 {
 	ofnode node, cpus;
 	u32 reg;
-	int ret;
+	int ret, pending;
 
 	cpus = ofnode_path("/cpus");
 	if (!ofnode_valid(cpus)) {
@@ -79,6 +91,15 @@ static int send_ipi_many(struct ipi_data *ipi)
 			pr_err("Cannot send IPI to hart %d\n", reg);
 			return ret;
 		}
+
+		if (wait) {
+			pending = 1;
+			while (pending) {
+				ret = riscv_get_ipi(reg, &pending);
+				if (ret)
+					return ret;
+			}
+		}
 	}
 
 	return 0;
@@ -92,21 +113,25 @@ void handle_ipi(ulong hart)
 	if (hart >= CONFIG_NR_CPUS)
 		return;
 
+	__smp_mb();
+
+	smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr;
+	invalidate_icache_all();
+
+	/*
+	 * Clear the IPI to acknowledge the request before jumping to the
+	 * requested function.
+	 */
 	ret = riscv_clear_ipi(hart);
 	if (ret) {
 		pr_err("Cannot clear IPI of hart %ld\n", hart);
 		return;
 	}
 
-	__smp_mb();
-
-	smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr;
-	invalidate_icache_all();
-
 	smp_function(hart, gd->arch.ipi[hart].arg0, gd->arch.ipi[hart].arg1);
 }
 
-int smp_call_function(ulong addr, ulong arg0, ulong arg1)
+int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait)
 {
 	int ret = 0;
 	struct ipi_data ipi;
@@ -115,7 +140,7 @@ int smp_call_function(ulong addr, ulong arg0, ulong arg1)
 	ipi.arg0 = arg0;
 	ipi.arg1 = arg1;
 
-	ret = send_ipi_many(&ipi);
+	ret = send_ipi_many(&ipi, wait);
 
 	return ret;
 }

+ 1 - 1
arch/riscv/lib/spl.c

@@ -41,7 +41,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
 
 	debug("image entry point: 0x%lX\n", spl_image->entry_point);
 #ifdef CONFIG_SMP
-	ret = smp_call_function(spl_image->entry_point, (ulong)fdt_blob, 0);
+	ret = smp_call_function(spl_image->entry_point, (ulong)fdt_blob, 0, 0);
 	if (ret)
 		hang();
 #endif

+ 9 - 0
board/AndesTech/ax25-ae350/Kconfig

@@ -21,9 +21,18 @@ config ENV_SIZE
 config ENV_OFFSET
 	default 0x140000 if ENV_IS_IN_SPI_FLASH
 
+config SPL_TEXT_BASE
+	default 0x800000
+
+config SPL_OPENSBI_LOAD_ADDR
+	default 0x01000000
+
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
 	select RISCV_NDS
+	select SUPPORT_SPL
 	imply SMP
+	imply SPL_RAM_SUPPORT
+	imply SPL_RAM_DEVICE
 
 endif

+ 4 - 0
board/AndesTech/ax25-ae350/MAINTAINERS

@@ -7,3 +7,7 @@ F:	configs/ae350_rv32_defconfig
 F:	configs/ae350_rv64_defconfig
 F:	configs/ae350_rv32_xip_defconfig
 F:	configs/ae350_rv64_xip_defconfig
+F:	configs/ae350_rv32_spl_defconfig
+F:	configs/ae350_rv64_spl_defconfig
+F:	configs/ae350_rv32_spl_xip_defconfig
+F:	configs/ae350_rv64_spl_xip_defconfig

+ 29 - 19
board/AndesTech/ax25-ae350/ax25-ae350.c

@@ -12,6 +12,7 @@
 #include <faraday/ftsmc020.h>
 #include <fdtdec.h>
 #include <dm.h>
+#include <spl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -29,29 +30,12 @@ int board_init(void)
 
 int dram_init(void)
 {
-	unsigned long sdram_base = PHYS_SDRAM_0;
-	unsigned long expected_size = PHYS_SDRAM_0_SIZE + PHYS_SDRAM_1_SIZE;
-	unsigned long actual_size;
-
-	actual_size = get_ram_size((void *)sdram_base, expected_size);
-	gd->ram_size = actual_size;
-
-	if (expected_size != actual_size) {
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-			actual_size >> 20, expected_size >> 20);
-	}
-
-	return 0;
+	return fdtdec_setup_mem_size_base();
 }
 
 int dram_init_banksize(void)
 {
-	gd->bd->bi_dram[0].start = PHYS_SDRAM_0;
-	gd->bd->bi_dram[0].size =  PHYS_SDRAM_0_SIZE;
-	gd->bd->bi_dram[1].start = PHYS_SDRAM_1;
-	gd->bd->bi_dram[1].size =  PHYS_SDRAM_1_SIZE;
-
-	return 0;
+	return fdtdec_setup_memory_banksize();
 }
 
 #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
@@ -110,3 +94,29 @@ int board_early_init_f(void)
 	return 0;
 }
 #endif
+
+#ifdef CONFIG_SPL
+void board_boot_order(u32 *spl_boot_list)
+{
+	u8 i;
+	u32 boot_devices[] = {
+#ifdef CONFIG_SPL_RAM_SUPPORT
+		BOOT_DEVICE_RAM,
+#endif
+#ifdef CONFIG_SPL_MMC_SUPPORT
+		BOOT_DEVICE_MMC1,
+#endif
+	};
+
+	for (i = 0; i < ARRAY_SIZE(boot_devices); i++)
+		spl_boot_list[i] = boot_devices[i];
+}
+#endif
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* boot using first FIT config */
+	return 0;
+}
+#endif

+ 7 - 0
common/spl/Kconfig

@@ -439,6 +439,13 @@ config SPL_FIT_IMAGE_TINY
 	  ensure this information is available to the next image
 	  invoked).
 
+config SPL_CACHE_SUPPORT
+	bool "Support CACHE drivers"
+	help
+	  Enable CACHE drivers in SPL. These drivers can keep data so that
+	  future requests for that data can be served faster. Enable this option
+	  to build the drivers in drivers/cache as part of an SPL build.
+
 config SPL_CPU_SUPPORT
 	bool "Support CPU drivers"
 	help

+ 12 - 1
common/spl/spl_opensbi.c

@@ -70,14 +70,25 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image)
 	opensbi_info.next_addr = uboot_entry;
 	opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S;
 	opensbi_info.options = SBI_SCRATCH_NO_BOOT_PRINTS;
+	opensbi_info.boot_hart = gd->arch.boot_hart;
 
 	opensbi_entry = (void (*)(ulong, ulong, ulong))spl_image->entry_point;
 	invalidate_icache_all();
 
 #ifdef CONFIG_SMP
+	/*
+	 * Start OpenSBI on all secondary harts and wait for acknowledgment.
+	 *
+	 * OpenSBI first relocates itself to its link address. This is done by
+	 * the main hart. To make sure no hart is still running U-Boot SPL
+	 * during relocation, we wait for all secondary harts to acknowledge
+	 * the call-function request before entering OpenSBI on the main hart.
+	 * Otherwise, code corruption can occur if the link address ranges of
+	 * U-Boot SPL and OpenSBI overlap.
+	 */
 	ret = smp_call_function((ulong)spl_image->entry_point,
 				(ulong)spl_image->fdt_addr,
-				(ulong)&opensbi_info);
+				(ulong)&opensbi_info, 1);
 	if (ret)
 		hang();
 #endif

+ 38 - 0
configs/ae350_rv32_spl_defconfig

@@ -0,0 +1,38 @@
+CONFIG_RISCV=y
+CONFIG_SPL=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SYS_TEXT_BASE=0x01200000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_PRIOR_STAGE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y

+ 40 - 0
configs/ae350_rv32_spl_xip_defconfig

@@ -0,0 +1,40 @@
+CONFIG_RISCV=y
+CONFIG_SPL=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SPL_TEXT_BASE=0x80000000
+CONFIG_SYS_TEXT_BASE=0x01200000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_XIP=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_BOARD=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y

+ 39 - 0
configs/ae350_rv64_spl_defconfig

@@ -0,0 +1,39 @@
+CONFIG_RISCV=y
+CONFIG_SPL=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SYS_TEXT_BASE=0x01200000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_ARCH_RV64I=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_PRIOR_STAGE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y

+ 41 - 0
configs/ae350_rv64_spl_xip_defconfig

@@ -0,0 +1,41 @@
+CONFIG_RISCV=y
+CONFIG_SPL=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SPL_TEXT_BASE=0x80000000
+CONFIG_SYS_TEXT_BASE=0x01200000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_ARCH_RV64I=y
+CONFIG_XIP=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_BOARD=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y

+ 2 - 1
configs/sifive_fu540_defconfig

@@ -7,8 +7,9 @@ CONFIG_RISCV_SMODE=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
 CONFIG_MISC_INIT_R=y
+CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00"
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_OF_PRIOR_STAGE=y
+CONFIG_OF_SEPARATE=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y

+ 206 - 3
doc/board/AndesTech/ax25-ae350.rst

@@ -324,6 +324,209 @@ Boot bbl and riscv-linux via U-Boot on QEMU
    / #
 
 
-TODO
-----
-Boot bbl and riscv-linux via U-Boot on AE350 board
+Running U-Boot SPL
+------------------
+The U-Boot SPL will boot in M mode and load the FIT image which include
+OpenSBI and U-Boot proper images. After loading progress, it will jump
+to OpenSBI first and then U-Boot proper which will run in S mode.
+
+
+How to build U-Boot SPL
+-----------------------
+Before building U-Boot SPL, OpenSBI must be build first. OpenSBI can be
+cloned and build for AE350 as below:
+
+git clone https://github.com/riscv/opensbi.git
+cd opensbi
+make PLATFORM=andes/ae350
+
+Copy OpenSBI FW_DYNAMIC image (build\platform\andes\ae350\firmware\fw_dynamic.bin)
+into U-Boot root directory
+
+
+How to build U-Boot SPL booting from RAM
+----------------------------------------
+With ae350_rv[32|64]_spl_defconfigs:
+
+U-Boot SPL will be loaded by gdb or FSBL and runs in RAM in machine mode
+and then load FIT image from RAM device on AE350.
+
+
+How to build U-Boot SPL booting from ROM
+----------------------------------------
+With ae350_rv[32|64]_spl_xip_defconfigs:
+
+U-Boot SPL can be burned into SPI flash and run in flash in machine mode
+and then load FIT image from SPI flash or MMC device on AE350.
+
+
+Messages of U-Boot SPL boots Kernel on AE350 board
+--------------------------------------------------
+
+.. code-block:: none
+
+U-Boot SPL 2020.01-rc1-00292-g67a3313-dirty (Nov 14 2019 - 11:26:21 +0800)
+Trying to boot from RAM
+
+OpenSBI v0.5-1-gdd8ef28 (Nov 14 2019 11:08:39)
+   ____                    _____ ____ _____
+  / __ \                  / ____|  _ \_   _|
+ | |  | |_ __   ___ _ __ | (___ | |_) || |
+ | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
+ | |__| | |_) |  __/ | | |____) | |_) || |_
+  \____/| .__/ \___|_| |_|_____/|____/_____|
+        | |
+        |_|
+
+Platform Name          : Andes AE350
+Platform HART Features : RV64ACIMSUX
+Platform Max HARTs     : 4
+Current Hart           : 0
+Firmware Base          : 0x0
+Firmware Size          : 84 KB
+Runtime SBI Version    : 0.2
+
+PMP0: 0x0000000000000000-0x000000000001ffff (A)
+PMP1: 0x0000000000000000-0x00000001ffffffff (A,R,W,X)
+
+
+U-Boot 2020.01-rc1-00292-g67a3313-dirty (Nov 14 2019 - 11:26:21 +0800)
+
+DRAM:  1 GiB
+Flash: 64 MiB
+MMC:   mmc@f0e00000: 0
+Loading Environment from SPI Flash... SF: Detected mx25u1635e with page size 256 Bytes, erase size 4 KiB, total 2 MiB
+OK
+In:    serial@f0300000
+Out:   serial@f0300000
+Err:   serial@f0300000
+Net:   no alias for ethernet0
+
+Warning: mac@e0100000 (eth0) using random MAC address - a2:ae:93:7b:cc:8f
+eth0: mac@e0100000
+Hit any key to stop autoboot:  0
+6455 bytes read in 31 ms (203.1 KiB/s)
+20421684 bytes read in 8647 ms (2.3 MiB/s)
+## Booting kernel from Legacy Image at 00600000 ...
+   Image Name:
+   Image Type:   RISC-V Linux Kernel Image (uncompressed)
+   Data Size:    20421620 Bytes = 19.5 MiB
+   Load Address: 00200000
+   Entry Point:  00200000
+   Verifying Checksum ... OK
+## Flattened Device Tree blob at 20000000
+   Booting using the fdt blob at 0x20000000
+   Loading Kernel Image
+   Loading Device Tree to 000000001effb000, end 000000001efff936 ... OK
+
+Starting kernel ...
+
+OF: fdt: Ignoring memory range 0x0 - 0x200000
+Linux version 4.17.0-00253-g49136e10bcb2 (sqa@atcsqa07) (gcc version 7.3.0 (2019-04-06_nds64le-linux-glibc-v5_experimental)) #1 SMP PREEMPT Sat Apr 6 23:41:49 CST 2019
+bootconsole [early0] enabled
+Initial ramdisk at: 0x        (ptrval) (13665712 bytes)
+Zone ranges:
+  DMA32    [mem 0x0000000000200000-0x000000003fffffff]
+  Normal   empty
+Movable zone start for each node
+Early memory node ranges
+  node   0: [mem 0x0000000000200000-0x000000003fffffff]
+Initmem setup node 0 [mem 0x0000000000200000-0x000000003fffffff]
+software IO TLB [mem 0x3b1f8000-0x3f1f8000] (64MB) mapped at [        (ptrval)-        (ptrval)]
+elf_platform is rv64i2p0m2p0a2p0c2p0xv5-0p0
+compatible privileged spec version 1.10
+percpu: Embedded 16 pages/cpu @        (ptrval) s28184 r8192 d29160 u65536
+Built 1 zonelists, mobility grouping on.  Total pages: 258055
+Kernel command line: console=ttyS0,38400n8 debug loglevel=7
+log_buf_len individual max cpu contribution: 4096 bytes
+log_buf_len total cpu_extra contributions: 12288 bytes
+log_buf_len min size: 16384 bytes
+log_buf_len: 32768 bytes
+early log buf free: 14608(89%)
+Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes)
+Inode-cache hash table entries: 65536 (order: 7, 524288 bytes)
+Sorting __ex_table...
+Memory: 944428K/1046528K available (3979K kernel code, 246K rwdata, 1490K rodata, 13523K init, 688K bss, 102100K reserved, 0K cma-reserved)
+SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
+Preemptible hierarchical RCU implementation.
+        Tasks RCU enabled.
+NR_IRQS: 72, nr_irqs: 72, preallocated irqs: 0
+riscv,cpu_intc,0: 64 local interrupts mapped
+riscv,cpu_intc,1: 64 local interrupts mapped
+riscv,cpu_intc,2: 64 local interrupts mapped
+riscv,cpu_intc,3: 64 local interrupts mapped
+riscv,plic0,e4000000: mapped 71 interrupts to 8/8 handlers
+clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1bacf917bf, max_idle_ns: 881590412290 ns
+sched_clock: 64 bits at 60MHz, resolution 16ns, wraps every 4398046511098ns
+Console: colour dummy device 40x30
+Calibrating delay loop (skipped), value calculated using timer frequency.. 120.00 BogoMIPS (lpj=600000)
+pid_max: default: 32768 minimum: 301
+Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)
+Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes)
+Hierarchical SRCU implementation.
+smp: Bringing up secondary CPUs ...
+CPU0: online
+CPU2: online
+CPU3: online
+smp: Brought up 1 node, 4 CPUs
+devtmpfs: initialized
+random: get_random_u32 called from bucket_table_alloc+0x198/0x1d8 with crng_init=0
+clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
+futex hash table entries: 1024 (order: 4, 65536 bytes)
+NET: Registered protocol family 16
+Advanced Linux Sound Architecture Driver Initialized.
+clocksource: Switched to clocksource riscv_clocksource
+NET: Registered protocol family 2
+tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes)
+TCP established hash table entries: 8192 (order: 4, 65536 bytes)
+TCP bind hash table entries: 8192 (order: 5, 131072 bytes)
+TCP: Hash tables configured (established 8192 bind 8192)
+UDP hash table entries: 512 (order: 2, 16384 bytes)
+UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
+NET: Registered protocol family 1
+RPC: Registered named UNIX socket transport module.
+RPC: Registered udp transport module.
+RPC: Registered tcp transport module.
+RPC: Registered tcp NFSv4.1 backchannel transport module.
+Unpacking initramfs...
+workingset: timestamp_bits=62 max_order=18 bucket_order=0
+NFS: Registering the id_resolver key type
+Key type id_resolver registered
+Key type id_legacy registered
+nfs4filelayout_init: NFSv4 File Layout Driver Registering...
+io scheduler noop registered
+io scheduler cfq registered (default)
+io scheduler mq-deadline registered
+io scheduler kyber registered
+Console: switching to colour frame buffer device 40x30
+Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
+console [ttyS0] disabled
+f0300000.serial: ttyS0 at MMIO 0xf0300020 (irq = 20, base_baud = 1228800) is a 16550A
+console [ttyS0] enabled
+console [ttyS0] enabled
+bootconsole [early0] disabled
+bootconsole [early0] disabled
+loop: module loaded
+tun: Universal TUN/TAP device driver, 1.6
+ftmac100: Loading version 0.2 ...
+ftmac100 e0100000.mac eth0: irq 21, mapped at         (ptrval)
+ftmac100 e0100000.mac eth0: generated random MAC address 4e:fd:bd:f3:04:fc
+ftsdc010 f0e00000.mmc: mmc0 - using hw SDIO IRQ
+mmc0: new SDHC card at address d555
+ftssp010 card registered!
+mmcblk0: mmc0:d555 SD04G 3.79 GiB
+NET: Registered protocol family 10
+ mmcblk0: p1
+Segment Routing with IPv6
+sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
+NET: Registered protocol family 17
+NET: Registered protocol family 15
+ALSA device list:
+  #0: ftssp_ac97 controller
+Freeing unused kernel memory: 13520K
+This architecture does not have kernel memory protection.
+Sysinit starting
+Sat Apr  6 23:33:53 CST 2019
+nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
+
+~ #

+ 1 - 4
doc/board/sifive/fu540.rst

@@ -58,10 +58,7 @@ firmware. We need to compile OpenSBI with below command:
 
 .. code-block:: none
 
-    make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot.bin> FW_PAYLOAD_FDT_PATH=<path to hifive-unleashed-a00.dtb from Linux>
-
-(Note: Prefer hifive-unleashed-a00.dtb from Linux-5.3 or higher)
-(Note: Linux-5.2 is also fine but it does not have ethernet DT node)
+make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot-dtb.bin>
 
 More detailed description of steps required to build FW_PAYLOAD firmware
 is beyond the scope of this document. Please refer OpenSBI documenation.

+ 1 - 0
drivers/Makefile

@@ -30,6 +30,7 @@ ifndef CONFIG_TPL_BUILD
 ifdef CONFIG_SPL_BUILD
 
 obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
+obj-$(CONFIG_SPL_CACHE_SUPPORT) += cache/
 obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
 obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
 obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/

+ 17 - 0
include/configs/ax25-ae350.h

@@ -7,6 +7,23 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_MAX_SIZE		0x00100000
+#define CONFIG_SPL_BSS_START_ADDR	0x04000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x00100000
+
+#ifndef CONFIG_XIP
+#define CONFIG_SPL_LOAD_FIT_ADDRESS	0x00200000
+#else
+#define CONFIG_SPL_LOAD_FIT_ADDRESS	0x80010000
+#endif
+
+#ifdef CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.itb"
+#endif
+#endif
+
 /*
  * CPU and Board Configuration Options
  */

+ 17 - 1
include/opensbi.h

@@ -11,7 +11,7 @@
 #define FW_DYNAMIC_INFO_MAGIC_VALUE		0x4942534f
 
 /** Maximum supported info version */
-#define FW_DYNAMIC_INFO_VERSION			0x1
+#define FW_DYNAMIC_INFO_VERSION			0x2
 
 /** Possible next mode values */
 #define FW_DYNAMIC_INFO_NEXT_MODE_U		0x0
@@ -35,6 +35,22 @@ struct fw_dynamic_info {
 	unsigned long next_mode;
 	/** Options for OpenSBI library */
 	unsigned long options;
+	/**
+	 * Preferred boot HART id
+	 *
+	 * It is possible that the previous booting stage uses same link
+	 * address as the FW_DYNAMIC firmware. In this case, the relocation
+	 * lottery mechanism can potentially overwrite the previous booting
+	 * stage while other HARTs are still running in the previous booting
+	 * stage leading to boot-time crash. To avoid this boot-time crash,
+	 * the previous booting stage can specify last HART that will jump
+	 * to the FW_DYNAMIC firmware as the preferred boot HART.
+	 *
+	 * To avoid specifying a preferred boot HART, the previous booting
+	 * stage can set it to -1UL which will force the FW_DYNAMIC firmware
+	 * to use the relocation lottery mechanism.
+	 */
+	unsigned long boot_hart;
 } __packed;
 
 #endif