Merge https://gitlab.denx.de/u-boot/custodians/u-boot-riscv
authorTom Rini <trini@konsulko.com>
Mon, 26 Aug 2019 13:50:46 +0000 (09:50 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 26 Aug 2019 13:50:46 +0000 (09:50 -0400)
- Support SPL and OpenSBI (FW_DYNAMIC firmware) boot.
- Fix qemu kconfig build warning.

32 files changed:
Kconfig
Makefile
arch/Kconfig
arch/riscv/Kconfig
arch/riscv/cpu/ax25/Kconfig
arch/riscv/cpu/cpu.c
arch/riscv/cpu/generic/Kconfig
arch/riscv/cpu/start.S
arch/riscv/cpu/u-boot-spl.lds [new file with mode: 0644]
arch/riscv/include/asm/encoding.h
arch/riscv/include/asm/spl.h [new file with mode: 0644]
arch/riscv/lib/Makefile
arch/riscv/lib/mkimage_fit_opensbi.sh [new file with mode: 0755]
arch/riscv/lib/spl.c [new file with mode: 0644]
board/emulation/qemu-riscv/Kconfig
board/emulation/qemu-riscv/MAINTAINERS
board/emulation/qemu-riscv/qemu-riscv.c
common/image.c
common/spl/Kconfig
common/spl/Makefile
common/spl/spl.c
common/spl/spl_fit.c
common/spl/spl_opensbi.c [new file with mode: 0644]
configs/qemu-riscv32_spl_defconfig [new file with mode: 0644]
configs/qemu-riscv64_spl_defconfig [new file with mode: 0644]
doc/board/emulation/qemu-riscv.rst
include/configs/qemu-riscv.h
include/fdtdec.h
include/image.h
include/opensbi.h [new file with mode: 0644]
include/spl.h
lib/fdtdec.c

diff --git a/Kconfig b/Kconfig
index d8e1aa4..1f0904f 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -252,7 +252,8 @@ config BUILD_TARGET
        default "u-boot-with-spl.sfp" if TARGET_SOCFPGA_GEN5
        default "u-boot-spl.kwb" if ARCH_MVEBU && SPL
        default "u-boot-elf.srec" if RCAR_GEN3
-       default "u-boot.itb" if SPL_LOAD_FIT && (ROCKCHIP_RK3399 || ARCH_SUNXI)
+       default "u-boot.itb" if SPL_LOAD_FIT && (ROCKCHIP_RK3399 || \
+                               ARCH_SUNXI || RISCV)
        default "u-boot.kwb" if KIRKWOOD
        default "u-boot-with-spl.bin" if ARCH_AT91 && SPL_NAND_SUPPORT
        help
@@ -465,6 +466,7 @@ config SPL_FIT_GENERATOR
        depends on SPL_FIT
        default "board/sunxi/mksunxi_fit_atf.sh" if SPL_LOAD_FIT && ARCH_SUNXI
        default "arch/arm/mach-rockchip/make_fit_atf.py" if SPL_LOAD_FIT && ARCH_ROCKCHIP
+       default "arch/riscv/lib/mkimage_fit_opensbi.sh" if SPL_LOAD_FIT && RISCV
        help
          Specifies a (platform specific) script file to generate the FIT
          source file used to build the U-Boot FIT image file. This gets
index 3b0864a..cf85e8c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1257,7 +1257,9 @@ MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
                -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
 
 u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \
-               $(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE
+               $(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin \
+                       $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_OF_HOSTFILE),dts/dt.dtb) \
+               ,u-boot.bin) FORCE
        $(call if_changed,mkimage)
        $(BOARD_SIZE_CHECK)
 
@@ -1267,7 +1269,9 @@ else
 MKIMAGEFLAGS_u-boot.itb = -E
 endif
 
-u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE
+u-boot.itb: u-boot-nodtb.bin \
+               $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_OF_HOSTFILE),dts/dt.dtb) \
+               $(U_BOOT_ITS) FORCE
        $(call if_changed,mkfitimage)
        $(BOARD_SIZE_CHECK)
 
index e510e97..f4ada57 100644 (file)
@@ -76,6 +76,12 @@ config RISCV
        imply MTD
        imply TIMER
        imply CMD_DM
+       imply SPL_DM
+       imply SPL_OF_CONTROL
+       imply SPL_LIBCOMMON_SUPPORT
+       imply SPL_LIBGENERIC_SUPPORT
+       imply SPL_SERIAL_SUPPORT
+       imply SPL_TIMER
 
 config SANDBOX
        bool "Sandbox"
index 8cfc7d0..01975d7 100644 (file)
@@ -113,6 +113,23 @@ config RISCV_SMODE
 
 endchoice
 
+choice
+       prompt "SPL Run Mode"
+       default SPL_RISCV_MMODE
+       depends on SPL
+
+config SPL_RISCV_MMODE
+       bool "Machine"
+       help
+         Choose this option to build U-Boot SPL for RISC-V M-Mode.
+
+config SPL_RISCV_SMODE
+       bool "Supervisor"
+       help
+         Choose this option to build U-Boot SPL for RISC-V S-Mode.
+
+endchoice
+
 config RISCV_ISA_C
        bool "Emit compressed instructions"
        default y
@@ -132,34 +149,40 @@ config 64BIT
 
 config SIFIVE_CLINT
        bool
-       depends on RISCV_MMODE
+       depends on RISCV_MMODE || SPL_RISCV_MMODE
        select REGMAP
        select SYSCON
+       select SPL_REGMAP if SPL
+       select SPL_SYSCON if SPL
        help
          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
+       depends on RISCV_MMODE || SPL_RISCV_MMODE
        select REGMAP
        select SYSCON
+       select SPL_REGMAP if SPL
+       select SPL_SYSCON if SPL
        help
          The Andes PLIC block holds memory-mapped claim and pending registers
          associated with software interrupt.
 
 config ANDES_PLMT
        bool
-       depends on RISCV_MMODE
+       depends on RISCV_MMODE || SPL_RISCV_MMODE
        select REGMAP
        select SYSCON
+       select SPL_REGMAP if SPL
+       select SPL_SYSCON if SPL
        help
          The Andes PLMT block holds memory-mapped mtime register
          associated with timer tick.
 
 config RISCV_RDTIME
        bool
-       default y if RISCV_SMODE
+       default y if RISCV_SMODE || SPL_RISCV_SMODE
        help
          The provides the riscv_get_time() API that is implemented using the
          standard rdtime instruction. This is the case for S-mode U-Boot, and
@@ -189,7 +212,7 @@ config NR_CPUS
 
 config SBI_IPI
        bool
-       default y if RISCV_SMODE
+       default y if RISCV_SMODE || SPL_RISCV_SMODE
        depends on SMP
 
 config XIP
@@ -203,4 +226,7 @@ config STACK_SIZE_SHIFT
        int
        default 13
 
+config SPL_LDSCRIPT
+       default "arch/riscv/cpu/u-boot-spl.lds"
+
 endmenu
index 6b4b92e..f4b59cb 100644 (file)
@@ -4,8 +4,8 @@ config RISCV_NDS
        imply CPU
        imply CPU_RISCV
        imply RISCV_TIMER
-       imply ANDES_PLIC if RISCV_MMODE
-       imply ANDES_PLMT if RISCV_MMODE
+       imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
+       imply ANDES_PLMT if (RISCV_MMODE || SPL_RISCV_MMODE)
        help
          Run U-Boot on AndeStar V5 platforms and use some specific features
          which are provided by Andes Technology AndeStar V5 families.
@@ -14,7 +14,7 @@ if RISCV_NDS
 
 config RISCV_NDS_CACHE
        bool "AndeStar V5 families specific cache support"
-       depends on RISCV_MMODE
+       depends on RISCV_MMODE || SPL_RISCV_MMODE
        help
          Provide Andes Technology AndeStar V5 families specific cache support.
 
index 5ca1857..e457f6a 100644 (file)
@@ -46,13 +46,13 @@ static inline bool supports_extension(char ext)
 
        return false;
 #else  /* !CONFIG_CPU */
-#ifdef CONFIG_RISCV_MMODE
+#if CONFIG_IS_ENABLED(RISCV_MMODE)
        return csr_read(CSR_MISA) & (1 << (ext - 'a'));
-#else  /* !CONFIG_RISCV_MMODE */
+#else  /* !CONFIG_IS_ENABLED(RISCV_MMODE) */
 #warning "There is no way to determine the available extensions in S-mode."
 #warning "Please convert your board to use the RISC-V CPU driver."
        return false;
-#endif /* CONFIG_RISCV_MMODE */
+#endif /* CONFIG_IS_ENABLED(RISCV_MMODE) */
 #endif /* CONFIG_CPU */
 }
 
index 1d6ab50..b2cb155 100644 (file)
@@ -8,5 +8,8 @@ config GENERIC_RISCV
        imply CPU
        imply CPU_RISCV
        imply RISCV_TIMER
-       imply SIFIVE_CLINT if RISCV_MMODE
+       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
        imply CMD_CPU
+       imply SPL_CPU_SUPPORT
+       imply SPL_OPENSBI
+       imply SPL_LOAD_FIT
index e06db40..b15209d 100644 (file)
@@ -39,7 +39,7 @@ secondary_harts_relocation_error:
 .section .text
 .globl _start
 _start:
-#ifdef CONFIG_RISCV_MMODE
+#if CONFIG_IS_ENABLED(RISCV_MMODE)
        csrr    a0, CSR_MHARTID
 #endif
 
@@ -62,7 +62,7 @@ _start:
 
 #ifdef CONFIG_SMP
        /* set xSIE bit to receive IPIs */
-#ifdef CONFIG_RISCV_MMODE
+#if CONFIG_IS_ENABLED(RISCV_MMODE)
        li      t0, MIE_MSIE
 #else
        li      t0, SIE_SSIE
@@ -75,7 +75,11 @@ _start:
  */
 call_board_init_f:
        li      t0, -16
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
+       li      t1, CONFIG_SPL_STACK
+#else
        li      t1, CONFIG_SYS_INIT_SP_ADDR
+#endif
        and     sp, t1, t0              /* force 16 byte alignment */
 
 call_board_init_f_0:
@@ -159,7 +163,57 @@ wait_for_gd_init:
 
        mv      a0, zero                /* a0 <-- boot_flags = 0 */
        la      t5, board_init_f
-       jr      t5                      /* jump to board_init_f() */
+       jalr    t5                      /* jump to board_init_f() */
+
+#ifdef CONFIG_SPL_BUILD
+spl_clear_bss:
+       la      t0, __bss_start
+       la      t1, __bss_end
+       beq     t0, t1, spl_stack_gd_setup
+
+spl_clear_bss_loop:
+       SREG    zero, 0(t0)
+       addi    t0, t0, REGBYTES
+       bne     t0, t1, spl_clear_bss_loop
+
+spl_stack_gd_setup:
+       jal     spl_relocate_stack_gd
+
+       /* skip setup if we did not relocate */
+       beqz    a0, spl_call_board_init_r
+       mv      s0, a0
+
+       /* setup stack on main hart */
+#ifdef CONFIG_SMP
+       /* tp: hart id */
+       slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
+       sub     sp, s0, t0
+#else
+       mv      sp, s0
+#endif
+
+       /* set new stack and global data pointer on secondary harts */
+spl_secondary_hart_stack_gd_setup:
+       la      a0, secondary_hart_relocate
+       mv      a1, s0
+       mv      a2, s0
+       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
+
+       /* set new global data pointer on main hart */
+1:     mv      gp, s0
+
+spl_call_board_init_r:
+       mv      a0, zero
+       mv      a1, zero
+       jal     board_init_r
+#endif
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -344,7 +398,7 @@ secondary_hart_loop:
 
 #ifdef CONFIG_SMP
        csrr    t0, MODE_PREFIX(ip)
-#ifdef CONFIG_RISCV_MMODE
+#if CONFIG_IS_ENABLED(RISCV_MMODE)
        andi    t0, t0, MIE_MSIE
 #else
        andi    t0, t0, SIE_SSIE
diff --git a/arch/riscv/cpu/u-boot-spl.lds b/arch/riscv/cpu/u-boot-spl.lds
new file mode 100644 (file)
index 0000000..32255d5
--- /dev/null
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Based on arch/riscv/cpu/u-boot.lds, which is
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ *
+ * and arch/mips/cpu/u-boot-spl.lds.
+ */
+MEMORY { .spl_mem : ORIGIN = IMAGE_TEXT_BASE, LENGTH = IMAGE_MAX_SIZE }
+MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+                   LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_ARCH("riscv")
+ENTRY(_start)
+
+SECTIONS
+{
+       . = ALIGN(4);
+       .text : {
+               arch/riscv/cpu/start.o  (.text)
+               *(.text*)
+       } > .spl_mem
+
+       . = ALIGN(4);
+       .rodata : {
+               *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+       } > .spl_mem
+
+       . = ALIGN(4);
+       .data : {
+               *(.data*)
+       } > .spl_mem
+       . = ALIGN(4);
+
+       .got : {
+               __got_start = .;
+               *(.got.plt) *(.got)
+               __got_end = .;
+       } > .spl_mem
+
+       . = ALIGN(4);
+
+       .u_boot_list : {
+               KEEP(*(SORT(.u_boot_list*)));
+       } > .spl_mem
+
+       . = ALIGN(4);
+
+       .binman_sym_table : {
+               __binman_sym_start = .;
+               KEEP(*(SORT(.binman_sym*)));
+               __binman_sym_end = .;
+       } > .spl_mem
+
+       . = ALIGN(4);
+
+       /DISCARD/ : { *(.rela.plt*) }
+       .rela.dyn : {
+               __rel_dyn_start = .;
+               *(.rela*)
+               __rel_dyn_end = .;
+       } > .spl_mem
+
+       . = ALIGN(4);
+
+       .dynsym : {
+               __dyn_sym_start = .;
+               *(.dynsym)
+               __dyn_sym_end = .;
+       } > .spl_mem
+
+       . = ALIGN(4);
+
+       _end = .;
+
+       .bss : {
+               __bss_start = .;
+               *(.bss*)
+               . = ALIGN(4);
+               __bss_end = .;
+       } > .bss_mem
+}
index c450eb9..a0695da 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <asm/csr.h>
 
-#ifdef CONFIG_RISCV_SMODE
+#if CONFIG_IS_ENABLED(RISCV_SMODE)
 #define MODE_PREFIX(__suffix)  s##__suffix
 #else
 #define MODE_PREFIX(__suffix)  m##__suffix
diff --git a/arch/riscv/include/asm/spl.h b/arch/riscv/include/asm/spl.h
new file mode 100644 (file)
index 0000000..45c03fb
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Based on arch/mips/include/asm/spl.h.
+ *
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
+ */
+#ifndef _ASM_RISCV_SPL_H_
+#define _ASM_RISCV_SPL_H_
+
+enum {
+       BOOT_DEVICE_RAM,
+       BOOT_DEVICE_MMC1,
+       BOOT_DEVICE_MMC2,
+       BOOT_DEVICE_MMC2_2,
+       BOOT_DEVICE_NAND,
+       BOOT_DEVICE_ONENAND,
+       BOOT_DEVICE_NOR,
+       BOOT_DEVICE_UART,
+       BOOT_DEVICE_SPI,
+       BOOT_DEVICE_USB,
+       BOOT_DEVICE_SATA,
+       BOOT_DEVICE_I2C,
+       BOOT_DEVICE_BOARD,
+       BOOT_DEVICE_DFU,
+       BOOT_DEVICE_XIP,
+       BOOT_DEVICE_BOOTROM,
+       BOOT_DEVICE_NONE
+};
+
+#endif
index 6ae6ebb..c9179a5 100644 (file)
@@ -10,15 +10,19 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
 obj-$(CONFIG_CMD_GO) += boot.o
 obj-y  += cache.o
-obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
+ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
 obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
 obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
 obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
+else
+obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
+obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
+endif
 obj-y  += interrupts.o
 obj-y  += reset.o
-obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
 obj-y   += setjmp.o
 obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SPL_BUILD)        += spl.o
 
 # For building EFI apps
 CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
diff --git a/arch/riscv/lib/mkimage_fit_opensbi.sh b/arch/riscv/lib/mkimage_fit_opensbi.sh
new file mode 100755 (executable)
index 0000000..d6f95e5
--- /dev/null
@@ -0,0 +1,100 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# script to generate FIT image source for RISC-V boards with OpenSBI
+# and, optionally, multiple device trees (given on the command line).
+#
+# usage: $0 [<dt_name> [<dt_name] ...]
+
+[ -z "$OPENSBI" ] && OPENSBI="fw_dynamic.bin"
+
+if [ -z "$UBOOT_LOAD_ADDR" ]; then
+       UBOOT_LOAD_ADDR="$(grep "^CONFIG_SYS_TEXT_BASE=" .config | awk 'BEGIN{FS="="} {print $2}')"
+fi
+
+if [ -z "$OPENSBI_LOAD_ADDR" ]; then
+       OPENSBI_LOAD_ADDR="$(grep "^CONFIG_SPL_OPENSBI_LOAD_ADDR=" .config | awk 'BEGIN{FS="="} {print $2}')"
+fi
+
+if [ ! -f $OPENSBI ]; then
+       echo "WARNING: OpenSBI binary \"$OPENSBI\" not found, resulting binary is not functional." >&2
+       OPENSBI=/dev/null
+fi
+
+cat << __HEADER_EOF
+/dts-v1/;
+
+/ {
+       description = "Configuration to load OpenSBI before U-Boot";
+
+       images {
+               uboot {
+                       description = "U-Boot";
+                       data = /incbin/("u-boot-nodtb.bin");
+                       type = "standalone";
+                       os = "U-Boot";
+                       arch = "riscv";
+                       compression = "none";
+                       load = <$UBOOT_LOAD_ADDR>;
+               };
+               opensbi {
+                       description = "RISC-V OpenSBI";
+                       data = /incbin/("$OPENSBI");
+                       type = "firmware";
+                       os = "opensbi";
+                       arch = "riscv";
+                       compression = "none";
+                       load = <$OPENSBI_LOAD_ADDR>;
+                       entry = <$OPENSBI_LOAD_ADDR>;
+               };
+__HEADER_EOF
+
+cnt=1
+for dtname in $*
+do
+       cat << __FDT_IMAGE_EOF
+               fdt_$cnt {
+                       description = "$(basename $dtname .dtb)";
+                       data = /incbin/("$dtname");
+                       type = "flat_dt";
+                       compression = "none";
+               };
+__FDT_IMAGE_EOF
+cnt=$((cnt+1))
+done
+
+cat << __CONF_HEADER_EOF
+       };
+       configurations {
+               default = "config_1";
+
+__CONF_HEADER_EOF
+
+if [ $# -eq 0 ]; then
+cat << __CONF_SECTION_EOF
+               config_1 {
+                       description = "U-Boot FIT";
+                       firmware = "opensbi";
+                       loadables = "uboot";
+               };
+__CONF_SECTION_EOF
+else
+cnt=1
+for dtname in $*
+do
+cat << __CONF_SECTION_EOF
+               config_$cnt {
+                       description = "$(basename $dtname .dtb)";
+                       firmware = "opensbi";
+                       loadables = "uboot";
+                       fdt = "fdt_$cnt";
+               };
+__CONF_SECTION_EOF
+cnt=$((cnt+1))
+done
+fi
+
+cat << __ITS_EOF
+       };
+};
+__ITS_EOF
diff --git a/arch/riscv/lib/spl.c b/arch/riscv/lib/spl.c
new file mode 100644 (file)
index 0000000..bea8695
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Fraunhofer AISEC,
+ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+ */
+#include <common.h>
+#include <spl.h>
+#include <asm/smp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+__weak void board_init_f(ulong dummy)
+{
+       int ret;
+
+       ret = spl_early_init();
+       if (ret)
+               panic("spl_early_init() failed: %d\n", ret);
+
+       arch_cpu_init_dm();
+
+       preloader_console_init();
+}
+
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
+{
+       typedef void __noreturn (*image_entry_riscv_t)(ulong hart, void *dtb);
+       void *fdt_blob;
+       int ret;
+
+#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL)
+       fdt_blob = spl_image->fdt_addr;
+#else
+       fdt_blob = (void *)gd->fdt_blob;
+#endif
+
+       image_entry_riscv_t image_entry =
+               (image_entry_riscv_t)spl_image->entry_point;
+       invalidate_icache_all();
+
+       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);
+       if (ret)
+               hang();
+#endif
+       image_entry(gd->arch.boot_hart, fdt_blob);
+}
index 6cc7c31..7ce1201 100644 (file)
@@ -13,13 +13,22 @@ config SYS_CONFIG_NAME
        default "qemu-riscv"
 
 config SYS_TEXT_BASE
+       default 0x81200000 if SPL
        default 0x80000000 if !RISCV_SMODE
        default 0x80200000 if RISCV_SMODE && ARCH_RV64I
        default 0x80400000 if RISCV_SMODE && ARCH_RV32I
 
+config SPL_TEXT_BASE
+       default 0x80000000
+
+config SPL_OPENSBI_LOAD_ADDR
+       hex
+       default 0x81000000
+
 config BOARD_SPECIFIC_OPTIONS # dummy
        def_bool y
        select GENERIC_RISCV
+       select SUPPORT_SPL
        imply SYS_NS16550
        imply VIRTIO_MMIO
        imply VIRTIO_NET
@@ -43,5 +52,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
        imply CMD_PCI
        imply E1000
        imply NVME
+       imply SPL_RAM_SUPPORT
+       imply SPL_RAM_DEVICE
 
 endif
index c701c83..78969ed 100644 (file)
@@ -5,5 +5,7 @@ F:      board/emulation/qemu-riscv/
 F:     include/configs/qemu-riscv.h
 F:     configs/qemu-riscv32_defconfig
 F:     configs/qemu-riscv32_smode_defconfig
+F:     configs/qemu-riscv32_spl_defconfig
 F:     configs/qemu-riscv64_defconfig
 F:     configs/qemu-riscv64_smode_defconfig
+F:     configs/qemu-riscv64_spl_defconfig
index 49e304f..37d48d0 100644 (file)
@@ -7,6 +7,7 @@
 #include <dm.h>
 #include <env.h>
 #include <fdtdec.h>
+#include <spl.h>
 #include <virtio_types.h>
 #include <virtio.h>
 
@@ -88,3 +89,19 @@ int ft_board_setup(void *blob, bd_t *bd)
 
        return 0;
 }
+
+#ifdef CONFIG_SPL
+u32 spl_boot_device(void)
+{
+       /* RISC-V QEMU only supports RAM as SPL boot device */
+       return BOOT_DEVICE_RAM;
+}
+#endif
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+       /* boot using first FIT config */
+       return 0;
+}
+#endif
index 84e859a..645584b 100644 (file)
@@ -132,6 +132,7 @@ static const table_entry_t uimage_os[] = {
 #if defined(CONFIG_BOOTM_OPENRTOS) || defined(USE_HOSTCC)
        {       IH_OS_OPENRTOS, "openrtos",     "OpenRTOS",             },
 #endif
+       {       IH_OS_OPENSBI,  "opensbi",      "RISC-V OpenSBI",       },
 
        {       -1,             "",             "",                     },
 };
index 94dcdff..bb56e3f 100644 (file)
@@ -1156,6 +1156,23 @@ config SPL_OPTEE
          OP-TEE is an open source Trusted OS  which is loaded by SPL.
          More detail at: https://github.com/OP-TEE/optee_os
 
+config SPL_OPENSBI
+       bool "Support RISC-V OpenSBI"
+       depends on RISCV && SPL_RISCV_MMODE && RISCV_SMODE
+       help
+         OpenSBI is an open-source implementation of the RISC-V Supervisor Binary
+         Interface (SBI) specification. U-Boot supports the OpenSBI FW_DYNAMIC
+         firmware. It is loaded and started by U-Boot SPL.
+
+         More details are available at https://github.com/riscv/opensbi and
+         https://github.com/riscv/riscv-sbi-doc
+
+config SPL_OPENSBI_LOAD_ADDR
+       hex "OpenSBI load address"
+       depends on SPL_OPENSBI
+       help
+         Load address of the OpenSBI binary.
+
 config TPL
        bool
        depends on SUPPORT_TPL
index d28de69..5ce6f4a 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_$(SPL_TPL_)NET_SUPPORT) += spl_net.o
 obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += spl_mmc.o
 obj-$(CONFIG_$(SPL_TPL_)ATF) += spl_atf.o
 obj-$(CONFIG_$(SPL_TPL_)OPTEE) += spl_optee.o
+obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o
 obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o
 obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o
 obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o
index 2c696f2..082fa2b 100644 (file)
@@ -659,6 +659,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
                                (void *)spl_image.entry_point);
                break;
 #endif
+#if CONFIG_IS_ENABLED(OPENSBI)
+       case IH_OS_OPENSBI:
+               debug("Jumping to U-Boot via RISC-V OpenSBI\n");
+               spl_invoke_opensbi(&spl_image);
+               break;
+#endif
 #ifdef CONFIG_SPL_OS_BOOT
        case IH_OS_LINUX:
                debug("Jumping to Linux\n");
@@ -775,7 +781,7 @@ ulong spl_relocate_stack_gd(void)
 #if CONFIG_IS_ENABLED(DM)
        dm_fixup_for_gd_move(new_gd);
 #endif
-#if !defined(CONFIG_ARM)
+#if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
        gd = new_gd;
 #endif
        return ptr;
index 2e2e09e..b3e3ccd 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/libfdt.h>
 #include <spl.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifndef CONFIG_SYS_BOOTM_LEN
 #define CONFIG_SYS_BOOTM_LEN   (64 << 20)
 #endif
@@ -279,25 +281,34 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
                              void *fit, int images, ulong base_offset)
 {
        struct spl_image_info image_info;
-       int node, ret;
+       int node, ret = 0;
+
+       /*
+        * Use the address following the image as target address for the
+        * device tree.
+        */
+       image_info.load_addr = spl_image->load_addr + spl_image->size;
 
        /* Figure out which device tree the board wants to use */
        node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
        if (node < 0) {
                debug("%s: cannot find FDT node\n", __func__);
-               return node;
-       }
-
-       /*
-        * Read the device tree and place it after the image.
-        * Align the destination address to ARCH_DMA_MINALIGN.
-        */
-       image_info.load_addr = spl_image->load_addr + spl_image->size;
-       ret = spl_load_fit_image(info, sector, fit, base_offset, node,
-                                &image_info);
 
-       if (ret < 0)
-               return ret;
+               /*
+                * U-Boot did not find a device tree inside the FIT image. Use
+                * the U-Boot device tree instead.
+                */
+               if (gd->fdt_blob)
+                       memcpy((void *)image_info.load_addr, gd->fdt_blob,
+                              fdt_totalsize(gd->fdt_blob));
+               else
+                       return node;
+       } else {
+               ret = spl_load_fit_image(info, sector, fit, base_offset, node,
+                                        &image_info);
+               if (ret < 0)
+                       return ret;
+       }
 
        /* Make the load-address of the FDT available for the SPL framework */
        spl_image->fdt_addr = (void *)image_info.load_addr;
diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c
new file mode 100644 (file)
index 0000000..a6b4480
--- /dev/null
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Fraunhofer AISEC,
+ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+ *
+ * Based on common/spl/spl_atf.c
+ */
+#include <common.h>
+#include <errno.h>
+#include <spl.h>
+#include <asm/smp.h>
+#include <opensbi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct fw_dynamic_info opensbi_info;
+
+static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node)
+{
+       int fit_images_node, node;
+       const char *fit_os;
+
+       fit_images_node = fdt_path_offset(blob, "/fit-images");
+       if (fit_images_node < 0)
+               return -ENODEV;
+
+       fdt_for_each_subnode(node, blob, fit_images_node) {
+               fit_os = fdt_getprop(blob, node, FIT_OS_PROP, NULL);
+               if (!fit_os)
+                       continue;
+
+               if (genimg_get_os_id(fit_os) == IH_OS_U_BOOT) {
+                       *uboot_node = node;
+                       return 0;
+               }
+       }
+
+       return -ENODEV;
+}
+
+void spl_invoke_opensbi(struct spl_image_info *spl_image)
+{
+       int ret, uboot_node;
+       ulong uboot_entry;
+       void (*opensbi_entry)(ulong hartid, ulong dtb, ulong info);
+
+       if (!spl_image->fdt_addr) {
+               pr_err("No device tree specified in SPL image\n");
+               hang();
+       }
+
+       /* Find U-Boot image in /fit-images */
+       ret = spl_opensbi_find_uboot_node(spl_image->fdt_addr, &uboot_node);
+       if (ret) {
+               pr_err("Can't find U-Boot node, %d", ret);
+               hang();
+       }
+
+       /* Get U-Boot entry point */
+       uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node,
+                                     "entry-point");
+       if (uboot_entry == FDT_ERROR)
+               uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node,
+                                             "load-addr");
+
+       /* Prepare obensbi_info object */
+       opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE;
+       opensbi_info.version = FW_DYNAMIC_INFO_VERSION;
+       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_entry = (void (*)(ulong, ulong, ulong))spl_image->entry_point;
+       invalidate_icache_all();
+
+#ifdef CONFIG_SMP
+       ret = smp_call_function((ulong)spl_image->entry_point,
+                               (ulong)spl_image->fdt_addr,
+                               (ulong)&opensbi_info);
+       if (ret)
+               hang();
+#endif
+       opensbi_entry(gd->arch.boot_hart, (ulong)spl_image->fdt_addr,
+                     (ulong)&opensbi_info);
+}
diff --git a/configs/qemu-riscv32_spl_defconfig b/configs/qemu-riscv32_spl_defconfig
new file mode 100644 (file)
index 0000000..78e755b
--- /dev/null
@@ -0,0 +1,11 @@
+CONFIG_RISCV=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL=y
+CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_RISCV_SMODE=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+# CONFIG_CMD_MII is not set
+CONFIG_OF_PRIOR_STAGE=y
diff --git a/configs/qemu-riscv64_spl_defconfig b/configs/qemu-riscv64_spl_defconfig
new file mode 100644 (file)
index 0000000..a3f5e29
--- /dev/null
@@ -0,0 +1,12 @@
+CONFIG_RISCV=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL=y
+CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_ARCH_RV64I=y
+CONFIG_RISCV_SMODE=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+# CONFIG_CMD_MII is not set
+CONFIG_OF_PRIOR_STAGE=y
index 2148334..fe7505e 100644 (file)
@@ -6,7 +6,8 @@ QEMU RISC-V
 
 QEMU for RISC-V supports a special 'virt' machine designed for emulation and
 virtualization purposes. This document describes how to run U-Boot under it.
-Both 32-bit 64-bit targets are supported.
+Both 32-bit and 64-bit targets are supported, running in either machine or
+supervisor mode.
 
 The QEMU virt machine models a generic RISC-V virtual machine with support for
 the VirtIO standard networking and block storage devices. It has CLINT, PLIC,
@@ -28,6 +29,11 @@ Set the CROSS_COMPILE environment variable as usual, and run:
     make qemu-riscv64_defconfig
     make
 
+This will compile U-Boot for machine mode. To build supervisor mode binaries,
+use the configurations qemu-riscv32_smode_defconfig and
+qemu-riscv64_smode_defconfig instead. Note that U-Boot running in supervisor
+mode requires a supervisor binary interface (SBI), such as RISC-V OpenSBI.
+
 Running U-Boot
 --------------
 The minimal QEMU command line to get U-Boot up and running is:
@@ -46,4 +52,56 @@ parameter. For example, '-m 2G' creates 2GiB memory for the target,
 and the memory node in the embedded DTB created by QEMU reflects
 the new setting.
 
+For instructions on how to run U-Boot in supervisor mode on QEMU
+with OpenSBI, see the documentation available with OpenSBI:
+https://github.com/riscv/opensbi/blob/master/docs/platform/qemu_virt.md
+
 These have been tested in QEMU 3.0.0.
+
+Running U-Boot SPL
+------------------
+In the default SPL configuration, U-Boot SPL starts in machine mode. U-Boot
+proper and OpenSBI (FW_DYNAMIC firmware) are bundled as FIT image and made
+available to U-Boot SPL. Both are then loaded by U-Boot SPL and the location
+of U-Boot proper is passed to OpenSBI. After initialization, U-Boot proper is
+started in supervisor mode by OpenSBI.
+
+OpenSBI must be compiled before compiling U-Boot. Version 0.4 and higher is
+supported by U-Boot. Clone the OpenSBI repository and run the following command.
+
+.. code-block:: console
+
+    git clone https://github.com/riscv/opensbi.git
+    cd opensbi
+    make PLATFORM=qemu/virt
+
+See the OpenSBI documentation for full details:
+https://github.com/riscv/opensbi/blob/master/docs/platform/qemu_virt.md
+
+To make the FW_DYNAMIC binary (build/platform/qemu/virt/firmware/fw_dynamic.bin)
+available to U-Boot, either copy it into the U-Boot root directory or specify
+its location with the OPENSBI environment variable. Afterwards, compile U-Boot
+with the following commands.
+
+- For 32-bit RISC-V::
+
+    make qemu-riscv32_spl_defconfig
+    make
+
+- For 64-bit RISC-V::
+
+    make qemu-riscv64_spl_defconfig
+    make
+
+The minimal QEMU commands to run U-Boot SPL in both 32-bit and 64-bit
+configurations are:
+
+- For 32-bit RISC-V::
+
+    qemu-system-riscv32 -nographic -machine virt -kernel spl/u-boot-spl \
+    -device loader,file=u-boot.itb,addr=0x80200000
+
+- For 64-bit RISC-V::
+
+    qemu-system-riscv64 -nographic -machine virt -kernel spl/u-boot-spl \
+    -device loader,file=u-boot.itb,addr=0x80200000
index ecea1d4..fa9b9af 100644 (file)
@@ -8,6 +8,18 @@
 
 #include <linux/sizes.h>
 
+#ifdef CONFIG_SPL
+
+#define CONFIG_SPL_MAX_SIZE            0x00100000
+#define CONFIG_SPL_BSS_START_ADDR      0x84000000
+#define CONFIG_SPL_BSS_MAX_SIZE                0x00100000
+#define CONFIG_SYS_SPL_MALLOC_START    0x84100000
+#define CONFIG_SYS_SPL_MALLOC_SIZE     0x00100000
+
+#define CONFIG_SPL_LOAD_FIT_ADDRESS    0x80200000
+
+#endif
+
 #define CONFIG_SYS_SDRAM_BASE          0x80000000
 #define CONFIG_SYS_INIT_SP_ADDR                (CONFIG_SYS_SDRAM_BASE + SZ_2M)
 
@@ -22,6 +34,7 @@
 /* Environment options */
 #define CONFIG_ENV_SIZE                        SZ_128K
 
+#ifndef CONFIG_SPL_BUILD
 #define BOOT_TARGET_DEVICES(func) \
        func(QEMU, qemu, na) \
        func(VIRTIO, virtio, 0) \
@@ -47,5 +60,6 @@
        "pxefile_addr_r=0x88200000\0" \
        "ramdisk_addr_r=0x88300000\0" \
        BOOTENV
+#endif
 
 #endif /* __CONFIG_H */
index e6c22dd..635f530 100644 (file)
@@ -54,7 +54,7 @@ struct bd_info;
 #define SPL_BUILD      0
 #endif
 
-#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
+#ifdef CONFIG_OF_PRIOR_STAGE
 extern phys_addr_t prior_stage_fdt_address;
 #endif
 
index 27d7cb9..404b733 100644 (file)
@@ -156,6 +156,7 @@ enum {
        IH_OS_OPENRTOS,         /* OpenRTOS     */
        IH_OS_ARM_TRUSTED_FIRMWARE,     /* ARM Trusted Firmware */
        IH_OS_TEE,                      /* Trusted Execution Environment */
+       IH_OS_OPENSBI,                  /* RISC-V OpenSBI */
 
        IH_OS_COUNT,
 };
diff --git a/include/opensbi.h b/include/opensbi.h
new file mode 100644 (file)
index 0000000..9f1d62e
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ *
+ * Based on include/sbi/{fw_dynamic.h,sbi_scratch.h} from the OpenSBI project.
+ */
+#ifndef OPENSBI_H
+#define OPENSBI_H
+
+/** Expected value of info magic ('OSBI' ascii string in hex) */
+#define FW_DYNAMIC_INFO_MAGIC_VALUE            0x4942534f
+
+/** Maximum supported info version */
+#define FW_DYNAMIC_INFO_VERSION                        0x1
+
+/** Possible next mode values */
+#define FW_DYNAMIC_INFO_NEXT_MODE_U            0x0
+#define FW_DYNAMIC_INFO_NEXT_MODE_S            0x1
+#define FW_DYNAMIC_INFO_NEXT_MODE_M            0x3
+
+enum sbi_scratch_options {
+       /** Disable prints during boot */
+       SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
+};
+
+/** Representation dynamic info passed by previous booting stage */
+struct fw_dynamic_info {
+       /** Info magic */
+       unsigned long magic;
+       /** Info version */
+       unsigned long version;
+       /** Next booting stage address */
+       unsigned long next_addr;
+       /** Next booting stage mode */
+       unsigned long next_mode;
+       /** Options for OpenSBI library */
+       unsigned long options;
+} __packed;
+
+#endif
index a90f971..e4640f3 100644 (file)
@@ -375,6 +375,11 @@ void spl_invoke_atf(struct spl_image_info *spl_image);
 void spl_optee_entry(void *arg0, void *arg1, void *arg2, void *arg3);
 
 /**
+ * spl_invoke_opensbi - boot using a RISC-V OpenSBI image
+ */
+void spl_invoke_opensbi(struct spl_image_info *spl_image);
+
+/**
  * board_return_to_bootrom - allow for boards to continue with the boot ROM
  *
  * If a board (e.g. the Rockchip RK3368 boards) provide some
index ef5e548..74525c8 100644 (file)
@@ -1535,16 +1535,14 @@ int fdtdec_setup(void)
                puts("Failed to read control FDT\n");
                return -1;
        }
+# elif defined(CONFIG_OF_PRIOR_STAGE)
+       gd->fdt_blob = (void *)prior_stage_fdt_address;
 # endif
 # ifndef CONFIG_SPL_BUILD
        /* Allow the early environment to override the fdt address */
-#  if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
-       gd->fdt_blob = (void *)prior_stage_fdt_address;
-#  else
        gd->fdt_blob = map_sysmem
                (env_get_ulong("fdtcontroladdr", 16,
                               (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
-#  endif
 # endif
 
 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)