forked from Mirrors/opensbi
adds riscv_vp platform
This commit is contained in:
16
platform/riscv_vp/Kconfig
Normal file
16
platform/riscv_vp/Kconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#
|
||||
# All mandatory drivers or libraries for this platform should
|
||||
# be directly selected by the PLATFORM_xyz kconfig symbol.
|
||||
#
|
||||
# All optional drivers or libraries for this platform should
|
||||
# be enabled via configs/defconfig of this platform.
|
||||
#
|
||||
config PLATFORM_TEMPLATE
|
||||
bool
|
||||
select IPI_MSWI
|
||||
select IRQCHIP_PLIC
|
||||
select SERIAL_UART8250
|
||||
select TIMER_MTIMER
|
||||
default n
|
0
platform/riscv_vp/configs/defconfig
Normal file
0
platform/riscv_vp/configs/defconfig
Normal file
99
platform/riscv_vp/objects.mk
Normal file
99
platform/riscv_vp/objects.mk
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
#
|
||||
|
||||
# Compiler pre-processor flags
|
||||
platform-cppflags-y =
|
||||
|
||||
# C Compiler and assembler flags.
|
||||
platform-cflags-y =
|
||||
platform-asflags-y =
|
||||
|
||||
# Linker flags: additional libraries and object files that the platform
|
||||
# code needs can be added here
|
||||
platform-ldflags-y =
|
||||
|
||||
#
|
||||
# Command for platform specific "make run"
|
||||
# Useful for development and debugging on plaftform simulator (such as QEMU)
|
||||
#
|
||||
# platform-runcmd = your_platform_run.sh
|
||||
|
||||
#
|
||||
# Platform RISC-V XLEN, ABI, ISA and Code Model configuration.
|
||||
# These are optional parameters but platforms can optionaly provide it.
|
||||
# Some of these are guessed based on GCC compiler capabilities
|
||||
#
|
||||
PLATFORM_RISCV_XLEN = 64
|
||||
PLATFORM_RISCV_ABI = lp64d
|
||||
PLATFORM_RISCV_ISA = rv64imafdc_zicsr_zifencei
|
||||
PLATFORM_RISCV_CODE_MODEL = medany
|
||||
|
||||
# Space separated list of object file names to be compiled for the platform
|
||||
platform-objs-y += platform.o
|
||||
|
||||
#
|
||||
# If the platform support requires a builtin device tree file, the name of
|
||||
# the device tree compiled file should be specified here. The device tree
|
||||
# source file be in the form <dt file name>.dts
|
||||
#
|
||||
# platform-objs-y += <dt file name>.o
|
||||
|
||||
# Optional parameter for path to external FDT
|
||||
# FW_FDT_PATH="path to platform flattened device tree file"
|
||||
|
||||
#
|
||||
# Dynamic firmware configuration.
|
||||
# Optional parameters are commented out. Uncomment and define these parameters
|
||||
# as needed.
|
||||
#
|
||||
FW_DYNAMIC=n
|
||||
|
||||
#
|
||||
# Jump firmware configuration.
|
||||
# Optional parameters are commented out. Uncomment and define these parameters
|
||||
# as needed.
|
||||
#
|
||||
FW_JUMP=n
|
||||
# This needs to be 4MB aligned for 32-bit support
|
||||
# This needs to be 2MB aligned for 64-bit support
|
||||
# ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||
# FW_JUMP_OFFSET=0x400000
|
||||
# else
|
||||
# FW_JUMP_OFFSET=0x200000
|
||||
# endif
|
||||
# FW_JUMP_FDT_OFFSET=0x2200000
|
||||
#
|
||||
# You can use fixed address for jump firmware as an alternative option.
|
||||
# SBI will prefer "<X>_ADDR" if both "<X>_ADDR" and "<X>_OFFSET" are
|
||||
# defined
|
||||
# ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||
# FW_JUMP_ADDR=0x80400000
|
||||
# else
|
||||
# FW_JUMP_ADDR=0x80200000
|
||||
# endif
|
||||
# FW_JUMP_FDT_ADDR=0x82200000
|
||||
|
||||
#
|
||||
# Firmware with payload configuration.
|
||||
# Optional parameters are commented out. Uncomment and define these parameters
|
||||
# as needed.
|
||||
#
|
||||
FW_PAYLOAD=y
|
||||
# This needs to be 4MB aligned for 32-bit support
|
||||
# This needs to be 2MB aligned for 64-bit support
|
||||
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||
FW_PAYLOAD_OFFSET=0x400000
|
||||
else
|
||||
FW_PAYLOAD_OFFSET=0x200000
|
||||
endif
|
||||
# FW_PAYLOAD_ALIGN=0x1000
|
||||
# FW_PAYLOAD_PATH="path to next boot stage binary image file"
|
||||
# FW_PAYLOAD_FDT_OFFSET=0x2200000
|
||||
#
|
||||
# You can use fixed address for payload firmware as an alternative option.
|
||||
# SBI will prefer "FW_PAYLOAD_FDT_ADDR" if both "FW_PAYLOAD_FDT_OFFSET"
|
||||
# and "FW_PAYLOAD_FDT_ADDR" are defined.
|
||||
# FW_PAYLOAD_FDT_ADDR=0x82200000
|
178
platform/riscv_vp/platform.c
Normal file
178
platform/riscv_vp/platform.c
Normal file
@@ -0,0 +1,178 @@
|
||||
#include <sbi/riscv_asm.h>
|
||||
#include <sbi/riscv_encoding.h>
|
||||
#include <sbi/sbi_const.h>
|
||||
#include <sbi/sbi_platform.h>
|
||||
#include <sbi/sbi_console.h>
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_ecall_interface.h>
|
||||
#include <sbi/sbi_ecall.h>
|
||||
#include <sbi/sbi_system.h>
|
||||
#include <sbi/riscv_asm.h>
|
||||
#include <sbi/sbi_timer.h>
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t RX_TX_REG;
|
||||
volatile uint32_t INT_CTRL_REG;
|
||||
volatile uint32_t CLK_DIVIDER_REG;
|
||||
volatile uint32_t FRAME_CONFIG_REG;
|
||||
volatile uint32_t STATUS_REG;
|
||||
} uart_t;
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t MSIP0;
|
||||
uint8_t fill0[16380];
|
||||
volatile uint32_t MTIMECMP0LO;
|
||||
volatile uint32_t MTIMECMP0HI;
|
||||
uint8_t fill1[32752];
|
||||
volatile uint32_t MTIME_LO;
|
||||
volatile uint32_t MTIME_HI;
|
||||
} aclint_t;
|
||||
|
||||
#define PERIPH(TYPE, ADDR) ((volatile TYPE *)(ADDR))
|
||||
#define uart PERIPH(uart_t, 0x10000000 + 0x01000)
|
||||
#define aclint PERIPH(aclint_t, 0x10000000 + 0x30000)
|
||||
static inline void set_aclint_mtimecmp0lo(volatile aclint_t* reg, uint32_t value) {
|
||||
reg->MTIMECMP0LO = (reg->MTIMECMP0LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
static inline void set_aclint_mtimecmp0hi(volatile aclint_t* reg, uint32_t value) {
|
||||
reg->MTIMECMP0HI = (reg->MTIMECMP0HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_aclint_mtime_lo(volatile aclint_t* reg) { return (reg->MTIME_LO >> 0) & 0xffffffff; }
|
||||
static inline uint32_t get_aclint_mtime_hi(volatile aclint_t* reg) { return (reg->MTIME_HI >> 0) & 0xffffffff; }
|
||||
|
||||
static inline uint32_t get_uart_rx_tx_reg_tx_free(volatile uart_t* reg) { return (reg->RX_TX_REG >> 15) & 0x1; }
|
||||
static inline void set_uart_rx_tx_reg_data(volatile uart_t* reg, uint8_t value) {
|
||||
reg->RX_TX_REG = (reg->RX_TX_REG & ~(0xffU << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_uart_rx_tx_reg_rx_avail(volatile uart_t* reg) { return (reg->RX_TX_REG >> 14) & 0x1; }
|
||||
static inline uint32_t get_uart_rx_tx_reg_data(volatile uart_t* reg) { return (reg->RX_TX_REG >> 0) & 0xff; }
|
||||
|
||||
static void riscv_vp_putc(char c){
|
||||
while(get_uart_rx_tx_reg_tx_free(uart) == 0)
|
||||
;
|
||||
set_uart_rx_tx_reg_data(uart, c);
|
||||
}
|
||||
static int riscv_vp_getc(){
|
||||
if (get_uart_rx_tx_reg_rx_avail(uart))
|
||||
return get_uart_rx_tx_reg_data(uart);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
const struct sbi_console_device minres_console = {
|
||||
.name = "riscv_vp-uart",
|
||||
.console_putc = riscv_vp_putc,
|
||||
.console_getc = riscv_vp_getc,
|
||||
};
|
||||
|
||||
void riscv_vp_reset(u32 reset_type, u32 reset_reason){
|
||||
switch (reset_type) {
|
||||
case SBI_SRST_RESET_TYPE_SHUTDOWN:
|
||||
sbi_printf("Shutting down system...\n");
|
||||
break;
|
||||
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
|
||||
sbi_printf("Performing cold reboot...\n");
|
||||
break;
|
||||
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
|
||||
sbi_printf("Performing warm reboot...\n");
|
||||
break;
|
||||
default:
|
||||
sbi_printf("Unknown system reset type: %u\n", reset_type);
|
||||
}
|
||||
while (1)
|
||||
wfi();
|
||||
};
|
||||
int riscv_vp_reset_check(u32 reset_type, u32 reset_reason){
|
||||
switch (reset_type) {
|
||||
case SBI_SRST_RESET_TYPE_SHUTDOWN:
|
||||
return 1;
|
||||
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
|
||||
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
|
||||
default:
|
||||
return 0;
|
||||
}};
|
||||
|
||||
|
||||
static struct sbi_system_reset_device reset_device = {
|
||||
.name = "riscv_vp-reset",
|
||||
.system_reset_check = riscv_vp_reset_check,
|
||||
.system_reset = riscv_vp_reset
|
||||
};
|
||||
|
||||
static u64 riscv_vp_timer_value(void){
|
||||
uint32_t hi, lo;
|
||||
do {
|
||||
hi = get_aclint_mtime_hi(aclint);
|
||||
lo = get_aclint_mtime_lo(aclint);
|
||||
} while (hi != get_aclint_mtime_hi(aclint));
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
static void riscv_vp_timer_event_start(u64 next_event){
|
||||
// sbi_printf("OpenSBI: setting timer at %#lx\n", next_event);
|
||||
set_aclint_mtimecmp0lo(aclint, (uint32_t)0xFFFFFFFF);
|
||||
set_aclint_mtimecmp0hi(aclint, (uint32_t)(next_event >> 32));
|
||||
set_aclint_mtimecmp0lo(aclint, (uint32_t)(next_event & 0xFFFFFFFF));
|
||||
}
|
||||
static void riscv_vp_timer_event_stop(void){
|
||||
// sbi_printf("OpenSBI: Cancelling pending event\n");
|
||||
set_aclint_mtimecmp0lo(aclint, (uint32_t)0xFFFFFFFF);
|
||||
set_aclint_mtimecmp0hi(aclint, (uint32_t)0xFFFFFFFF);
|
||||
}
|
||||
static int riscv_vp_timer_warm_init(void){
|
||||
riscv_vp_timer_event_stop();
|
||||
return 0;
|
||||
}
|
||||
static struct sbi_timer_device timer_device = {
|
||||
.name = "riscv_vp_timer",
|
||||
.timer_freq = 32768,
|
||||
.timer_value = riscv_vp_timer_value,
|
||||
.timer_event_start = riscv_vp_timer_event_start,
|
||||
.timer_event_stop = riscv_vp_timer_event_stop,
|
||||
.warm_init = riscv_vp_timer_warm_init
|
||||
};
|
||||
|
||||
static int platform_early_init(bool cold_boot){
|
||||
if (cold_boot){
|
||||
sbi_console_set_device(&minres_console);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int platform_final_init(bool cold_boot){
|
||||
if (cold_boot){
|
||||
sbi_system_reset_add_device(&reset_device);
|
||||
sbi_timer_set_device(&timer_device);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int platform_irqchip_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int platform_ipi_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int platform_timer_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const struct sbi_platform_operations platform_ops = {
|
||||
.early_init = platform_early_init,
|
||||
.final_init = platform_final_init,
|
||||
.irqchip_init = platform_irqchip_init,
|
||||
.ipi_init = platform_ipi_init,
|
||||
.timer_init = platform_timer_init
|
||||
};
|
||||
|
||||
|
||||
const struct sbi_platform platform = {
|
||||
.opensbi_version = OPENSBI_VERSION,
|
||||
.platform_version = SBI_PLATFORM_VERSION(0x1, 0x07),
|
||||
.name = "riscv_vp",
|
||||
.features = SBI_PLATFORM_DEFAULT_FEATURES,
|
||||
.hart_count = 1,
|
||||
.hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
|
||||
.heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(1),
|
||||
.platform_ops_addr = (unsigned long)&platform_ops
|
||||
};
|
Reference in New Issue
Block a user