149 lines
4.3 KiB
Diff
149 lines
4.3 KiB
Diff
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
|
|
+};
|