Ver código fonte

u-boot: Add support for SMP boot on Freedom U540

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Alistair Francis 5 anos atrás
pai
commit
a05b1d8932
19 arquivos alterados com 1867 adições e 0 exclusões
  1. 286 0
      recipes-bsp/u-boot/files/0001-riscv-add-infrastructure-for-calling-functions-on-ot.patch
  2. 122 0
      recipes-bsp/u-boot/files/0002-riscv-import-the-supervisor-binary-interface-header-.patch
  3. 85 0
      recipes-bsp/u-boot/files/0003-riscv-implement-IPI-platform-functions-using-SBI.patch
  4. 62 0
      recipes-bsp/u-boot/files/0004-riscv-delay-initialization-of-caches-and-debug-UART.patch
  5. 44 0
      recipes-bsp/u-boot/files/0005-riscv-save-hart-ID-in-register-tp-instead-of-s0.patch
  6. 283 0
      recipes-bsp/u-boot/files/0006-riscv-add-support-for-multi-hart-systems.patch
  7. 55 0
      recipes-bsp/u-boot/files/0007-riscv-boot-images-passed-to-bootm-on-all-harts.patch
  8. 44 0
      recipes-bsp/u-boot/files/0008-riscv-do-not-rely-on-hart-ID-passed-by-previous-boot.patch
  9. 51 0
      recipes-bsp/u-boot/files/0009-riscv-hang-if-relocation-of-secondary-harts-fails.patch
  10. 26 0
      recipes-bsp/u-boot/files/0010-riscv-fu540-enable-SMP.patch
  11. 27 0
      recipes-bsp/u-boot/files/0011-riscv-qemu-enable-SMP.patch
  12. 209 0
      recipes-bsp/u-boot/files/0012-riscv-Add-a-SYSCON-driver-for-Andestech-s-PLIC.patch
  13. 145 0
      recipes-bsp/u-boot/files/0013-riscv-Add-a-SYSCON-driver-for-Andestech-s-PLMT.patch
  14. 56 0
      recipes-bsp/u-boot/files/0014-riscv-ax25-Add-platform-specific-Kconfig-options.patch
  15. 32 0
      recipes-bsp/u-boot/files/0015-riscv-ax25-Andes-specific-cache-shall-only-support-i.patch
  16. 257 0
      recipes-bsp/u-boot/files/0016-riscv-dts-ae350-support-SMP.patch
  17. 27 0
      recipes-bsp/u-boot/files/0017-riscv-ae350-enable-SMP.patch
  18. 35 0
      recipes-bsp/u-boot/files/0018-riscv-dts-fix-CONFIG_DEFAULT_DEVICE_TREE-failure.patch
  19. 21 0
      recipes-bsp/u-boot/u-boot_2019.04.bbappend

+ 286 - 0
recipes-bsp/u-boot/files/0001-riscv-add-infrastructure-for-calling-functions-on-ot.patch

@@ -0,0 +1,286 @@
+From fa33f08fd657b8568ede929df8a79bd113e9c5b1 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:32 +0100
+Subject: [PATCH 01/18] riscv: add infrastructure for calling functions on
+ other harts
+
+Harts on RISC-V boot independently, U-Boot is responsible for managing
+them. Functions are called on other harts with smp_call_function(),
+which sends inter-processor interrupts (IPIs) to all other available
+harts. Available harts are those marked as available in the device tree
+and present in the available_harts mask stored in global data. The
+available_harts mask is used to register all harts that have entered
+U-Boot. Functions are specified with their address and two function
+arguments (argument 2 and 3). The first function argument is always the
+hart ID of the hart calling the function. On the other harts, the IPI
+interrupt handler handle_ipi() must be called on software interrupts to
+handle the request and call the specified function.
+
+Functions are stored in the ipi_data data structure. Every hart has its
+own data structure in global data. While this is not required at the
+moment (all harts are expected to boot Linux), this does allow future
+expansion, where other harts may be used for monitoring or other tasks.
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ arch/riscv/Kconfig                   |  19 +++++
+ arch/riscv/include/asm/global_data.h |   6 ++
+ arch/riscv/include/asm/smp.h         |  53 ++++++++++++
+ arch/riscv/lib/Makefile              |   1 +
+ arch/riscv/lib/smp.c                 | 118 +++++++++++++++++++++++++++
+ 5 files changed, 197 insertions(+)
+ create mode 100644 arch/riscv/include/asm/smp.h
+ create mode 100644 arch/riscv/lib/smp.c
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 36512a8995..4d7a115569 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -120,4 +120,23 @@ config RISCV_RDTIME
+ config SYS_MALLOC_F_LEN
+ 	default 0x1000
+ 
++config SMP
++	bool "Symmetric Multi-Processing"
++	help
++	  This enables support for systems with more than one CPU. If
++	  you say N here, U-Boot will run on single and multiprocessor
++	  machines, but will use only one CPU of a multiprocessor
++	  machine. If you say Y here, U-Boot will run on many, but not
++	  all, single processor machines.
++
++config NR_CPUS
++	int "Maximum number of CPUs (2-32)"
++	range 2 32
++	depends on SMP
++	default 8
++	help
++	  On multiprocessor machines, U-Boot sets up a stack for each CPU.
++	  Stack memory is pre-allocated. U-Boot must therefore know the
++	  maximum number of CPUs that may be present.
++
+ endmenu
+diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
+index a3a342c6e1..80e3165e39 100644
+--- a/arch/riscv/include/asm/global_data.h
++++ b/arch/riscv/include/asm/global_data.h
+@@ -10,12 +10,18 @@
+ #ifndef	__ASM_GBL_DATA_H
+ #define __ASM_GBL_DATA_H
+ 
++#include <asm/smp.h>
++
+ /* Architecture-specific global data */
+ struct arch_global_data {
+ 	long boot_hart;		/* boot hart id */
+ #ifdef CONFIG_SIFIVE_CLINT
+ 	void __iomem *clint;	/* clint base address */
+ #endif
++#ifdef CONFIG_SMP
++	struct ipi_data ipi[CONFIG_NR_CPUS];
++#endif
++	ulong available_harts;
+ };
+ 
+ #include <asm-generic/global_data.h>
+diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
+new file mode 100644
+index 0000000000..bc863fdbaf
+--- /dev/null
++++ b/arch/riscv/include/asm/smp.h
+@@ -0,0 +1,53 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2019 Fraunhofer AISEC,
++ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
++ */
++
++#ifndef _ASM_RISCV_SMP_H
++#define _ASM_RISCV_SMP_H
++
++/**
++ * struct ipi_data - Inter-processor interrupt (IPI) data structure
++ *
++ * IPIs are used for SMP support to communicate to other harts what function to
++ * call. Functions are in the form
++ * void (*addr)(ulong hart, ulong arg0, ulong arg1).
++ *
++ * The function address and the two arguments, arg0 and arg1, are stored in the
++ * IPI data structure. The hart ID is inserted by the hart handling the IPI and
++ * calling the function.
++ *
++ * @addr: Address of function
++ * @arg0: First argument of function
++ * @arg1: Second argument of function
++ */
++struct ipi_data {
++	ulong addr;
++	ulong arg0;
++	ulong arg1;
++};
++
++/**
++ * handle_ipi() - interrupt handler for software interrupts
++ *
++ * The IPI interrupt handler must be called to handle software interrupts. It
++ * calls the function specified in the hart's IPI data structure.
++ *
++ * @hart: Hart ID of the current hart
++ */
++void handle_ipi(ulong hart);
++
++/**
++ * smp_call_function() - Call a function on all other harts
++ *
++ * Send IPIs with the specified function call to all harts.
++ *
++ * @addr: Address of function
++ * @arg0: First argument of function
++ * @arg1: Second argument of function
++ * @return 0 if OK, -ve on error
++ */
++int smp_call_function(ulong addr, ulong arg0, ulong arg1);
++
++#endif
+diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
+index edfa61690c..19370f9749 100644
+--- a/arch/riscv/lib/Makefile
++++ b/arch/riscv/lib/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
+ obj-y	+= interrupts.o
+ obj-y	+= reset.o
+ obj-y   += setjmp.o
++obj-$(CONFIG_SMP) += smp.o
+ 
+ # For building EFI apps
+ CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
+diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
+new file mode 100644
+index 0000000000..caa292ccd2
+--- /dev/null
++++ b/arch/riscv/lib/smp.c
+@@ -0,0 +1,118 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2019 Fraunhofer AISEC,
++ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <asm/barrier.h>
++#include <asm/smp.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++/**
++ * riscv_send_ipi() - Send inter-processor interrupt (IPI)
++ *
++ * Platform code must provide this function.
++ *
++ * @hart: Hart ID of receiving hart
++ * @return 0 if OK, -ve on error
++ */
++extern int riscv_send_ipi(int hart);
++
++/**
++ * riscv_clear_ipi() - Clear inter-processor interrupt (IPI)
++ *
++ * Platform code must provide this function.
++ *
++ * @hart: Hart ID of hart to be cleared
++ * @return 0 if OK, -ve on error
++ */
++extern int riscv_clear_ipi(int hart);
++
++static int send_ipi_many(struct ipi_data *ipi)
++{
++	ofnode node, cpus;
++	u32 reg;
++	int ret;
++
++	cpus = ofnode_path("/cpus");
++	if (!ofnode_valid(cpus)) {
++		pr_err("Can't find cpus node!\n");
++		return -EINVAL;
++	}
++
++	ofnode_for_each_subnode(node, cpus) {
++		/* skip if hart is marked as not available in the device tree */
++		if (!ofnode_is_available(node))
++			continue;
++
++		/* read hart ID of CPU */
++		ret = ofnode_read_u32(node, "reg", &reg);
++		if (ret)
++			continue;
++
++		/* skip if it is the hart we are running on */
++		if (reg == gd->arch.boot_hart)
++			continue;
++
++		if (reg >= CONFIG_NR_CPUS) {
++			pr_err("Hart ID %d is out of range, increase CONFIG_NR_CPUS\n",
++			       reg);
++			continue;
++		}
++
++		/* skip if hart is not available */
++		if (!(gd->arch.available_harts & (1 << reg)))
++			continue;
++
++		gd->arch.ipi[reg].addr = ipi->addr;
++		gd->arch.ipi[reg].arg0 = ipi->arg0;
++		gd->arch.ipi[reg].arg1 = ipi->arg1;
++
++		ret = riscv_send_ipi(reg);
++		if (ret) {
++			pr_err("Cannot send IPI to hart %d\n", reg);
++			return ret;
++		}
++	}
++
++	return 0;
++}
++
++void handle_ipi(ulong hart)
++{
++	int ret;
++	void (*smp_function)(ulong hart, ulong arg0, ulong arg1);
++
++	if (hart >= CONFIG_NR_CPUS)
++		return;
++
++	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 ret = 0;
++	struct ipi_data ipi;
++
++	ipi.addr = addr;
++	ipi.arg0 = arg0;
++	ipi.arg1 = arg1;
++
++	ret = send_ipi_many(&ipi);
++
++	return ret;
++}
+-- 
+2.21.0
+

+ 122 - 0
recipes-bsp/u-boot/files/0002-riscv-import-the-supervisor-binary-interface-header-.patch

@@ -0,0 +1,122 @@
+From 34a0626fc344f51cd768efecdd52628b677fb9a8 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:33 +0100
+Subject: [PATCH 02/18] riscv: import the supervisor binary interface header
+ file
+
+Import the supervisor binary interface (SBI) header file from Linux
+(arch/riscv/include/asm/sbi.h). The last change to it was in commit
+6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI").
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Atish Patra <atish.patra@wdc.com>
+---
+ arch/riscv/include/asm/sbi.h | 94 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 94 insertions(+)
+ create mode 100644 arch/riscv/include/asm/sbi.h
+
+diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
+new file mode 100644
+index 0000000000..ced57defdd
+--- /dev/null
++++ b/arch/riscv/include/asm/sbi.h
+@@ -0,0 +1,94 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2015 Regents of the University of California
++ *
++ * Taken from Linux arch/riscv/include/asm/sbi.h
++ */
++
++#ifndef _ASM_RISCV_SBI_H
++#define _ASM_RISCV_SBI_H
++
++#include <linux/types.h>
++
++#define SBI_SET_TIMER 0
++#define SBI_CONSOLE_PUTCHAR 1
++#define SBI_CONSOLE_GETCHAR 2
++#define SBI_CLEAR_IPI 3
++#define SBI_SEND_IPI 4
++#define SBI_REMOTE_FENCE_I 5
++#define SBI_REMOTE_SFENCE_VMA 6
++#define SBI_REMOTE_SFENCE_VMA_ASID 7
++#define SBI_SHUTDOWN 8
++
++#define SBI_CALL(which, arg0, arg1, arg2) ({			\
++	register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);	\
++	register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);	\
++	register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);	\
++	register uintptr_t a7 asm ("a7") = (uintptr_t)(which);	\
++	asm volatile ("ecall"					\
++		      : "+r" (a0)				\
++		      : "r" (a1), "r" (a2), "r" (a7)		\
++		      : "memory");				\
++	a0;							\
++})
++
++/* Lazy implementations until SBI is finalized */
++#define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0)
++#define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0)
++#define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0)
++
++static inline void sbi_console_putchar(int ch)
++{
++	SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch);
++}
++
++static inline int sbi_console_getchar(void)
++{
++	return SBI_CALL_0(SBI_CONSOLE_GETCHAR);
++}
++
++static inline void sbi_set_timer(uint64_t stime_value)
++{
++#if __riscv_xlen == 32
++	SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32);
++#else
++	SBI_CALL_1(SBI_SET_TIMER, stime_value);
++#endif
++}
++
++static inline void sbi_shutdown(void)
++{
++	SBI_CALL_0(SBI_SHUTDOWN);
++}
++
++static inline void sbi_clear_ipi(void)
++{
++	SBI_CALL_0(SBI_CLEAR_IPI);
++}
++
++static inline void sbi_send_ipi(const unsigned long *hart_mask)
++{
++	SBI_CALL_1(SBI_SEND_IPI, hart_mask);
++}
++
++static inline void sbi_remote_fence_i(const unsigned long *hart_mask)
++{
++	SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask);
++}
++
++static inline void sbi_remote_sfence_vma(const unsigned long *hart_mask,
++					 unsigned long start,
++					 unsigned long size)
++{
++	SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask);
++}
++
++static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
++					      unsigned long start,
++					      unsigned long size,
++					      unsigned long asid)
++{
++	SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask);
++}
++
++#endif
+-- 
+2.21.0
+

+ 85 - 0
recipes-bsp/u-boot/files/0003-riscv-implement-IPI-platform-functions-using-SBI.patch

@@ -0,0 +1,85 @@
+From f152febb2a97696f7c7e6df46bf585cfc962a835 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:34 +0100
+Subject: [PATCH 03/18] riscv: implement IPI platform functions using SBI
+
+The supervisor binary interface (SBI) provides the necessary functions
+to implement the platform IPI functions riscv_send_ipi() and
+riscv_clear_ipi(). Use it to implement them.
+
+This adds support for inter-processor interrupts (IPIs) on RISC-V CPUs
+running in supervisor mode. Support for machine mode is already
+available for CPUs that include the SiFive CLINT.
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Atish Patra <atish.patra@wdc.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ arch/riscv/Kconfig       |  5 +++++
+ arch/riscv/lib/Makefile  |  1 +
+ arch/riscv/lib/sbi_ipi.c | 25 +++++++++++++++++++++++++
+ 3 files changed, 31 insertions(+)
+ create mode 100644 arch/riscv/lib/sbi_ipi.c
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 4d7a115569..9da609b33b 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -139,4 +139,9 @@ config NR_CPUS
+ 	  Stack memory is pre-allocated. U-Boot must therefore know the
+ 	  maximum number of CPUs that may be present.
+ 
++config SBI_IPI
++	bool
++	default y if RISCV_SMODE
++	depends on SMP
++
+ endmenu
+diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
+index 19370f9749..35dbf643e4 100644
+--- a/arch/riscv/lib/Makefile
++++ b/arch/riscv/lib/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
+ obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
+ obj-y	+= interrupts.o
+ obj-y	+= reset.o
++obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
+ obj-y   += setjmp.o
+ obj-$(CONFIG_SMP) += smp.o
+ 
+diff --git a/arch/riscv/lib/sbi_ipi.c b/arch/riscv/lib/sbi_ipi.c
+new file mode 100644
+index 0000000000..170346da68
+--- /dev/null
++++ b/arch/riscv/lib/sbi_ipi.c
+@@ -0,0 +1,25 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2019 Fraunhofer AISEC,
++ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
++ */
++
++#include <common.h>
++#include <asm/sbi.h>
++
++int riscv_send_ipi(int hart)
++{
++	ulong mask;
++
++	mask = 1UL << hart;
++	sbi_send_ipi(&mask);
++
++	return 0;
++}
++
++int riscv_clear_ipi(int hart)
++{
++	sbi_clear_ipi();
++
++	return 0;
++}
+-- 
+2.21.0
+

+ 62 - 0
recipes-bsp/u-boot/files/0004-riscv-delay-initialization-of-caches-and-debug-UART.patch

@@ -0,0 +1,62 @@
+From 2503ccc55ff2031ae2ff476fb06f666e6d1c7a64 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:35 +0100
+Subject: [PATCH 04/18] riscv: delay initialization of caches and debug UART
+
+Move the initialization of the caches and the debug UART until after
+board_init_f_init_reserve. This is in preparation for SMP support, where
+code prior to this point will be executed by all harts. This ensures
+that initialization will only be performed once on the main hart running
+U-Boot.
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ arch/riscv/cpu/start.S | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
+index 81ea52b170..a30f6f7194 100644
+--- a/arch/riscv/cpu/start.S
++++ b/arch/riscv/cpu/start.S
+@@ -45,10 +45,6 @@ _start:
+ 	/* mask all interrupts */
+ 	csrw	MODE_PREFIX(ie), zero
+ 
+-	/* Enable cache */
+-	jal	icache_enable
+-	jal	dcache_enable
+-
+ /*
+  * Set stackpointer in internal/ex RAM to call board_init_f
+  */
+@@ -57,10 +53,6 @@ call_board_init_f:
+ 	li	t1, CONFIG_SYS_INIT_SP_ADDR
+ 	and	sp, t1, t0		/* force 16 byte alignment */
+ 
+-#ifdef CONFIG_DEBUG_UART
+-	jal	debug_uart_init
+-#endif
+-
+ call_board_init_f_0:
+ 	mv	a0, sp
+ 	jal	board_init_f_alloc_reserve
+@@ -74,6 +66,14 @@ call_board_init_f_0:
+ 	/* save the boot hart id to global_data */
+ 	SREG	s0, GD_BOOT_HART(gp)
+ 
++	/* Enable cache */
++	jal	icache_enable
++	jal	dcache_enable
++
++#ifdef CONFIG_DEBUG_UART
++	jal	debug_uart_init
++#endif
++
+ 	mv	a0, zero		/* a0 <-- boot_flags = 0 */
+ 	la	t5, board_init_f
+ 	jr	t5			/* jump to board_init_f() */
+-- 
+2.21.0
+

+ 44 - 0
recipes-bsp/u-boot/files/0005-riscv-save-hart-ID-in-register-tp-instead-of-s0.patch

@@ -0,0 +1,44 @@
+From 1446b26f7652124f0e3e98c348cdbc4fc55eb0cb Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:36 +0100
+Subject: [PATCH 05/18] riscv: save hart ID in register tp instead of s0
+
+The hart ID passed by the previous boot stage is currently stored in
+register s0. If we divert the control flow inside a function, which is
+required as part of multi-hart support, the function epilog may not be
+called, clobbering register s0. Save the hart ID in the unallocatable
+register tp instead to protect the hart ID.
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Rick Chen <rick@andestech.com>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+---
+ arch/riscv/cpu/start.S | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
+index a30f6f7194..bcc0ff696d 100644
+--- a/arch/riscv/cpu/start.S
++++ b/arch/riscv/cpu/start.S
+@@ -36,7 +36,7 @@
+ .globl _start
+ _start:
+ 	/* save hart id and dtb pointer */
+-	mv	s0, a0
++	mv	tp, a0
+ 	mv	s1, a1
+ 
+ 	la	t0, trap_entry
+@@ -64,7 +64,7 @@ call_board_init_f_0:
+ 	jal	board_init_f_init_reserve
+ 
+ 	/* save the boot hart id to global_data */
+-	SREG	s0, GD_BOOT_HART(gp)
++	SREG	tp, GD_BOOT_HART(gp)
+ 
+ 	/* Enable cache */
+ 	jal	icache_enable
+-- 
+2.21.0
+

+ 283 - 0
recipes-bsp/u-boot/files/0006-riscv-add-support-for-multi-hart-systems.patch

@@ -0,0 +1,283 @@
+From 3dea63c8445b25eb3de471410bbafcf54c9f0e9b Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:37 +0100
+Subject: [PATCH 06/18] riscv: add support for multi-hart systems
+
+On RISC-V, all harts boot independently. To be able to run on a
+multi-hart system, U-Boot must be extended with the functionality to
+manage all harts in the system. All harts entering U-Boot are registered
+in the available_harts mask stored in global data. A hart lottery system
+as used in the Linux kernel selects the hart U-Boot runs on. All other
+harts are halted. U-Boot can delegate functions to them using
+smp_call_function().
+
+Every hart has a valid pointer to the global data structure and a 8KiB
+stack by default. The stack size is set with CONFIG_STACK_SIZE_SHIFT.
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ arch/riscv/Kconfig           |   4 ++
+ arch/riscv/cpu/cpu.c         |   9 ++-
+ arch/riscv/cpu/start.S       | 134 ++++++++++++++++++++++++++++++++++-
+ arch/riscv/include/asm/csr.h |   1 +
+ arch/riscv/lib/asm-offsets.c |   1 +
+ 5 files changed, 147 insertions(+), 2 deletions(-)
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 9da609b33b..3a4470daf3 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -144,4 +144,8 @@ config SBI_IPI
+ 	default y if RISCV_SMODE
+ 	depends on SMP
+ 
++config STACK_SIZE_SHIFT
++	int
++	default 13
++
+ endmenu
+diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
+index e662140427..c32de8a4c3 100644
+--- a/arch/riscv/cpu/cpu.c
++++ b/arch/riscv/cpu/cpu.c
+@@ -12,10 +12,17 @@
+ #include <dm/uclass-internal.h>
+ 
+ /*
+- * prior_stage_fdt_address must be stored in the data section since it is used
++ * The variables here must be stored in the data section since they are used
+  * before the bss section is available.
+  */
+ phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
++u32 hart_lottery __attribute__((section(".data"))) = 0;
++
++/*
++ * The main hart running U-Boot has acquired available_harts_lock until it has
++ * finished initialization of global data.
++ */
++u32 available_harts_lock = 1;
+ 
+ static inline bool supports_extension(char ext)
+ {
+diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
+index bcc0ff696d..f55b8cbc37 100644
+--- a/arch/riscv/cpu/start.S
++++ b/arch/riscv/cpu/start.S
+@@ -13,6 +13,7 @@
+ #include <config.h>
+ #include <common.h>
+ #include <elf.h>
++#include <asm/csr.h>
+ #include <asm/encoding.h>
+ #include <generated/asm-offsets.h>
+ 
+@@ -45,6 +46,23 @@ _start:
+ 	/* mask all interrupts */
+ 	csrw	MODE_PREFIX(ie), zero
+ 
++#ifdef CONFIG_SMP
++	/* check if hart is within range */
++	/* tp: hart id */
++	li	t0, CONFIG_NR_CPUS
++	bge	tp, t0, hart_out_of_bounds_loop
++#endif
++
++#ifdef CONFIG_SMP
++	/* set xSIE bit to receive IPIs */
++#ifdef CONFIG_RISCV_MMODE
++	li	t0, MIE_MSIE
++#else
++	li	t0, SIE_SSIE
++#endif
++	csrs	MODE_PREFIX(ie), t0
++#endif
++
+ /*
+  * Set stackpointer in internal/ex RAM to call board_init_f
+  */
+@@ -56,7 +74,30 @@ call_board_init_f:
+ call_board_init_f_0:
+ 	mv	a0, sp
+ 	jal	board_init_f_alloc_reserve
++
++	/*
++	 * Set global data pointer here for all harts, uninitialized at this
++	 * point.
++	 */
++	mv	gp, a0
++
++	/* setup stack */
++#ifdef CONFIG_SMP
++	/* tp: hart id */
++	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
++	sub	sp, a0, t0
++#else
+ 	mv	sp, a0
++#endif
++
++	/*
++	 * Pick hart to initialize global data and run U-Boot. The other harts
++	 * wait for initialization to complete.
++	 */
++	la	t0, hart_lottery
++	li	s2, 1
++	amoswap.w s2, t1, 0(t0)
++	bnez	s2, wait_for_gd_init
+ 
+ 	la	t0, prior_stage_fdt_address
+ 	SREG	s1, 0(t0)
+@@ -66,6 +107,33 @@ call_board_init_f_0:
+ 	/* save the boot hart id to global_data */
+ 	SREG	tp, GD_BOOT_HART(gp)
+ 
++	la	t0, available_harts_lock
++	fence	rw, w
++	amoswap.w zero, zero, 0(t0)
++
++wait_for_gd_init:
++	la	t0, available_harts_lock
++	li	t1, 1
++1:	amoswap.w t1, t1, 0(t0)
++	fence	r, rw
++	bnez	t1, 1b
++
++	/* register available harts in the available_harts mask */
++	li	t1, 1
++	sll	t1, t1, tp
++	LREG	t2, GD_AVAILABLE_HARTS(gp)
++	or	t2, t2, t1
++	SREG	t2, GD_AVAILABLE_HARTS(gp)
++
++	fence	rw, w
++	amoswap.w zero, zero, 0(t0)
++
++	/*
++	 * Continue on hart lottery winner, others branch to
++	 * secondary_hart_loop.
++	 */
++	bnez	s2, secondary_hart_loop
++
+ 	/* Enable cache */
+ 	jal	icache_enable
+ 	jal	dcache_enable
+@@ -95,7 +163,14 @@ relocate_code:
+  *Set up the stack
+  */
+ stack_setup:
++#ifdef CONFIG_SMP
++	/* tp: hart id */
++	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
++	sub	sp, s2, t0
++#else
+ 	mv	sp, s2
++#endif
++
+ 	la	t0, _start
+ 	sub	t6, s4, t0		/* t6 <- relocation offset */
+ 	beq	t0, s4, clear_bss	/* skip relocation */
+@@ -175,13 +250,30 @@ clear_bss:
+ 	add	t0, t0, t6		/* t0 <- rel __bss_start in RAM */
+ 	la	t1, __bss_end		/* t1 <- rel __bss_end in FLASH */
+ 	add	t1, t1, t6		/* t1 <- rel __bss_end in RAM */
+-	beq	t0, t1, call_board_init_r
++	beq	t0, t1, relocate_secondary_harts
+ 
+ clbss_l:
+ 	SREG	zero, 0(t0)		/* clear loop... */
+ 	addi	t0, t0, REGBYTES
+ 	bne	t0, t1, clbss_l
+ 
++relocate_secondary_harts:
++#ifdef CONFIG_SMP
++	/* send relocation IPI */
++	la	t0, secondary_hart_relocate
++	add	a0, t0, t6
++
++	/* store relocation offset */
++	mv	s5, t6
++
++	mv	a1, s2
++	mv	a2, s3
++	jal	smp_call_function
++
++	/* restore relocation offset */
++	mv	t6, s5
++#endif
++
+ /*
+  * We are done. Do not return, instead branch to second part of board
+  * initialization, now running from RAM.
+@@ -202,3 +294,43 @@ call_board_init_r:
+  * jump to it ...
+  */
+ 	jr	t4			/* jump to board_init_r() */
++
++#ifdef CONFIG_SMP
++hart_out_of_bounds_loop:
++	/* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
++	wfi
++	j	hart_out_of_bounds_loop
++#endif
++
++#ifdef CONFIG_SMP
++/* SMP relocation entry */
++secondary_hart_relocate:
++	/* a1: new sp */
++	/* a2: new gd */
++	/* tp: hart id */
++
++	/* setup stack */
++	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
++	sub	sp, a1, t0
++
++	/* update global data pointer */
++	mv	gp, a2
++#endif
++
++secondary_hart_loop:
++	wfi
++
++#ifdef CONFIG_SMP
++	csrr	t0, MODE_PREFIX(ip)
++#ifdef CONFIG_RISCV_MMODE
++	andi	t0, t0, MIE_MSIE
++#else
++	andi	t0, t0, SIE_SSIE
++#endif
++	beqz	t0, secondary_hart_loop
++
++	mv	a0, tp
++	jal	handle_ipi
++#endif
++
++	j	secondary_hart_loop
+diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
+index 86136f542c..644e6baa15 100644
+--- a/arch/riscv/include/asm/csr.h
++++ b/arch/riscv/include/asm/csr.h
+@@ -46,6 +46,7 @@
+ #endif
+ 
+ /* Interrupt Enable and Interrupt Pending flags */
++#define MIE_MSIE	_AC(0x00000008, UL) /* Software Interrupt Enable */
+ #define SIE_SSIE	_AC(0x00000002, UL) /* Software Interrupt Enable */
+ #define SIE_STIE	_AC(0x00000020, UL) /* Timer Interrupt Enable */
+ 
+diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c
+index e0b71f5691..f998402bd1 100644
+--- a/arch/riscv/lib/asm-offsets.c
++++ b/arch/riscv/lib/asm-offsets.c
+@@ -14,6 +14,7 @@
+ int main(void)
+ {
+ 	DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart));
++	DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts));
+ 
+ 	return 0;
+ }
+-- 
+2.21.0
+

+ 55 - 0
recipes-bsp/u-boot/files/0007-riscv-boot-images-passed-to-bootm-on-all-harts.patch

@@ -0,0 +1,55 @@
+From f28ad250e6ef95ca58490b4e8651749d4f7e5c06 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:38 +0100
+Subject: [PATCH 07/18] riscv: boot images passed to bootm on all harts
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ arch/riscv/lib/bootm.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
+index f36b8702ef..efbd3e23e7 100644
+--- a/arch/riscv/lib/bootm.c
++++ b/arch/riscv/lib/bootm.c
+@@ -13,6 +13,7 @@
+ #include <image.h>
+ #include <asm/byteorder.h>
+ #include <asm/csr.h>
++#include <asm/smp.h>
+ #include <dm/device.h>
+ #include <dm/root.h>
+ #include <u-boot/zlib.h>
+@@ -81,6 +82,9 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
+ {
+ 	void (*kernel)(ulong hart, void *dtb);
+ 	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
++#ifdef CONFIG_SMP
++	int ret;
++#endif
+ 
+ 	kernel = (void (*)(ulong, void *))images->ep;
+ 
+@@ -92,8 +96,15 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
+ 	announce_and_cleanup(fake);
+ 
+ 	if (!fake) {
+-		if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
++		if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
++#ifdef CONFIG_SMP
++			ret = smp_call_function(images->ep,
++						(ulong)images->ft_addr, 0);
++			if (ret)
++				hang();
++#endif
+ 			kernel(gd->arch.boot_hart, images->ft_addr);
++		}
+ 	}
+ }
+ 
+-- 
+2.21.0
+

+ 44 - 0
recipes-bsp/u-boot/files/0008-riscv-do-not-rely-on-hart-ID-passed-by-previous-boot.patch

@@ -0,0 +1,44 @@
+From e04324025275dee6e3e9a968c8d12e98c9b47567 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:39 +0100
+Subject: [PATCH 08/18] riscv: do not rely on hart ID passed by previous boot
+ stage
+
+RISC-V U-Boot expects the hart ID to be passed to it via register a0 by
+the previous boot stage. Machine mode firmware such as BBL and OpenSBI
+do this when starting their payload (U-Boot) in supervisor mode. If
+U-Boot is running in machine mode, this task must be handled by the boot
+ROM. Explicitly populate register a0 with the hart ID from the mhartid
+CSR to avoid possible problems on RISC-V processors with a boot ROM that
+does not handle this task.
+
+Suggested-by: Rick Chen <rick@andestech.com>
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Atish Patra <atish.patra@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Rick Chen <rick@andestech.com>
+Tested-by: Rick Chen <rick@andestech.com>
+---
+ arch/riscv/cpu/start.S | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
+index f55b8cbc37..5ac899b141 100644
+--- a/arch/riscv/cpu/start.S
++++ b/arch/riscv/cpu/start.S
+@@ -36,6 +36,10 @@
+ .section .text
+ .globl _start
+ _start:
++#ifdef CONFIG_RISCV_MMODE
++	csrr	a0, mhartid
++#endif
++
+ 	/* save hart id and dtb pointer */
+ 	mv	tp, a0
+ 	mv	s1, a1
+-- 
+2.21.0
+

+ 51 - 0
recipes-bsp/u-boot/files/0009-riscv-hang-if-relocation-of-secondary-harts-fails.patch

@@ -0,0 +1,51 @@
+From 8ac39e2974d9f1395969a500e692f45717c4ccf2 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:40 +0100
+Subject: [PATCH 09/18] riscv: hang if relocation of secondary harts fails
+
+Print an error message and hang if smp_call_function() returns an error,
+indicating that relocation of the secondary harts has failed.
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+---
+ arch/riscv/cpu/start.S | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
+index 5ac899b141..a4433fbd6b 100644
+--- a/arch/riscv/cpu/start.S
++++ b/arch/riscv/cpu/start.S
+@@ -33,6 +33,10 @@
+ #define SYM_SIZE		0x18
+ #endif
+ 
++.section .data
++secondary_harts_relocation_error:
++	.ascii "Relocation of secondary harts has failed, error %d\n"
++
+ .section .text
+ .globl _start
+ _start:
+@@ -274,8 +278,15 @@ relocate_secondary_harts:
+ 	mv	a2, s3
+ 	jal	smp_call_function
+ 
++	/* hang if relocation of secondary harts has failed */
++	beqz	a0, 1f
++	mv	a1, a0
++	la	a0, secondary_harts_relocation_error
++	jal	printf
++	jal	hang
++
+ 	/* restore relocation offset */
+-	mv	t6, s5
++1:	mv	t6, s5
+ #endif
+ 
+ /*
+-- 
+2.21.0
+

+ 26 - 0
recipes-bsp/u-boot/files/0010-riscv-fu540-enable-SMP.patch

@@ -0,0 +1,26 @@
+From 0ed93a8c59d7c100241390d912329e3e45382977 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:41 +0100
+Subject: [PATCH 10/18] riscv: fu540: enable SMP
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ board/sifive/fu540/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig
+index 6be3d88144..f46437901d 100644
+--- a/board/sifive/fu540/Kconfig
++++ b/board/sifive/fu540/Kconfig
+@@ -38,5 +38,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
+ 	imply PHY_LIB
+ 	imply PHY_MSCC
+ 	imply SIFIVE_SERIAL
++	imply SMP
+ 
+ endif
+-- 
+2.21.0
+

+ 27 - 0
recipes-bsp/u-boot/files/0011-riscv-qemu-enable-SMP.patch

@@ -0,0 +1,27 @@
+From d0a8fd3e4d2a5ab19b8f2d27d40dacb4942ba5a4 Mon Sep 17 00:00:00 2001
+From: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Date: Sun, 17 Mar 2019 19:28:42 +0100
+Subject: [PATCH 11/18] riscv: qemu: enable SMP
+
+Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+Reviewed-by: Anup Patel <anup.patel@wdc.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Tested-by: Bin Meng <bmeng.cn@gmail.com>
+---
+ board/emulation/qemu-riscv/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
+index 88d07d568e..cf057e7de6 100644
+--- a/board/emulation/qemu-riscv/Kconfig
++++ b/board/emulation/qemu-riscv/Kconfig
+@@ -34,5 +34,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
+ 	imply BOARD_LATE_INIT
+ 	imply OF_BOARD_SETUP
+ 	imply SIFIVE_SERIAL
++	imply SMP
+ 
+ endif
+-- 
+2.21.0
+

+ 209 - 0
recipes-bsp/u-boot/files/0012-riscv-Add-a-SYSCON-driver-for-Andestech-s-PLIC.patch

@@ -0,0 +1,209 @@
+From 0d389468e2144f3ba3bdbc566c05c0c05dc14fc6 Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Tue, 2 Apr 2019 15:56:39 +0800
+Subject: [PATCH 12/18] riscv: Add a SYSCON driver for Andestech's PLIC
+
+The Platform-Level Interrupt Controller (PLIC)
+block holds memory-mapped claim and pending registers
+associated with software interrupt. It is required
+for handling IPI.
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ arch/riscv/Kconfig                   |   9 +++
+ arch/riscv/include/asm/global_data.h |   3 +
+ arch/riscv/include/asm/syscon.h      |   3 +-
+ arch/riscv/lib/Makefile              |   1 +
+ arch/riscv/lib/andes_plic.c          | 113 +++++++++++++++++++++++++++
+ 5 files changed, 127 insertions(+), 2 deletions(-)
+ create mode 100644 arch/riscv/lib/andes_plic.c
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 3a4470daf3..511768befc 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -109,6 +109,15 @@ config SIFIVE_CLINT
+ 	  The SiFive CLINT block holds memory-mapped control and status registers
+ 	  associated with software and timer interrupts.
+ 
++config ANDES_PLIC
++	bool
++	depends on RISCV_MMODE
++	select REGMAP
++	select SYSCON
++	help
++	  The Andes PLIC block holds memory-mapped claim and pending registers
++	  associated with software interrupt.
++
+ config RISCV_RDTIME
+ 	bool
+ 	default y if RISCV_SMODE
+diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
+index 80e3165e39..b86791094b 100644
+--- a/arch/riscv/include/asm/global_data.h
++++ b/arch/riscv/include/asm/global_data.h
+@@ -18,6 +18,9 @@ struct arch_global_data {
+ #ifdef CONFIG_SIFIVE_CLINT
+ 	void __iomem *clint;	/* clint base address */
+ #endif
++#ifdef CONFIG_ANDES_PLIC
++	void __iomem *plic;	/* plic base address */
++#endif
+ #ifdef CONFIG_SMP
+ 	struct ipi_data ipi[CONFIG_NR_CPUS];
+ #endif
+diff --git a/arch/riscv/include/asm/syscon.h b/arch/riscv/include/asm/syscon.h
+index d311ee6b45..a086208261 100644
+--- a/arch/riscv/include/asm/syscon.h
++++ b/arch/riscv/include/asm/syscon.h
+@@ -8,12 +8,11 @@
+ 
+ /*
+  * System controllers in a RISC-V system
+- *
+- * So far only SiFive's Core Local Interruptor (CLINT) is defined.
+  */
+ enum {
+ 	RISCV_NONE,
+ 	RISCV_SYSCON_CLINT,	/* Core Local Interruptor (CLINT) */
++	RISCV_SYSCON_PLIC,	/* Platform Level Interrupt Controller (PLIC) */
+ };
+ 
+ #endif /* _ASM_SYSCON_H */
+diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
+index 35dbf643e4..1bf554bad5 100644
+--- a/arch/riscv/lib/Makefile
++++ b/arch/riscv/lib/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_CMD_GO) += boot.o
+ obj-y	+= cache.o
+ obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
+ obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
++obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
+ obj-y	+= interrupts.o
+ obj-y	+= reset.o
+ obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
+diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c
+new file mode 100644
+index 0000000000..2ffe49ac90
+--- /dev/null
++++ b/arch/riscv/lib/andes_plic.c
+@@ -0,0 +1,113 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2019, Rick Chen <rick@andestech.com>
++ *
++ * U-Boot syscon driver for Andes's Platform Level Interrupt Controller (PLIC).
++ * The PLIC block holds memory-mapped claim and pending registers
++ * associated with software interrupt.
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <dm/device-internal.h>
++#include <dm/lists.h>
++#include <dm/uclass-internal.h>
++#include <regmap.h>
++#include <syscon.h>
++#include <asm/io.h>
++#include <asm/syscon.h>
++#include <cpu.h>
++
++/* pending register */
++#define PENDING_REG(base, hart)	((ulong)(base) + 0x1000 + (hart) * 8)
++/* enable register */
++#define ENABLE_REG(base, hart)	((ulong)(base) + 0x2000 + (hart) * 0x80)
++/* claim register */
++#define CLAIM_REG(base, hart)	((ulong)(base) + 0x200004 + (hart) * 0x1000)
++
++#define ENABLE_HART_IPI         (0x80808080)
++#define SEND_IPI_TO_HART(hart)  (0x80 >> (hart))
++
++DECLARE_GLOBAL_DATA_PTR;
++static int init_plic(void);
++
++#define PLIC_BASE_GET(void)						\
++	do {								\
++		long *ret;						\
++									\
++		if (!gd->arch.plic) {					\
++			ret = syscon_get_first_range(RISCV_SYSCON_PLIC); \
++			if (IS_ERR(ret))				\
++				return PTR_ERR(ret);			\
++			gd->arch.plic = ret;				\
++			init_plic();					\
++		}							\
++	} while (0)
++
++static int enable_ipi(int harts)
++{
++	int i;
++	int en = ENABLE_HART_IPI;
++
++	for (i = 0; i < harts; i++) {
++		en = en >> i;
++		writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, i));
++	}
++
++	return 0;
++}
++
++static int init_plic(void)
++{
++	struct udevice *dev;
++	int ret;
++
++	ret = uclass_find_first_device(UCLASS_CPU, &dev);
++	if (ret)
++		return ret;
++
++	if (ret == 0 && dev) {
++		ret = cpu_get_count(dev);
++		if (ret < 0)
++			return ret;
++
++		enable_ipi(ret);
++		return 0;
++	}
++
++	return -ENODEV;
++}
++
++int riscv_send_ipi(int hart)
++{
++	PLIC_BASE_GET();
++
++	writel(SEND_IPI_TO_HART(hart),
++	       (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart));
++
++	return 0;
++}
++
++int riscv_clear_ipi(int hart)
++{
++	u32 source_id;
++
++	PLIC_BASE_GET();
++
++	source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart));
++	writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plic, hart));
++
++	return 0;
++}
++
++static const struct udevice_id andes_plic_ids[] = {
++	{ .compatible = "riscv,plic1", .data = RISCV_SYSCON_PLIC },
++	{ }
++};
++
++U_BOOT_DRIVER(andes_plic) = {
++	.name		= "andes_plic",
++	.id		= UCLASS_SYSCON,
++	.of_match	= andes_plic_ids,
++	.flags		= DM_FLAG_PRE_RELOC,
++};
+-- 
+2.21.0
+

+ 145 - 0
recipes-bsp/u-boot/files/0013-riscv-Add-a-SYSCON-driver-for-Andestech-s-PLMT.patch

@@ -0,0 +1,145 @@
+From a1f24875c346a1bf8940b793a27364631d9aabf7 Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Tue, 2 Apr 2019 15:56:40 +0800
+Subject: [PATCH 13/18] riscv: Add a SYSCON driver for Andestech's PLMT
+
+The platform-Level Machine Timer (PLMT) block
+holds memory-mapped mtime register associated
+with timer tick.
+
+This driver implements the riscv_get_time() which
+is required by the generic RISC-V timer driver.
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ arch/riscv/Kconfig                   |  9 +++++
+ arch/riscv/include/asm/global_data.h |  3 ++
+ arch/riscv/include/asm/syscon.h      |  1 +
+ arch/riscv/lib/Makefile              |  1 +
+ arch/riscv/lib/andes_plmt.c          | 53 ++++++++++++++++++++++++++++
+ 5 files changed, 67 insertions(+)
+ create mode 100644 arch/riscv/lib/andes_plmt.c
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 511768befc..ae8ff7b765 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -118,6 +118,15 @@ config ANDES_PLIC
+ 	  The Andes PLIC block holds memory-mapped claim and pending registers
+ 	  associated with software interrupt.
+ 
++config ANDES_PLMT
++	bool
++	depends on RISCV_MMODE
++	select REGMAP
++	select SYSCON
++	help
++	  The Andes PLMT block holds memory-mapped mtime register
++	  associated with timer tick.
++
+ config RISCV_RDTIME
+ 	bool
+ 	default y if RISCV_SMODE
+diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
+index b86791094b..dffcd45bf0 100644
+--- a/arch/riscv/include/asm/global_data.h
++++ b/arch/riscv/include/asm/global_data.h
+@@ -21,6 +21,9 @@ struct arch_global_data {
+ #ifdef CONFIG_ANDES_PLIC
+ 	void __iomem *plic;	/* plic base address */
+ #endif
++#ifdef CONFIG_ANDES_PLMT
++	void __iomem *plmt;	/* plmt base address */
++#endif
+ #ifdef CONFIG_SMP
+ 	struct ipi_data ipi[CONFIG_NR_CPUS];
+ #endif
+diff --git a/arch/riscv/include/asm/syscon.h b/arch/riscv/include/asm/syscon.h
+index a086208261..26a008ca59 100644
+--- a/arch/riscv/include/asm/syscon.h
++++ b/arch/riscv/include/asm/syscon.h
+@@ -13,6 +13,7 @@ enum {
+ 	RISCV_NONE,
+ 	RISCV_SYSCON_CLINT,	/* Core Local Interruptor (CLINT) */
+ 	RISCV_SYSCON_PLIC,	/* Platform Level Interrupt Controller (PLIC) */
++	RISCV_SYSCON_PLMT,	/* Platform Level Machine Timer (PLMT) */
+ };
+ 
+ #endif /* _ASM_SYSCON_H */
+diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
+index 1bf554bad5..1c332db436 100644
+--- a/arch/riscv/lib/Makefile
++++ b/arch/riscv/lib/Makefile
+@@ -12,6 +12,7 @@ obj-y	+= cache.o
+ obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
+ obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
+ obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
++obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
+ obj-y	+= interrupts.o
+ obj-y	+= reset.o
+ obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
+diff --git a/arch/riscv/lib/andes_plmt.c b/arch/riscv/lib/andes_plmt.c
+new file mode 100644
+index 0000000000..84f4607500
+--- /dev/null
++++ b/arch/riscv/lib/andes_plmt.c
+@@ -0,0 +1,53 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2019, Rick Chen <rick@andestech.com>
++ *
++ * U-Boot syscon driver for Andes's Platform Level Machine Timer (PLMT).
++ * The PLMT block holds memory-mapped mtime register
++ * associated with timer tick.
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <regmap.h>
++#include <syscon.h>
++#include <asm/io.h>
++#include <asm/syscon.h>
++
++/* mtime register */
++#define MTIME_REG(base)			((ulong)(base))
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#define PLMT_BASE_GET(void)						\
++	do {								\
++		long *ret;						\
++									\
++		if (!gd->arch.plmt) {					\
++			ret = syscon_get_first_range(RISCV_SYSCON_PLMT); \
++			if (IS_ERR(ret))				\
++				return PTR_ERR(ret);			\
++			gd->arch.plmt = ret;				\
++		}							\
++	} while (0)
++
++int riscv_get_time(u64 *time)
++{
++	PLMT_BASE_GET();
++
++	*time = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
++
++	return 0;
++}
++
++static const struct udevice_id andes_plmt_ids[] = {
++	{ .compatible = "riscv,plmt0", .data = RISCV_SYSCON_PLMT },
++	{ }
++};
++
++U_BOOT_DRIVER(andes_plmt) = {
++	.name		= "andes_plmt",
++	.id		= UCLASS_SYSCON,
++	.of_match	= andes_plmt_ids,
++	.flags		= DM_FLAG_PRE_RELOC,
++};
+-- 
+2.21.0
+

+ 56 - 0
recipes-bsp/u-boot/files/0014-riscv-ax25-Add-platform-specific-Kconfig-options.patch

@@ -0,0 +1,56 @@
+From 8848474c5e9093ac27f6b7cc8be156629c7d0bad Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Tue, 2 Apr 2019 15:56:41 +0800
+Subject: [PATCH 14/18] riscv: ax25: Add platform-specific Kconfig options
+
+Add ax25 RISC-V platform-specific Kconfig options,
+to include CPU and timer drivers. Also disable
+ATCPIT100 SoC timer and replace by PLMT.
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ arch/riscv/cpu/ax25/Kconfig  | 6 ++++++
+ configs/ae350_rv32_defconfig | 1 -
+ configs/ae350_rv64_defconfig | 1 -
+ 3 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig
+index e9dbca2fae..68bd4e9419 100644
+--- a/arch/riscv/cpu/ax25/Kconfig
++++ b/arch/riscv/cpu/ax25/Kconfig
+@@ -1,5 +1,11 @@
+ config RISCV_NDS
+ 	bool
++	select ARCH_EARLY_INIT_R
++	imply CPU
++	imply CPU_RISCV
++	imply RISCV_TIMER
++	imply ANDES_PLIC if RISCV_MMODE
++	imply ANDES_PLMT if RISCV_MMODE
+ 	help
+ 	  Run U-Boot on AndeStar V5 platforms and use some specific features
+ 	  which are provided by Andes Technology AndeStar V5 families.
+diff --git a/configs/ae350_rv32_defconfig b/configs/ae350_rv32_defconfig
+index 6e0be88d7c..f02945599f 100644
+--- a/configs/ae350_rv32_defconfig
++++ b/configs/ae350_rv32_defconfig
+@@ -34,4 +34,3 @@ CONFIG_BAUDRATE=38400
+ CONFIG_SYS_NS16550=y
+ CONFIG_SPI=y
+ CONFIG_ATCSPI200_SPI=y
+-CONFIG_ATCPIT100_TIMER=y
+diff --git a/configs/ae350_rv64_defconfig b/configs/ae350_rv64_defconfig
+index b472a76d17..98635a2ff9 100644
+--- a/configs/ae350_rv64_defconfig
++++ b/configs/ae350_rv64_defconfig
+@@ -35,4 +35,3 @@ CONFIG_BAUDRATE=38400
+ CONFIG_SYS_NS16550=y
+ CONFIG_SPI=y
+ CONFIG_ATCSPI200_SPI=y
+-CONFIG_ATCPIT100_TIMER=y
+-- 
+2.21.0
+

+ 32 - 0
recipes-bsp/u-boot/files/0015-riscv-ax25-Andes-specific-cache-shall-only-support-i.patch

@@ -0,0 +1,32 @@
+From dda00ae4ef357233a72c74e6c02d27b70c844422 Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Tue, 2 Apr 2019 15:56:42 +0800
+Subject: [PATCH 15/18] riscv: ax25: Andes specific cache shall only support in
+ M-mode
+
+Limit the cache configuration only can be supported in M mode.
+It can not be manipulated in S mode.
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ arch/riscv/cpu/ax25/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig
+index 68bd4e9419..6b4b92e692 100644
+--- a/arch/riscv/cpu/ax25/Kconfig
++++ b/arch/riscv/cpu/ax25/Kconfig
+@@ -14,6 +14,7 @@ if RISCV_NDS
+ 
+ config RISCV_NDS_CACHE
+ 	bool "AndeStar V5 families specific cache support"
++	depends on RISCV_MMODE
+ 	help
+ 	  Provide Andes Technology AndeStar V5 families specific cache support.
+ 
+-- 
+2.21.0
+

+ 257 - 0
recipes-bsp/u-boot/files/0016-riscv-dts-ae350-support-SMP.patch

@@ -0,0 +1,257 @@
+From a1ce531ab24b1ef5e69dbf29ecbfc6898b454ec1 Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Tue, 2 Apr 2019 15:56:43 +0800
+Subject: [PATCH 16/18] riscv: dts: ae350 support SMP
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ arch/riscv/dts/ae350_32.dts | 81 +++++++++++++++++++++++++++----------
+ arch/riscv/dts/ae350_64.dts | 81 +++++++++++++++++++++++++++----------
+ 2 files changed, 118 insertions(+), 44 deletions(-)
+
+diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts
+index 0679827313..2ec01a5ce7 100644
+--- a/arch/riscv/dts/ae350_32.dts
++++ b/arch/riscv/dts/ae350_32.dts
+@@ -26,16 +26,49 @@
+ 			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>;
+ 			CPU0_intc: interrupt-controller {
+ 				#interrupt-cells = <1>;
+ 				interrupt-controller;
+ 				compatible = "riscv,cpu-intc";
+ 			};
+ 		};
++		CPU1: cpu@1 {
++			device_type = "cpu";
++			reg = <1>;
++			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>;
++			CPU1_intc: interrupt-controller {
++				#interrupt-cells = <1>;
++				interrupt-controller;
++				compatible = "riscv,cpu-intc";
++			};
++		};
++
++		L2: l2-cache@e0500000 {
++			compatible = "cache";
++			cache-level = <2>;
++			cache-size = <0x40000>;
++			reg = <0x0 0xe0500000 0x0 0x40000>;
++		};
+ 	};
+ 
+ 	memory@0 {
+@@ -46,32 +79,32 @@
+ 	soc {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+-		compatible = "andestech,riscv-ae350-soc";
++		compatible = "simple-bus";
+ 		ranges;
+ 
+-	plic0: interrupt-controller@e4000000 {
+-		compatible = "riscv,plic0";
+-		#address-cells = <1>;
+-		#interrupt-cells = <1>;
+-		interrupt-controller;
+-		reg = <0xe4000000 0x2000000>;
+-		riscv,ndev=<71>;
+-		interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+-	};
++		plic0: interrupt-controller@e4000000 {
++			compatible = "riscv,plic0";
++			#address-cells = <1>;
++			#interrupt-cells = <1>;
++			interrupt-controller;
++			reg = <0xe4000000 0x2000000>;
++			riscv,ndev=<71>;
++			interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>;
++		};
+ 
+-	plic1: interrupt-controller@e6400000 {
+-		compatible = "riscv,plic1";
+-		#address-cells = <1>;
+-		#interrupt-cells = <1>;
+-		interrupt-controller;
+-		reg = <0xe6400000 0x400000>;
+-		riscv,ndev=<1>;
+-		interrupts-extended = <&CPU0_intc 3>;
+-	};
++		plic1: interrupt-controller@e6400000 {
++			compatible = "riscv,plic1";
++			#address-cells = <1>;
++			#interrupt-cells = <1>;
++			interrupt-controller;
++			reg = <0xe6400000 0x400000>;
++			riscv,ndev=<2>;
++			interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>;
++		};
+ 
+-	plmt0@e6000000 {
+-		compatible = "riscv,plmt0";
+-			interrupts-extended = <&CPU0_intc 7>;
++		plmt0@e6000000 {
++			compatible = "riscv,plmt0";
++			interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>;
+ 			reg = <0xe6000000 0x100000>;
+ 		};
+ 	};
+@@ -146,6 +179,10 @@
+ 		interrupt-parent = <&plic0>;
+ 	};
+ 
++	pmu {
++		compatible = "riscv,base-pmu";
++	};
++
+ 	virtio_mmio@fe007000 {
+ 		interrupts = <0x17 0x4>;
+ 		interrupt-parent = <0x2>;
+diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts
+index e48c298645..cde5cdeff8 100644
+--- a/arch/riscv/dts/ae350_64.dts
++++ b/arch/riscv/dts/ae350_64.dts
+@@ -26,16 +26,49 @@
+ 			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>;
+ 			CPU0_intc: interrupt-controller {
+ 				#interrupt-cells = <1>;
+ 				interrupt-controller;
+ 				compatible = "riscv,cpu-intc";
+ 			};
+ 		};
++		CPU1: cpu@1 {
++			device_type = "cpu";
++			reg = <1>;
++			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>;
++			CPU1_intc: interrupt-controller {
++				#interrupt-cells = <1>;
++				interrupt-controller;
++				compatible = "riscv,cpu-intc";
++			};
++		};
++
++		L2: l2-cache@e0500000 {
++			compatible = "cache";
++			cache-level = <2>;
++			cache-size = <0x40000>;
++			reg = <0x0 0xe0500000 0x0 0x40000>;
++		};
+ 	};
+ 
+ 	memory@0 {
+@@ -46,32 +79,32 @@
+ 	soc {
+ 		#address-cells = <2>;
+ 		#size-cells = <2>;
+-		compatible = "andestech,riscv-ae350-soc";
++		compatible = "simple-bus";
+ 		ranges;
+ 
+-	plic0: interrupt-controller@e4000000 {
+-		compatible = "riscv,plic0";
+-		#address-cells = <2>;
+-		#interrupt-cells = <2>;
+-		interrupt-controller;
+-		reg = <0x0 0xe4000000 0x0 0x2000000>;
+-		riscv,ndev=<71>;
+-		interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+-	};
++		plic0: interrupt-controller@e4000000 {
++			compatible = "riscv,plic0";
++			#address-cells = <2>;
++			#interrupt-cells = <2>;
++			interrupt-controller;
++			reg = <0x0 0xe4000000 0x0 0x2000000>;
++			riscv,ndev=<71>;
++			interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>;
++		};
+ 
+-	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>;
+-	};
++		plic1: interrupt-controller@e6400000 {
++			compatible = "riscv,plic1";
++			#address-cells = <2>;
++			#interrupt-cells = <2>;
++			interrupt-controller;
++			reg = <0x0 0xe6400000 0x0 0x400000>;
++			riscv,ndev=<2>;
++			interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>;
++		};
+ 
+-	plmt0@e6000000 {
+-		compatible = "riscv,plmt0";
+-			interrupts-extended = <&CPU0_intc 7>;
++		plmt0@e6000000 {
++			compatible = "riscv,plmt0";
++			interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>;
+ 			reg = <0x0 0xe6000000 0x0 0x100000>;
+ 		};
+ 	};
+@@ -146,6 +179,10 @@
+ 		interrupt-parent = <&plic0>;
+ 	};
+ 
++	pmu {
++		compatible = "riscv,base-pmu";
++	};
++
+ 	virtio_mmio@fe007000 {
+ 		interrupts = <0x17 0x4>;
+ 		interrupt-parent = <0x2>;
+-- 
+2.21.0
+

+ 27 - 0
recipes-bsp/u-boot/files/0017-riscv-ae350-enable-SMP.patch

@@ -0,0 +1,27 @@
+From 076b845893f3bb59dfad80b012d28191c19e2f7b Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Tue, 2 Apr 2019 15:56:44 +0800
+Subject: [PATCH 17/18] riscv: ae350: enable SMP
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ board/AndesTech/ax25-ae350/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/board/AndesTech/ax25-ae350/Kconfig b/board/AndesTech/ax25-ae350/Kconfig
+index 44cb302f70..5e682b679d 100644
+--- a/board/AndesTech/ax25-ae350/Kconfig
++++ b/board/AndesTech/ax25-ae350/Kconfig
+@@ -24,5 +24,6 @@ config ENV_OFFSET
+ config BOARD_SPECIFIC_OPTIONS # dummy
+ 	def_bool y
+ 	select RISCV_NDS
++	imply SMP
+ 
+ endif
+-- 
+2.21.0
+

+ 35 - 0
recipes-bsp/u-boot/files/0018-riscv-dts-fix-CONFIG_DEFAULT_DEVICE_TREE-failure.patch

@@ -0,0 +1,35 @@
+From 48b90d9db5d32e587901c4f33175488dd20fe0a5 Mon Sep 17 00:00:00 2001
+From: Rick Chen <rick@andestech.com>
+Date: Wed, 3 Apr 2019 10:43:37 +0800
+Subject: [PATCH 18/18] riscv: dts: fix CONFIG_DEFAULT_DEVICE_TREE failure
+
+It occurs since commit 27cb7300ffda
+("Ensure device tree DTS is compiled").
+
+More details can refer to
+89c2b5c02049aea746b1edee0b4e1d8519dec2f4
+ARM: fix arch/arm/dts/Makefile
+
+Signed-off-by: Rick Chen <rick@andestech.com>
+Cc: Greentime Hu <greentime@andestech.com>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+---
+ arch/riscv/dts/Makefile | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
+index b400defb38..f9cd606a9a 100644
+--- a/arch/riscv/dts/Makefile
++++ b/arch/riscv/dts/Makefile
+@@ -1,5 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0+
+ 
++dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb
++
+ targets += $(dtb-y)
+ 
+ DTC_FLAGS += -R 4 -p 0x1000
+-- 
+2.21.0
+

+ 21 - 0
recipes-bsp/u-boot/u-boot_2019.04.bbappend

@@ -0,0 +1,21 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://0001-riscv-add-infrastructure-for-calling-functions-on-ot.patch \
+            file://0002-riscv-import-the-supervisor-binary-interface-header-.patch \
+            file://0003-riscv-implement-IPI-platform-functions-using-SBI.patch \
+            file://0004-riscv-delay-initialization-of-caches-and-debug-UART.patch \
+            file://0005-riscv-save-hart-ID-in-register-tp-instead-of-s0.patch \
+            file://0006-riscv-add-support-for-multi-hart-systems.patch \
+            file://0007-riscv-boot-images-passed-to-bootm-on-all-harts.patch \
+            file://0008-riscv-do-not-rely-on-hart-ID-passed-by-previous-boot.patch \
+            file://0009-riscv-hang-if-relocation-of-secondary-harts-fails.patch \
+            file://0010-riscv-fu540-enable-SMP.patch \
+            file://0011-riscv-qemu-enable-SMP.patch \
+            file://0012-riscv-Add-a-SYSCON-driver-for-Andestech-s-PLIC.patch \
+            file://0013-riscv-Add-a-SYSCON-driver-for-Andestech-s-PLMT.patch \
+            file://0014-riscv-ax25-Add-platform-specific-Kconfig-options.patch \
+            file://0015-riscv-ax25-Andes-specific-cache-shall-only-support-i.patch \
+            file://0016-riscv-dts-ae350-support-SMP.patch \
+            file://0017-riscv-ae350-enable-SMP.patch \
+            file://0018-riscv-dts-fix-CONFIG_DEFAULT_DEVICE_TREE-failure.patch \
+           "