Working OpenSBI 1.2

This commit is contained in:
Rodrigo Arias 2024-06-27 11:29:15 +02:00
parent c8efa952f9
commit 1bfc32e91a
6 changed files with 1013 additions and 4 deletions

438
alveo-uart-sbi-hack.patch Normal file
View File

@ -0,0 +1,438 @@
diff --git a/include/sbi_utils/serial/alveo_uart.h b/include/sbi_utils/serial/alveo_uart.h
new file mode 100644
index 0000000..0b6408c
--- /dev/null
+++ b/include/sbi_utils/serial/alveo_uart.h
@@ -0,0 +1,13 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SERIAL_ALVEO_UART_H__
+#define __SERIAL_ALVEO_UART_H__
+
+#include <sbi/sbi_types.h>
+
+int alveo_uart_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
+ u32 reg_width, u32 reg_offset);
+
+#endif
diff --git a/lib/utils/serial/Kconfig b/lib/utils/serial/Kconfig
index e3589ca..b754c7c 100644
--- a/lib/utils/serial/Kconfig
+++ b/lib/utils/serial/Kconfig
@@ -84,6 +84,10 @@ config SERIAL_UART8250
bool "8250 UART support"
default n
+config SERIAL_ALVEO_UART
+ bool "ALveo UART support"
+ default n
+
config SERIAL_XILINX_UARTLITE
bool "Xilinx UART Lite support"
default n
diff --git a/lib/utils/serial/alveo_uart.c b/lib/utils/serial/alveo_uart.c
new file mode 100644
index 0000000..a351741
--- /dev/null
+++ b/lib/utils/serial/alveo_uart.c
@@ -0,0 +1,123 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_console.h>
+#include <sbi_utils/serial/alveo_uart.h>
+
+/* clang-format off */
+
+#define UART_RBR_OFFSET 0 /* In: Recieve Buffer Register */
+#define UART_THR_OFFSET 0 /* Out: Transmitter Holding Register */
+#define UART_DLL_OFFSET 0 /* Out: Divisor Latch Low */
+#define UART_IER_OFFSET 1 /* I/O: Interrupt Enable Register */
+#define UART_DLM_OFFSET 1 /* Out: Divisor Latch High */
+#define UART_FCR_OFFSET 2 /* Out: FIFO Control Register */
+#define UART_IIR_OFFSET 2 /* I/O: Interrupt Identification Register */
+#define UART_LCR_OFFSET 3 /* Out: Line Control Register */
+#define UART_MCR_OFFSET 4 /* Out: Modem Control Register */
+#define UART_LSR_OFFSET 5 /* In: Line Status Register */
+#define UART_MSR_OFFSET 6 /* In: Modem Status Register */
+#define UART_SCR_OFFSET 7 /* I/O: Scratch Register */
+#define UART_MDR1_OFFSET 8 /* I/O: Mode Register */
+
+#define UART_LSR_FIFOE 0x80 /* Fifo error */
+#define UART_LSR_TEMT 0x40 /* Transmitter empty */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */
+#define UART_LSR_FE 0x08 /* Frame error indicator */
+#define UART_LSR_PE 0x04 /* Parity error indicator */
+#define UART_LSR_OE 0x02 /* Overrun error indicator */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */
+
+/* clang-format on */
+
+static volatile char *alveo_uart_base;
+static u32 alveo_uart_in_freq;
+static u32 alveo_uart_baudrate;
+static u32 alveo_uart_reg_width;
+static u32 alveo_uart_reg_shift;
+
+static u32 get_reg(u32 num)
+{
+ u32 offset = num << alveo_uart_reg_shift;
+
+ if (alveo_uart_reg_width == 1)
+ return readb(alveo_uart_base + offset);
+ else if (alveo_uart_reg_width == 2)
+ return readw(alveo_uart_base + offset);
+ else
+ return readl(alveo_uart_base + offset);
+}
+
+static void set_reg(u32 num, u32 val)
+{
+ u32 offset = num << alveo_uart_reg_shift;
+
+ if (alveo_uart_reg_width == 1)
+ writeb(val, alveo_uart_base + offset);
+ else if (alveo_uart_reg_width == 2)
+ writew(val, alveo_uart_base + offset);
+ else
+ writel(val, alveo_uart_base + offset);
+}
+
+static void alveo_uart_putc(char ch)
+{
+ while (!(get_reg(UART_LSR_OFFSET) & UART_LSR_TEMT))
+ ;
+
+ set_reg(UART_THR_OFFSET, ch);
+}
+
+static int alveo_uart_getc(void)
+{
+ if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
+ return get_reg(UART_RBR_OFFSET);
+ return -1;
+}
+
+static struct sbi_console_device alveo_uart_console = {
+ .name = "alveo_uart",
+ .console_putc = alveo_uart_putc,
+ .console_getc = alveo_uart_getc
+};
+
+int alveo_uart_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
+ u32 reg_width, u32 reg_offset)
+{
+ u16 bdiv = 0;
+
+ alveo_uart_base = (volatile char *)base + reg_offset;
+ alveo_uart_reg_shift = reg_shift;
+ alveo_uart_reg_width = reg_width;
+ alveo_uart_in_freq = in_freq;
+ alveo_uart_baudrate = baudrate;
+
+ if (alveo_uart_baudrate) {
+ bdiv = alveo_uart_in_freq / (16 * alveo_uart_baudrate);
+ }
+
+ /* Disable all interrupts */
+ set_reg(UART_IER_OFFSET, 0x00);
+ /* Enable DLAB */
+ set_reg(UART_LCR_OFFSET, 0x80);
+
+ if (bdiv) {
+ /* Set divisor low byte */
+ set_reg(UART_DLL_OFFSET, bdiv & 0xff);
+ /* Set divisor high byte */
+ set_reg(UART_DLM_OFFSET, (bdiv >> 8) & 0xff);
+ }
+
+ /* 8 bits, no parity, one stop bit */
+ set_reg(UART_LCR_OFFSET, 0x03); // previous was 0x0B
+ /* Disable all interrupts*/
+ set_reg(UART_IER_OFFSET, 0x00);
+
+ sbi_console_set_device(&alveo_uart_console);
+
+ return 0;
+}
diff --git a/lib/utils/serial/objects.mk b/lib/utils/serial/objects.mk
index 1e6bd2e..0268bdf 100644
--- a/lib/utils/serial/objects.mk
+++ b/lib/utils/serial/objects.mk
@@ -44,5 +44,6 @@ libsbiutils-objs-$(CONFIG_SERIAL_SHAKTI) += serial/shakti-uart.o
libsbiutils-objs-$(CONFIG_SERIAL_SIFIVE) += serial/sifive-uart.o
libsbiutils-objs-$(CONFIG_SERIAL_LITEX) += serial/litex-uart.o
libsbiutils-objs-$(CONFIG_SERIAL_UART8250) += serial/uart8250.o
+libsbiutils-objs-$(CONFIG_SERIAL_ALVEO_UART) += serial/alveo_uart.o
libsbiutils-objs-$(CONFIG_SERIAL_XILINX_UARTLITE) += serial/xlnx-uartlite.o
libsbiutils-objs-$(CONFIG_SERIAL_SEMIHOSTING) += serial/semihosting.o
diff --git a/platform/fpga/sargantana_alveo/Kconfig b/platform/fpga/sargantana_alveo/Kconfig
new file mode 100644
index 0000000..bf3e7e6
--- /dev/null
+++ b/platform/fpga/sargantana_alveo/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+config PLATFORM_SARGANTANA_ALVEO_FPGA
+ bool
+ select FDT
+ select IPI_MSWI
+ select IRQCHIP_PLIC
+ select SERIAL_ALVEO_UART
+ select TIMER_MTIMER
+ default y
diff --git a/platform/fpga/sargantana_alveo/configs/defconfig b/platform/fpga/sargantana_alveo/configs/defconfig
new file mode 100644
index 0000000..e69de29
diff --git a/platform/fpga/sargantana_alveo/objects.mk b/platform/fpga/sargantana_alveo/objects.mk
new file mode 100644
index 0000000..d444abe
--- /dev/null
+++ b/platform/fpga/sargantana_alveo/objects.mk
@@ -0,0 +1,87 @@
+#
+# 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 = rv64imafd
+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
+
+# Firmware load address configuration. This is mandatory.
+FW_TEXT_START=0x80000000
+
+# 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_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_ADDR=0x82200000
diff --git a/platform/fpga/sargantana_alveo/platform.c b/platform/fpga/sargantana_alveo/platform.c
new file mode 100644
index 0000000..a359b34
--- /dev/null
+++ b/platform/fpga/sargantana_alveo/platform.c
@@ -0,0 +1,146 @@
+/*
+ * 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/sbi_const.h>
+#include <sbi/sbi_platform.h>
+
+/*
+ * Include these files as needed.
+ * See objects.mk SARGANTANA_ALVEO_xxx configuration parameters.
+ */
+
+#include <sbi_utils/serial/alveo_uart.h>
+#include <sbi/sbi_timer.h>
+
+#define SARGANTANA_ALVEO_HART_COUNT 1
+
+#define SARGANTANA_ALVEO_UART_BASE_ADDR 0x40000000
+#define SARGANTANA_ALVEO_UART_OFFSET 0x1000
+//#define SARGANTANA_ALVEO_UART_ADDR SARGANTANA_ALVEO_UART_BASE_ADDR + SARGANTANA_ALVEO_UART_XLNX_OFFSET
+#define SARGANTANA_ALVEO_UART_INPUT_FREQ 50000000
+#define SARGANTANA_ALVEO_UART_BAUDRATE 115200
+
+#define SARGANTANA_ALVEO_TIMER_BASE 0x40170000
+#define ADDR_TIME_L 0x0u // 32 lower bits of the time register
+#define ADDR_TIME_H 0x1u // 32 higher bits of the time register
+#define ADDR_TIMECMP_L 0x2u // 32 lower bits of the time comparator
+#define ADDR_TIMECMP_H 0x3u // 32 higher bits of the time comparator
+
+volatile uint32_t *timer_base_ptr = (uint32_t *)(SARGANTANA_ALVEO_TIMER_BASE);
+
+/*
+ * Platform early initialization.
+ */
+static int sargantana_alveo_early_init(bool cold_boot)
+{
+ return 0;
+}
+
+/*
+ * Platform final initialization.
+ */
+static int sargantana_alveo_final_init(bool cold_boot)
+{
+ return 0;
+}
+
+/*
+ * Initialize the platform console.
+ */
+static int sargantana_alveo_console_init(void)
+{
+ return alveo_uart_init(SARGANTANA_ALVEO_UART_BASE_ADDR,
+ SARGANTANA_ALVEO_UART_INPUT_FREQ,
+ SARGANTANA_ALVEO_UART_BAUDRATE,
+ 2, 4,
+ SARGANTANA_ALVEO_UART_OFFSET);
+}
+
+/*
+ * Initialize the platform interrupt controller for current HART.
+ */
+static int sargantana_alveo_irqchip_init(bool cold_boot)
+{
+ u32 hartid = current_hartid();
+ return hartid;
+}
+
+/*
+ * Initialize IPI for current HART.
+ */
+static int sargantana_alveo_ipi_init(bool cold_boot)
+{
+ return 0;
+}
+
+/*
+ * Get platform timer value.
+ */
+static u64 sargantana_alveo_timer_value(void)
+{
+ return ((u64)*(timer_base_ptr + ADDR_TIME_H) << 32) + *(timer_base_ptr + ADDR_TIME_L);
+}
+
+/*
+ * Start platform timer event for current HART.
+ */
+static void sargantana_alveo_timer_event_start(u64 next_event)
+{
+ *(timer_base_ptr + ADDR_TIMECMP_H) = next_event >> 32;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = next_event;
+}
+
+/*
+ * Stop platform timer event for current HART.
+ */
+static void sargantana_alveo_timer_event_stop(void)
+{
+
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
+}
+
+static struct sbi_timer_device mtimer = {
+ .name = "generic_timer", // TODO Where the timer comes from? I would prefer a better name :p
+ .timer_freq = SARGANTANA_ALVEO_UART_INPUT_FREQ,
+ .timer_value = sargantana_alveo_timer_value,
+ .timer_event_start = sargantana_alveo_timer_event_start,
+ .timer_event_stop = sargantana_alveo_timer_event_stop
+};
+
+/*
+ * Initialize platform timer for current HART.
+ */
+static int sargantana_alveo_timer_init(bool cold_boot)
+{
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
+ sbi_timer_set_device(&mtimer);
+ return 0;
+}
+
+/*
+ * Platform descriptor.
+ */
+const struct sbi_platform_operations sargantana_alveo_ops = {
+ .early_init = sargantana_alveo_early_init,
+ .final_init = sargantana_alveo_final_init,
+ .console_init = sargantana_alveo_console_init,
+ .irqchip_init = sargantana_alveo_irqchip_init,
+ .ipi_init = sargantana_alveo_ipi_init,
+ .timer_init = sargantana_alveo_timer_init
+};
+const struct sbi_platform platform = {
+ .opensbi_version = OPENSBI_VERSION,
+ .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
+ .name = "Sargantana (for Xilinx Alveo FPGA)",
+ .features = SBI_PLATFORM_DEFAULT_FEATURES,
+ .hart_count = SARGANTANA_ALVEO_HART_COUNT,
+ .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
+ .platform_ops_addr = (unsigned long)&sargantana_alveo_ops
+};

View File

@ -5,6 +5,13 @@
"${modulesPath}/installer/sd-card/sd-image.nix"
];
# No need, Lagarto OX has support for rv64gc.
#nixpkgs.crossSystem = {
# system = "riscv64-linux";
# gcc.arch = "rv64imafd";
# gcc.tune = "rv64imafd";
#};
#boot.kernelPackages = pkgs.linuxPackages_latest;
boot = {
kernelPatches = [
@ -121,12 +128,61 @@
echo 'booti ''${kernel_addr_r} ''${ramdisk_addr_r}:''${ramdisk_size} ''${fdtcontroladdr}' >> $out
'';
opensbi = prev.opensbi.overrideAttrs (old: {
makeFlags = old.makeFlags ++ [
"PLATFORM=fpga/openpiton"
# Lagarto OX doesn't work with newer versions of OpenSBI (1.3, 1.4), not
# sure why.
opensbi = prev.opensbi.overrideAttrs (old: rec {
version = "1.2"; # ok
#version = "1.3"; # bad
#version = "1.4"; # bad
src = prev.fetchFromGitHub {
owner = "riscv-software-src";
repo = "opensbi";
rev = "v${version}";
hash = "sha256-Zcl+SE2nySMycV/ozsl4AvGipRsMblA5mt3oVZ81Z44="; #1.2
#hash = "sha256-Dr16fVUGLYGnGYHkjAyqpJxt8p95F0CJIU9ESGWKGWo="; #1.3
#hash = "sha256-T8ZeAzjM9aeTXitjE7s+m+jjGGtDo2jK1qO5EuKiVLU="; #1.4
};
#NIX_DEBUG=5;
# Compile dts to dtb form
nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ prev.buildPackages.dtc ];
dtsFile = ./ox-plic.dts;
preBuild = ''
dtc -O dtb -o ox.dtb $dtsFile
'';
makeFlags = [
"PLATFORM=fpga/ox_alveo"
#"CONFIG_SBI_ECALL_RFENCE=n"
#"PLATFORM_RISCV_ISA=rv64imafd" # No compressed instructions
#"PLATFORM_RISCV_ISA=rv64g" # No compressed instructions
#"PLATFORM_RISCV_ABI=lp64d"
"FW_PAYLOAD_PATH=${final.uboot}/u-boot-nodtb.bin"
"FW_FDT_PATH=ox.dtb"
];
patches = [ ./opensbi-lagarto-hun.patch ];
patches = [ ./ox-alveo-platform-plic.patch ];
});
# opensbi = prev.opensbi.overrideAttrs (old: {
# #NIX_DEBUG=5;
# # Compile dts to dtb form
# #nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ prev.buildPackages.dtc ];
# #preBuild = ''
# # dtc -O dtb -o ox.dtb ${./ox.dts}
# #'';
# makeFlags = old.makeFlags ++ [
# "PLATFORM=fpga/sargantana_alveo"
# #"PLATFORM_RISCV_ISA=rv64imafd" # No compressed instructions
# "PLATFORM_RISCV_ISA=rv64g" # No compressed instructions
# #"PLATFORM_RISCV_ABI=lp64d"
# "FW_PAYLOAD_PATH=${final.uboot}/u-boot-nodtb.bin"
# #"FW_FDT_PATH=ox.dtb"
# ];
# patches = [ ./alveo-uart-sbi-hack.patch ];
# });
# opensbi = prev.opensbi.overrideAttrs (old: {
# makeFlags = old.makeFlags ++ [
# "PLATFORM=fpga/openpiton"
# "FW_PAYLOAD_PATH=${final.uboot}/u-boot-nodtb.bin"
# ];
# patches = [ ./opensbi-lagarto-hun.patch ];
# });
}) ];
}

View File

@ -0,0 +1,166 @@
diff --git a/platform/fpga/ox_alveo/Kconfig b/platform/fpga/ox_alveo/Kconfig
new file mode 100644
index 0000000..bf3e7e6
--- /dev/null
+++ b/platform/fpga/ox_alveo/Kconfig
@@ -0,0 +1,5 @@
+config PLATFORM_OX_ALVEO_FPGA
+ bool
+ select SERIAL_UART8250
+ select IRQCHIP_PLIC
+ default y
diff --git a/platform/fpga/ox_alveo/configs/defconfig b/platform/fpga/ox_alveo/configs/defconfig
new file mode 100644
index 0000000..e69de29
diff --git a/platform/fpga/ox_alveo/objects.mk b/platform/fpga/ox_alveo/objects.mk
new file mode 100644
index 0000000..d444abe
--- /dev/null
+++ b/platform/fpga/ox_alveo/objects.mk
@@ -0,0 +1,19 @@
+platform-cppflags-y =
+platform-cflags-y =
+platform-asflags-y =
+platform-ldflags-y =
+PLATFORM_RISCV_XLEN = 64
+PLATFORM_RISCV_ABI = lp64d
+PLATFORM_RISCV_ISA = rv64g
+PLATFORM_RISCV_CODE_MODEL = medany
+
+platform-objs-y += platform.o
+
+FW_TEXT_START=0x80000000
+
+FW_DYNAMIC=n
+FW_JUMP=n
+FW_PAYLOAD=y
+
+FW_PAYLOAD_OFFSET=0x200000
+FW_PAYLOAD_ALIGN=0x1000
diff --git a/platform/fpga/ox_alveo/platform.c b/platform/fpga/ox_alveo/platform.c
new file mode 100644
index 0000000..a359b34
--- /dev/null
+++ b/platform/fpga/ox_alveo/platform.c
@@ -0,0 +1,121 @@
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_const.h>
+#include <sbi/sbi_platform.h>
+#include <sbi_utils/serial/uart8250.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/irqchip/plic.h>
+
+#define OX_ALVEO_HART_COUNT 1
+
+#define OX_ALVEO_UART_BASE_ADDR 0x40000000
+#define OX_ALVEO_UART_OFFSET 0x1000
+#define OX_ALVEO_UART_INPUT_FREQ 50000000
+#define OX_ALVEO_UART_BAUDRATE 115200
+#define OX_ALVEO_PLIC_ADDR 0x40800000
+#define OX_ALVEO_PLIC_NUM_SOURCES 3
+
+#define OX_ALVEO_TIMER_BASE 0x40170000
+#define ADDR_TIME_L 0x0u // 32 lower bits of the time register
+#define ADDR_TIME_H 0x1u // 32 higher bits of the time register
+#define ADDR_TIMECMP_L 0x2u // 32 lower bits of the time comparator
+#define ADDR_TIMECMP_H 0x3u // 32 higher bits of the time comparator
+
+volatile uint32_t *timer_base_ptr = (uint32_t *)(OX_ALVEO_TIMER_BASE);
+
+static struct plic_data plic = {
+ .addr = OX_ALVEO_PLIC_ADDR,
+ .num_src = OX_ALVEO_PLIC_NUM_SOURCES,
+};
+
+static int ox_alveo_early_init(bool cold_boot) // Platform early initialization.
+{
+ return 0;
+}
+
+static int ox_alveo_final_init(bool cold_boot) // Platform final initialization.
+{
+ return 0;
+}
+
+static int ox_alveo_console_init(void) // Initialize the platform console.
+{
+ return uart8250_init(OX_ALVEO_UART_BASE_ADDR,
+ OX_ALVEO_UART_INPUT_FREQ,
+ OX_ALVEO_UART_BAUDRATE,
+ 2, 4,
+ OX_ALVEO_UART_OFFSET);
+}
+
+static int ox_alveo_irqchip_init(bool cold_boot) // Initialize the platform interrupt controller for current HART.
+{
+ u32 hartid = current_hartid();
+ int ret;
+
+ /* Example if the generic PLIC driver is used */
+ if (cold_boot) {
+ ret = plic_cold_irqchip_init(&plic);
+ if (ret)
+ return ret;
+ }
+
+ return plic_warm_irqchip_init(&plic, 2 * hartid, -1);
+}
+
+static int ox_alveo_ipi_init(bool cold_boot) // Initialize IPI for current HART.
+{
+ return 0;
+}
+
+static u64 ox_alveo_timer_value(void) // Get platform timer value.
+{
+ return ((u64)*(timer_base_ptr + ADDR_TIME_H) << 32) + *(timer_base_ptr + ADDR_TIME_L);
+}
+
+static void ox_alveo_timer_event_start(u64 next_event) // Start platform timer event for current HART.
+{
+ *(timer_base_ptr + ADDR_TIMECMP_H) = next_event >> 32;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = next_event;
+}
+
+static void ox_alveo_timer_event_stop(void) // Stop platform timer event for current HART.
+{
+
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
+}
+
+static struct sbi_timer_device mtimer = {
+ .name = "axi_timer",
+ .timer_freq = OX_ALVEO_UART_INPUT_FREQ,
+ .timer_value = ox_alveo_timer_value,
+ .timer_event_start = ox_alveo_timer_event_start,
+ .timer_event_stop = ox_alveo_timer_event_stop
+};
+
+static int ox_alveo_timer_init(bool cold_boot) // Initialize platform timer for current HART.
+{
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
+ sbi_timer_set_device(&mtimer);
+ return 0;
+}
+
+const struct sbi_platform_operations ox_alveo_ops = { // Platform descriptor.
+ .early_init = ox_alveo_early_init,
+ .final_init = ox_alveo_final_init,
+ .console_init = ox_alveo_console_init,
+ .irqchip_init = ox_alveo_irqchip_init,
+ .ipi_init = ox_alveo_ipi_init,
+ .timer_init = ox_alveo_timer_init
+};
+
+const struct sbi_platform platform = {
+ .opensbi_version = OPENSBI_VERSION,
+ .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
+ .name = "ox (Rodrigo NixOS version)",
+ .features = SBI_PLATFORM_DEFAULT_FEATURES,
+ .hart_count = OX_ALVEO_HART_COUNT,
+ .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
+ .platform_ops_addr = (unsigned long)&ox_alveo_ops
+};

148
ox-alveo-platform.patch Normal file
View File

@ -0,0 +1,148 @@
diff --git a/platform/fpga/ox_alveo/Kconfig b/platform/fpga/ox_alveo/Kconfig
new file mode 100644
index 0000000..bf3e7e6
--- /dev/null
+++ b/platform/fpga/ox_alveo/Kconfig
@@ -0,0 +1,4 @@
+config PLATFORM_OX_ALVEO_FPGA
+ bool
+ select SERIAL_UART8250
+ default y
diff --git a/platform/fpga/ox_alveo/configs/defconfig b/platform/fpga/ox_alveo/configs/defconfig
new file mode 100644
index 0000000..e69de29
diff --git a/platform/fpga/ox_alveo/objects.mk b/platform/fpga/ox_alveo/objects.mk
new file mode 100644
index 0000000..d444abe
--- /dev/null
+++ b/platform/fpga/ox_alveo/objects.mk
@@ -0,0 +1,19 @@
+platform-cppflags-y =
+platform-cflags-y =
+platform-asflags-y =
+platform-ldflags-y =
+PLATFORM_RISCV_XLEN = 64
+PLATFORM_RISCV_ABI = lp64d
+PLATFORM_RISCV_ISA = rv64imafd
+PLATFORM_RISCV_CODE_MODEL = medany
+
+platform-objs-y += platform.o
+
+FW_TEXT_START=0x80000000
+
+FW_DYNAMIC=n
+FW_JUMP=n
+FW_PAYLOAD=y
+
+FW_PAYLOAD_OFFSET=0x200000
+FW_PAYLOAD_ALIGN=0x1000
diff --git a/platform/fpga/ox_alveo/platform.c b/platform/fpga/ox_alveo/platform.c
new file mode 100644
index 0000000..a359b34
--- /dev/null
+++ b/platform/fpga/ox_alveo/platform.c
@@ -0,0 +1,104 @@
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_const.h>
+#include <sbi/sbi_platform.h>
+#include <sbi_utils/serial/uart8250.h>
+#include <sbi/sbi_timer.h>
+
+#define OX_ALVEO_HART_COUNT 1
+
+#define OX_ALVEO_UART_BASE_ADDR 0x40000000
+#define OX_ALVEO_UART_OFFSET 0x1000
+#define OX_ALVEO_UART_INPUT_FREQ 50000000
+#define OX_ALVEO_UART_BAUDRATE 115200
+
+#define OX_ALVEO_TIMER_BASE 0x40170000
+#define ADDR_TIME_L 0x0u // 32 lower bits of the time register
+#define ADDR_TIME_H 0x1u // 32 higher bits of the time register
+#define ADDR_TIMECMP_L 0x2u // 32 lower bits of the time comparator
+#define ADDR_TIMECMP_H 0x3u // 32 higher bits of the time comparator
+
+volatile uint32_t *timer_base_ptr = (uint32_t *)(OX_ALVEO_TIMER_BASE);
+
+static int ox_alveo_early_init(bool cold_boot) // Platform early initialization.
+{
+ return 0;
+}
+
+static int ox_alveo_final_init(bool cold_boot) // Platform final initialization.
+{
+ return 0;
+}
+
+static int ox_alveo_console_init(void) // Initialize the platform console.
+{
+ return uart8250_init(OX_ALVEO_UART_BASE_ADDR,
+ OX_ALVEO_UART_INPUT_FREQ,
+ OX_ALVEO_UART_BAUDRATE,
+ 2, 4,
+ OX_ALVEO_UART_OFFSET);
+}
+
+static int ox_alveo_irqchip_init(bool cold_boot) // Initialize the platform interrupt controller for current HART.
+{
+ u32 hartid = current_hartid();
+ return hartid;
+}
+
+static int ox_alveo_ipi_init(bool cold_boot) // Initialize IPI for current HART.
+{
+ return 0;
+}
+
+static u64 ox_alveo_timer_value(void) // Get platform timer value.
+{
+ return ((u64)*(timer_base_ptr + ADDR_TIME_H) << 32) + *(timer_base_ptr + ADDR_TIME_L);
+}
+
+static void ox_alveo_timer_event_start(u64 next_event) // Start platform timer event for current HART.
+{
+ *(timer_base_ptr + ADDR_TIMECMP_H) = next_event >> 32;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = next_event;
+}
+
+static void ox_alveo_timer_event_stop(void) // Stop platform timer event for current HART.
+{
+
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
+}
+
+static struct sbi_timer_device mtimer = {
+ .name = "axi_timer",
+ .timer_freq = OX_ALVEO_UART_INPUT_FREQ,
+ .timer_value = ox_alveo_timer_value,
+ .timer_event_start = ox_alveo_timer_event_start,
+ .timer_event_stop = ox_alveo_timer_event_stop
+};
+
+static int ox_alveo_timer_init(bool cold_boot) // Initialize platform timer for current HART.
+{
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
+ sbi_timer_set_device(&mtimer);
+ return 0;
+}
+
+const struct sbi_platform_operations ox_alveo_ops = { // Platform descriptor.
+ .early_init = ox_alveo_early_init,
+ .final_init = ox_alveo_final_init,
+ .console_init = ox_alveo_console_init,
+ .irqchip_init = ox_alveo_irqchip_init,
+ .ipi_init = ox_alveo_ipi_init,
+ .timer_init = ox_alveo_timer_init
+};
+
+const struct sbi_platform platform = {
+ .opensbi_version = OPENSBI_VERSION,
+ .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
+ .name = "ox (for Xilinx Alveo FPGA)",
+ .features = SBI_PLATFORM_DEFAULT_FEATURES,
+ .hart_count = OX_ALVEO_HART_COUNT,
+ .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
+ .platform_ops_addr = (unsigned long)&ox_alveo_ops
+};

143
ox-plic.dts Normal file
View File

@ -0,0 +1,143 @@
/dts-v1/;
/ {
#address-cells = <0x00000002>;
#size-cells = <0x00000002>;
compatible = "riscv,rv64i";
model = "Barcelona Supercomputing Center - Lagarto Ox";
chosen {
bootargs = "earlyprintk ignore_loglevel earlycon=sbi console=hvc0 root=/dev/pmem0p1 ro init=/bin/bash";
};
cpus {
#address-cells = <0x00000001>;
#size-cells = <0x00000000>;
timebase-frequency = <0x0000c350>;
cpu@0 {
clock-frequency = <0x02FAF080>;
device_type = "cpu";
reg = <0x00000000>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafd";
mmu-type = "riscv,sv39";
tlb-split;
L3: interrupt-controller {
#interrupt-cells = <0x00000001>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};
};
memory@80000000 {
device_type = "memory";
reg = <0x00000000 0x80000000 0x00000000 0x77e00000>;
};
reserved-memory {
#address-cells = <0x00000002>;
#size-cells = <0x00000002>;
ranges;
eth_pool: dma_pool@60000000 {
reg = <0x00000000 0x60000000 0x00000000 0x10000000>;
compatible = "shared-dma-pool";
};
onic_pool: dma_pool@70000000 {
reg = <0x00000000 0x70000000 0x00000000 0x10000000>;
compatible = "shared-dma-pool";
};
};
eth0_clk: eth0_clk {
compatible = "fixed-clock";
#clock-cells = <0x00000000>;
clock-frequency = <0x09502f90>;
};
pmem@1bff00000 {
volatile;
compatible = "pmem-region";
reg = <0x00000001 0xbff00000 0x00000000 0xc0100000>;
};
pmem2@1b7f00000 {
#address-cells = <0x00000002>;
#size-cells = <0x00000002>;
volatile;
compatible = "pmem-region";
reg = <0x00000001 0xb7f00000 0x00000000 0x08000000>;
};
pmem3@f7e00000 {
volatile;
compatible = "pmem-region";
reg = <0x00000000 0xf7e00000 0x00000000 0xc0100000>;
};
soc {
#address-cells = <0x00000002>;
#size-cells = <0x00000002>;
compatible = "BSC,Lagarto-bare-soc", "simple-bus";
ranges;
serial@40001000 {
compatible = "ns16750";
reg = <0x00000000 0x40001000 0x00000000 0x00001000>;
interrupts = <0x00000000>;
port-number = <0x00000000>;
reg-shift = <0x00000002>;
clock-frequency = <0x02FAF080>;
current-speed = <0x0001c200>;
status = "okay";
};
ethernet0 {
xlnx,rxmem = <0x000005f2>;
carv,mtu = <0x000005dc>;
carv,no-mac;
device_type = "network";
local-mac-address = [02 05 00 01 00 05];
axistream-connected = <0x000000fe>;
compatible = "xlnx,xxv-ethernet-1.0-carv";
memory-region = <&eth_pool>;
};
dma@40400000 {
xlnx,include-dre;
phandle = <0x000000fe>;
#dma-cells = <0x00000001>;
compatible = "xlnx,axi-dma-1.00.a";
clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk", "m_axi_sg_aclk";
clocks = <&eth0_clk>, <&eth0_clk>, <&eth0_clk>, <&eth0_clk>;
reg = <0x00000000 0x40400000 0x00000000 0x00400000>;
interrupt-names = "mm2s_introut", "s2mm_introut";
interrupt-parent = <&PLIC0>;
interrupts = <0x00000002 0x00000003>;
xlnx,addrwidth = <0x00000028>;
xlnx,include-sg;
xlnx,sg-length-width = <0x00000017>;
dma-channel@40400000 {
compatible = "xlnx,axi-dma-mm2s-channel";
dma-channels = <0x00000000>;
interrupts = <0x00000002>;
xlnx,datawidth = <0x00000040>;
xlnx,device-id = <0x00000000>;
xlnx,include-dre;
};
dma-channel@40400030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <0x00000001>;
interrupts = <0x00000003>;
xlnx,datawidth = <0x00000040>;
xlnx,device-id = <0x00000000>;
xlnx,include-dre;
};
};
clint@40002000 {
reg-names = "control";
interrupts-extended = <0x00000004 0x00000003 0x00000004 0x00000007 0x00000005 0x00000003 0x00000005 0x00000007 0x00000006 0x00000003 0x00000006 0x00000007 0x00000007 0x00000003 0x00000007 0x00000007>;
compatible = "riscv,clint0";
#interrupt-cells = <0x00000001>;
reg = <0x00000000 0x40002000 0x00000000 0x000c0000>;
};
PLIC0: plic@40800000 {
#interrupt-cells = <1>;
compatible = "riscv,plic0";
interrupt-controller;
interrupts-extended = <&L3 3 &L3 7>;
reg = < 0x00000000 0x40800000 0x00000000 0x00400000>;
riscv,ndev = <0x00000003>;
riscv,max-priority = <0x00000007>;
};
};
};

58
ox.dts Normal file
View File

@ -0,0 +1,58 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "riscv,rv64i";
model = "Barcelona Supercomputing Center - OX";
chosen {
bootargs = "earlycon=sbi console=ttyS0,115200n8";
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <50000>; // 32.768 kHz
CPU0: cpu@0 {
//clock-frequency = <25000000>; // 25 MHz
clock-frequency = <50000000>; // 50 MHz
device_type = "cpu";
reg = <0>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafd";
mmu-type = "riscv,sv39";
tlb-split;
// HLIC - hart local interrupt controller
CPU0_intc: interrupt-controller {
#address-cells = <1>;
#interrupt-cells = <1>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};
};
uart0: serial@40001000 {
compatible = "ns16750";
//reg = <0x40001000 0x1000>;
reg = <0x00000000 0x40001000 0x00000000 0x00000100>;
interrupts = <0>;
port-number = <0>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <25000000>;
current-speed = <115200>;
status = "okay";
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x40000000>;
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
};
};