+ 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
This commit is contained in:
Tom Rini 2023-11-02 09:30:34 -04:00
commit b0c391ce0c
20 changed files with 666 additions and 20 deletions

View file

@ -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}

View file

@ -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:

View file

@ -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"

View file

@ -26,7 +26,7 @@
.text
/* trap entry */
.align 2
.align 6
.global trap_entry
trap_entry:
addi sp, sp, -32 * REGBYTES

View file

@ -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>;

View file

@ -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_ */

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -12,6 +12,7 @@ U-Boot API documentation
efi
event
getopt
interrupt
linker_lists
lmb
logging

6
doc/api/interrupt.rst Normal file
View file

@ -0,0 +1,6 @@
.. SPDX-License-Identifier: GPL-2.0+
Interrupt API
=============
.. kernel-doc:: include/interrupt.h

View file

@ -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;
}

View file

@ -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

View file

@ -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

274
drivers/rng/jh7110_rng.c Normal file
View file

@ -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,
};

116
drivers/rng/riscv_zkr_rng.c Normal file
View file

@ -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,
};

View file

@ -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" \

45
include/interrupt.h Normal file
View file

@ -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);