From 6b20dc165e6d7c409b247af746db5bc29be318dd Mon Sep 17 00:00:00 2001 From: Lukas Auer Date: Sun, 20 Oct 2019 20:53:47 +0200 Subject: [PATCH 01/17] riscv: increase stack size to avoid a stack overflow during distro boot This fixes a problem, where booting Linux using distro boot will sometimes lead to an invalid instruction exception on the main hart. The secondary harts are not affected and boot Linux successfully. The root cause of this problem is a stack overflow on the main hart. With distro boot, the current default stack size of 8KiB on RISC-V is not sufficient and will cause a stack overflow. The stacks are allocated sequentially. In the case of a stack overflow the stack of the main hart can reach into that of another hart and be corrupted. The stack overflow previously did not cause any problems, because only stack frames, which are not used anymore since the hart enters Linux, were corrupted. Starting with GCC 9, the stack usage has decreased. Now, only the most recent stack frame overflows into the stack of a secondary hart and is corrupted. The illegal instruction exception is caused by the secondary hart overwriting the return address in the stack frame of the main hart with an address that does not include valid code. Increase the default stack size of each hart to 16KiB to avoid this problem. Reported-by: Aurelien Jarno Signed-off-by: Lukas Auer Tested-by: David Abdurachmanov Tested-by: Aurelien Jarno Reviewed-by: Rick Chen --- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 01975d7c60..85e15ebffa 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -224,7 +224,7 @@ config XIP config STACK_SIZE_SHIFT int - default 13 + default 14 config SPL_LDSCRIPT default "arch/riscv/cpu/u-boot-spl.lds" From b82a18549fc3c64a261f7d8bfcd8009dc8eb2220 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 18 Nov 2019 16:59:40 +0530 Subject: [PATCH 02/17] riscv: dts: Add hifive-unleashed-a00 dts from Linux Sync the hifive-unleashed-a00 dts from Linux with below commit details: commit <2993c9b04e616df0848b655d7202a707a70fc876> ("riscv: dts: HiFive Unleashed: add default chosen/stdout-path") Idea is to periodically sync the dts from Linux instead of tweaking internal changes one after another, so better not add any intermediate changes in between. This would help to maintain the dts files easy and meaningful since we are reusing device tree files from Linux. Signed-off-by: Jagan Teki Reviewed-by: Bin Meng Reviewed-by: Anup Patel --- arch/riscv/dts/Makefile | 1 + arch/riscv/dts/fu540-c000.dtsi | 251 ++++++++++++++++++++++++ arch/riscv/dts/hifive-unleashed-a00.dts | 96 +++++++++ 3 files changed, 348 insertions(+) create mode 100644 arch/riscv/dts/fu540-c000.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00.dts diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index f9cd606a9a..4f30e6936f 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb +dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb targets += $(dtb-y) diff --git a/arch/riscv/dts/fu540-c000.dtsi b/arch/riscv/dts/fu540-c000.dtsi new file mode 100644 index 0000000000..afa43c7ea3 --- /dev/null +++ b/arch/riscv/dts/fu540-c000.dtsi @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* Copyright (c) 2018-2019 SiFive, Inc */ + +/dts-v1/; + +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,fu540-c000", "sifive,fu540"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + ethernet0 = ð0; + }; + + chosen { + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: cpu@0 { + compatible = "sifive,e51", "sifive,rocket0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <16384>; + reg = <0>; + riscv,isa = "rv64imac"; + status = "disabled"; + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + cpu1: cpu@1 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <1>; + riscv,isa = "rv64imafdc"; + tlb-split; + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + cpu2: cpu@2 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <2>; + riscv,isa = "rv64imafdc"; + tlb-split; + cpu2_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + cpu3: cpu@3 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <3>; + riscv,isa = "rv64imafdc"; + tlb-split; + cpu3_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + cpu4: cpu@4 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <4>; + riscv,isa = "rv64imafdc"; + tlb-split; + cpu4_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,fu540-c000", "sifive,fu540", "simple-bus"; + ranges; + plic0: interrupt-controller@c000000 { + #interrupt-cells = <1>; + compatible = "sifive,plic-1.0.0"; + reg = <0x0 0xc000000 0x0 0x4000000>; + riscv,ndev = <53>; + interrupt-controller; + interrupts-extended = < + &cpu0_intc 0xffffffff + &cpu1_intc 0xffffffff &cpu1_intc 9 + &cpu2_intc 0xffffffff &cpu2_intc 9 + &cpu3_intc 0xffffffff &cpu3_intc 9 + &cpu4_intc 0xffffffff &cpu4_intc 9>; + }; + prci: clock-controller@10000000 { + compatible = "sifive,fu540-c000-prci"; + reg = <0x0 0x10000000 0x0 0x1000>; + clocks = <&hfclk>, <&rtcclk>; + #clock-cells = <1>; + }; + uart0: serial@10010000 { + compatible = "sifive,fu540-c000-uart", "sifive,uart0"; + reg = <0x0 0x10010000 0x0 0x1000>; + interrupt-parent = <&plic0>; + interrupts = <4>; + clocks = <&prci PRCI_CLK_TLCLK>; + status = "disabled"; + }; + uart1: serial@10011000 { + compatible = "sifive,fu540-c000-uart", "sifive,uart0"; + reg = <0x0 0x10011000 0x0 0x1000>; + interrupt-parent = <&plic0>; + interrupts = <5>; + clocks = <&prci PRCI_CLK_TLCLK>; + status = "disabled"; + }; + i2c0: i2c@10030000 { + compatible = "sifive,fu540-c000-i2c", "sifive,i2c0"; + reg = <0x0 0x10030000 0x0 0x1000>; + interrupt-parent = <&plic0>; + interrupts = <50>; + clocks = <&prci PRCI_CLK_TLCLK>; + reg-shift = <2>; + reg-io-width = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + qspi0: spi@10040000 { + compatible = "sifive,fu540-c000-spi", "sifive,spi0"; + reg = <0x0 0x10040000 0x0 0x1000 + 0x0 0x20000000 0x0 0x10000000>; + interrupt-parent = <&plic0>; + interrupts = <51>; + clocks = <&prci PRCI_CLK_TLCLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + qspi1: spi@10041000 { + compatible = "sifive,fu540-c000-spi", "sifive,spi0"; + reg = <0x0 0x10041000 0x0 0x1000 + 0x0 0x30000000 0x0 0x10000000>; + interrupt-parent = <&plic0>; + interrupts = <52>; + clocks = <&prci PRCI_CLK_TLCLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + qspi2: spi@10050000 { + compatible = "sifive,fu540-c000-spi", "sifive,spi0"; + reg = <0x0 0x10050000 0x0 0x1000>; + interrupt-parent = <&plic0>; + interrupts = <6>; + clocks = <&prci PRCI_CLK_TLCLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + eth0: ethernet@10090000 { + compatible = "sifive,fu540-c000-gem"; + interrupt-parent = <&plic0>; + interrupts = <53>; + reg = <0x0 0x10090000 0x0 0x2000 + 0x0 0x100a0000 0x0 0x1000>; + local-mac-address = [00 00 00 00 00 00]; + clock-names = "pclk", "hclk"; + clocks = <&prci PRCI_CLK_GEMGXLPLL>, + <&prci PRCI_CLK_GEMGXLPLL>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + pwm0: pwm@10020000 { + compatible = "sifive,fu540-c000-pwm", "sifive,pwm0"; + reg = <0x0 0x10020000 0x0 0x1000>; + interrupt-parent = <&plic0>; + interrupts = <42 43 44 45>; + clocks = <&prci PRCI_CLK_TLCLK>; + #pwm-cells = <3>; + status = "disabled"; + }; + pwm1: pwm@10021000 { + compatible = "sifive,fu540-c000-pwm", "sifive,pwm0"; + reg = <0x0 0x10021000 0x0 0x1000>; + interrupt-parent = <&plic0>; + interrupts = <46 47 48 49>; + clocks = <&prci PRCI_CLK_TLCLK>; + #pwm-cells = <3>; + status = "disabled"; + }; + + }; +}; diff --git a/arch/riscv/dts/hifive-unleashed-a00.dts b/arch/riscv/dts/hifive-unleashed-a00.dts new file mode 100644 index 0000000000..88cfcb96bf --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00.dts @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* Copyright (c) 2018-2019 SiFive, Inc */ + +#include "fu540-c000.dtsi" + +/* Clock frequency (in Hz) of the PCB crystal for rtcclk */ +#define RTCCLK_FREQ 1000000 + +/ { + #address-cells = <2>; + #size-cells = <2>; + model = "SiFive HiFive Unleashed A00"; + compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000"; + + chosen { + stdout-path = "serial0"; + }; + + cpus { + timebase-frequency = ; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + + soc { + }; + + hfclk: hfclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <33333333>; + clock-output-names = "hfclk"; + }; + + rtcclk: rtcclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + clock-output-names = "rtcclk"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&qspi0 { + status = "okay"; + flash@0 { + compatible = "issi,is25wp256", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&qspi2 { + status = "okay"; + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + spi-max-frequency = <20000000>; + voltage-ranges = <3300 3300>; + disable-wp; + }; +}; + +ð0 { + status = "okay"; + phy-mode = "gmii"; + phy-handle = <&phy0>; + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; From 31fbf6032ddd9b968b1ca102f71fe7f42fabf58a Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Wed, 4 Dec 2019 14:52:46 +0800 Subject: [PATCH 03/17] Use dts support from U-Boot via OF_SEPARATE instead of depending from opensbi. This would help to make the necessary changes in drivers and device trees in U-Boot tree itself. This feature would also be helpful to not pass dtb during opensbi builds. Signed-off-by: Jagan Teki Reviewed-by: Bin Meng Reviewed-by: Anup Patel Signed-off-by: Rick Chen --- configs/sifive_fu540_defconfig | 3 ++- doc/board/sifive/fu540.rst | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_fu540_defconfig index 48eccd766b..7d38ec9a70 100644 --- a/configs/sifive_fu540_defconfig +++ b/configs/sifive_fu540_defconfig @@ -7,8 +7,9 @@ CONFIG_RISCV_SMODE=y CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_MISC_INIT_R=y +CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00" CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y -CONFIG_OF_PRIOR_STAGE=y +CONFIG_OF_SEPARATE=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_DM_MTD=y diff --git a/doc/board/sifive/fu540.rst b/doc/board/sifive/fu540.rst index 7807f5b2c1..3937222c6c 100644 --- a/doc/board/sifive/fu540.rst +++ b/doc/board/sifive/fu540.rst @@ -58,10 +58,7 @@ firmware. We need to compile OpenSBI with below command: .. code-block:: none - make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH= FW_PAYLOAD_FDT_PATH= - -(Note: Prefer hifive-unleashed-a00.dtb from Linux-5.3 or higher) -(Note: Linux-5.2 is also fine but it does not have ethernet DT node) +make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH= More detailed description of steps required to build FW_PAYLOAD firmware is beyond the scope of this document. Please refer OpenSBI documenation. From ca06444aac2c643db3a3f2eb37afc60fae15177e Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:21 +0800 Subject: [PATCH 04/17] riscv: ax25: add SPL support The U-Boot SPL will boot in M mode and load the FIT image which include OpenSBI and U-Boot proper images. After loading progress, it will jump to OpenSBI first and then U-Boot proper which will run in S mode. Also remove V5L2_CACHE due to U-Boot SPL code size consideration. Without this concern, it can be enable manually for performance. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- arch/riscv/cpu/ax25/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig index d411a79c21..8d8d71dcbf 100644 --- a/arch/riscv/cpu/ax25/Kconfig +++ b/arch/riscv/cpu/ax25/Kconfig @@ -6,7 +6,9 @@ config RISCV_NDS imply RISCV_TIMER imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE) imply ANDES_PLMT if (RISCV_MMODE || SPL_RISCV_MMODE) - imply V5L2_CACHE + imply SPL_CPU_SUPPORT + imply SPL_OPENSBI + imply SPL_LOAD_FIT help Run U-Boot on AndeStar V5 platforms and use some specific features which are provided by Andes Technology AndeStar V5 families. From cd61e86e6d2a86b3affd90eeae3f5c97fe990b04 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:22 +0800 Subject: [PATCH 05/17] riscv: ax25-ae350: add SPL configuration This patch provides four configurations which can support U-Boot SPL to boot from RAM or FLASH and then boot FIT image including OpenSBI FW_DYNAMIC firmware and U-Boot proper images from RAM or MMC boot devices. With ae350_rv[32|64]_spl_defconfigs: U-Boot SPL will be loaded by gdb or FSBL and runs in RAM in machine mode and then load FIT image from RAM device on AE350. With ae350_rv[32|64]_spl_xip_defconfigs: U-Boot SPL can be burned into SPI flash and run in flash in machine mode and then load FIT image from SPI flash or MMC device on AE350. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- board/AndesTech/ax25-ae350/Kconfig | 9 ++++++ board/AndesTech/ax25-ae350/MAINTAINERS | 4 +++ board/AndesTech/ax25-ae350/ax25-ae350.c | 27 ++++++++++++++++ configs/ae350_rv32_spl_defconfig | 38 +++++++++++++++++++++++ configs/ae350_rv32_spl_xip_defconfig | 40 ++++++++++++++++++++++++ configs/ae350_rv64_spl_defconfig | 39 +++++++++++++++++++++++ configs/ae350_rv64_spl_xip_defconfig | 41 +++++++++++++++++++++++++ include/configs/ax25-ae350.h | 17 ++++++++++ 8 files changed, 215 insertions(+) create mode 100644 configs/ae350_rv32_spl_defconfig create mode 100644 configs/ae350_rv32_spl_xip_defconfig create mode 100644 configs/ae350_rv64_spl_defconfig create mode 100644 configs/ae350_rv64_spl_xip_defconfig diff --git a/board/AndesTech/ax25-ae350/Kconfig b/board/AndesTech/ax25-ae350/Kconfig index 5e682b679d..321dd0cb10 100644 --- a/board/AndesTech/ax25-ae350/Kconfig +++ b/board/AndesTech/ax25-ae350/Kconfig @@ -21,9 +21,18 @@ config ENV_SIZE config ENV_OFFSET default 0x140000 if ENV_IS_IN_SPI_FLASH +config SPL_TEXT_BASE + default 0x800000 + +config SPL_OPENSBI_LOAD_ADDR + default 0x01000000 + config BOARD_SPECIFIC_OPTIONS # dummy def_bool y select RISCV_NDS + select SUPPORT_SPL imply SMP + imply SPL_RAM_SUPPORT + imply SPL_RAM_DEVICE endif diff --git a/board/AndesTech/ax25-ae350/MAINTAINERS b/board/AndesTech/ax25-ae350/MAINTAINERS index feed5d1298..eebee167c3 100644 --- a/board/AndesTech/ax25-ae350/MAINTAINERS +++ b/board/AndesTech/ax25-ae350/MAINTAINERS @@ -7,3 +7,7 @@ F: configs/ae350_rv32_defconfig F: configs/ae350_rv64_defconfig F: configs/ae350_rv32_xip_defconfig F: configs/ae350_rv64_xip_defconfig +F: configs/ae350_rv32_spl_defconfig +F: configs/ae350_rv64_spl_defconfig +F: configs/ae350_rv32_spl_xip_defconfig +F: configs/ae350_rv64_spl_xip_defconfig diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c index b43eebb7a6..b0164a9a47 100644 --- a/board/AndesTech/ax25-ae350/ax25-ae350.c +++ b/board/AndesTech/ax25-ae350/ax25-ae350.c @@ -12,6 +12,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -110,3 +111,29 @@ int board_early_init_f(void) return 0; } #endif + +#ifdef CONFIG_SPL +void board_boot_order(u32 *spl_boot_list) +{ + u8 i; + u32 boot_devices[] = { +#ifdef CONFIG_SPL_RAM_SUPPORT + BOOT_DEVICE_RAM, +#endif +#ifdef CONFIG_SPL_MMC_SUPPORT + BOOT_DEVICE_MMC1, +#endif + }; + + for (i = 0; i < ARRAY_SIZE(boot_devices); i++) + spl_boot_list[i] = boot_devices[i]; +} +#endif + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + /* boot using first FIT config */ + return 0; +} +#endif diff --git a/configs/ae350_rv32_spl_defconfig b/configs/ae350_rv32_spl_defconfig new file mode 100644 index 0000000000..8bd6a2638b --- /dev/null +++ b/configs/ae350_rv32_spl_defconfig @@ -0,0 +1,38 @@ +CONFIG_RISCV=y +CONFIG_SPL=y +CONFIG_RISCV_SMODE=y +CONFIG_SYS_TEXT_BASE=0x01200000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_AX25_AE350=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_OF_PRIOR_STAGE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_CFI_FLASH=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x0 +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y diff --git a/configs/ae350_rv32_spl_xip_defconfig b/configs/ae350_rv32_spl_xip_defconfig new file mode 100644 index 0000000000..9c605fe907 --- /dev/null +++ b/configs/ae350_rv32_spl_xip_defconfig @@ -0,0 +1,40 @@ +CONFIG_RISCV=y +CONFIG_SPL=y +CONFIG_RISCV_SMODE=y +CONFIG_SPL_TEXT_BASE=0x80000000 +CONFIG_SYS_TEXT_BASE=0x01200000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_AX25_AE350=y +CONFIG_XIP=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_OF_BOARD=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_CFI_FLASH=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x0 +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y diff --git a/configs/ae350_rv64_spl_defconfig b/configs/ae350_rv64_spl_defconfig new file mode 100644 index 0000000000..806f327610 --- /dev/null +++ b/configs/ae350_rv64_spl_defconfig @@ -0,0 +1,39 @@ +CONFIG_RISCV=y +CONFIG_SPL=y +CONFIG_RISCV_SMODE=y +CONFIG_SYS_TEXT_BASE=0x01200000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_AX25_AE350=y +CONFIG_ARCH_RV64I=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_OF_PRIOR_STAGE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_CFI_FLASH=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x0 +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y diff --git a/configs/ae350_rv64_spl_xip_defconfig b/configs/ae350_rv64_spl_xip_defconfig new file mode 100644 index 0000000000..1bacc5f36b --- /dev/null +++ b/configs/ae350_rv64_spl_xip_defconfig @@ -0,0 +1,41 @@ +CONFIG_RISCV=y +CONFIG_SPL=y +CONFIG_RISCV_SMODE=y +CONFIG_SPL_TEXT_BASE=0x80000000 +CONFIG_SYS_TEXT_BASE=0x01200000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_AX25_AE350=y +CONFIG_ARCH_RV64I=y +CONFIG_XIP=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_OF_BOARD=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_CFI_FLASH=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x0 +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y diff --git a/include/configs/ax25-ae350.h b/include/configs/ax25-ae350.h index 5fd7a6043f..4504962171 100644 --- a/include/configs/ax25-ae350.h +++ b/include/configs/ax25-ae350.h @@ -7,6 +7,23 @@ #ifndef __CONFIG_H #define __CONFIG_H +#ifdef CONFIG_SPL +#define CONFIG_SPL_MAX_SIZE 0x00100000 +#define CONFIG_SPL_BSS_START_ADDR 0x04000000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x00100000 + +#ifndef CONFIG_XIP +#define CONFIG_SPL_LOAD_FIT_ADDRESS 0x00200000 +#else +#define CONFIG_SPL_LOAD_FIT_ADDRESS 0x80010000 +#endif + +#ifdef CONFIG_SPL_MMC_SUPPORT +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.itb" +#endif +#endif + /* * CPU and Board Configuration Options */ From 7e24518c904d9cab8185a1248a24e86c4ceb19ae Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:23 +0800 Subject: [PATCH 06/17] riscv: ax25-ae350: Use generic memory size setup To get memory size from device tree instead of get_ram_size(). This can avoid memory access fault in U-Boot proper after PMP configurations in OpenSBI. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- board/AndesTech/ax25-ae350/ax25-ae350.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c index b0164a9a47..47e6929365 100644 --- a/board/AndesTech/ax25-ae350/ax25-ae350.c +++ b/board/AndesTech/ax25-ae350/ax25-ae350.c @@ -30,29 +30,12 @@ int board_init(void) int dram_init(void) { - unsigned long sdram_base = PHYS_SDRAM_0; - unsigned long expected_size = PHYS_SDRAM_0_SIZE + PHYS_SDRAM_1_SIZE; - unsigned long actual_size; - - actual_size = get_ram_size((void *)sdram_base, expected_size); - gd->ram_size = actual_size; - - if (expected_size != actual_size) { - printf("Warning: Only %lu of %lu MiB SDRAM is working\n", - actual_size >> 20, expected_size >> 20); - } - - return 0; + return fdtdec_setup_mem_size_base(); } int dram_init_banksize(void) { - gd->bd->bi_dram[0].start = PHYS_SDRAM_0; - gd->bd->bi_dram[0].size = PHYS_SDRAM_0_SIZE; - gd->bd->bi_dram[1].start = PHYS_SDRAM_1; - gd->bd->bi_dram[1].size = PHYS_SDRAM_1_SIZE; - - return 0; + return fdtdec_setup_memory_banksize(); } #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH) From 43a0832ba09068d1ab0628afbe62e498450ece63 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:24 +0800 Subject: [PATCH 07/17] riscv: andes_plic: Fix some wrong configurations Fix two wrong settings of andes plic driver as below: 1. Fix wrong pending register base definition. 2. Declaring the en variable in enable_ipi() as unsigned int instead of int can help to fix wrong plic enabling setting in RV64. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- arch/riscv/lib/andes_plic.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index 28568e4e2b..42394b9b6e 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -19,7 +19,7 @@ #include /* pending register */ -#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + (hart) * 8) +#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + ((hart) / 4) * 4) /* enable register */ #define ENABLE_REG(base, hart) ((ulong)(base) + 0x2000 + (hart) * 0x80) /* claim register */ @@ -46,7 +46,7 @@ static int init_plic(void); static int enable_ipi(int hart) { - int en; + unsigned int en; en = ENABLE_HART_IPI >> hart; writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, hart)); @@ -94,10 +94,13 @@ static int init_plic(void) int riscv_send_ipi(int hart) { + unsigned int ipi; + PLIC_BASE_GET(); - writel(SEND_IPI_TO_HART(hart), - (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart)); + ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); + writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic, + gd->arch.boot_hart)); return 0; } From 8ba595b6bda56eac15d721554ea0ab8fc6a48f73 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:25 +0800 Subject: [PATCH 08/17] riscv: ax25: cache: Add SPL_RISCV_MMODE for SPL The mcache_ctl csr only can be manipulated in M mode. Add SPL_RISCV_MMODE for U-Boot SPL to control cache operation. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- arch/riscv/cpu/ax25/cache.c | 60 ++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/arch/riscv/cpu/ax25/cache.c b/arch/riscv/cpu/ax25/cache.c index 1455f2298f..9f424198b4 100644 --- a/arch/riscv/cpu/ax25/cache.c +++ b/arch/riscv/cpu/ax25/cache.c @@ -12,18 +12,46 @@ #include #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) /* mcctlcommand */ #define CCTL_REG_MCCTLCOMMAND_NUM 0x7cc /* D-cache operation */ #define CCTL_L1D_WBINVAL_ALL 6 #endif +#endif + +#ifdef CONFIG_V5L2_CACHE +static void _cache_enable(void) +{ + struct udevice *dev = NULL; + + uclass_find_first_device(UCLASS_CACHE, &dev); + + if (dev) + cache_enable(dev); +} + +static void _cache_disable(void) +{ + struct udevice *dev = NULL; + + uclass_find_first_device(UCLASS_CACHE, &dev); + + if (dev) + cache_disable(dev); +} +#endif void flush_dcache_all(void) { +#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL); #endif +#endif +#endif } void flush_dcache_range(unsigned long start, unsigned long end) @@ -40,6 +68,7 @@ void icache_enable(void) { #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "ori t0, t1, 0x1\n\t" @@ -47,12 +76,14 @@ void icache_enable(void) ); #endif #endif +#endif } void icache_disable(void) { #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "fence.i\n\t" "csrr t1, mcache_ctl\n\t" @@ -61,24 +92,23 @@ void icache_disable(void) ); #endif #endif +#endif } void dcache_enable(void) { #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE - struct udevice *dev = NULL; - +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "ori t0, t1, 0x2\n\t" "csrw mcache_ctl, t0\n\t" ); - - uclass_find_first_device(UCLASS_CACHE, &dev); - - if (dev) - cache_enable(dev); +#endif +#ifdef CONFIG_V5L2_CACHE + _cache_enable(); +#endif #endif #endif } @@ -87,19 +117,17 @@ void dcache_disable(void) { #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE - struct udevice *dev = NULL; - +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL); asm volatile ( "csrr t1, mcache_ctl\n\t" "andi t0, t1, ~0x2\n\t" "csrw mcache_ctl, t0\n\t" ); - - uclass_find_first_device(UCLASS_CACHE, &dev); - - if (dev) - cache_disable(dev); +#endif +#ifdef CONFIG_V5L2_CACHE + _cache_disable(); +#endif #endif #endif } @@ -109,6 +137,7 @@ int icache_status(void) int ret = 0; #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "andi %0, t1, 0x01\n\t" @@ -116,6 +145,7 @@ int icache_status(void) : : "memory" ); +#endif #endif return ret; @@ -126,6 +156,7 @@ int dcache_status(void) int ret = 0; #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "andi %0, t1, 0x02\n\t" @@ -133,6 +164,7 @@ int dcache_status(void) : : "memory" ); +#endif #endif return ret; From 31dae22faa65534cb71631f6c74cbdcf4930a339 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:26 +0800 Subject: [PATCH 09/17] spl: cache: Allow cache drivers in SPL When ax25-ae350 try to enable v5l2 cache driver in SPL configuration, it need this option for cache support in SPL. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- common/spl/Kconfig | 7 +++++++ drivers/Makefile | 1 + 2 files changed, 8 insertions(+) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index c8cb715c3a..a72412718b 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -439,6 +439,13 @@ config SPL_FIT_IMAGE_TINY ensure this information is available to the next image invoked). +config SPL_CACHE_SUPPORT + bool "Support CACHE drivers" + help + Enable CACHE drivers in SPL. These drivers can keep data so that + future requests for that data can be served faster. Enable this option + to build the drivers in drivers/cache as part of an SPL build. + config SPL_CPU_SUPPORT bool "Support CPU drivers" help diff --git a/drivers/Makefile b/drivers/Makefile index 0d1d6bd851..e977f19af6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -30,6 +30,7 @@ ifndef CONFIG_TPL_BUILD ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/ +obj-$(CONFIG_SPL_CACHE_SUPPORT) += cache/ obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/ obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/ obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/ From 444c46413fb691c7abbb2bec3ed498ab08fa36f8 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:27 +0800 Subject: [PATCH 10/17] riscv: Fix clear bss loop in the start-up code For RV64, it will use sd instruction to clear t0 register, and the increament will be 8 bytes. So if the difference between__bss_strat and __bss_end was not 8 bytes aligned, the clear bss loop will overflow and acks like system hang. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- arch/riscv/cpu/start.S | 4 ++-- arch/riscv/cpu/u-boot-spl.lds | 2 +- arch/riscv/cpu/u-boot.lds | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 0a2ce6d691..ee6d4717da 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -174,7 +174,7 @@ spl_clear_bss: spl_clear_bss_loop: SREG zero, 0(t0) addi t0, t0, REGBYTES - bne t0, t1, spl_clear_bss_loop + blt t0, t1, spl_clear_bss_loop spl_stack_gd_setup: jal spl_relocate_stack_gd @@ -324,7 +324,7 @@ clear_bss: clbss_l: SREG zero, 0(t0) /* clear loop... */ addi t0, t0, REGBYTES - bne t0, t1, clbss_l + blt t0, t1, clbss_l relocate_secondary_harts: #ifdef CONFIG_SMP diff --git a/arch/riscv/cpu/u-boot-spl.lds b/arch/riscv/cpu/u-boot-spl.lds index 32255d58de..955dd3106d 100644 --- a/arch/riscv/cpu/u-boot-spl.lds +++ b/arch/riscv/cpu/u-boot-spl.lds @@ -76,7 +76,7 @@ SECTIONS .bss : { __bss_start = .; *(.bss*) - . = ALIGN(4); + . = ALIGN(8); __bss_end = .; } > .bss_mem } diff --git a/arch/riscv/cpu/u-boot.lds b/arch/riscv/cpu/u-boot.lds index 11bc4a738b..838a844399 100644 --- a/arch/riscv/cpu/u-boot.lds +++ b/arch/riscv/cpu/u-boot.lds @@ -82,7 +82,7 @@ SECTIONS .bss : { __bss_start = .; *(.bss*) - . = ALIGN(4); + . = ALIGN(8); __bss_end = .; } } From f05b6569a936af61a4d448ddc899e7b8c0e5b3c8 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:28 +0800 Subject: [PATCH 11/17] riscv: dts: Support four cores SMP Add CPU2 and CPU3 information in cpus node to support four cores SMP booting. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- arch/riscv/dts/ae350_32.dts | 57 +++++++++++++++++++++++++++++++++++-- arch/riscv/dts/ae350_64.dts | 57 +++++++++++++++++++++++++++++++++++-- 2 files changed, 108 insertions(+), 6 deletions(-) diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts index 97b7cee983..c6c2040d31 100644 --- a/arch/riscv/dts/ae350_32.dts +++ b/arch/riscv/dts/ae350_32.dts @@ -62,6 +62,48 @@ compatible = "riscv,cpu-intc"; }; }; + CPU2: cpu@2 { + device_type = "cpu"; + reg = <2>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv32imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv32"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-line-size = <32>; + d-cache-size = <0x8000>; + d-cache-line-size = <32>; + next-level-cache = <&L2>; + CPU2_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU3: cpu@3 { + device_type = "cpu"; + reg = <3>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv32imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv32"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-line-size = <32>; + d-cache-size = <0x8000>; + d-cache-line-size = <32>; + next-level-cache = <&L2>; + CPU3_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; }; L2: l2-cache@e0500000 { @@ -94,7 +136,10 @@ interrupt-controller; reg = <0xe4000000 0x2000000>; riscv,ndev=<71>; - interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>; + interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 + &CPU1_intc 11 &CPU1_intc 9 + &CPU2_intc 11 &CPU2_intc 9 + &CPU3_intc 11 &CPU3_intc 9>; }; plic1: interrupt-controller@e6400000 { @@ -104,12 +149,18 @@ interrupt-controller; reg = <0xe6400000 0x400000>; riscv,ndev=<2>; - interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>; + interrupts-extended = <&CPU0_intc 3 + &CPU1_intc 3 + &CPU2_intc 3 + &CPU3_intc 3>; }; plmt0@e6000000 { compatible = "riscv,plmt0"; - interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>; + interrupts-extended = <&CPU0_intc 7 + &CPU1_intc 7 + &CPU2_intc 7 + &CPU3_intc 7>; reg = <0xe6000000 0x100000>; }; }; diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts index d8f00f8d3a..c57efe3f2d 100644 --- a/arch/riscv/dts/ae350_64.dts +++ b/arch/riscv/dts/ae350_64.dts @@ -62,6 +62,48 @@ compatible = "riscv,cpu-intc"; }; }; + CPU2: cpu@2 { + device_type = "cpu"; + reg = <2>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv39"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-line-size = <32>; + d-cache-size = <0x8000>; + d-cache-line-size = <32>; + next-level-cache = <&L2>; + CPU2_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU3: cpu@3 { + device_type = "cpu"; + reg = <3>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv39"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-line-size = <32>; + d-cache-size = <0x8000>; + d-cache-line-size = <32>; + next-level-cache = <&L2>; + CPU3_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; }; L2: l2-cache@e0500000 { @@ -94,7 +136,10 @@ interrupt-controller; reg = <0x0 0xe4000000 0x0 0x2000000>; riscv,ndev=<71>; - interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>; + interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 + &CPU1_intc 11 &CPU1_intc 9 + &CPU2_intc 11 &CPU2_intc 9 + &CPU3_intc 11 &CPU3_intc 9>; }; plic1: interrupt-controller@e6400000 { @@ -104,12 +149,18 @@ interrupt-controller; reg = <0x0 0xe6400000 0x0 0x400000>; riscv,ndev=<2>; - interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>; + interrupts-extended = <&CPU0_intc 3 + &CPU1_intc 3 + &CPU2_intc 3 + &CPU3_intc 3>; }; plmt0@e6000000 { compatible = "riscv,plmt0"; - interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>; + interrupts-extended = <&CPU0_intc 7 + &CPU1_intc 7 + &CPU2_intc 7 + &CPU3_intc 7>; reg = <0x0 0xe6000000 0x0 0x100000>; }; }; From cca8b1e5b20cdab7299a5ee7139e70783f73ccdf Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:29 +0800 Subject: [PATCH 12/17] riscv: dts: Add #address-cells and #size-cells in nor node Those are required for cfi-flash driver to get correct address information. Also modify size description correctly. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- arch/riscv/dts/ae350_32.dts | 4 +++- arch/riscv/dts/ae350_64.dts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts index c6c2040d31..3f8525fe56 100644 --- a/arch/riscv/dts/ae350_32.dts +++ b/arch/riscv/dts/ae350_32.dts @@ -296,8 +296,10 @@ }; nor@0,0 { + #address-cells = <1>; + #size-cells = <1>; compatible = "cfi-flash"; - reg = <0x88000000 0x1000>; + reg = <0x88000000 0x4000000>; bank-width = <2>; device-width = <1>; }; diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts index c57efe3f2d..482c707503 100644 --- a/arch/riscv/dts/ae350_64.dts +++ b/arch/riscv/dts/ae350_64.dts @@ -296,8 +296,10 @@ }; nor@0,0 { + #address-cells = <2>; + #size-cells = <2>; compatible = "cfi-flash"; - reg = <0x0 0x88000000 0x0 0x1000>; + reg = <0x0 0x88000000 0x0 0x4000000>; bank-width = <2>; device-width = <1>; }; From 04883bf7acca36fce8908c2a1c0f8377b10456e5 Mon Sep 17 00:00:00 2001 From: Rick Chen Date: Thu, 14 Nov 2019 13:52:30 +0800 Subject: [PATCH 13/17] doc: update AX25-AE350 RISC-V documentation Add descriptions about U-Boot SPL feature and how to build and run. Signed-off-by: Rick Chen Cc: KC Lin Cc: Alan Kao --- doc/board/AndesTech/ax25-ae350.rst | 209 ++++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 3 deletions(-) diff --git a/doc/board/AndesTech/ax25-ae350.rst b/doc/board/AndesTech/ax25-ae350.rst index 7a0189382d..a7bd1a75e8 100644 --- a/doc/board/AndesTech/ax25-ae350.rst +++ b/doc/board/AndesTech/ax25-ae350.rst @@ -324,6 +324,209 @@ Boot bbl and riscv-linux via U-Boot on QEMU / # -TODO ----- -Boot bbl and riscv-linux via U-Boot on AE350 board +Running U-Boot SPL +------------------ +The U-Boot SPL will boot in M mode and load the FIT image which include +OpenSBI and U-Boot proper images. After loading progress, it will jump +to OpenSBI first and then U-Boot proper which will run in S mode. + + +How to build U-Boot SPL +----------------------- +Before building U-Boot SPL, OpenSBI must be build first. OpenSBI can be +cloned and build for AE350 as below: + +git clone https://github.com/riscv/opensbi.git +cd opensbi +make PLATFORM=andes/ae350 + +Copy OpenSBI FW_DYNAMIC image (build\platform\andes\ae350\firmware\fw_dynamic.bin) +into U-Boot root directory + + +How to build U-Boot SPL booting from RAM +---------------------------------------- +With ae350_rv[32|64]_spl_defconfigs: + +U-Boot SPL will be loaded by gdb or FSBL and runs in RAM in machine mode +and then load FIT image from RAM device on AE350. + + +How to build U-Boot SPL booting from ROM +---------------------------------------- +With ae350_rv[32|64]_spl_xip_defconfigs: + +U-Boot SPL can be burned into SPI flash and run in flash in machine mode +and then load FIT image from SPI flash or MMC device on AE350. + + +Messages of U-Boot SPL boots Kernel on AE350 board +-------------------------------------------------- + +.. code-block:: none + +U-Boot SPL 2020.01-rc1-00292-g67a3313-dirty (Nov 14 2019 - 11:26:21 +0800) +Trying to boot from RAM + +OpenSBI v0.5-1-gdd8ef28 (Nov 14 2019 11:08:39) + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + +Platform Name : Andes AE350 +Platform HART Features : RV64ACIMSUX +Platform Max HARTs : 4 +Current Hart : 0 +Firmware Base : 0x0 +Firmware Size : 84 KB +Runtime SBI Version : 0.2 + +PMP0: 0x0000000000000000-0x000000000001ffff (A) +PMP1: 0x0000000000000000-0x00000001ffffffff (A,R,W,X) + + +U-Boot 2020.01-rc1-00292-g67a3313-dirty (Nov 14 2019 - 11:26:21 +0800) + +DRAM: 1 GiB +Flash: 64 MiB +MMC: mmc@f0e00000: 0 +Loading Environment from SPI Flash... SF: Detected mx25u1635e with page size 256 Bytes, erase size 4 KiB, total 2 MiB +OK +In: serial@f0300000 +Out: serial@f0300000 +Err: serial@f0300000 +Net: no alias for ethernet0 + +Warning: mac@e0100000 (eth0) using random MAC address - a2:ae:93:7b:cc:8f +eth0: mac@e0100000 +Hit any key to stop autoboot: 0 +6455 bytes read in 31 ms (203.1 KiB/s) +20421684 bytes read in 8647 ms (2.3 MiB/s) +## Booting kernel from Legacy Image at 00600000 ... + Image Name: + Image Type: RISC-V Linux Kernel Image (uncompressed) + Data Size: 20421620 Bytes = 19.5 MiB + Load Address: 00200000 + Entry Point: 00200000 + Verifying Checksum ... OK +## Flattened Device Tree blob at 20000000 + Booting using the fdt blob at 0x20000000 + Loading Kernel Image + Loading Device Tree to 000000001effb000, end 000000001efff936 ... OK + +Starting kernel ... + +OF: fdt: Ignoring memory range 0x0 - 0x200000 +Linux version 4.17.0-00253-g49136e10bcb2 (sqa@atcsqa07) (gcc version 7.3.0 (2019-04-06_nds64le-linux-glibc-v5_experimental)) #1 SMP PREEMPT Sat Apr 6 23:41:49 CST 2019 +bootconsole [early0] enabled +Initial ramdisk at: 0x (ptrval) (13665712 bytes) +Zone ranges: + DMA32 [mem 0x0000000000200000-0x000000003fffffff] + Normal empty +Movable zone start for each node +Early memory node ranges + node 0: [mem 0x0000000000200000-0x000000003fffffff] +Initmem setup node 0 [mem 0x0000000000200000-0x000000003fffffff] +software IO TLB [mem 0x3b1f8000-0x3f1f8000] (64MB) mapped at [ (ptrval)- (ptrval)] +elf_platform is rv64i2p0m2p0a2p0c2p0xv5-0p0 +compatible privileged spec version 1.10 +percpu: Embedded 16 pages/cpu @ (ptrval) s28184 r8192 d29160 u65536 +Built 1 zonelists, mobility grouping on. Total pages: 258055 +Kernel command line: console=ttyS0,38400n8 debug loglevel=7 +log_buf_len individual max cpu contribution: 4096 bytes +log_buf_len total cpu_extra contributions: 12288 bytes +log_buf_len min size: 16384 bytes +log_buf_len: 32768 bytes +early log buf free: 14608(89%) +Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes) +Inode-cache hash table entries: 65536 (order: 7, 524288 bytes) +Sorting __ex_table... +Memory: 944428K/1046528K available (3979K kernel code, 246K rwdata, 1490K rodata, 13523K init, 688K bss, 102100K reserved, 0K cma-reserved) +SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1 +Preemptible hierarchical RCU implementation. + Tasks RCU enabled. +NR_IRQS: 72, nr_irqs: 72, preallocated irqs: 0 +riscv,cpu_intc,0: 64 local interrupts mapped +riscv,cpu_intc,1: 64 local interrupts mapped +riscv,cpu_intc,2: 64 local interrupts mapped +riscv,cpu_intc,3: 64 local interrupts mapped +riscv,plic0,e4000000: mapped 71 interrupts to 8/8 handlers +clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1bacf917bf, max_idle_ns: 881590412290 ns +sched_clock: 64 bits at 60MHz, resolution 16ns, wraps every 4398046511098ns +Console: colour dummy device 40x30 +Calibrating delay loop (skipped), value calculated using timer frequency.. 120.00 BogoMIPS (lpj=600000) +pid_max: default: 32768 minimum: 301 +Mount-cache hash table entries: 2048 (order: 2, 16384 bytes) +Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes) +Hierarchical SRCU implementation. +smp: Bringing up secondary CPUs ... +CPU0: online +CPU2: online +CPU3: online +smp: Brought up 1 node, 4 CPUs +devtmpfs: initialized +random: get_random_u32 called from bucket_table_alloc+0x198/0x1d8 with crng_init=0 +clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns +futex hash table entries: 1024 (order: 4, 65536 bytes) +NET: Registered protocol family 16 +Advanced Linux Sound Architecture Driver Initialized. +clocksource: Switched to clocksource riscv_clocksource +NET: Registered protocol family 2 +tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes) +TCP established hash table entries: 8192 (order: 4, 65536 bytes) +TCP bind hash table entries: 8192 (order: 5, 131072 bytes) +TCP: Hash tables configured (established 8192 bind 8192) +UDP hash table entries: 512 (order: 2, 16384 bytes) +UDP-Lite hash table entries: 512 (order: 2, 16384 bytes) +NET: Registered protocol family 1 +RPC: Registered named UNIX socket transport module. +RPC: Registered udp transport module. +RPC: Registered tcp transport module. +RPC: Registered tcp NFSv4.1 backchannel transport module. +Unpacking initramfs... +workingset: timestamp_bits=62 max_order=18 bucket_order=0 +NFS: Registering the id_resolver key type +Key type id_resolver registered +Key type id_legacy registered +nfs4filelayout_init: NFSv4 File Layout Driver Registering... +io scheduler noop registered +io scheduler cfq registered (default) +io scheduler mq-deadline registered +io scheduler kyber registered +Console: switching to colour frame buffer device 40x30 +Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled +console [ttyS0] disabled +f0300000.serial: ttyS0 at MMIO 0xf0300020 (irq = 20, base_baud = 1228800) is a 16550A +console [ttyS0] enabled +console [ttyS0] enabled +bootconsole [early0] disabled +bootconsole [early0] disabled +loop: module loaded +tun: Universal TUN/TAP device driver, 1.6 +ftmac100: Loading version 0.2 ... +ftmac100 e0100000.mac eth0: irq 21, mapped at (ptrval) +ftmac100 e0100000.mac eth0: generated random MAC address 4e:fd:bd:f3:04:fc +ftsdc010 f0e00000.mmc: mmc0 - using hw SDIO IRQ +mmc0: new SDHC card at address d555 +ftssp010 card registered! +mmcblk0: mmc0:d555 SD04G 3.79 GiB +NET: Registered protocol family 10 + mmcblk0: p1 +Segment Routing with IPv6 +sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver +NET: Registered protocol family 17 +NET: Registered protocol family 15 +ALSA device list: + #0: ftssp_ac97 controller +Freeing unused kernel memory: 13520K +This architecture does not have kernel memory protection. +Sysinit starting +Sat Apr 6 23:33:53 CST 2019 +nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering... + +~ # From b86f6d1e649f237849297b5ec6b5566b7a92b2b4 Mon Sep 17 00:00:00 2001 From: Lukas Auer Date: Sun, 8 Dec 2019 23:28:49 +0100 Subject: [PATCH 14/17] spl: opensbi: specify main hart as preferred boot hart OpenSBI uses a relocation lottery to determine the hart to relocate OpenSBI to its link address. In the U-Boot SPL boot flow, the main hart schedules the secondary harts to enter OpenSBI before doing so itself. One of the secondary harts will therefore always be the winner of the relocation lottery. This is problematic if the link address ranges of OpenSBI and U-Boot SPL overlap. OpenSBI will be relocated and therefore overwrite U-Boot SPL while some harts may still run it, leading to code corruption. Avoid this problem by specifying the main hart as the preferred boot hart to perform the OpenSBI relocation. The main hart will be the last hart to enter OpenSBI, relocation can therefore occur safely. The boot hart field was added to version 2 of the OpenSBI FW_DYNAMIC info structure. The header file include/opensbi.h is synchronized with include/sbi/fw_dynamic.h from the OpenSBI project to update the info structure. The header file is recent as of commit 7a13beb21326 ("firmware: Add preferred boot HART field in struct fw_dynamic_info"). Reported-by: Rick Chen Suggested-by: Anup Patel Signed-off-by: Lukas Auer Reviewed-by: Rick Chen Tested-by: Rick Chen Reviewed-by: Anup Patel --- common/spl/spl_opensbi.c | 1 + include/opensbi.h | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c index 2345f949f0..fed41b1e66 100644 --- a/common/spl/spl_opensbi.c +++ b/common/spl/spl_opensbi.c @@ -70,6 +70,7 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) opensbi_info.next_addr = uboot_entry; opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S; opensbi_info.options = SBI_SCRATCH_NO_BOOT_PRINTS; + opensbi_info.boot_hart = gd->arch.boot_hart; opensbi_entry = (void (*)(ulong, ulong, ulong))spl_image->entry_point; invalidate_icache_all(); diff --git a/include/opensbi.h b/include/opensbi.h index 9f1d62e7dd..d812cc8ccd 100644 --- a/include/opensbi.h +++ b/include/opensbi.h @@ -11,7 +11,7 @@ #define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f /** Maximum supported info version */ -#define FW_DYNAMIC_INFO_VERSION 0x1 +#define FW_DYNAMIC_INFO_VERSION 0x2 /** Possible next mode values */ #define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0 @@ -35,6 +35,22 @@ struct fw_dynamic_info { unsigned long next_mode; /** Options for OpenSBI library */ unsigned long options; + /** + * Preferred boot HART id + * + * It is possible that the previous booting stage uses same link + * address as the FW_DYNAMIC firmware. In this case, the relocation + * lottery mechanism can potentially overwrite the previous booting + * stage while other HARTs are still running in the previous booting + * stage leading to boot-time crash. To avoid this boot-time crash, + * the previous booting stage can specify last HART that will jump + * to the FW_DYNAMIC firmware as the preferred boot HART. + * + * To avoid specifying a preferred boot HART, the previous booting + * stage can set it to -1UL which will force the FW_DYNAMIC firmware + * to use the relocation lottery mechanism. + */ + unsigned long boot_hart; } __packed; #endif From 8b3e97badf97d6e399014fb4a152031f8a0c94ba Mon Sep 17 00:00:00 2001 From: Lukas Auer Date: Sun, 8 Dec 2019 23:28:50 +0100 Subject: [PATCH 15/17] riscv: add functions for reading the IPI status Add the function riscv_get_ipi() for reading the pending status of IPIs. The supported controllers are Andes' Platform Level Interrupt Controller (PLIC), the Supervisor Binary Interface (SBI), and SiFive's Core Local Interruptor (CLINT). Signed-off-by: Lukas Auer Reviewed-by: Rick Chen --- arch/riscv/lib/andes_plic.c | 11 +++++++++++ arch/riscv/lib/sbi_ipi.c | 11 +++++++++++ arch/riscv/lib/sifive_clint.c | 9 +++++++++ arch/riscv/lib/smp.c | 12 ++++++++++++ 4 files changed, 43 insertions(+) diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index 42394b9b6e..3868569a65 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -117,6 +117,17 @@ int riscv_clear_ipi(int hart) return 0; } +int riscv_get_ipi(int hart, int *pending) +{ + PLIC_BASE_GET(); + + *pending = readl((void __iomem *)PENDING_REG(gd->arch.plic, + gd->arch.boot_hart)); + *pending = !!(*pending & SEND_IPI_TO_HART(hart)); + + return 0; +} + static const struct udevice_id andes_plic_ids[] = { { .compatible = "riscv,plic1", .data = RISCV_SYSCON_PLIC }, { } diff --git a/arch/riscv/lib/sbi_ipi.c b/arch/riscv/lib/sbi_ipi.c index 170346da68..9a698ce74e 100644 --- a/arch/riscv/lib/sbi_ipi.c +++ b/arch/riscv/lib/sbi_ipi.c @@ -23,3 +23,14 @@ int riscv_clear_ipi(int hart) return 0; } + +int riscv_get_ipi(int hart, int *pending) +{ + /* + * The SBI does not support reading the IPI status. We always return 0 + * to indicate that no IPI is pending. + */ + *pending = 0; + + return 0; +} diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/sifive_clint.c index d24e0d585b..d7899d16d7 100644 --- a/arch/riscv/lib/sifive_clint.c +++ b/arch/riscv/lib/sifive_clint.c @@ -71,6 +71,15 @@ int riscv_clear_ipi(int hart) return 0; } +int riscv_get_ipi(int hart, int *pending) +{ + CLINT_BASE_GET(); + + *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); + + return 0; +} + static const struct udevice_id sifive_clint_ids[] = { { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT }, { } diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c index 705437862a..188a7e34bd 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -32,6 +32,18 @@ extern int riscv_send_ipi(int hart); */ extern int riscv_clear_ipi(int hart); +/** + * riscv_get_ipi() - Get status of inter-processor interrupt (IPI) + * + * Platform code must provide this function. + * + * @hart: Hart ID of hart to be checked + * @pending: Pointer to variable with result of the check, + * 1 if IPI is pending, 0 otherwise + * @return 0 if OK, -ve on error + */ +extern int riscv_get_ipi(int hart, int *pending); + static int send_ipi_many(struct ipi_data *ipi) { ofnode node, cpus; From 90ae28143700bae4edd23930a7772899ad259058 Mon Sep 17 00:00:00 2001 From: Lukas Auer Date: Sun, 8 Dec 2019 23:28:51 +0100 Subject: [PATCH 16/17] riscv: add option to wait for ack from secondary harts in smp functions Add a wait option to smp_call_function() to wait for the secondary harts to acknowledge the call-function request. The request is considered to be acknowledged once each secondary hart has cleared the corresponding IPI. As part of the call-function request, the secondary harts invalidate the instruction cache after clearing the IPI. This adds a delay between acknowledgment (clear IPI) and fulfillment (call function) of the request. We want to use the acknowledgment to be able to judge when the request has been completed. Remove the delay by clearing the IPI after cache invalidation and just before calling the function from the request. Signed-off-by: Lukas Auer Reviewed-by: Rick Chen Tested-by: Rick Chen Reviewed-by: Anup Patel --- arch/riscv/cpu/start.S | 2 ++ arch/riscv/include/asm/smp.h | 3 ++- arch/riscv/lib/bootm.c | 2 +- arch/riscv/lib/smp.c | 31 ++++++++++++++++++++++--------- arch/riscv/lib/spl.c | 2 +- common/spl/spl_opensbi.c | 2 +- 6 files changed, 29 insertions(+), 13 deletions(-) diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index ee6d4717da..1a55b7d570 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -197,6 +197,7 @@ spl_secondary_hart_stack_gd_setup: la a0, secondary_hart_relocate mv a1, s0 mv a2, s0 + mv a3, zero jal smp_call_function /* hang if relocation of secondary harts has failed */ @@ -337,6 +338,7 @@ relocate_secondary_harts: mv a1, s2 mv a2, s3 + mv a3, zero jal smp_call_function /* hang if relocation of secondary harts has failed */ diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index bc863fdbaf..74de92ed13 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -46,8 +46,9 @@ void handle_ipi(ulong hart); * @addr: Address of function * @arg0: First argument of function * @arg1: Second argument of function + * @wait: Wait for harts to acknowledge request * @return 0 if OK, -ve on error */ -int smp_call_function(ulong addr, ulong arg0, ulong arg1); +int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait); #endif diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index efbd3e23e7..e96137a50c 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -99,7 +99,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) { #ifdef CONFIG_SMP ret = smp_call_function(images->ep, - (ulong)images->ft_addr, 0); + (ulong)images->ft_addr, 0, 0); if (ret) hang(); #endif diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c index 188a7e34bd..17adb35730 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -44,11 +44,11 @@ extern int riscv_clear_ipi(int hart); */ extern int riscv_get_ipi(int hart, int *pending); -static int send_ipi_many(struct ipi_data *ipi) +static int send_ipi_many(struct ipi_data *ipi, int wait) { ofnode node, cpus; u32 reg; - int ret; + int ret, pending; cpus = ofnode_path("/cpus"); if (!ofnode_valid(cpus)) { @@ -91,6 +91,15 @@ static int send_ipi_many(struct ipi_data *ipi) pr_err("Cannot send IPI to hart %d\n", reg); return ret; } + + if (wait) { + pending = 1; + while (pending) { + ret = riscv_get_ipi(reg, &pending); + if (ret) + return ret; + } + } } return 0; @@ -104,21 +113,25 @@ void handle_ipi(ulong hart) if (hart >= CONFIG_NR_CPUS) return; + __smp_mb(); + + smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr; + invalidate_icache_all(); + + /* + * Clear the IPI to acknowledge the request before jumping to the + * requested function. + */ ret = riscv_clear_ipi(hart); if (ret) { pr_err("Cannot clear IPI of hart %ld\n", hart); return; } - __smp_mb(); - - smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr; - invalidate_icache_all(); - smp_function(hart, gd->arch.ipi[hart].arg0, gd->arch.ipi[hart].arg1); } -int smp_call_function(ulong addr, ulong arg0, ulong arg1) +int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait) { int ret = 0; struct ipi_data ipi; @@ -127,7 +140,7 @@ int smp_call_function(ulong addr, ulong arg0, ulong arg1) ipi.arg0 = arg0; ipi.arg1 = arg1; - ret = send_ipi_many(&ipi); + ret = send_ipi_many(&ipi, wait); return ret; } diff --git a/arch/riscv/lib/spl.c b/arch/riscv/lib/spl.c index a544df0a2b..dc7577f751 100644 --- a/arch/riscv/lib/spl.c +++ b/arch/riscv/lib/spl.c @@ -41,7 +41,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) debug("image entry point: 0x%lX\n", spl_image->entry_point); #ifdef CONFIG_SMP - ret = smp_call_function(spl_image->entry_point, (ulong)fdt_blob, 0); + ret = smp_call_function(spl_image->entry_point, (ulong)fdt_blob, 0, 0); if (ret) hang(); #endif diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c index fed41b1e66..58bf2468ce 100644 --- a/common/spl/spl_opensbi.c +++ b/common/spl/spl_opensbi.c @@ -78,7 +78,7 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) #ifdef CONFIG_SMP ret = smp_call_function((ulong)spl_image->entry_point, (ulong)spl_image->fdt_addr, - (ulong)&opensbi_info); + (ulong)&opensbi_info, 0); if (ret) hang(); #endif From 0e1233ce9069a87a84a4385de456665d2bc9229d Mon Sep 17 00:00:00 2001 From: Lukas Auer Date: Sun, 8 Dec 2019 23:28:52 +0100 Subject: [PATCH 17/17] spl: opensbi: wait for ack from secondary harts before entering OpenSBI At the start, OpenSBI relocates itself to its link address. If the link address ranges of U-Boot SPL and OpenSBI overlap, the relocation can lead to code corruption if a hart is still running U-Boot SPL during relocation. To avoid this problem, the main hart is specified as the preferred boot hart to perform the relocation. This fixes the code corruption problems based on the assumption that since the main hart schedules the secondary harts to enter OpenSBI, it will be the last to enter OpenSBI. However it was reported that this assumption is not always correct. To make sure the assumption always holds true, wait for all secondary harts to acknowledge the call-function request before entering OpenSBI on the main hart. Reported-by: Rick Chen Signed-off-by: Lukas Auer Reviewed-by: Rick Chen Tested-by: Rick Chen Reviewed-by: Anup Patel --- common/spl/spl_opensbi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c index 58bf2468ce..6404373eca 100644 --- a/common/spl/spl_opensbi.c +++ b/common/spl/spl_opensbi.c @@ -76,9 +76,19 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) invalidate_icache_all(); #ifdef CONFIG_SMP + /* + * Start OpenSBI on all secondary harts and wait for acknowledgment. + * + * OpenSBI first relocates itself to its link address. This is done by + * the main hart. To make sure no hart is still running U-Boot SPL + * during relocation, we wait for all secondary harts to acknowledge + * the call-function request before entering OpenSBI on the main hart. + * Otherwise, code corruption can occur if the link address ranges of + * U-Boot SPL and OpenSBI overlap. + */ ret = smp_call_function((ulong)spl_image->entry_point, (ulong)spl_image->fdt_addr, - (ulong)&opensbi_info, 0); + (ulong)&opensbi_info, 1); if (ret) hang(); #endif