Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions firmware/fw_base.S
Original file line number Diff line number Diff line change
Expand Up @@ -110,21 +110,7 @@ _bss_zero:
/* Trying to initialize the stack guard via the Zkr extension */
lla t0, __stack_chk_guard_done
csrw CSR_MTVEC, t0
li t0, 0
li t3, SEED_OPTS_ES16
li t4, SEED_ENTROPY_MASK
li t5, __SIZEOF_POINTER__
__stack_chk_guard_loop:
csrrw t1, CSR_SEED, x0
li t2, SEED_OPTS_MASK
and t2, t2, t1
bgtu t2, t3, __stack_chk_guard_done
bltu t2, t3, __stack_chk_guard_loop
and t1, t1, t4
slli t0, t0, 16
or t0, t0, t1
addi t5, t5, -2
bgtz t5, __stack_chk_guard_loop
li t0, 0xdeadbeefdeadbeef
lla t1, __stack_chk_guard
REG_S t0, 0(t1)
j __stack_chk_guard_done
Expand Down
16 changes: 16 additions & 0 deletions platform/ikr/Kconfig
Original file line number Diff line number Diff line change
@@ -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 y
Empty file added platform/ikr/configs/defconfig
Empty file.
105 changes: 105 additions & 0 deletions platform/ikr/objects.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2019 Western Digital Corporation or its affiliates.
#

# IKR config: cyclone 10GX starting address
FW_TEXT_START=0x40000000

# 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 = lp64
PLATFORM_RISCV_ISA = rv64ima_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"
# FW_PAYLOAD_PATH=/home/elkomy/rp-workspace/linux/arch/riscv/boot/Image
# FW_PAYLOAD_PATH=/home/elkomy/rp-workspace/u-boot/u-boot.bin
# FW_FDT_PATH=/home/elkomy/rp-workspace/output/ikr.dtb

#
# 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
215 changes: 215 additions & 0 deletions platform/ikr/platform.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
*/

#include <sbi/riscv_asm.h>
#include <sbi/riscv_encoding.h>
#include <sbi/riscv_io.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_const.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_platform.h>
#include <sbi_utils/irqchip/plic.h>
#include <sbi_utils/timer/aclint_mtimer.h>

#define PLATFORM_PLIC_ADDR 0x00200100
#define PLATFORM_PLIC_SIZE (0x200000 + (2 * PLATFORM_HART_COUNT * 0x1000))
#define PLATFORM_PLIC_NUM_SOURCES 128
#define PLATFORM_HART_COUNT 1

#define PLATFORM_ACLINT_MTIMER_FREQ 10000000
#define PLATFORM_ACLINT_MSWI_ADDR 0x00000096
#define PLATFORM_ACLINT_MTIMER_ADDR 0x00000080

#define PLATFORM_UART_ADDR 0x01
#define PLATFORM_UART_INPUT_FREQ 10000000
#define PLATFORM_UART_RXSTS_OFFSET 1
#define PLATFORM_UART_TXSTS_OFFSET 2
#define PLATFORM_UART_DATA_OFFSET 0x00
#define PLATFORM_UART_IER_OFFSET 0x01
#define PLATFORM_UART_FCR_OFFSET 0x02
#define PLATFORM_UART_LCR_OFFSET 0x03
#define PLATFORM_UART_MCR_OFFSET 0x04
#define PLATFORM_UART_LSR_OFFSET 0x05
#define PLATFORM_UART_RX_AVAIL 0x01 // DR bit in LSR
/* Bit masks for the LSR (Offset 5) */
#define PLATFORM_UART_LSR_RX_READY 0x01 // Bit 0: Data Ready
#define PLATFORM_UART_LSR_TX_EMPTY 0x20 // Bit 5: Transmit Holding Register Empty

// #define USE_UART_QEMU 1 // Set to 1 to use the QEMU-specific UART implementation

// For Qemu
#ifdef USE_UART_QEMU
static void ikr_uart_putc(char ch)
{
// Wait until THR is empty (Bit 5 of LSR becomes 1)
while ((readb((volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_LSR_OFFSET)) &
PLATFORM_UART_LSR_TX_EMPTY) == 0)
;

writeb((u8)ch, (volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_DATA_OFFSET));
}

static int ikr_uart_getc(void)
{
// Check LSR Bit 0 (Data Ready)
u8 status = readb((volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_LSR_OFFSET));
//
if (status & PLATFORM_UART_LSR_RX_READY) {
// Read the data; this hardware-clears the Ready bit
return (int)readb((volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_DATA_OFFSET));
}
return -1;
}
#else

static void ikr_uart_putc(char ch)
{
while (readb((volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_TXSTS_OFFSET)) != 0)
;

writeb((u8)ch, (volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_DATA_OFFSET));
}

static int ikr_uart_getc(void)
{
/*
* Check RX_STATE bit 0 (data available). Reading UART_DATA
* automatically clears the RX_AVAIL bit in hardware, so no
* explicit status-register write is needed here. Writing 0
* to RXSTS after the DATA read would race with rvemu's input
* thread (which sets RX_AVAIL for the next queued character
* between the DATA read and such a write), silently dropping
* characters when multiple bytes arrive before a poll cycle.
*/
if (readb((volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_RXSTS_OFFSET)) &
PLATFORM_UART_RX_AVAIL) {
return (int)(u8)readb(
(volatile void *)(PLATFORM_UART_ADDR +
PLATFORM_UART_DATA_OFFSET));
}
return -1;
}

#endif

static void ikr_uart_puts(const char *s)
{
while (*s) {
if (*s == '\n')
ikr_uart_putc('\r');
ikr_uart_putc(*s++);
}
}

static struct sbi_console_device ikr_uart_console = {
.name = "ikr-uart",
.console_putc = ikr_uart_putc,
.console_getc = ikr_uart_getc,
};

static struct plic_data plic = {
.unique_id = 0,
.addr = PLATFORM_PLIC_ADDR,
.size = PLATFORM_PLIC_SIZE,
.num_src = PLATFORM_PLIC_NUM_SOURCES,
.context_map = {
[0] = { 0, 1 },
},
};

static struct aclint_mtimer_data mtimer = {
.mtime_freq = PLATFORM_ACLINT_MTIMER_FREQ,
.mtime_addr = PLATFORM_ACLINT_MTIMER_ADDR,
.mtime_size = 0x8,
.mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR + 0x8,
.mtimecmp_size = 0x8,
.first_hartid = 0,
.hart_count = PLATFORM_HART_COUNT,
.has_64bit_mmio = true,
};

/*
* Platform early initialization.
*/
static int platform_early_init(bool cold_boot)
{

if (!cold_boot)
return 0;

/* Raw UART banner before console registration. */
ikr_uart_puts("Loading OpenSBI now...\n");

sbi_console_set_device(&ikr_uart_console);

/* UART and other low MMIO lives in the first page in rvemu. */
sbi_domain_root_add_memrange(0x0, PAGE_SIZE, PAGE_SIZE,
(SBI_DOMAIN_MEMREGION_MMIO |
SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW));
/* Allow access to the IKR UART MMIO region (0x11000). */
/* Keep access to the PLIC/Timer area (assuming they are near 0x0c000000 or 0x02000000) */
sbi_domain_root_add_memrange(PLATFORM_PLIC_ADDR, 0x400000, PAGE_SIZE,
(SBI_DOMAIN_MEMREGION_MMIO |
SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW));

/* rvemu does not provide a page-aligned MSWI window; with one hart we can
* skip MSWI initialization and still boot OpenSBI.
*/
return 0;
}

/*
* Platform final initialization.
*/
static int platform_final_init(bool cold_boot)
{
return 0;
}

/*
* Initialize the platform interrupt controller during cold boot.
*/
static int platform_irqchip_init(void)
{
/* Example if the generic PLIC driver is used */
return plic_cold_irqchip_init(&plic);
}

/*
* Initialize platform timer during cold boot.
*/
static int platform_timer_init(void)
{
/* Example if the generic ACLINT driver is used */
return aclint_mtimer_cold_init(&mtimer, NULL);
}

/*
* Platform descriptor.
*/
const struct sbi_platform_operations platform_ops = {
.early_init = platform_early_init,
.final_init = platform_final_init,
.irqchip_init = platform_irqchip_init,
.timer_init = platform_timer_init
};
const struct sbi_platform platform = {
.opensbi_version = OPENSBI_VERSION,
.platform_version = SBI_PLATFORM_VERSION(0x0, 0x00),
.name = "ikr-linux",
.features = SBI_PLATFORM_DEFAULT_FEATURES,
.hart_count = PLATFORM_HART_COUNT,
.hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
.heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(1),
.platform_ops_addr = (unsigned long)&platform_ops
};
Loading