diff --git a/dts/bindings/cpu/neorv32-cpu.yaml b/dts/bindings/cpu/neorv32-cpu.yaml new file mode 100644 index 00000000000..417ce963cee --- /dev/null +++ b/dts/bindings/cpu/neorv32-cpu.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +description: NEORV32 RISC-V CPU + +compatible: "neorv32-cpu" + +include: cpu.yaml diff --git a/dts/riscv/neorv32.dtsi b/dts/riscv/neorv32.dtsi new file mode 100644 index 00000000000..603fae59ee1 --- /dev/null +++ b/dts/riscv/neorv32.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "neorv32-cpu"; + reg = <0>; + device_type = "cpu"; + + intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #address-cells = <1>; + #interrupt-cells = <1>; + + firq: firq { + interrupt-map-mask = <0x0 0xffffffff>; + interrupt-map = < + 0 0 &intc 0 16 + 0 1 &intc 0 17 + 0 2 &intc 0 18 + 0 3 &intc 0 19 + 0 4 &intc 0 20 + 0 5 &intc 0 21 + 0 6 &intc 0 22 + 0 7 &intc 0 23 + 0 8 &intc 0 24 + 0 9 &intc 0 25 + 0 10 &intc 0 26 + 0 11 &intc 0 27 + 0 12 &intc 0 28 + 0 13 &intc 0 29 + 0 14 &intc 0 30 + 0 15 &intc 0 31 + >; + #interrupt-cells = <1>; + }; + }; + }; + }; + + soc { + compatible = "simple-bus"; + interrupt-parent = <&firq>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sysinfo: syscon@ffffffe0 { + compatible = "neorv-sysinfo", "syscon"; + status = "okay"; + reg = <0xffffffe0 32>; + label = "SYSINFO"; + }; + }; +}; diff --git a/soc/riscv/riscv-privilege/neorv32/CMakeLists.txt b/soc/riscv/riscv-privilege/neorv32/CMakeLists.txt new file mode 100644 index 00000000000..7f7c334fedd --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + reset.S + soc_irq.S + soc.c +) diff --git a/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series b/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series new file mode 100644 index 00000000000..dc022ea1d1e --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series @@ -0,0 +1,24 @@ +# Copyright (c) 2021 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_NEORV32 + +config SOC_SERIES + default "neorv32" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if RISCV_MACHINE_TIMER + +config NUM_IRQS + default 32 + +config RISCV_HAS_CPU_IDLE + default y + +config RISCV_GP + default y + +config SYSCON + default y + +endif # SOC_SERIES_NEORV32 diff --git a/soc/riscv/riscv-privilege/neorv32/Kconfig.series b/soc/riscv/riscv-privilege/neorv32/Kconfig.series new file mode 100644 index 00000000000..0079fb311f4 --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/Kconfig.series @@ -0,0 +1,21 @@ +# Copyright (c) 2021 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_NEORV32 + bool "NEORV32 Processor" + select RISCV + select SOC_FAMILY_RISCV_PRIVILEGE + help + Enable support for the NEORV32 Processor (SoC). + + The NEORV32 CPU implementation must have the following RISC-V ISA + extensions enabled in order to support Zephyr: + - M (Integer Multiplication and Division) + - Zicsr (Control and Status Register (CSR) Instructions) + + The following NEORV32 CPU ISA extensions are not currently supported + by Zephyr and can safely be disabled: + - A (Atomic Instructions) + - E (Embedded, only 16 integer registers) + - Zbb (Basic Bit Manipulation) + - Zfinx (Floating Point in Integer Registers) diff --git a/soc/riscv/riscv-privilege/neorv32/Kconfig.soc b/soc/riscv/riscv-privilege/neorv32/Kconfig.soc new file mode 100644 index 00000000000..b1a50c95375 --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/Kconfig.soc @@ -0,0 +1,32 @@ +# Copyright (c) 2021 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "NEORV32 Version" + depends on SOC_SERIES_NEORV32 + +config SOC_NEORV32_V1_6_1 + bool "v1.6.1" + # NEORV32 RISC-V ISA A extension implements only LR/SC, not AMO + select ATOMIC_OPERATIONS_C + +endchoice + +if SOC_SERIES_NEORV32 + +config SOC_NEORV32_VERSION + hex + default 0x01060100 if SOC_NEORV32_V1_6_1 + help + The targeted NEORV32 version as BCD-coded number. The format is + identical to that of the NEORV32 Machine implementation ID (mimpid) + register. + +config SOC_NEORV32_ISA_C + bool "RISC-V ISA Extension \"C\"" + select COMPRESSED_ISA + help + Enable this if the NEORV32 CPU implementation supports the RISC-V ISA + "C" extension (Compressed Instructions). + +endif # SOC_SERIES_NEORV32 diff --git a/soc/riscv/riscv-privilege/neorv32/linker.ld b/soc/riscv/riscv-privilege/neorv32/linker.ld new file mode 100644 index 00000000000..d5801e57d91 --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/linker.ld @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +MEMORY +{ + IO (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512 +} + +SECTIONS +{ + SECTION_PROLOGUE(io, (NOLOAD),) + { + PROVIDE(__io_start = ORIGIN(IO)); + PROVIDE(__io_end = ORIGIN(IO) + LENGTH(IO)); + } GROUP_LINK_IN(IO) +} + +#include diff --git a/soc/riscv/riscv-privilege/neorv32/reset.S b/soc/riscv/riscv-privilege/neorv32/reset.S new file mode 100644 index 00000000000..aae9239dbbd --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/reset.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* exports */ +GTEXT(__reset) + +/* imports */ +GTEXT(__initialize) + +SECTION_FUNC(reset, __reset) + /* Zerorize zero register */ + lui x0, 0 + + /* Disable insterrupts */ + csrw mstatus, x0 + csrw mie, x0 + +#ifdef CONFIG_USERSPACE + /* Disable counter access outside M-mode */ + csrw mcounteren, x0 +#endif /* CONFIG_USERSPACE */ + + /* Allow mcycle and minstret counters to increment */ + li x11, ~5 + csrw mcountinhibit, x11 + + /* Zerorize counters */ + csrw mcycle, x0 + csrw mcycleh, x0 + csrw minstret, x0 + csrw minstreth, x0 + + /* + * Simplify dummy machine trap code by not having to decode + * instruction width. + */ + .option push + .option norvc + + /* + * Temporarily setup a dummy machine trap vector to catch (and ignore) + * Store Access faults due to unimplemented peripherals. + */ + csrr x6, mtvec + la x7, __dummy_trap_handler + csrw mtvec, x7 + + /* Attempt to zerorize all IO peripheral registers */ + la x8, __io_start + la x9, __io_end +1: sw x0, 0(x8) + addi x8, x8, 4 + bne x8, x9, 1b + + /* Restore previous machine trap vector */ + csrw mtvec, x6 + + .option pop + + /* Jump to __initialize */ + call __initialize + +.balign 4 +SECTION_FUNC(reset, __dummy_trap_handler) + csrr x5, mepc + addi x5, x5, 4 + csrw mepc, x5 + mret diff --git a/soc/riscv/riscv-privilege/neorv32/soc.c b/soc/riscv/riscv-privilege/neorv32/soc.c new file mode 100644 index 00000000000..fa629bfbb52 --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/soc.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT) +void soc_interrupt_init(void) +{ + (void)irq_lock(); + + __asm__ volatile ("csrwi mie, 0\n"); +} +#endif diff --git a/soc/riscv/riscv-privilege/neorv32/soc.h b/soc/riscv/riscv-privilege/neorv32/soc.h new file mode 100644 index 00000000000..9a0971faebe --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/soc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef RISCV_NEORV32_SOC_H +#define RISCV_NEORV32_SOC_H + +#include +#include + +/* Machine System Timer (MTIME) registers */ +#define RISCV_MTIME_BASE 0xffffff90U +#define RISCV_MTIMECMP_BASE 0xffffff98U + +/* System information (SYSINFO) register offsets */ +#define NEORV32_SYSINFO_CLK 0x00U +#define NEORV32_SYSINFO_CPU 0x04U +#define NEORV32_SYSINFO_FEATURES 0x08U +#define NEORV32_SYSINFO_CACHE 0x0cU +#define NEORV32_SYSINFO_ISPACE_BASE 0xf0U +#define NEORV32_SYSINFO_IMEM_SIZE 0xf4U +#define NEORV32_SYSINFO_DSPACE_BASE 0xf8U +#define NEORV32_SYSINFO_DMEM_SIZE 0xfcU + +/* System information (SYSINFO) CPU register bits */ +#define NEORV32_SYSINFO_CPU_ZICSR BIT(0) +#define NEORV32_SYSINFO_CPU_ZIFENCEI BIT(1) +#define NEORV32_SYSINFO_CPU_ZMMUL BIT(2) +#define NEORV32_SYSINFO_CPU_ZBB BIT(3) +#define NEORV32_SYSINFO_CPU_ZFINX BIT(5) +#define NEORV32_SYSINFO_CPU_ZXSCNT BIT(6) +#define NEORV32_SYSINFO_CPU_ZXNOCNT BIT(7) +#define NEORV32_SYSINFO_CPU_PMP BIT(8) +#define NEORV32_SYSINFO_CPU_HPM BIT(9) +#define NEORV32_SYSINFO_CPU_DEBUGMODE BIT(10) +#define NEORV32_SYSINFO_CPU_FASTMUL BIT(30) +#define NEORV32_SYSINFO_CPU_FASTSHIFT BIT(31) + +/* System information (SYSINFO) FEATURES register bits */ +#define NEORV32_SYSINFO_FEATURES_BOOTLOADER BIT(0) +#define NEORV32_SYSINFO_FEATURES_MEM_EXT BIT(1) +#define NEORV32_SYSINFO_FEATURES_MEM_INT_IMEM BIT(2) +#define NEORV32_SYSINFO_FEATURES_MEM_INT_DMEM BIT(3) +#define NEORV32_SYSINFO_FEATURES_MEM_EXT_ENDIAN BIT(4) +#define NEORV32_SYSINFO_FEATURES_ICACHE BIT(5) +#define NEORV32_SYSINFO_FEATURES_OCD BIT(14) +#define NEORV32_SYSINFO_FEATURES_HW_RESET BIT(15) +#define NEORV32_SYSINFO_FEATURES_IO_GPIO BIT(16) +#define NEORV32_SYSINFO_FEATURES_IO_MTIME BIT(17) +#define NEORV32_SYSINFO_FEATURES_IO_UART0 BIT(18) +#define NEORV32_SYSINFO_FEATURES_IO_SPI BIT(19) +#define NEORV32_SYSINFO_FEATURES_IO_TWI BIT(20) +#define NEORV32_SYSINFO_FEATURES_IO_PWM BIT(21) +#define NEORV32_SYSINFO_FEATURES_IO_WDT BIT(22) +#define NEORV32_SYSINFO_FEATURES_IO_CFS BIT(23) +#define NEORV32_SYSINFO_FEATURES_IO_TRNG BIT(24) +#define NEORV32_SYSINFO_FEATURES_IO_SLINK BIT(25) +#define NEORV32_SYSINFO_FEATURES_IO_UART1 BIT(26) +#define NEORV32_SYSINFO_FEATURES_IO_NEOLED BIT(27) + +#endif /* RISCV_NEORV32_SOC_H */ diff --git a/soc/riscv/riscv-privilege/neorv32/soc_irq.S b/soc/riscv/riscv-privilege/neorv32/soc_irq.S new file mode 100644 index 00000000000..6377cb031bf --- /dev/null +++ b/soc/riscv/riscv-privilege/neorv32/soc_irq.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +GTEXT(__soc_handle_irq) + +/* + * SOC-specific function to handle pending IRQ number generating the interrupt. + * Exception number is given as parameter via register a0. + */ +SECTION_FUNC(exception.other, __soc_handle_irq) + /* + * The the MIP CSR on the NEORV32 is read-only and can thus not be used for + * clearing a pending IRQ. Instead we disable the IRQ in the MIE CSR and + * re-enable it (if it was enabled when clearing). + */ + li t1, 1 + sll t0, t1, a0 + csrrc t2, mie, t0 + and t1, t2, t0 + csrrs t2, mie, t1 + + /* Return */ + jalr x0, ra