soc: neorv32: update to support NEORV32 v1.11.1
Update the NEORV32 SoC, peripheral drivers, and board to support NEORV32 v1.11.1. Notable changes include: - Optional RISC-V ISA Kconfigs are now selected on the board level. - Peripheral registers are now automatically reset in hardware, no need for software initialization code. - The NEORV32 GPIO controller now supports 32 pins, not 64. Interrupt support will be submitted in a separate PR. - Default board configuration has 64k RAM and is clocked at 18 MHz. Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
This commit is contained in:
parent
4899cc10ac
commit
63c24d9d34
20 changed files with 340 additions and 409 deletions
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if((CONFIG_BOARD_NEORV32) AND (CONFIG_BUILD_OUTPUT_BIN))
|
||||
|
@ -18,7 +18,7 @@ if((CONFIG_BOARD_NEORV32) AND (CONFIG_BUILD_OUTPUT_BIN))
|
|||
|
||||
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
|
||||
COMMAND ${IMAGE_GEN}
|
||||
ARGS -app_img
|
||||
ARGS -app_vhd
|
||||
${CONFIG_KERNEL_BIN_NAME}.bin
|
||||
${CONFIG_KERNEL_BIN_NAME}.vhd
|
||||
${PROJECT_BINARY_DIR}
|
||||
|
|
7
boards/others/neorv32/Kconfig
Normal file
7
boards/others/neorv32/Kconfig
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_NEORV32
|
||||
select RISCV_ISA_RV32I
|
||||
select RISCV_ISA_EXT_M
|
||||
select ATOMIC_OPERATIONS_C
|
|
@ -13,7 +13,7 @@ For more information about the NEORV32, see the following websites:
|
|||
- `The NEORV32 RISC-V Processor Datasheet`_
|
||||
- `The NEORV32 RISC-V Processor User Guide`_
|
||||
|
||||
The currently supported version is 1.8.6.
|
||||
The currently supported version is NEORV32 v1.11.1.
|
||||
|
||||
Supported Features
|
||||
==================
|
||||
|
@ -27,7 +27,7 @@ using :ref:`devicetree overlays <use-dt-overlays>`.
|
|||
System Clock
|
||||
============
|
||||
|
||||
The default board configuration assumes a system clock of 100 MHz. The clock
|
||||
The default board configuration assumes a system clock of 18 MHz. The clock
|
||||
frequency can be overridden by changing the ``clock-frequency`` property of the
|
||||
``cpu0`` devicetree node.
|
||||
|
||||
|
@ -37,9 +37,10 @@ CPU
|
|||
The default board configuration assumes the NEORV32 CPU implementation has the
|
||||
following RISC-V ISA extensions enabled:
|
||||
|
||||
- C (Compresses Instructions)
|
||||
- I (Base Integer Instruction Set, 32-bit)
|
||||
- M (Integer Multiplication and Division)
|
||||
- Zicsr (Control and Status Register (CSR) Instructions)
|
||||
- Zicsr (Control and Status Register (CSR) Instructions, always enabled)
|
||||
- Zifencei (Instruction-fetch fence, always enabled)
|
||||
|
||||
Internal Instruction Memory
|
||||
===========================
|
||||
|
@ -52,7 +53,7 @@ instruction memory can be overridden by changing the ``reg`` property of the
|
|||
Internal Data Memory
|
||||
====================
|
||||
|
||||
The default board configuration assumes the NEORV32 SoC implementation has a 32k
|
||||
The default board configuration assumes the NEORV32 SoC implementation has a 64k
|
||||
byte internal data memory (DMEM). The size of the data memory can be overridden
|
||||
by changing the ``reg`` property of the ``dmem`` devicetree node.
|
||||
|
||||
|
@ -115,21 +116,21 @@ implementation with the On-Chip Debugger (OCD) and bootloader enabled.
|
|||
|
||||
The default board configuration uses an :ref:`openocd-debug-host-tools`
|
||||
configuration similar to the example provided by the NEORV32 project. Other
|
||||
JTAGs can be used by providing further arguments when building. Here is an
|
||||
example for using the Flyswatter JTAG:
|
||||
JTAGs can be used by providing further arguments when flashing. Here is an
|
||||
example for using the Flyswatter JTAG @ 2 kHz:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/hello_world
|
||||
:board: neorv32
|
||||
:goals: flash
|
||||
:gen-args: -DBOARD_RUNNER_ARGS_openocd="--config;interface/ftdi/flyswatter.cfg;--config;neorv32.cfg;--cmd-pre-init;'adapter speed 2000'"
|
||||
:flash-args: --config interface/ftdi/flyswatter.cfg --config neorv32.cfg --cmd-pre-init 'adapter speed 2000'
|
||||
|
||||
After flashing, you should see message similar to the following in the terminal:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
*** Booting Zephyr OS build zephyr-vn.n.nn ***
|
||||
Hello World! neorv32
|
||||
Hello World! neorv32/neorv32
|
||||
|
||||
Note, however, that the application was not persisted in flash memory by the
|
||||
above steps. It was merely written to internal block RAM in the FPGA. It will
|
||||
|
@ -176,7 +177,7 @@ similar to the following in the terminal:
|
|||
.. code-block:: console
|
||||
|
||||
*** Booting Zephyr OS build zephyr-vn.n.nn ***
|
||||
Hello World! neorv32
|
||||
Hello World! neorv32/neorv32
|
||||
|
||||
.. _The NEORV32 RISC-V Processor GitHub:
|
||||
https://github.com/stnolting/neorv32
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -29,25 +29,9 @@
|
|||
zephyr,uart-pipe = &uart0;
|
||||
};
|
||||
|
||||
soc {
|
||||
imem: memory@0 {
|
||||
compatible = "soc-nv-flash", "mmio-sram";
|
||||
reg = <0x0 DT_SIZE_K(64)>;
|
||||
};
|
||||
|
||||
bootrom: memory@ffff0000 {
|
||||
compatible = "soc-nv-flash", "mmio-sram";
|
||||
reg = <0xffff0000 DT_SIZE_K(4)>;
|
||||
};
|
||||
|
||||
dmem: memory@80000000 {
|
||||
compatible = "mmio-sram";
|
||||
reg = <0x80000000 DT_SIZE_K(32)>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led0: led0 {
|
||||
gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
|
||||
label = "LED_0";
|
||||
|
@ -71,7 +55,30 @@
|
|||
};
|
||||
|
||||
&cpu0 {
|
||||
clock-frequency = <DT_FREQ_M(100)>;
|
||||
riscv,isa = "rv32im_zicsr_zifencei";
|
||||
clock-frequency = <DT_FREQ_M(18)>;
|
||||
};
|
||||
|
||||
&bootrom {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&imem {
|
||||
status = "okay";
|
||||
reg = <0x0 DT_SIZE_K(64)>;
|
||||
};
|
||||
|
||||
&dmem {
|
||||
status = "okay";
|
||||
reg = <0x80000000 DT_SIZE_K(64)>;
|
||||
};
|
||||
|
||||
&clint {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mtimer {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
|
@ -79,10 +86,6 @@
|
|||
current-speed = <19200>;
|
||||
};
|
||||
|
||||
&gpio_lo {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio_hi {
|
||||
&gpio {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ arch: riscv
|
|||
toolchain:
|
||||
- cross-compile
|
||||
- zephyr
|
||||
ram: 32
|
||||
ram: 64
|
||||
flash: 64
|
||||
supported:
|
||||
- gpio
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_SOC_NEORV32_ISA_C=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -17,10 +17,19 @@
|
|||
|
||||
LOG_MODULE_REGISTER(neorv32_trng, CONFIG_ENTROPY_LOG_LEVEL);
|
||||
|
||||
/* TRNG CTRL register bits */
|
||||
#define NEORV32_TRNG_CTRL_DATA_MASK BIT_MASK(8)
|
||||
#define NEORV32_TRNG_CTRL_EN BIT(30)
|
||||
#define NEORV32_TRNG_CTRL_VALID BIT(31)
|
||||
/* Register offsets */
|
||||
#define NEORV32_TRNG_CTRL 0x00
|
||||
#define NEORV32_TRNG_DATA 0x04
|
||||
|
||||
/* CTRL register bits */
|
||||
#define NEORV32_TRNG_CTRL_EN BIT(0)
|
||||
#define NEORV32_TRNG_CTRL_FIFO_CLR BIT(1)
|
||||
#define NEORV32_TRNG_CTRL_FIFO_DEPTH GENMASK(5, 2)
|
||||
#define NEORV32_TRNG_CTRL_SIM_MODE BIT(6)
|
||||
#define NEORV32_TRNG_CTRL_AVAIL BIT(7)
|
||||
|
||||
/* DATA register bits */
|
||||
#define NEORV32_TRNG_DATA_MASK GENMASK(7, 0)
|
||||
|
||||
struct neorv32_trng_config {
|
||||
const struct device *syscon;
|
||||
|
@ -31,14 +40,21 @@ static inline uint32_t neorv32_trng_read_ctrl(const struct device *dev)
|
|||
{
|
||||
const struct neorv32_trng_config *config = dev->config;
|
||||
|
||||
return sys_read32(config->base);
|
||||
return sys_read32(config->base + NEORV32_TRNG_CTRL);
|
||||
}
|
||||
|
||||
static inline void neorv32_trng_write_ctrl(const struct device *dev, uint32_t ctrl)
|
||||
{
|
||||
const struct neorv32_trng_config *config = dev->config;
|
||||
|
||||
sys_write32(ctrl, config->base);
|
||||
sys_write32(ctrl, config->base + NEORV32_TRNG_CTRL);
|
||||
}
|
||||
|
||||
static inline uint8_t neorv32_trng_read_data(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_trng_config *config = dev->config;
|
||||
|
||||
return sys_read32(config->base + NEORV32_TRNG_DATA) & NEORV32_TRNG_DATA_MASK;
|
||||
}
|
||||
|
||||
static int neorv32_trng_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t len)
|
||||
|
@ -48,8 +64,8 @@ static int neorv32_trng_get_entropy(const struct device *dev, uint8_t *buffer, u
|
|||
while (len > 0) {
|
||||
ctrl = neorv32_trng_read_ctrl(dev);
|
||||
|
||||
if ((ctrl & NEORV32_TRNG_CTRL_VALID) != 0) {
|
||||
*buffer++ = ctrl & NEORV32_TRNG_CTRL_DATA_MASK;
|
||||
if ((ctrl & NEORV32_TRNG_CTRL_AVAIL) != 0) {
|
||||
*buffer++ = neorv32_trng_read_data(dev);
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +81,8 @@ static int neorv32_trng_get_entropy_isr(const struct device *dev, uint8_t *buffe
|
|||
|
||||
if ((flags & ENTROPY_BUSYWAIT) == 0) {
|
||||
ctrl = neorv32_trng_read_ctrl(dev);
|
||||
if ((ctrl & NEORV32_TRNG_CTRL_VALID) != 0) {
|
||||
*buffer = ctrl & NEORV32_TRNG_CTRL_DATA_MASK;
|
||||
if ((ctrl & NEORV32_TRNG_CTRL_AVAIL) != 0) {
|
||||
*buffer = neorv32_trng_read_data(dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -93,13 +109,13 @@ static int neorv32_trng_init(const struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_FEATURES, &features);
|
||||
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_SOC, &features);
|
||||
if (err < 0) {
|
||||
LOG_ERR("failed to determine implemented features (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((features & NEORV32_SYSINFO_FEATURES_IO_TRNG) == 0) {
|
||||
if ((features & NEORV32_SYSINFO_SOC_IO_TRNG) == 0) {
|
||||
LOG_ERR("neorv32 trng not supported");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -20,6 +20,10 @@ LOG_MODULE_REGISTER(gpio_neorv32, CONFIG_GPIO_LOG_LEVEL);
|
|||
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
|
||||
/* Register offsets */
|
||||
#define NEORV32_GPIO_PORT_IN 0x00
|
||||
#define NEORV32_GPIO_PORT_OUT 0x04
|
||||
|
||||
/* Maximum number of GPIOs supported */
|
||||
#define MAX_GPIOS 32
|
||||
|
||||
|
@ -27,8 +31,7 @@ struct neorv32_gpio_config {
|
|||
/* gpio_driver_config needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
const struct device *syscon;
|
||||
mm_reg_t input;
|
||||
mm_reg_t output;
|
||||
mm_reg_t base;
|
||||
};
|
||||
|
||||
struct neorv32_gpio_data {
|
||||
|
@ -42,14 +45,14 @@ static inline uint32_t neorv32_gpio_read(const struct device *dev)
|
|||
{
|
||||
const struct neorv32_gpio_config *config = dev->config;
|
||||
|
||||
return sys_read32(config->input);
|
||||
return sys_read32(config->base + NEORV32_GPIO_PORT_IN);
|
||||
}
|
||||
|
||||
static inline void neorv32_gpio_write(const struct device *dev, uint32_t val)
|
||||
{
|
||||
const struct neorv32_gpio_config *config = dev->config;
|
||||
|
||||
sys_write32(val, config->output);
|
||||
sys_write32(val, config->base + NEORV32_GPIO_PORT_OUT);
|
||||
}
|
||||
|
||||
static int neorv32_gpio_pin_configure(const struct device *dev, gpio_pin_t pin,
|
||||
|
@ -179,13 +182,13 @@ static int neorv32_gpio_init(const struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_FEATURES, &features);
|
||||
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_SOC, &features);
|
||||
if (err < 0) {
|
||||
LOG_ERR("failed to determine implemented features (err %d)", err);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((features & NEORV32_SYSINFO_FEATURES_IO_GPIO) == 0) {
|
||||
if ((features & NEORV32_SYSINFO_SOC_IO_GPIO) == 0) {
|
||||
LOG_ERR("neorv32 gpio not supported");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -216,8 +219,7 @@ static DEVICE_API(gpio, neorv32_gpio_driver_api) = {
|
|||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n) \
|
||||
}, \
|
||||
.syscon = DEVICE_DT_GET(DT_INST_PHANDLE(n, syscon)), \
|
||||
.input = DT_INST_REG_ADDR_BY_NAME(n, input), \
|
||||
.output = DT_INST_REG_ADDR_BY_NAME(n, output), \
|
||||
.base = DT_INST_REG_ADDR(n), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -9,59 +9,63 @@
|
|||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/syscon.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/sys/sys_io.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/irq.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/spinlock.h>
|
||||
#include <zephyr/sys/sys_io.h>
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
LOG_MODULE_REGISTER(uart_neorv32, CONFIG_UART_LOG_LEVEL);
|
||||
|
||||
/* NEORV32 UART registers offsets */
|
||||
#define NEORV32_UART_CTRL_OFFSET 0x00
|
||||
#define NEORV32_UART_DATA_OFFSET 0x04
|
||||
#define NEORV32_UART_CTRL 0x00
|
||||
#define NEORV32_UART_DATA 0x04
|
||||
|
||||
/* UART_CTRL register bits */
|
||||
/* NEORV32 UART CTRL register bits */
|
||||
#define NEORV32_UART_CTRL_EN BIT(0)
|
||||
#define NEORV32_UART_CTRL_SIM_MODE BIT(1)
|
||||
#define NEORV32_UART_CTRL_HWFC_EN BIT(2)
|
||||
#define NEORV32_UART_CTRL_PRSC_POS 3U
|
||||
#define NEORV32_UART_CTRL_PRSC_MASK BIT_MASK(3)
|
||||
#define NEORV32_UART_CTRL_BAUD_POS 6U
|
||||
#define NEORV32_UART_CTRL_BAUD_MASK BIT_MASK(10)
|
||||
#define NEORV32_UART_CTRL_PRSC GENMASK(5, 3)
|
||||
#define NEORV32_UART_CTRL_BAUD GENMASK(15, 6)
|
||||
#define NEORV32_UART_CTRL_RX_NEMPTY BIT(16)
|
||||
#define NEORV32_UART_CTRL_RX_HALF BIT(17)
|
||||
#define NEORV32_UART_CTRL_RX_FULL BIT(18)
|
||||
#define NEORV32_UART_CTRL_TX_NEMPTY BIT(19)
|
||||
#define NEORV32_UART_CTRL_TX_HALF BIT(20)
|
||||
#define NEORV32_UART_CTRL_TX_EMPTY BIT(19)
|
||||
#define NEORV32_UART_CTRL_TX_NHALF BIT(20)
|
||||
#define NEORV32_UART_CTRL_TX_FULL BIT(21)
|
||||
#define NEORV32_UART_CTRL_IRQ_RX_NEMPTY BIT(22)
|
||||
#define NEORV32_UART_CTRL_IRQ_RX_HALF BIT(23)
|
||||
#define NEORV32_UART_CTRL_IRQ_RX_FULL BIT(24)
|
||||
#define NEORV32_UART_CTRL_IRQ_TX_EMPTY BIT(25)
|
||||
#define NEORV32_UART_CTRL_IRQ_TX_NHALF BIT(26)
|
||||
#define NEORV32_UART_CTRL_UART_CTRL_RX_CLR BIT(28)
|
||||
#define NEORV32_UART_CTRL_UART_CTRL_TX_CLR BIT(29)
|
||||
#define NEORV32_UART_CTRL_RX_OVER BIT(30)
|
||||
#define NEORV32_UART_CTRL_TX_BUSY BIT(31)
|
||||
|
||||
/* NEORV32 UART DATA register bits */
|
||||
#define NEORV32_UART_DATA_RTX GENMASK(7, 0)
|
||||
#define NEORV32_UART_DATA_RX_FIFO_SIZE GENMASK(11, 8)
|
||||
#define NEORV32_UART_DATA_TX_FIFO_SIZE GENMASK(15, 12)
|
||||
|
||||
struct neorv32_uart_config {
|
||||
const struct device *syscon;
|
||||
uint32_t feature_mask;
|
||||
mm_reg_t base;
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
void (*irq_config_func)(const struct device *dev);
|
||||
unsigned int tx_irq;
|
||||
unsigned int rx_irq;
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
};
|
||||
|
||||
struct neorv32_uart_data {
|
||||
struct uart_config uart_cfg;
|
||||
uint32_t last_data;
|
||||
struct k_spinlock lock;
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
struct k_timer timer;
|
||||
uart_irq_callback_user_data_t callback;
|
||||
void *callback_data;
|
||||
uint32_t last_ctrl;
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
};
|
||||
|
||||
|
@ -69,44 +73,37 @@ static inline uint32_t neorv32_uart_read_ctrl(const struct device *dev)
|
|||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
|
||||
return sys_read32(config->base + NEORV32_UART_CTRL_OFFSET);
|
||||
return sys_read32(config->base + NEORV32_UART_CTRL);
|
||||
}
|
||||
|
||||
static inline void neorv32_uart_write_ctrl(const struct device *dev, uint32_t ctrl)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
|
||||
sys_write32(ctrl, config->base + NEORV32_UART_CTRL_OFFSET);
|
||||
sys_write32(ctrl, config->base + NEORV32_UART_CTRL);
|
||||
}
|
||||
|
||||
static inline uint32_t neorv32_uart_read_data(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
uint32_t reg;
|
||||
|
||||
/* Cache status bits as they are cleared upon read */
|
||||
reg = sys_read32(config->base + NEORV32_UART_DATA_OFFSET);
|
||||
data->last_data = reg;
|
||||
|
||||
return reg;
|
||||
return sys_read32(config->base + NEORV32_UART_DATA);
|
||||
}
|
||||
|
||||
static inline void neorv32_uart_write_data(const struct device *dev, uint32_t data)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
|
||||
sys_write32(data, config->base + NEORV32_UART_DATA_OFFSET);
|
||||
sys_write32(data, config->base + NEORV32_UART_DATA);
|
||||
}
|
||||
|
||||
static int neorv32_uart_poll_in(const struct device *dev, unsigned char *c)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t ctrl;
|
||||
|
||||
data = neorv32_uart_read_data(dev);
|
||||
|
||||
if ((data & NEORV32_UART_CTRL_RX_NEMPTY) != 0) {
|
||||
*c = data & BIT_MASK(8);
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
if ((ctrl & NEORV32_UART_CTRL_RX_NEMPTY) != 0U) {
|
||||
*c = neorv32_uart_read_data(dev) & NEORV32_UART_DATA_RTX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -115,7 +112,7 @@ static int neorv32_uart_poll_in(const struct device *dev, unsigned char *c)
|
|||
|
||||
static void neorv32_uart_poll_out(const struct device *dev, unsigned char c)
|
||||
{
|
||||
while ((neorv32_uart_read_ctrl(dev) & NEORV32_UART_CTRL_TX_BUSY) != 0) {
|
||||
while ((neorv32_uart_read_ctrl(dev) & NEORV32_UART_CTRL_TX_FULL) != 0U) {
|
||||
}
|
||||
|
||||
neorv32_uart_write_data(dev, c);
|
||||
|
@ -123,11 +120,15 @@ static void neorv32_uart_poll_out(const struct device *dev, unsigned char c)
|
|||
|
||||
static int neorv32_uart_configure(const struct device *dev, const struct uart_config *cfg)
|
||||
{
|
||||
const uint16_t baudxx_max = FIELD_GET(NEORV32_UART_CTRL_BAUD, NEORV32_UART_CTRL_BAUD);
|
||||
const uint8_t prscx_max = FIELD_GET(NEORV32_UART_CTRL_PRSC, NEORV32_UART_CTRL_PRSC);
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
uint32_t ctrl = NEORV32_UART_CTRL_EN;
|
||||
k_spinlock_key_t key;
|
||||
uint16_t baudxx = 0;
|
||||
uint8_t prscx = 0;
|
||||
uint32_t ctrl;
|
||||
bool hwfc_en;
|
||||
uint32_t clk;
|
||||
int err;
|
||||
|
||||
|
@ -143,20 +144,17 @@ static int neorv32_uart_configure(const struct device *dev, const struct uart_co
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
switch (cfg->parity) {
|
||||
case UART_CFG_PARITY_NONE:
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unsupported parity mode %d", cfg->parity);
|
||||
if (cfg->parity != UART_CFG_PARITY_NONE) {
|
||||
LOG_ERR("hardware only supports parity mode none");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
switch (cfg->flow_ctrl) {
|
||||
case UART_CFG_FLOW_CTRL_NONE:
|
||||
ctrl |= 0;
|
||||
hwfc_en = false;
|
||||
break;
|
||||
case UART_CFG_FLOW_CTRL_RTS_CTS:
|
||||
ctrl |= NEORV32_UART_CTRL_HWFC_EN;
|
||||
hwfc_en = true;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unsupported flow control mode %d", cfg->flow_ctrl);
|
||||
|
@ -179,7 +177,7 @@ static int neorv32_uart_configure(const struct device *dev, const struct uart_co
|
|||
* clock / 2.
|
||||
*/
|
||||
baudxx = clk / (2 * cfg->baudrate);
|
||||
while (baudxx >= NEORV32_UART_CTRL_BAUD_MASK) {
|
||||
while (baudxx >= baudxx_max) {
|
||||
if ((prscx == 2) || (prscx == 4)) {
|
||||
baudxx >>= 3;
|
||||
} else {
|
||||
|
@ -189,16 +187,30 @@ static int neorv32_uart_configure(const struct device *dev, const struct uart_co
|
|||
prscx++;
|
||||
}
|
||||
|
||||
if (prscx > NEORV32_UART_CTRL_PRSC_MASK) {
|
||||
if (prscx > prscx_max) {
|
||||
LOG_ERR("unsupported baud rate %d", cfg->baudrate);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ctrl |= (baudxx - 1) << NEORV32_UART_CTRL_BAUD_POS;
|
||||
ctrl |= prscx << NEORV32_UART_CTRL_PRSC_POS;
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
ctrl |= NEORV32_UART_CTRL_EN;
|
||||
|
||||
if (hwfc_en) {
|
||||
ctrl |= NEORV32_UART_CTRL_HWFC_EN;
|
||||
} else {
|
||||
ctrl &= ~NEORV32_UART_CTRL_HWFC_EN;
|
||||
}
|
||||
|
||||
ctrl &= ~(NEORV32_UART_CTRL_BAUD | NEORV32_UART_CTRL_PRSC);
|
||||
ctrl |= FIELD_PREP(NEORV32_UART_CTRL_BAUD, baudxx - 1U) |
|
||||
FIELD_PREP(NEORV32_UART_CTRL_PRSC, prscx);
|
||||
|
||||
data->uart_cfg = *cfg;
|
||||
neorv32_uart_write_ctrl(dev, ctrl);
|
||||
data->uart_cfg = *cfg;
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -215,28 +227,25 @@ static int neorv32_uart_config_get(const struct device *dev, struct uart_config
|
|||
}
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
static int neorv32_uart_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
|
||||
static int neorv32_uart_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
int count = 0;
|
||||
|
||||
if (len <= 0) {
|
||||
if (size <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
__ASSERT_NO_MSG(tx_data != NULL);
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
if ((ctrl & NEORV32_UART_CTRL_TX_BUSY) == 0) {
|
||||
neorv32_uart_write_data(dev, *tx_data);
|
||||
return 1;
|
||||
while (count < size && (neorv32_uart_read_ctrl(dev) & NEORV32_UART_CTRL_TX_FULL) == 0U) {
|
||||
neorv32_uart_write_data(dev, tx_data[count++]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
static int neorv32_uart_fifo_read(const struct device *dev, uint8_t *rx_data, const int size)
|
||||
{
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
int count = 0;
|
||||
|
||||
if (size <= 0) {
|
||||
|
@ -245,104 +254,100 @@ static int neorv32_uart_fifo_read(const struct device *dev, uint8_t *rx_data, co
|
|||
|
||||
__ASSERT_NO_MSG(rx_data != NULL);
|
||||
|
||||
while ((data->last_data & NEORV32_UART_CTRL_RX_NEMPTY) != 0) {
|
||||
rx_data[count++] = data->last_data & BIT_MASK(8);
|
||||
data->last_data &= ~(NEORV32_UART_CTRL_RX_NEMPTY);
|
||||
|
||||
if (count >= size) {
|
||||
break;
|
||||
}
|
||||
|
||||
(void)neorv32_uart_read_data(dev);
|
||||
while (count < size && (neorv32_uart_read_ctrl(dev) & NEORV32_UART_CTRL_RX_NEMPTY) != 0U) {
|
||||
rx_data[count++] = neorv32_uart_read_data(dev) & NEORV32_UART_DATA_RTX;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void neorv32_uart_tx_soft_isr(struct k_timer *timer)
|
||||
{
|
||||
const struct device *dev = k_timer_user_data_get(timer);
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
uart_irq_callback_user_data_t callback = data->callback;
|
||||
|
||||
if (callback) {
|
||||
callback(dev, data->callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void neorv32_uart_irq_tx_enable(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
uint32_t ctrl;
|
||||
|
||||
irq_enable(config->tx_irq);
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
if ((ctrl & NEORV32_UART_CTRL_TX_BUSY) == 0) {
|
||||
/*
|
||||
* TX done event already generated an edge interrupt. Generate a
|
||||
* soft interrupt and have it call the callback function in
|
||||
* timer isr context.
|
||||
*/
|
||||
k_timer_start(&data->timer, K_NO_WAIT, K_NO_WAIT);
|
||||
}
|
||||
ctrl |= NEORV32_UART_CTRL_IRQ_TX_EMPTY;
|
||||
neorv32_uart_write_ctrl(dev, ctrl);
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
}
|
||||
|
||||
static void neorv32_uart_irq_tx_disable(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
uint32_t ctrl;
|
||||
|
||||
irq_disable(config->tx_irq);
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
ctrl &= ~NEORV32_UART_CTRL_IRQ_TX_EMPTY;
|
||||
neorv32_uart_write_ctrl(dev, ctrl);
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
}
|
||||
|
||||
static int neorv32_uart_irq_tx_ready(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
uint32_t ctrl;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
|
||||
if (!irq_is_enabled(config->tx_irq)) {
|
||||
if ((data->last_ctrl & NEORV32_UART_CTRL_IRQ_TX_EMPTY) == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
|
||||
return (ctrl & NEORV32_UART_CTRL_TX_BUSY) == 0;
|
||||
return (data->last_ctrl & NEORV32_UART_CTRL_TX_FULL) == 0U;
|
||||
}
|
||||
|
||||
static void neorv32_uart_irq_rx_enable(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
uint32_t ctrl;
|
||||
|
||||
irq_enable(config->rx_irq);
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
ctrl |= NEORV32_UART_CTRL_IRQ_RX_NEMPTY;
|
||||
neorv32_uart_write_ctrl(dev, ctrl);
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
}
|
||||
|
||||
static void neorv32_uart_irq_rx_disable(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
uint32_t ctrl;
|
||||
|
||||
irq_disable(config->rx_irq);
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
ctrl &= ~NEORV32_UART_CTRL_IRQ_RX_NEMPTY;
|
||||
neorv32_uart_write_ctrl(dev, ctrl);
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
}
|
||||
|
||||
static int neorv32_uart_irq_tx_complete(const struct device *dev)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
|
||||
return (ctrl & NEORV32_UART_CTRL_TX_BUSY) == 0;
|
||||
return (data->last_ctrl & NEORV32_UART_CTRL_TX_BUSY) == 0U;
|
||||
}
|
||||
|
||||
static int neorv32_uart_irq_rx_ready(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
|
||||
if (!irq_is_enabled(config->rx_irq)) {
|
||||
if ((data->last_ctrl & NEORV32_UART_CTRL_IRQ_RX_NEMPTY) == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (data->last_data & NEORV32_UART_CTRL_RX_NEMPTY) != 0;
|
||||
return (data->last_ctrl & NEORV32_UART_CTRL_RX_NEMPTY) != 0U;
|
||||
}
|
||||
|
||||
static int neorv32_uart_irq_is_pending(const struct device *dev)
|
||||
|
@ -353,12 +358,14 @@ static int neorv32_uart_irq_is_pending(const struct device *dev)
|
|||
|
||||
static int neorv32_uart_irq_update(const struct device *dev)
|
||||
{
|
||||
const struct neorv32_uart_config *config = dev->config;
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
|
||||
if (irq_is_enabled(config->rx_irq)) {
|
||||
/* Cache data for use by rx_ready() and fifo_read() */
|
||||
(void)neorv32_uart_read_data(dev);
|
||||
}
|
||||
/* Cache the CTRL register for use in the following functions:
|
||||
* - neorv32_uart_irq_tx_complete()
|
||||
* - neorv32_uart_irq_tx_ready()
|
||||
* - neorv32_uart_irq_rx_ready()
|
||||
*/
|
||||
data->last_ctrl = neorv32_uart_read_ctrl(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -395,7 +402,7 @@ static int neorv32_uart_init(const struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_FEATURES, &features);
|
||||
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_SOC, &features);
|
||||
if (err < 0) {
|
||||
LOG_ERR("failed to determine implemented features (err %d)", err);
|
||||
return -EIO;
|
||||
|
@ -407,9 +414,6 @@ static int neorv32_uart_init(const struct device *dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
k_timer_init(&data->timer, &neorv32_uart_tx_soft_isr, NULL);
|
||||
k_timer_user_data_set(&data->timer, (void *)dev);
|
||||
|
||||
config->irq_config_func(dev);
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
||||
|
@ -420,7 +424,12 @@ static int neorv32_uart_init(const struct device *dev)
|
|||
static int neorv32_uart_pm_action(const struct device *dev,
|
||||
enum pm_device_action action)
|
||||
{
|
||||
uint32_t ctrl = neorv32_uart_read_ctrl(dev);
|
||||
struct neorv32_uart_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
uint32_t ctrl;
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
ctrl = neorv32_uart_read_ctrl(dev);
|
||||
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
|
@ -434,6 +443,7 @@ static int neorv32_uart_pm_action(const struct device *dev,
|
|||
}
|
||||
|
||||
neorv32_uart_write_ctrl(dev, ctrl);
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -470,16 +480,16 @@ static DEVICE_API(uart, neorv32_uart_driver_api) = {
|
|||
DT_IRQ_BY_NAME(node_id, tx, priority), \
|
||||
neorv32_uart_isr, \
|
||||
DEVICE_DT_GET(node_id), 0); \
|
||||
irq_enable(DT_IRQ_BY_NAME(node_id, tx, irq)); \
|
||||
\
|
||||
IRQ_CONNECT(DT_IRQ_BY_NAME(node_id, rx, irq), \
|
||||
DT_IRQ_BY_NAME(node_id, rx, priority), \
|
||||
neorv32_uart_isr, \
|
||||
DEVICE_DT_GET(node_id), 0); \
|
||||
irq_enable(DT_IRQ_BY_NAME(node_id, rx, irq)); \
|
||||
}
|
||||
#define NEORV32_UART_CONFIG_INIT(node_id, n) \
|
||||
.irq_config_func = neorv32_uart_config_func_##n, \
|
||||
.tx_irq = DT_IRQ_BY_NAME(node_id, tx, irq), \
|
||||
.rx_irq = DT_IRQ_BY_NAME(node_id, rx, irq),
|
||||
.irq_config_func = neorv32_uart_config_func_##n,
|
||||
#else
|
||||
#define NEORV32_UART_CONFIG_FUNC(node_id, n)
|
||||
#define NEORV32_UART_CONFIG_INIT(node_id, n)
|
||||
|
@ -502,7 +512,7 @@ static DEVICE_API(uart, neorv32_uart_driver_api) = {
|
|||
\
|
||||
static const struct neorv32_uart_config neorv32_uart_##n##_config = { \
|
||||
.syscon = DEVICE_DT_GET(DT_PHANDLE(node_id, syscon)), \
|
||||
.feature_mask = NEORV32_SYSINFO_FEATURES_IO_UART##n, \
|
||||
.feature_mask = NEORV32_SYSINFO_SOC_IO_UART##n, \
|
||||
.base = DT_REG_ADDR(node_id), \
|
||||
NEORV32_UART_CONFIG_INIT(node_id, n) \
|
||||
}; \
|
||||
|
|
|
@ -8,9 +8,6 @@ properties:
|
|||
reg:
|
||||
required: true
|
||||
|
||||
reg-names:
|
||||
required: true
|
||||
|
||||
syscon:
|
||||
type: phandle
|
||||
required: true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -20,7 +20,6 @@
|
|||
|
||||
cpu0: cpu@0 {
|
||||
compatible = "neorv32-cpu", "riscv";
|
||||
riscv,isa = "rv32imc_zicsr";
|
||||
reg = <0>;
|
||||
device_type = "cpu";
|
||||
|
||||
|
@ -64,77 +63,76 @@
|
|||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
mtimer: timer@ffffff90 {
|
||||
imem: memory@0 {
|
||||
compatible = "soc-nv-flash", "mmio-sram";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dmem: memory@80000000 {
|
||||
compatible = "mmio-sram";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
bootrom: rom@ffe00000 {
|
||||
compatible = "neorv32-bootrom", "mmio-sram";
|
||||
status = "disabled";
|
||||
reg = <0xffe00000 0x10000>;
|
||||
};
|
||||
|
||||
clint: clint@fff40000 {
|
||||
compatible = "neorv32-clint", "sifive,clint0";
|
||||
status = "disabled";
|
||||
reg = <0xfff40000 0x10000>;
|
||||
interrupts-extended = <&intc 3>;
|
||||
};
|
||||
|
||||
mtimer: timer@fff4bff8 {
|
||||
compatible = "riscv,machine-timer";
|
||||
reg = <0xffffff90 0x8 0xffffff98 0x8>;
|
||||
status = "disabled";
|
||||
reg = <0xfff4bff8 0x8 0xfff44000 0x8>;
|
||||
reg-names = "mtime", "mtimecmp";
|
||||
interrupts-extended = <&intc 7>;
|
||||
};
|
||||
|
||||
uart0: serial@ffffffa0 {
|
||||
uart0: serial@fff50000 {
|
||||
compatible = "neorv32-uart";
|
||||
status = "disabled";
|
||||
reg = <0xffffffa0 8>;
|
||||
reg = <0xfff50000 0x10000>;
|
||||
interrupts = <2>, <3>;
|
||||
interrupt-names = "RX", "TX";
|
||||
syscon = <&sysinfo>;
|
||||
};
|
||||
|
||||
trng: rng@ffffffb8 {
|
||||
compatible = "neorv32-trng";
|
||||
status = "disabled";
|
||||
reg = <0xffffffb8 4>;
|
||||
syscon = <&sysinfo>;
|
||||
};
|
||||
|
||||
gpio: gpio {
|
||||
compatible = "simple-bus";
|
||||
gpio-map-mask = <0xffffffe0 0xffffffc0>;
|
||||
gpio-map-pass-thru = <0x1f 0x3f>;
|
||||
gpio-map = <
|
||||
0x00 0x0 &gpio_lo 0x0 0x0
|
||||
0x20 0x0 &gpio_hi 0x0 0x0
|
||||
>;
|
||||
#gpio-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
gpio_lo: gpio@ffffffc0 {
|
||||
compatible = "neorv32-gpio";
|
||||
status = "disabled";
|
||||
reg = <0xffffffc0 4 0xffffffc8 4>;
|
||||
reg-names = "input", "output";
|
||||
gpio-controller;
|
||||
ngpios = <32>;
|
||||
syscon = <&sysinfo>;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_hi: gpio@ffffffc4 {
|
||||
compatible = "neorv32-gpio";
|
||||
status = "disabled";
|
||||
reg = <0xffffffc4 4 0xffffffcc 4>;
|
||||
reg-names = "input", "output";
|
||||
gpio-controller;
|
||||
ngpios = <32>;
|
||||
syscon = <&sysinfo>;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
uart1: serial@ffffffd0 {
|
||||
uart1: serial@fff60000 {
|
||||
compatible = "neorv32-uart";
|
||||
status = "disabled";
|
||||
reg = <0xffffffd0 8>;
|
||||
reg = <0xfff60000 0x10000>;
|
||||
interrupts = <4>, <5>;
|
||||
interrupt-names = "RX", "TX";
|
||||
syscon = <&sysinfo>;
|
||||
};
|
||||
|
||||
sysinfo: syscon@ffffffe0 {
|
||||
trng: rng@fffa0000 {
|
||||
compatible = "neorv32-trng";
|
||||
status = "disabled";
|
||||
reg = <0xfffa0000 0x10000>;
|
||||
syscon = <&sysinfo>;
|
||||
};
|
||||
|
||||
gpio: gpio@fffc0000 {
|
||||
compatible = "neorv32-gpio";
|
||||
status = "disabled";
|
||||
reg = <0xfffc0000 0x10000>;
|
||||
syscon = <&sysinfo>;
|
||||
gpio-controller;
|
||||
ngpios = <32>;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
sysinfo: syscon@fffe0000 {
|
||||
compatible = "neorv-sysinfo", "syscon";
|
||||
status = "okay";
|
||||
reg = <0xffffffe0 32>;
|
||||
reg = <0xfffe0000 0x10000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -7,4 +7,4 @@ zephyr_sources(
|
|||
soc.c
|
||||
)
|
||||
|
||||
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")
|
||||
set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "")
|
||||
|
|
|
@ -3,31 +3,20 @@
|
|||
|
||||
config SOC_NEORV32
|
||||
select RISCV
|
||||
select RISCV_ISA_RV32I
|
||||
select RISCV_ISA_EXT_M
|
||||
select RISCV_ISA_EXT_ZICSR
|
||||
select RISCV_ISA_EXT_ZIFENCEI
|
||||
select RISCV_PRIVILEGED
|
||||
select RISCV_SOC_HAS_GP_RELATIVE_ADDRESSING
|
||||
# NEORV32 RISC-V ISA A extension implements only LR/SC, not AMO
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select RISCV_ISA_EXT_ZICSR
|
||||
select RISCV_ISA_EXT_ZIFENCEI
|
||||
imply XIP
|
||||
|
||||
if SOC_NEORV32
|
||||
|
||||
config SOC_NEORV32_VERSION
|
||||
hex
|
||||
default 0x01080600
|
||||
default 0x01110100
|
||||
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 RISCV_ISA_EXT_C
|
||||
help
|
||||
Enable this if the NEORV32 CPU implementation supports the RISC-V ISA
|
||||
"C" extension (Compressed Instructions).
|
||||
|
||||
endif # SOC_NEORV32
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if SOC_NEORV32
|
||||
|
@ -12,12 +12,4 @@ config NUM_IRQS
|
|||
config SYSCON
|
||||
default y
|
||||
|
||||
config SERIAL_INIT_PRIORITY
|
||||
default 55
|
||||
depends on SERIAL
|
||||
|
||||
config ENTROPY_INIT_PRIORITY
|
||||
default 55
|
||||
depends on ENTROPY_GENERATOR
|
||||
|
||||
endif # SOC_NEORV32
|
||||
|
|
|
@ -8,15 +8,9 @@ config SOC_NEORV32
|
|||
|
||||
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)
|
||||
- Zicsr (always enabled)
|
||||
- Zifencei (always enabled)
|
||||
- Zicntr
|
||||
|
||||
config SOC
|
||||
default "neorv32" if SOC_NEORV32
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/linker/linker-tool.h>
|
||||
|
||||
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 <zephyr/arch/riscv/common/linker.ld>
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -13,9 +13,6 @@ GTEXT(__reset)
|
|||
GTEXT(__initialize)
|
||||
|
||||
SECTION_FUNC(reset, __reset)
|
||||
/* Zerorize zero register */
|
||||
lui x0, 0
|
||||
|
||||
/* Disable interrupts */
|
||||
csrw mstatus, x0
|
||||
csrw mie, x0
|
||||
|
@ -26,7 +23,7 @@ SECTION_FUNC(reset, __reset)
|
|||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
/* Allow mcycle and minstret counters to increment */
|
||||
li x11, ~2
|
||||
li x11, ~5
|
||||
csrw mcountinhibit, x11
|
||||
|
||||
/* Zerorize counters */
|
||||
|
@ -35,39 +32,5 @@ SECTION_FUNC(reset, __reset)
|
|||
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
|
||||
|
|
|
@ -1,56 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
* Copyright (c) 2021,2025 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef RISCV_NEORV32_SOC_H
|
||||
#define RISCV_NEORV32_SOC_H
|
||||
#ifndef _NEORV32_SOC_H
|
||||
#define _NEORV32_SOC_H
|
||||
|
||||
/* System information (SYSINFO) register offsets */
|
||||
#define NEORV32_SYSINFO_CLK 0x00U
|
||||
#define NEORV32_SYSINFO_CPU 0x04U
|
||||
#define NEORV32_SYSINFO_FEATURES 0x08U
|
||||
#define NEORV32_SYSINFO_MISC 0x04U
|
||||
#define NEORV32_SYSINFO_SOC 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) MISC register bits */
|
||||
#define NEORV32_SYSINFO_MISC_IMEM GENMASK(7, 0)
|
||||
#define NEORV32_SYSINFO_MISC_DMEM GENMASK(15, 8)
|
||||
#define NEORV32_SYSINFO_MISC_HART GENMASK(23, 16)
|
||||
#define NEORV32_SYSINFO_MISC_BOOT GENMASK(31, 24)
|
||||
|
||||
/* 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)
|
||||
/* System information (SYSINFO) SOC register bits */
|
||||
#define NEORV32_SYSINFO_SOC_BOOTLOADER BIT(0)
|
||||
#define NEORV32_SYSINFO_SOC_XBUS BIT(1)
|
||||
#define NEORV32_SYSINFO_SOC_MEM_INT_IMEM BIT(2)
|
||||
#define NEORV32_SYSINFO_SOC_MEM_INT_DMEM BIT(3)
|
||||
#define NEORV32_SYSINFO_SOC_OCD BIT(4)
|
||||
#define NEORV32_SYSINFO_SOC_ICACHE BIT(5)
|
||||
#define NEORV32_SYSINFO_SOC_DCACHE BIT(6)
|
||||
#define NEORV32_SYSINFO_SOC_XBUS_CACHE BIT(8)
|
||||
#define NEORV32_SYSINFO_SOC_OCD_AUTH BIT(11)
|
||||
#define NEORV32_SYSINFO_SOC_IMEM_ROM BIT(12)
|
||||
#define NEORV32_SYSINFO_SOC_IO_TWD BIT(13)
|
||||
#define NEORV32_SYSINFO_SOC_IO_DMA BIT(14)
|
||||
#define NEORV32_SYSINFO_SOC_IO_GPIO BIT(15)
|
||||
#define NEORV32_SYSINFO_SOC_IO_CLINT BIT(16)
|
||||
#define NEORV32_SYSINFO_SOC_IO_UART0 BIT(17)
|
||||
#define NEORV32_SYSINFO_SOC_IO_SPI BIT(18)
|
||||
#define NEORV32_SYSINFO_SOC_IO_TWI BIT(19)
|
||||
#define NEORV32_SYSINFO_SOC_IO_PWM BIT(20)
|
||||
#define NEORV32_SYSINFO_SOC_IO_WDT BIT(21)
|
||||
#define NEORV32_SYSINFO_SOC_IO_CFS BIT(22)
|
||||
#define NEORV32_SYSINFO_SOC_IO_TRNG BIT(23)
|
||||
#define NEORV32_SYSINFO_SOC_IO_SDI BIT(24)
|
||||
#define NEORV32_SYSINFO_SOC_IO_UART1 BIT(25)
|
||||
#define NEORV32_SYSINFO_SOC_IO_NEOLED BIT(26)
|
||||
#define NEORV32_SYSINFO_SOC_IO_GPTMR BIT(28)
|
||||
#define NEORV32_SYSINFO_SOC_IO_SLINK BIT(29)
|
||||
#define NEORV32_SYSINFO_SOC_IO_ONEWIRE BIT(30)
|
||||
#define NEORV32_SYSINFO_SOC_IO_CRC BIT(31)
|
||||
|
||||
#endif /* RISCV_NEORV32_SOC_H */
|
||||
/* System information (SYSINFO) CACHE register bits */
|
||||
#define NEORV32_SYSINFO_CACHE_INST_BLOCK_SIZE GENMASK(3, 0)
|
||||
#define NEORV32_SYSINFO_CACHE_INST_NUM_BLOCKS GENMASK(7, 4)
|
||||
#define NEORV32_SYSINFO_CACHE_DATA_BLOCK_SIZE GENMASK(11, 8)
|
||||
#define NEORV32_SYSINFO_CACHE_DATA_NUM_BLOCKS GENMASK(15, 12)
|
||||
#define NEORV32_SYSINFO_CACHE_XBUS_BLOCK_SIZE GENMASK(27, 24)
|
||||
#define NEORV32_SYSINFO_CACHE_XBUS_NUM_BLOCKS GENMASK(31, 28)
|
||||
|
||||
#endif /* _NEORV32_SOC_H */
|
||||
|
|
|
@ -13,16 +13,4 @@ GTEXT(__soc_handle_irq)
|
|||
* Exception number is given as parameter via register a0.
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_handle_irq)
|
||||
/*
|
||||
* 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 */
|
||||
ret
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&trng {
|
||||
status = "okay";
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue