aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-11-02 09:30:34 -0400
committerTom Rini <trini@konsulko.com>2023-11-02 09:30:34 -0400
commitb0c391ce0c01064a96711965e22f5d745e73edc3 (patch)
treefd9655433e4af8ee818e80267ff42713ff8d2290
parent658caf0bf14e163be78b6fc063d883d1252163a2 (diff)
parent9d22d4a7cef7f2fdaf5c060b71574e6f82ea5ff0 (diff)
Merge https://source.denx.de/u-boot/custodians/u-boot-riscv
+ CI: Use OpenSBI 1.3.1 release for testing + riscv: Support resume after exception + rng: Support RNG provided by RISC-V Zkr ISA extension + board: starfive VF2: Support jtag + board: starfive VF2: Support TRNG driver + board: sifive unmatched: Move kernel load address
-rw-r--r--.azure-pipelines.yml8
-rw-r--r--.gitlab-ci.yml8
-rw-r--r--arch/riscv/Kconfig18
-rw-r--r--arch/riscv/cpu/mtrap.S2
-rw-r--r--arch/riscv/dts/jh7110.dtsi10
-rw-r--r--arch/riscv/include/asm/arch-jh7110/gpio.h85
-rw-r--r--arch/riscv/include/asm/io.h45
-rw-r--r--arch/riscv/lib/cache.c2
-rw-r--r--arch/riscv/lib/interrupts.c13
-rw-r--r--board/starfive/visionfive2/spl.c23
-rw-r--r--configs/starfive_visionfive2_defconfig2
-rw-r--r--doc/api/index.rst1
-rw-r--r--doc/api/interrupt.rst6
-rw-r--r--drivers/clk/starfive/clk-jh7110.c10
-rw-r--r--drivers/rng/Kconfig14
-rw-r--r--drivers/rng/Makefile2
-rw-r--r--drivers/rng/jh7110_rng.c274
-rw-r--r--drivers/rng/riscv_zkr_rng.c116
-rw-r--r--include/configs/sifive-unmatched.h2
-rw-r--r--include/interrupt.h45
20 files changed, 666 insertions, 20 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index eb9353fc3d..d6f3fa423c 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -203,12 +203,12 @@ stages:
grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
grub-mkimage --prefix=\"\" -o ~/grub_x64.efi -O x86_64-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
if [[ "\${TEST_PY_BD}" == "qemu-riscv32_spl" ]]; then
- wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.2/opensbi-1.2-rv-bin.tar.xz | tar -C /tmp -xJ;
- export OPENSBI=/tmp/opensbi-1.2-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
+ wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
+ export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
fi
if [[ "\${TEST_PY_BD}" == "qemu-riscv64_spl" ]] || [[ "\${TEST_PY_BD}" == "sifive_unleashed" ]]; then
- wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.2/opensbi-1.2-rv-bin.tar.xz | tar -C /tmp -xJ;
- export OPENSBI=/tmp/opensbi-1.2-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
+ wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
+ export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
fi
# the below corresponds to .gitlab-ci.yml "script"
cd \${WORK_DIR}
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1e11b5a6fe..fee165198a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -32,12 +32,12 @@ stages:
- grub-mkimage --prefix="" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- grub-mkimage --prefix="" -o ~/grub_x64.efi -O x86_64-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- if [[ "${TEST_PY_BD}" == "qemu-riscv32_spl" ]]; then
- wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.2/opensbi-1.2-rv-bin.tar.xz | tar -C /tmp -xJ;
- export OPENSBI=/tmp/opensbi-1.2-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
+ wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
+ export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
fi
- if [[ "${TEST_PY_BD}" == "qemu-riscv64_spl" ]] || [[ "${TEST_PY_BD}" == "sifive_unleashed" ]]; then
- wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.2/opensbi-1.2-rv-bin.tar.xz | tar -C /tmp -xJ;
- export OPENSBI=/tmp/opensbi-1.2-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
+ wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
+ export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
fi
after_script:
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 8fc81fb284..6d0d812ddb 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -14,6 +14,9 @@ config TARGET_ANDES_AE350
config TARGET_MICROCHIP_ICICLE
bool "Support Microchip PolarFire-SoC Icicle Board"
+config TARGET_OPENPITON_RISCV64
+ bool "Support RISC-V cores on OpenPiton SoC"
+
config TARGET_QEMU_VIRT
bool "Support QEMU Virt Board"
@@ -24,6 +27,10 @@ config TARGET_SIFIVE_UNMATCHED
bool "Support SiFive Unmatched Board"
select SYS_CACHE_SHIFT_6
+config TARGET_SIPEED_MAIX
+ bool "Support Sipeed Maix Board"
+ select SYS_CACHE_SHIFT_6
+
config TARGET_STARFIVE_VISIONFIVE2
bool "Support StarFive VisionFive2 Board"
select BOARD_LATE_INIT
@@ -32,13 +39,6 @@ config TARGET_TH1520_LPI4A
bool "Support Sipeed's TH1520 Lichee PI 4A Board"
select SYS_CACHE_SHIFT_6
-config TARGET_SIPEED_MAIX
- bool "Support Sipeed Maix Board"
- select SYS_CACHE_SHIFT_6
-
-config TARGET_OPENPITON_RISCV64
- bool "Support RISC-V cores on OpenPiton SoC"
-
endchoice
config SYS_ICACHE_OFF
@@ -76,12 +76,12 @@ config SPL_ZERO_MEM_BEFORE_USE
source "board/AndesTech/ae350/Kconfig"
source "board/emulation/qemu-riscv/Kconfig"
source "board/microchip/mpfs_icicle/Kconfig"
+source "board/openpiton/riscv64/Kconfig"
source "board/sifive/unleashed/Kconfig"
source "board/sifive/unmatched/Kconfig"
-source "board/thead/th1520_lpi4a/Kconfig"
-source "board/openpiton/riscv64/Kconfig"
source "board/sipeed/maix/Kconfig"
source "board/starfive/visionfive2/Kconfig"
+source "board/thead/th1520_lpi4a/Kconfig"
# platform-specific options below
source "arch/riscv/cpu/andesv5/Kconfig"
diff --git a/arch/riscv/cpu/mtrap.S b/arch/riscv/cpu/mtrap.S
index 6eb3ed1d5a..5cad7b41ff 100644
--- a/arch/riscv/cpu/mtrap.S
+++ b/arch/riscv/cpu/mtrap.S
@@ -26,7 +26,7 @@
.text
/* trap entry */
- .align 2
+ .align 6
.global trap_entry
trap_entry:
addi sp, sp, -32 * REGBYTES
diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi
index ec237a46ff..13c47f7caa 100644
--- a/arch/riscv/dts/jh7110.dtsi
+++ b/arch/riscv/dts/jh7110.dtsi
@@ -627,6 +627,16 @@
status = "disabled";
};
+ rng: rng@1600c000 {
+ compatible = "starfive,jh7110-trng";
+ reg = <0x0 0x1600C000 0x0 0x4000>;
+ clocks = <&stgcrg JH7110_STGCLK_SEC_HCLK>,
+ <&stgcrg JH7110_STGCLK_SEC_MISCAHB>;
+ clock-names = "hclk", "ahb";
+ resets = <&stgcrg JH7110_STGRST_SEC_TOP_HRESETN>;
+ interrupts = <30>;
+ };
+
aoncrg: clock-controller@17000000 {
compatible = "starfive,jh7110-aoncrg";
reg = <0x0 0x17000000 0x0 0x10000>;
diff --git a/arch/riscv/include/asm/arch-jh7110/gpio.h b/arch/riscv/include/asm/arch-jh7110/gpio.h
new file mode 100644
index 0000000000..90aa2f8a9e
--- /dev/null
+++ b/arch/riscv/include/asm/arch-jh7110/gpio.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#ifndef _GPIO_STARFIVE_H_
+#define _GPIO_STARFIVE_H_
+
+#include <asm/arch/regs.h>
+
+#define GPIO_NUM_SHIFT 2 /*one dword include 4 gpios*/
+#define GPIO_BYTE_SHIFT 3
+
+#define GPIO_INDEX_MASK 0x3
+
+#define GPIO_DOEN_MASK 0x3f
+#define GPIO_DOUT_MASK 0x7f
+#define GPIO_DIN_MASK 0x7f
+#define GPIO_DS_MASK 0x06
+#define GPIO_DS_SHIFT 1
+#define GPIO_SLEW_MASK BIT(5)
+#define GPIO_SLEW_SHIFT 5
+#define GPIO_PULL_MASK 0x18
+#define GPIO_PULL_SHIFT 3
+#define GPIO_PULL_UP 1
+#define GPIO_PULL_DOWN 2
+
+#define NR_GPIOS 64
+
+#define GPIO_OFFSET(gpio) \
+ (((gpio) >> GPIO_NUM_SHIFT) << GPIO_NUM_SHIFT)
+
+#define GPIO_SHIFT(gpio) \
+ (((gpio) & GPIO_INDEX_MASK) << GPIO_BYTE_SHIFT)
+
+enum gpio_state {
+ LOW,
+ HIGH
+};
+
+#define GPIO_DOEN 0x0
+#define GPIO_DOUT 0x40
+#define GPIO_DIN 0x80
+#define GPIO_EN 0xdc
+#define GPIO_LOW_IE 0x100
+#define GPIO_HIGH_IE 0x104
+#define GPIO_CONFIG 0x120
+
+#define SYS_IOMUX_DOEN(gpio, oen) \
+ clrsetbits_le32(JH7110_SYS_IOMUX + GPIO_OFFSET(gpio), \
+ GPIO_DOEN_MASK << GPIO_SHIFT(gpio), \
+ (oen) << GPIO_SHIFT(gpio))
+
+#define SYS_IOMUX_DOUT(gpio, gpo) \
+ clrsetbits_le32(JH7110_SYS_IOMUX + GPIO_DOUT + GPIO_OFFSET(gpio), \
+ GPIO_DOUT_MASK << GPIO_SHIFT(gpio), \
+ ((gpo) & GPIO_DOUT_MASK) << GPIO_SHIFT(gpio))
+
+#define SYS_IOMUX_DIN(gpio, gpi)\
+ clrsetbits_le32(JH7110_SYS_IOMUX + GPIO_DIN + GPIO_OFFSET(gpi), \
+ GPIO_DIN_MASK << GPIO_SHIFT(gpi), \
+ ((gpio + 2) & GPIO_DIN_MASK) << GPIO_SHIFT(gpi))
+
+#define SYS_IOMUX_SET_DS(gpio, ds) \
+ clrsetbits_le32(JH7110_SYS_IOMUX + GPIO_CONFIG + gpio * 4, \
+ GPIO_DS_MASK, (ds) << GPIO_DS_SHIFT)
+
+#define SYS_IOMUX_SET_SLEW(gpio, slew) \
+ clrsetbits_le32(JH7110_SYS_IOMUX + GPIO_CONFIG + gpio * 4, \
+ GPIO_SLEW_MASK, (slew) << GPIO_SLEW_SHIFT)
+
+#define SYS_IOMUX_SET_PULL(gpio, pull) \
+ clrsetbits_le32(JH7110_SYS_IOMUX + GPIO_CONFIG + gpio * 4, \
+ GPIO_PULL_MASK, (pull) << GPIO_PULL_SHIFT)
+
+#define SYS_IOMUX_COMPLEX(gpio, gpi, gpo, oen) \
+ do { \
+ SYS_IOMUX_DOEN(gpio, oen); \
+ SYS_IOMUX_DOUT(gpio, gpo); \
+ SYS_IOMUX_DIN(gpio, gpi); \
+ } while (0)
+
+#endif /* _GPIO_STARFIVE_H_ */
diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
index b16e6dfa37..4170877a1a 100644
--- a/arch/riscv/include/asm/io.h
+++ b/arch/riscv/include/asm/io.h
@@ -323,6 +323,51 @@ static inline void writesl(unsigned int *addr, const void *data, int longlen)
#define insw_p(port, to, len) insw(port, to, len)
#define insl_p(port, to, len) insl(port, to, len)
+/*
+ * Unordered I/O memory access primitives. These are even more relaxed than
+ * the relaxed versions, as they don't even order accesses between successive
+ * operations to the I/O regions.
+ */
+#define readb_cpu(c) ({ u8 __r = __raw_readb(c); __r; })
+#define readw_cpu(c) ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
+#define readl_cpu(c) ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
+
+#define writeb_cpu(v, c) ((void)__raw_writeb((v), (c)))
+#define writew_cpu(v, c) ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
+#define writel_cpu(v, c) ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
+
+#ifdef CONFIG_64BIT
+#define readq_cpu(c) ({ u64 __r = le64_to_cpu((__force __le64)__raw_readq(c)); __r; })
+#define writeq_cpu(v, c) ((void)__raw_writeq((__force u64)cpu_to_le64(v), (c)))
+#endif
+
+/*
+ * Relaxed I/O memory access primitives. These follow the Device memory
+ * ordering rules but do not guarantee any ordering relative to Normal memory
+ * accesses. These are defined to order the indicated access (either a read or
+ * write) with all other I/O memory accesses to the same peripheral. Since the
+ * platform specification defines that all I/O regions are strongly ordered on
+ * channel 0, no explicit fences are required to enforce this ordering.
+ */
+/* FIXME: These are now the same as asm-generic */
+#define __io_rbr() do {} while (0)
+#define __io_rar() do {} while (0)
+#define __io_rbw() do {} while (0)
+#define __io_raw() do {} while (0)
+
+#define readb_relaxed(c) ({ u8 __v; __io_rbr(); __v = readb_cpu(c); __io_rar(); __v; })
+#define readw_relaxed(c) ({ u16 __v; __io_rbr(); __v = readw_cpu(c); __io_rar(); __v; })
+#define readl_relaxed(c) ({ u32 __v; __io_rbr(); __v = readl_cpu(c); __io_rar(); __v; })
+
+#define writeb_relaxed(v, c) ({ __io_rbw(); writeb_cpu((v), (c)); __io_raw(); })
+#define writew_relaxed(v, c) ({ __io_rbw(); writew_cpu((v), (c)); __io_raw(); })
+#define writel_relaxed(v, c) ({ __io_rbw(); writel_cpu((v), (c)); __io_raw(); })
+
+#ifdef CONFIG_64BIT
+#define readq_relaxed(c) ({ u64 __v; __io_rbr(); __v = readq_cpu(c); __io_rar(); __v; })
+#define writeq_relaxed(v, c) ({ __io_rbw(); writeq_cpu((v), (c)); __io_raw(); })
+#endif
+
#include <asm-generic/io.h>
#endif /* __ASM_RISCV_IO_H */
diff --git a/arch/riscv/lib/cache.c b/arch/riscv/lib/cache.c
index c46b49eb0a..afad7e117f 100644
--- a/arch/riscv/lib/cache.c
+++ b/arch/riscv/lib/cache.c
@@ -19,7 +19,7 @@ __weak void flush_dcache_range(unsigned long start, unsigned long end)
{
}
-void invalidate_icache_range(unsigned long start, unsigned long end)
+__weak void invalidate_icache_range(unsigned long start, unsigned long end)
{
/*
* RISC-V does not have an instruction for invalidating parts of the
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index 02dbcfd423..a26ccc721f 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -12,6 +12,7 @@
#include <linux/compat.h>
#include <efi_loader.h>
#include <hang.h>
+#include <interrupt.h>
#include <irq_func.h>
#include <asm/global_data.h>
#include <asm/ptrace.h>
@@ -21,6 +22,13 @@
DECLARE_GLOBAL_DATA_PTR;
+static struct resume_data *resume;
+
+void set_resume(struct resume_data *data)
+{
+ resume = data;
+}
+
static void show_efi_loaded_images(uintptr_t epc)
{
efi_print_image_infos((void *)epc);
@@ -105,6 +113,11 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
"Store/AMO page fault",
};
+ if (resume) {
+ resume->code = code;
+ longjmp(resume->jump, 1);
+ }
+
if (code < ARRAY_SIZE(exception_code))
printf("Unhandled exception: %s\n", exception_code[code]);
else
diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c
index ad5f71a201..336f0cdfc9 100644
--- a/board/starfive/visionfive2/spl.c
+++ b/board/starfive/visionfive2/spl.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <asm/arch/eeprom.h>
+#include <asm/arch/gpio.h>
#include <asm/arch/regs.h>
#include <asm/arch/spl.h>
#include <asm/io.h>
@@ -172,10 +173,32 @@ void spl_perform_fixups(struct spl_image_info *spl_image)
/* Update the memory size which read form eeprom or DT */
fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size);
}
+
+static void jh7110_jtag_init(void)
+{
+ /* nTRST: GPIO36 */
+ SYS_IOMUX_DOEN(36, HIGH);
+ SYS_IOMUX_DIN(36, 4);
+ /* TDI: GPIO61 */
+ SYS_IOMUX_DOEN(61, HIGH);
+ SYS_IOMUX_DIN(61, 19);
+ /* TMS: GPIO63 */
+ SYS_IOMUX_DOEN(63, HIGH);
+ SYS_IOMUX_DIN(63, 20);
+ /* TCK: GPIO60 */
+ SYS_IOMUX_DOEN(60, HIGH);
+ SYS_IOMUX_DIN(60, 29);
+ /* TDO: GPIO44 */
+ SYS_IOMUX_DOEN(44, 8);
+ SYS_IOMUX_DOUT(44, 22);
+}
+
int spl_board_init_f(void)
{
int ret;
+ jh7110_jtag_init();
+
ret = spl_soc_init();
if (ret) {
debug("JH7110 SPL init failed: %d\n", ret);
diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig
index b21754feaf..b15e7d24db 100644
--- a/configs/starfive_visionfive2_defconfig
+++ b/configs/starfive_visionfive2_defconfig
@@ -120,6 +120,8 @@ CONFIG_SPL_PINCTRL_STARFIVE=y
CONFIG_SPL_PINCTRL_STARFIVE_JH7110=y
CONFIG_PINCTRL_STARFIVE=y
# CONFIG_RAM_SIFIVE is not set
+CONFIG_DM_RNG=y
+CONFIG_RNG_JH7110=y
CONFIG_SYS_NS16550=y
CONFIG_CADENCE_QSPI=y
CONFIG_TIMER_EARLY=y
diff --git a/doc/api/index.rst b/doc/api/index.rst
index 2f0218c47a..51b2013af3 100644
--- a/doc/api/index.rst
+++ b/doc/api/index.rst
@@ -12,6 +12,7 @@ U-Boot API documentation
efi
event
getopt
+ interrupt
linker_lists
lmb
logging
diff --git a/doc/api/interrupt.rst b/doc/api/interrupt.rst
new file mode 100644
index 0000000000..5721231d91
--- /dev/null
+++ b/doc/api/interrupt.rst
@@ -0,0 +1,6 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Interrupt API
+=============
+
+.. kernel-doc:: include/interrupt.h
diff --git a/drivers/clk/starfive/clk-jh7110.c b/drivers/clk/starfive/clk-jh7110.c
index 31aaf3340f..a835541e48 100644
--- a/drivers/clk/starfive/clk-jh7110.c
+++ b/drivers/clk/starfive/clk-jh7110.c
@@ -539,6 +539,16 @@ static int jh7110_stgcrg_init(struct udevice *dev)
"pcie1_tl", "stg_axiahb",
OFFSET(JH7110_STGCLK_PCIE1_TL)));
+ /* Security clocks */
+ clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_SEC_HCLK),
+ starfive_clk_gate(priv->reg,
+ "sec_ahb", "stg_axiahb",
+ OFFSET(JH7110_STGCLK_SEC_HCLK)));
+ clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_SEC_MISCAHB),
+ starfive_clk_gate(priv->reg,
+ "sec_misc_ahb", "stg_axiahb",
+ OFFSET(JH7110_STGCLK_SEC_MISCAHB)));
+
return 0;
}
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
index 994cc35b27..a89c899568 100644
--- a/drivers/rng/Kconfig
+++ b/drivers/rng/Kconfig
@@ -48,6 +48,14 @@ config RNG_OPTEE
accessible to normal world but reserved and used by the OP-TEE
to avoid the weakness of a software PRNG.
+config RNG_RISCV_ZKR
+ bool "RISC-V Zkr random number generator"
+ depends on RISCV_SMODE
+ help
+ This driver provides a Random Number Generator based on the
+ Zkr RISC-V ISA extension which provides an interface to an
+ NIST SP 800-90B or BSI AIS-31 compliant physical entropy source.
+
config RNG_STM32
bool "Enable random number generator for STM32"
depends on ARCH_STM32 || ARCH_STM32MP
@@ -91,4 +99,10 @@ config TPM_RNG
functionality. Enable random number generator on TPM
devices.
+config RNG_JH7110
+ bool "StarFive JH7110 Random Number Generator support"
+ depends on DM_RNG && STARFIVE_JH7110
+ help
+ Enable True Random Number Generator in StarFive JH7110 SoCs.
+
endif
diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile
index 47b323e61e..7e64c4cdfc 100644
--- a/drivers/rng/Makefile
+++ b/drivers/rng/Makefile
@@ -10,8 +10,10 @@ obj-$(CONFIG_RNG_MSM) += msm_rng.o
obj-$(CONFIG_RNG_NPCM) += npcm_rng.o
obj-$(CONFIG_RNG_OPTEE) += optee_rng.o
obj-$(CONFIG_RNG_STM32) += stm32_rng.o
+obj-$(CONFIG_RNG_RISCV_ZKR) += riscv_zkr_rng.o
obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o
obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o
obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o
obj-$(CONFIG_RNG_ARM_RNDR) += arm_rndr.o
obj-$(CONFIG_TPM_RNG) += tpm_rng.o
+obj-$(CONFIG_RNG_JH7110) += jh7110_rng.o
diff --git a/drivers/rng/jh7110_rng.c b/drivers/rng/jh7110_rng.c
new file mode 100644
index 0000000000..eb21afe4e7
--- /dev/null
+++ b/drivers/rng/jh7110_rng.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * TRNG driver for the StarFive JH7110 SoC
+ *
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <reset.h>
+#include <rng.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+
+/* trng register offset */
+#define STARFIVE_CTRL 0x00
+#define STARFIVE_STAT 0x04
+#define STARFIVE_MODE 0x08
+#define STARFIVE_SMODE 0x0C
+#define STARFIVE_IE 0x10
+#define STARFIVE_ISTAT 0x14
+#define STARFIVE_RAND0 0x20
+#define STARFIVE_RAND1 0x24
+#define STARFIVE_RAND2 0x28
+#define STARFIVE_RAND3 0x2C
+#define STARFIVE_RAND4 0x30
+#define STARFIVE_RAND5 0x34
+#define STARFIVE_RAND6 0x38
+#define STARFIVE_RAND7 0x3C
+#define STARFIVE_AUTO_RQSTS 0x60
+#define STARFIVE_AUTO_AGE 0x64
+
+/* CTRL CMD */
+#define STARFIVE_CTRL_EXEC_NOP 0x0
+#define STARFIVE_CTRL_GENE_RANDNUM 0x1
+#define STARFIVE_CTRL_EXEC_RANDRESEED 0x2
+
+/* STAT */
+#define STARFIVE_STAT_NONCE_MODE BIT(2)
+#define STARFIVE_STAT_R256 BIT(3)
+#define STARFIVE_STAT_MISSION_MODE BIT(8)
+#define STARFIVE_STAT_SEEDED BIT(9)
+#define STARFIVE_STAT_LAST_RESEED(x) ((x) << 16)
+#define STARFIVE_STAT_SRVC_RQST BIT(27)
+#define STARFIVE_STAT_RAND_GENERATING BIT(30)
+#define STARFIVE_STAT_RAND_SEEDING BIT(31)
+#define STARFIVE_STAT_RUNNING (STARFIVE_STAT_RAND_GENERATING | \
+ STARFIVE_STAT_RAND_SEEDING)
+
+/* MODE */
+#define STARFIVE_MODE_R256 BIT(3)
+
+/* SMODE */
+#define STARFIVE_SMODE_NONCE_MODE BIT(2)
+#define STARFIVE_SMODE_MISSION_MODE BIT(8)
+#define STARFIVE_SMODE_MAX_REJECTS(x) ((x) << 16)
+
+/* IE */
+#define STARFIVE_IE_RAND_RDY_EN BIT(0)
+#define STARFIVE_IE_SEED_DONE_EN BIT(1)
+#define STARFIVE_IE_LFSR_LOCKUP_EN BIT(4)
+#define STARFIVE_IE_GLBL_EN BIT(31)
+
+#define STARFIVE_IE_ALL (STARFIVE_IE_GLBL_EN | \
+ STARFIVE_IE_RAND_RDY_EN | \
+ STARFIVE_IE_SEED_DONE_EN | \
+ STARFIVE_IE_LFSR_LOCKUP_EN)
+
+/* ISTAT */
+#define STARFIVE_ISTAT_RAND_RDY BIT(0)
+#define STARFIVE_ISTAT_SEED_DONE BIT(1)
+#define STARFIVE_ISTAT_LFSR_LOCKUP BIT(4)
+
+#define STARFIVE_RAND_LEN sizeof(u32)
+
+enum mode {
+ PRNG_128BIT,
+ PRNG_256BIT,
+};
+
+struct starfive_trng_plat {
+ void *base;
+ struct clk *hclk;
+ struct clk *ahb;
+ struct reset_ctl *rst;
+ u32 mode;
+};
+
+static inline int starfive_trng_wait_idle(struct starfive_trng_plat *trng)
+{
+ u32 stat;
+
+ return readl_relaxed_poll_timeout(trng->base + STARFIVE_STAT, stat,
+ !(stat & STARFIVE_STAT_RUNNING),
+ 100000);
+}
+
+static inline void starfive_trng_irq_mask_clear(struct starfive_trng_plat *trng)
+{
+ /* clear register: ISTAT */
+ u32 data = readl(trng->base + STARFIVE_ISTAT);
+
+ writel(data, trng->base + STARFIVE_ISTAT);
+}
+
+static int starfive_trng_cmd(struct starfive_trng_plat *trng, u32 cmd)
+{
+ u32 stat, flg;
+ int ret;
+
+ switch (cmd) {
+ case STARFIVE_CTRL_GENE_RANDNUM:
+ writel(cmd, trng->base + STARFIVE_CTRL);
+ flg = STARFIVE_ISTAT_RAND_RDY;
+ break;
+ case STARFIVE_CTRL_EXEC_RANDRESEED:
+ writel(cmd, trng->base + STARFIVE_CTRL);
+ flg = STARFIVE_ISTAT_SEED_DONE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = readl_relaxed_poll_timeout(trng->base + STARFIVE_ISTAT, stat,
+ (stat & flg), 1000);
+ writel(flg, trng->base + STARFIVE_ISTAT);
+
+ return ret;
+}
+
+static int starfive_trng_read(struct udevice *dev, void *data, size_t len)
+{
+ struct starfive_trng_plat *trng = dev_get_plat(dev);
+ u8 *buffer = data;
+ int iter_mask;
+
+ if (trng->mode == PRNG_256BIT)
+ iter_mask = 7;
+ else
+ iter_mask = 3;
+
+ for (int i = 0; len; ++i, i &= iter_mask) {
+ u32 val;
+ size_t step;
+ int ret;
+
+ if (!i) {
+ ret = starfive_trng_cmd(trng,
+ STARFIVE_CTRL_GENE_RANDNUM);
+ if (ret)
+ return ret;
+ }
+
+ val = readl(trng->base + STARFIVE_RAND0 +
+ (i * STARFIVE_RAND_LEN));
+ step = min_t(size_t, len, STARFIVE_RAND_LEN);
+ memcpy(buffer, &val, step);
+ buffer += step;
+ len -= step;
+ }
+
+ return 0;
+}
+
+static int starfive_trng_init(struct starfive_trng_plat *trng)
+{
+ u32 mode, intr = 0;
+
+ /* setup Auto Request/Age register */
+ writel(0, trng->base + STARFIVE_AUTO_AGE);
+ writel(0, trng->base + STARFIVE_AUTO_RQSTS);
+
+ /* clear register: ISTAT */
+ starfive_trng_irq_mask_clear(trng);
+
+ intr |= STARFIVE_IE_ALL;
+ writel(intr, trng->base + STARFIVE_IE);
+
+ mode = readl(trng->base + STARFIVE_MODE);
+
+ switch (trng->mode) {
+ case PRNG_128BIT:
+ mode &= ~STARFIVE_MODE_R256;
+ break;
+ case PRNG_256BIT:
+ mode |= STARFIVE_MODE_R256;
+ break;
+ default:
+ mode |= STARFIVE_MODE_R256;
+ break;
+ }
+
+ writel(mode, trng->base + STARFIVE_MODE);
+
+ return starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED);
+}
+
+static int starfive_trng_probe(struct udevice *dev)
+{
+ struct starfive_trng_plat *pdata = dev_get_plat(dev);
+ int err;
+
+ err = clk_enable(pdata->hclk);
+ if (err)
+ return err;
+
+ err = clk_enable(pdata->ahb);
+ if (err)
+ goto err_ahb;
+
+ err = reset_deassert(pdata->rst);
+ if (err)
+ goto err_reset;
+
+ pdata->mode = PRNG_256BIT;
+
+ err = starfive_trng_init(pdata);
+ if (err)
+ goto err_trng_init;
+
+ return 0;
+
+err_trng_init:
+ reset_assert(pdata->rst);
+err_reset:
+ clk_disable(pdata->ahb);
+err_ahb:
+ clk_disable(pdata->hclk);
+
+ return err;
+}
+
+static int starfive_trng_of_to_plat(struct udevice *dev)
+{
+ struct starfive_trng_plat *pdata = dev_get_plat(dev);
+
+ pdata->base = (void *)dev_read_addr(dev);
+ if (!pdata->base)
+ return -ENODEV;
+
+ pdata->hclk = devm_clk_get(dev, "hclk");
+ if (IS_ERR(pdata->hclk))
+ return -ENODEV;
+
+ pdata->ahb = devm_clk_get(dev, "ahb");
+ if (IS_ERR(pdata->ahb))
+ return -ENODEV;
+
+ pdata->rst = devm_reset_control_get(dev, NULL);
+ if (IS_ERR(pdata->rst))
+ return -ENODEV;
+
+ return 0;
+}
+
+static const struct dm_rng_ops starfive_trng_ops = {
+ .read = starfive_trng_read,
+};
+
+static const struct udevice_id starfive_trng_match[] = {
+ {
+ .compatible = "starfive,jh7110-trng",
+ },
+ {},
+};
+
+U_BOOT_DRIVER(starfive_trng) = {
+ .name = "jh7110-trng",
+ .id = UCLASS_RNG,
+ .of_match = starfive_trng_match,
+ .probe = starfive_trng_probe,
+ .ops = &starfive_trng_ops,
+ .plat_auto = sizeof(struct starfive_trng_plat),
+ .of_to_plat = starfive_trng_of_to_plat,
+};
diff --git a/drivers/rng/riscv_zkr_rng.c b/drivers/rng/riscv_zkr_rng.c
new file mode 100644
index 0000000000..8c9e111e2e
--- /dev/null
+++ b/drivers/rng/riscv_zkr_rng.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The RISC-V Zkr extension provides CSR seed which provides access to a
+ * random number generator.
+ */
+
+#define LOG_CATEGORY UCLASS_RNG
+
+#include <dm.h>
+#include <interrupt.h>
+#include <log.h>
+#include <rng.h>
+
+#define DRIVER_NAME "riscv_zkr"
+
+enum opst {
+ /** @BIST: built in self test running */
+ BIST = 0b00,
+ /** @WAIT: sufficient amount of entropy is not yet available */
+ WAIT = 0b01,
+ /** @ES16: 16bits of entropy available */
+ ES16 = 0b10,
+ /** @DEAD: unrecoverable self-test error */
+ DEAD = 0b11,
+};
+
+static unsigned long read_seed(void)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("csrrw %0, seed, x0" : "=r" (ret) : : "memory");
+
+ return ret;
+}
+
+static int riscv_zkr_read(struct udevice *dev, void *data, size_t len)
+{
+ u8 *ptr = data;
+
+ while (len) {
+ u32 val;
+
+ val = read_seed();
+
+ switch (val >> 30) {
+ case BIST:
+ continue;
+ case WAIT:
+ continue;
+ case ES16:
+ *ptr++ = val & 0xff;
+ if (--len) {
+ *ptr++ = val >> 8;
+ --len;
+ }
+ break;
+ case DEAD:
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * riscv_zkr_probe() - check if the seed register is available
+ *
+ * If the SBI software has not set mseccfg.sseed=1 or the Zkr
+ * extension is not available this probe function will result
+ * in an exception. Currently we cannot recover from this.
+ *
+ * @dev: RNG device
+ * Return: 0 if successfully probed
+ */
+static int riscv_zkr_probe(struct udevice *dev)
+{
+ struct resume_data resume;
+ int ret;
+ u32 val;
+
+ /* Check if reading seed leads to interrupt */
+ set_resume(&resume);
+ ret = setjmp(resume.jump);
+ if (ret)
+ log_debug("Exception %ld reading seed CSR\n", resume.code);
+ else
+ val = read_seed();
+ set_resume(NULL);
+ if (ret)
+ return -ENODEV;
+
+ do {
+ val = read_seed();
+ val >>= 30;
+ } while (val == BIST || val == WAIT);
+
+ if (val == DEAD)
+ return -ENODEV;
+
+ return 0;
+}
+
+static const struct dm_rng_ops riscv_zkr_ops = {
+ .read = riscv_zkr_read,
+};
+
+U_BOOT_DRIVER(riscv_zkr) = {
+ .name = DRIVER_NAME,
+ .id = UCLASS_RNG,
+ .ops = &riscv_zkr_ops,
+ .probe = riscv_zkr_probe,
+};
+
+U_BOOT_DRVINFO(cpu_riscv_zkr) = {
+ .name = DRIVER_NAME,
+};
diff --git a/include/configs/sifive-unmatched.h b/include/configs/sifive-unmatched.h
index 74150b7d4b..de8bfc1123 100644
--- a/include/configs/sifive-unmatched.h
+++ b/include/configs/sifive-unmatched.h
@@ -36,7 +36,7 @@
"name=system,size=-,bootable,type=${type_guid_gpt_system};"
#define CFG_EXTRA_ENV_SETTINGS \
- "kernel_addr_r=0x84000000\0" \
+ "kernel_addr_r=0x80200000\0" \
"kernel_comp_addr_r=0x88000000\0" \
"kernel_comp_size=0x4000000\0" \
"fdt_addr_r=0x8c000000\0" \
diff --git a/include/interrupt.h b/include/interrupt.h
new file mode 100644
index 0000000000..46ef2e196d
--- /dev/null
+++ b/include/interrupt.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <asm/setjmp.h>
+
+/**
+ * struct resume_data - data for resume after interrupt
+ */
+struct resume_data {
+ /** @jump: longjmp buffer */
+ jmp_buf jump;
+ /** @code: exception code */
+ ulong code;
+};
+
+/**
+ * set_resume() - set longjmp buffer for resuming after exception
+ *
+ * By calling this function it is possible to use a long jump to catch an
+ * exception. The caller sets the long jump buffer with set_resume() and then
+ * executes setjmp(). If an exception occurs, the code will return to the
+ * setjmp caller(). The exception code will be returned in @data->code.
+ *
+ * After the critical operation call set_resume(NULL) so that an exception in
+ * another part of the code will not accidently invoke the long jump.
+ *
+ * .. code-block:: c
+ *
+ * // This example shows how to use set_resume().
+ *
+ * struct resume_data resume;
+ * int ret;
+ *
+ * set_resume(&resume);
+ * ret = setjmp(resume.jump);
+ * if (ret) {
+ * printf("An exception %ld occurred\n", resume.code);
+ * } else {
+ * // Do what might raise an exception here.
+ * }
+ * set_resume(NULL);
+ *
+ * @data: pointer to structure with longjmp address
+ * Return: 0 before an exception, 1 after an exception occurred
+ */
+void set_resume(struct resume_data *data);