diff options
author | Tom Rini <trini@konsulko.com> | 2019-12-09 21:53:23 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2019-12-09 21:53:23 -0500 |
commit | 520f9559020894950d4e962aba52220c8a1d6bfe (patch) | |
tree | f39b28ef809b2cd4236803e9e1d7f98c97f0dbd5 /arch | |
parent | 1045ff4d1af9e3e8a2ad4cf04a7263d49e90cfa7 (diff) | |
parent | 0e1233ce9069a87a84a4385de456665d2bc9229d (diff) | |
download | u-boot-520f9559020894950d4e962aba52220c8a1d6bfe.tar.gz u-boot-520f9559020894950d4e962aba52220c8a1d6bfe.tar.bz2 u-boot-520f9559020894950d4e962aba52220c8a1d6bfe.zip |
Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-riscv
- Increase stack size to avoid a stack overflow during distro boot.
- Add hifive-unleashed-a00.dts for SIFIVE FU540.
- Add OF_SEPARATE support for SIFIVE FU540.
- Add SPL support for Andes AX25 AE350.
- Improve U-Boot SPL / OpenSBI smp boot flow for RISC-V.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/riscv/Kconfig | 2 | ||||
-rw-r--r-- | arch/riscv/cpu/ax25/Kconfig | 4 | ||||
-rw-r--r-- | arch/riscv/cpu/ax25/cache.c | 60 | ||||
-rw-r--r-- | arch/riscv/cpu/start.S | 6 | ||||
-rw-r--r-- | arch/riscv/cpu/u-boot-spl.lds | 2 | ||||
-rw-r--r-- | arch/riscv/cpu/u-boot.lds | 2 | ||||
-rw-r--r-- | arch/riscv/dts/Makefile | 1 | ||||
-rw-r--r-- | arch/riscv/dts/ae350_32.dts | 61 | ||||
-rw-r--r-- | arch/riscv/dts/ae350_64.dts | 61 | ||||
-rw-r--r-- | arch/riscv/dts/fu540-c000.dtsi | 251 | ||||
-rw-r--r-- | arch/riscv/dts/hifive-unleashed-a00.dts | 96 | ||||
-rw-r--r-- | arch/riscv/include/asm/smp.h | 3 | ||||
-rw-r--r-- | arch/riscv/lib/andes_plic.c | 22 | ||||
-rw-r--r-- | arch/riscv/lib/bootm.c | 2 | ||||
-rw-r--r-- | arch/riscv/lib/sbi_ipi.c | 11 | ||||
-rw-r--r-- | arch/riscv/lib/sifive_clint.c | 9 | ||||
-rw-r--r-- | arch/riscv/lib/smp.c | 43 | ||||
-rw-r--r-- | arch/riscv/lib/spl.c | 2 |
18 files changed, 594 insertions, 44 deletions
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" 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. 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 <asm/csr.h> #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) /* mcctlcommand */ #define CCTL_REG_MCCTLCOMMAND_NUM 0x7cc /* D-cache operation */ #define CCTL_L1D_WBINVAL_ALL 6 #endif +#endif + +#ifdef CONFIG_V5L2_CACHE +static void _cache_enable(void) +{ + struct udevice *dev = NULL; + + uclass_find_first_device(UCLASS_CACHE, &dev); + + if (dev) + cache_enable(dev); +} + +static void _cache_disable(void) +{ + struct udevice *dev = NULL; + + uclass_find_first_device(UCLASS_CACHE, &dev); + + if (dev) + cache_disable(dev); +} +#endif void flush_dcache_all(void) { +#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL); #endif +#endif +#endif } void flush_dcache_range(unsigned long start, unsigned long end) @@ -40,6 +68,7 @@ void icache_enable(void) { #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "ori t0, t1, 0x1\n\t" @@ -47,12 +76,14 @@ void icache_enable(void) ); #endif #endif +#endif } void icache_disable(void) { #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "fence.i\n\t" "csrr t1, mcache_ctl\n\t" @@ -61,24 +92,23 @@ void icache_disable(void) ); #endif #endif +#endif } void dcache_enable(void) { #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE - struct udevice *dev = NULL; - +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "ori t0, t1, 0x2\n\t" "csrw mcache_ctl, t0\n\t" ); - - uclass_find_first_device(UCLASS_CACHE, &dev); - - if (dev) - cache_enable(dev); +#endif +#ifdef CONFIG_V5L2_CACHE + _cache_enable(); +#endif #endif #endif } @@ -87,19 +117,17 @@ void dcache_disable(void) { #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE - struct udevice *dev = NULL; - +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL); asm volatile ( "csrr t1, mcache_ctl\n\t" "andi t0, t1, ~0x2\n\t" "csrw mcache_ctl, t0\n\t" ); - - uclass_find_first_device(UCLASS_CACHE, &dev); - - if (dev) - cache_disable(dev); +#endif +#ifdef CONFIG_V5L2_CACHE + _cache_disable(); +#endif #endif #endif } @@ -109,6 +137,7 @@ int icache_status(void) int ret = 0; #ifdef CONFIG_RISCV_NDS_CACHE +#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE) asm volatile ( "csrr t1, mcache_ctl\n\t" "andi %0, t1, 0x01\n\t" @@ -117,6 +146,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" @@ -134,6 +165,7 @@ int dcache_status(void) : "memory" ); #endif +#endif return ret; } diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 0a2ce6d691..1a55b7d570 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 @@ -197,6 +197,7 @@ spl_secondary_hart_stack_gd_setup: la a0, secondary_hart_relocate mv a1, s0 mv a2, s0 + mv a3, zero jal smp_call_function /* hang if relocation of secondary harts has failed */ @@ -324,7 +325,7 @@ clear_bss: clbss_l: SREG zero, 0(t0) /* clear loop... */ addi t0, t0, REGBYTES - bne t0, t1, clbss_l + blt t0, t1, clbss_l relocate_secondary_harts: #ifdef CONFIG_SMP @@ -337,6 +338,7 @@ relocate_secondary_harts: mv a1, s2 mv a2, s3 + mv a3, zero jal smp_call_function /* hang if relocation of secondary harts has failed */ 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 = .; } } 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/ae350_32.dts b/arch/riscv/dts/ae350_32.dts index 97b7cee983..3f8525fe56 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>; }; }; @@ -245,8 +296,10 @@ }; nor@0,0 { + #address-cells = <1>; + #size-cells = <1>; compatible = "cfi-flash"; - reg = <0x88000000 0x1000>; + reg = <0x88000000 0x4000000>; bank-width = <2>; device-width = <1>; }; diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts index d8f00f8d3a..482c707503 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>; }; }; @@ -245,8 +296,10 @@ }; nor@0,0 { + #address-cells = <2>; + #size-cells = <2>; compatible = "cfi-flash"; - reg = <0x0 0x88000000 0x0 0x1000>; + reg = <0x0 0x88000000 0x0 0x4000000>; bank-width = <2>; device-width = <1>; }; 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 <dt-bindings/clock/sifive-fu540-prci.h> + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,fu540-c000", "sifive,fu540"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + ethernet0 = ð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 = <RTCCLK_FREQ>; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + + soc { + }; + + hfclk: hfclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <33333333>; + clock-output-names = "hfclk"; + }; + + rtcclk: rtcclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <RTCCLK_FREQ>; + clock-output-names = "rtcclk"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&qspi0 { + status = "okay"; + flash@0 { + compatible = "issi,is25wp256", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&qspi2 { + status = "okay"; + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + spi-max-frequency = <20000000>; + voltage-ranges = <3300 3300>; + disable-wp; + }; +}; + +ð0 { + status = "okay"; + phy-mode = "gmii"; + phy-handle = <&phy0>; + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; 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/andes_plic.c b/arch/riscv/lib/andes_plic.c index 28568e4e2b..3868569a65 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -19,7 +19,7 @@ #include <cpu.h> /* pending register */ -#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + (hart) * 8) +#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + ((hart) / 4) * 4) /* enable register */ #define ENABLE_REG(base, hart) ((ulong)(base) + 0x2000 + (hart) * 0x80) /* claim register */ @@ -46,7 +46,7 @@ static int init_plic(void); static int enable_ipi(int hart) { - int en; + unsigned int en; en = ENABLE_HART_IPI >> hart; writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, hart)); @@ -94,10 +94,13 @@ static int init_plic(void) int riscv_send_ipi(int hart) { + unsigned int ipi; + PLIC_BASE_GET(); - writel(SEND_IPI_TO_HART(hart), - (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart)); + ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); + writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic, + gd->arch.boot_hart)); return 0; } @@ -114,6 +117,17 @@ int riscv_clear_ipi(int hart) return 0; } +int riscv_get_ipi(int hart, int *pending) +{ + PLIC_BASE_GET(); + + *pending = readl((void __iomem *)PENDING_REG(gd->arch.plic, + gd->arch.boot_hart)); + *pending = !!(*pending & SEND_IPI_TO_HART(hart)); + + return 0; +} + static const struct udevice_id andes_plic_ids[] = { { .compatible = "riscv,plic1", .data = RISCV_SYSCON_PLIC }, { } 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/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..17adb35730 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -32,11 +32,23 @@ extern int riscv_send_ipi(int hart); */ extern int riscv_clear_ipi(int hart); -static int send_ipi_many(struct ipi_data *ipi) +/** + * riscv_get_ipi() - Get status of inter-processor interrupt (IPI) + * + * Platform code must provide this function. + * + * @hart: Hart ID of hart to be checked + * @pending: Pointer to variable with result of the check, + * 1 if IPI is pending, 0 otherwise + * @return 0 if OK, -ve on error + */ +extern int riscv_get_ipi(int hart, int *pending); + +static int send_ipi_many(struct ipi_data *ipi, int wait) { ofnode node, cpus; u32 reg; - int ret; + int ret, pending; cpus = ofnode_path("/cpus"); if (!ofnode_valid(cpus)) { @@ -79,6 +91,15 @@ static int send_ipi_many(struct ipi_data *ipi) pr_err("Cannot send IPI to hart %d\n", reg); return ret; } + + if (wait) { + pending = 1; + while (pending) { + ret = riscv_get_ipi(reg, &pending); + if (ret) + return ret; + } + } } return 0; @@ -92,21 +113,25 @@ void handle_ipi(ulong hart) if (hart >= CONFIG_NR_CPUS) return; + __smp_mb(); + + smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr; + invalidate_icache_all(); + + /* + * Clear the IPI to acknowledge the request before jumping to the + * requested function. + */ ret = riscv_clear_ipi(hart); if (ret) { pr_err("Cannot clear IPI of hart %ld\n", hart); return; } - __smp_mb(); - - smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr; - invalidate_icache_all(); - smp_function(hart, gd->arch.ipi[hart].arg0, gd->arch.ipi[hart].arg1); } -int smp_call_function(ulong addr, ulong arg0, ulong arg1) +int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait) { int ret = 0; struct ipi_data ipi; @@ -115,7 +140,7 @@ int smp_call_function(ulong addr, ulong arg0, ulong arg1) ipi.arg0 = arg0; ipi.arg1 = arg1; - ret = send_ipi_many(&ipi); + ret = send_ipi_many(&ipi, wait); return ret; } 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 |