mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-25 05:04:23 +08:00
+ 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:
commit
b0c391ce0c
@ -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}
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
@ -26,7 +26,7 @@
|
||||
.text
|
||||
|
||||
/* trap entry */
|
||||
.align 2
|
||||
.align 6
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
@ -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>;
|
||||
|
85
arch/riscv/include/asm/arch-jh7110/gpio.h
Normal file
85
arch/riscv/include/asm/arch-jh7110/gpio.h
Normal 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_ */
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -12,6 +12,7 @@ U-Boot API documentation
|
||||
efi
|
||||
event
|
||||
getopt
|
||||
interrupt
|
||||
linker_lists
|
||||
lmb
|
||||
logging
|
||||
|
6
doc/api/interrupt.rst
Normal file
6
doc/api/interrupt.rst
Normal file
@ -0,0 +1,6 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Interrupt API
|
||||
=============
|
||||
|
||||
.. kernel-doc:: include/interrupt.h
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
274
drivers/rng/jh7110_rng.c
Normal 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
116
drivers/rng/riscv_zkr_rng.c
Normal 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,
|
||||
};
|
@ -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
45
include/interrupt.h
Normal 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);
|
Loading…
Reference in New Issue
Block a user