summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-12-09 21:53:23 -0500
committerTom Rini <trini@konsulko.com>2019-12-09 21:53:23 -0500
commit520f9559020894950d4e962aba52220c8a1d6bfe (patch)
treef39b28ef809b2cd4236803e9e1d7f98c97f0dbd5 /arch
parent1045ff4d1af9e3e8a2ad4cf04a7263d49e90cfa7 (diff)
parent0e1233ce9069a87a84a4385de456665d2bc9229d (diff)
downloadu-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/Kconfig2
-rw-r--r--arch/riscv/cpu/ax25/Kconfig4
-rw-r--r--arch/riscv/cpu/ax25/cache.c60
-rw-r--r--arch/riscv/cpu/start.S6
-rw-r--r--arch/riscv/cpu/u-boot-spl.lds2
-rw-r--r--arch/riscv/cpu/u-boot.lds2
-rw-r--r--arch/riscv/dts/Makefile1
-rw-r--r--arch/riscv/dts/ae350_32.dts61
-rw-r--r--arch/riscv/dts/ae350_64.dts61
-rw-r--r--arch/riscv/dts/fu540-c000.dtsi251
-rw-r--r--arch/riscv/dts/hifive-unleashed-a00.dts96
-rw-r--r--arch/riscv/include/asm/smp.h3
-rw-r--r--arch/riscv/lib/andes_plic.c22
-rw-r--r--arch/riscv/lib/bootm.c2
-rw-r--r--arch/riscv/lib/sbi_ipi.c11
-rw-r--r--arch/riscv/lib/sifive_clint.c9
-rw-r--r--arch/riscv/lib/smp.c43
-rw-r--r--arch/riscv/lib/spl.c2
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 = &eth0;
+ };
+
+ chosen {
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu0: cpu@0 {
+ compatible = "sifive,e51", "sifive,rocket0", "riscv";
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <16384>;
+ reg = <0>;
+ riscv,isa = "rv64imac";
+ status = "disabled";
+ cpu0_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu1: cpu@1 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <1>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ cpu1_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu2: cpu@2 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <2>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ cpu2_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu3: cpu@3 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <3>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ cpu3_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu4: cpu@4 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <4>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ cpu4_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ };
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "sifive,fu540-c000", "sifive,fu540", "simple-bus";
+ ranges;
+ plic0: interrupt-controller@c000000 {
+ #interrupt-cells = <1>;
+ compatible = "sifive,plic-1.0.0";
+ reg = <0x0 0xc000000 0x0 0x4000000>;
+ riscv,ndev = <53>;
+ interrupt-controller;
+ interrupts-extended = <
+ &cpu0_intc 0xffffffff
+ &cpu1_intc 0xffffffff &cpu1_intc 9
+ &cpu2_intc 0xffffffff &cpu2_intc 9
+ &cpu3_intc 0xffffffff &cpu3_intc 9
+ &cpu4_intc 0xffffffff &cpu4_intc 9>;
+ };
+ prci: clock-controller@10000000 {
+ compatible = "sifive,fu540-c000-prci";
+ reg = <0x0 0x10000000 0x0 0x1000>;
+ clocks = <&hfclk>, <&rtcclk>;
+ #clock-cells = <1>;
+ };
+ uart0: serial@10010000 {
+ compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+ reg = <0x0 0x10010000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <4>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ status = "disabled";
+ };
+ uart1: serial@10011000 {
+ compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+ reg = <0x0 0x10011000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <5>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ status = "disabled";
+ };
+ i2c0: i2c@10030000 {
+ compatible = "sifive,fu540-c000-i2c", "sifive,i2c0";
+ reg = <0x0 0x10030000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <50>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ qspi0: spi@10040000 {
+ compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+ reg = <0x0 0x10040000 0x0 0x1000
+ 0x0 0x20000000 0x0 0x10000000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <51>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ qspi1: spi@10041000 {
+ compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+ reg = <0x0 0x10041000 0x0 0x1000
+ 0x0 0x30000000 0x0 0x10000000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <52>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ qspi2: spi@10050000 {
+ compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+ reg = <0x0 0x10050000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <6>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ eth0: ethernet@10090000 {
+ compatible = "sifive,fu540-c000-gem";
+ interrupt-parent = <&plic0>;
+ interrupts = <53>;
+ reg = <0x0 0x10090000 0x0 0x2000
+ 0x0 0x100a0000 0x0 0x1000>;
+ local-mac-address = [00 00 00 00 00 00];
+ clock-names = "pclk", "hclk";
+ clocks = <&prci PRCI_CLK_GEMGXLPLL>,
+ <&prci PRCI_CLK_GEMGXLPLL>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ pwm0: pwm@10020000 {
+ compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+ reg = <0x0 0x10020000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <42 43 44 45>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+ pwm1: pwm@10021000 {
+ compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+ reg = <0x0 0x10021000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <46 47 48 49>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ };
+};
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;
+ };
+};
+
+&eth0 {
+ 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