bflb: Make BL60x independant from SDK

Reorganize and update soc folder files for SDK-independance
Reorganize and update hal_bouffalolab files for SDK-independance
Reorganize and update soc dts files for SDK-independance
Update serial and pinctrl driver files for SDK-independance
Update ai_wb2_12f, bl604e_iot_dvk, and dt_bl10_dvk
to new bl60x support
and fixup openocd config of ai_wb2_12f

Signed-off-by: Camille BAUD <mail@massdriver.space>
This commit is contained in:
Camille BAUD
2025-06-21 21:39:10 +02:00
committed by Chris Friedt
parent 0c352f1b3a
commit bdffc08279
40 changed files with 860 additions and 838 deletions

View File

@@ -6,7 +6,7 @@
/dts-v1/;
#include <bflb/bl60x.dtsi>
#include <bflb/bl602.dtsi>
#include "ai_wb2_12f-pinctrl.dtsi"
/ {
@@ -15,6 +15,7 @@
chosen {
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,itcm = &itcm;
zephyr,dtcm = &dtcm;
zephyr,sram = &sram0;
@@ -27,18 +28,30 @@
clock-frequency = <DT_FREQ_M(192)>;
};
&spi1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x4000b000 0x1000 0x23000000 0x400000>;
&flashctrl {
flash0: flash@23000000 {
compatible = "soc-nv-flash", "zb,25vq32";
reg = <0x23000000 (0x400000 - 0x2000)>;
write-block-size = <256>;
erase-block-size = <DT_SIZE_K(4)>;
/* jedec-id = [5e 40 16]; */
flash0: flash@0 {
compatible = "zb,25vq32", "jedec,spi-nor";
status = "disabled";
size = <DT_SIZE_M(128)>;
jedec-id = [5e 40 16];
reg = <0>;
spi-max-frequency = <DT_FREQ_M(133)>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
slot0_partition: partition@0 {
label = "image-0";
reg = <0x00000000 0x00100000>;
read-only;
};
storage_partition: partition@100000 {
label = "storage";
reg = <0x00100000 (0x300000 - 0x2000)>;
};
};
};
};

View File

@@ -38,23 +38,22 @@ echo "Ready for Remote Connections"
$_TARGETNAME.0 configure -event reset-assert-pre {
echo "reset-assert-pre"
adapter speed 100
adapter speed 400
}
$_TARGETNAME.0 configure -event reset-deassert-post {
echo "reset-deassert-post"
adapter speed 100
adapter speed 400
reg mstatus 0x7800
reg mie 0x0
# reg pc 0x23000000
reg mstatus 0x0
reg pc 0x21000000
}
$_TARGETNAME.0 configure -event reset-init {
echo "reset-init"
adapter speed 3000
adapter speed 400
}
$_TARGETNAME.0 configure -event gdb-attach {

View File

@@ -2,4 +2,4 @@
interface cmsis-dap
adapter speed 1000
adapter speed 400

View File

@@ -6,7 +6,7 @@
/dts-v1/;
#include <bflb/bl60x.dtsi>
#include <bflb/bl604.dtsi>
#include "bl604e_iot_dvk-pinctrl.dtsi"
/ {
@@ -15,6 +15,7 @@
chosen {
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,itcm = &itcm;
zephyr,dtcm = &dtcm;
zephyr,sram = &sram0;
@@ -27,18 +28,30 @@
clock-frequency = <DT_FREQ_M(192)>;
};
&spi1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x4000b000 0x1000 0x23000000 0xc00000>;
&flashctrl {
flash0: flash@23000000 {
compatible = "soc-nv-flash", "issi,is25lp128";
reg = <0x23000000 (0x1000000 - 0x2000)>;
write-block-size = <256>;
erase-block-size = <DT_SIZE_K(4)>;
/* jedec-id = [96 60 18]; */
flash0: flash@0 {
compatible = "issi,is25lp128", "jedec,spi-nor";
status = "disabled";
size = <DT_SIZE_M(128)>;
jedec-id = [96 60 18];
reg = <0>;
spi-max-frequency = <DT_FREQ_M(133)>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
slot0_partition: partition@0 {
label = "image-0";
reg = <0x00000000 0x100000>;
read-only;
};
storage_partition: partition@100000 {
label = "storage";
reg = <0x00100000 (0xF00000 - 0x2000)>;
};
};
};
};

View File

@@ -14,6 +14,7 @@
chosen {
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,itcm = &itcm;
zephyr,dtcm = &dtcm;
zephyr,sram = &sram0;
@@ -26,18 +27,30 @@
clock-frequency = <DT_FREQ_M(192)>;
};
&spi1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x4000b000 0x1000 0x23000000 0xc00000>;
&flashctrl {
flash0: flash@23000000 {
compatible = "soc-nv-flash", "issi,is25lp128";
reg = <0x23000000 (0x1000000 - 0x2000)>;
write-block-size = <256>;
erase-block-size = <DT_SIZE_K(4)>;
/* jedec-id = [96 60 18]; */
flash0: flash@0 {
compatible = "issi,is25lp128", "jedec,spi-nor";
status = "disabled";
size = <DT_SIZE_M(128)>;
jedec-id = [96 60 18];
reg = <0>;
spi-max-frequency = <DT_FREQ_M(133)>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
slot0_partition: partition@0 {
label = "image-0";
reg = <0x00000000 0x100000>;
read-only;
};
storage_partition: partition@100000 {
label = "storage";
reg = <0x00100000 (0xF00000 - 0x2000)>;
};
};
};
};

View File

@@ -10,7 +10,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_ARM_MPS2 pinctrl_arm_mps2.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ARM_MPS3 pinctrl_arm_mps3.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ARM_MPS4 pinctrl_arm_mps4.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ARM_V2M_BEETLE pinctrl_arm_v2m_beetle.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_BFLB pinctrl_bflb.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ITE_IT8XXX2 pinctrl_ite_it8xxx2.c)
@@ -59,3 +58,8 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_WCH_20X_30X_AFIO pinctrl_wch_20x_30x
zephyr_library_sources_ifdef(CONFIG_PINCTRL_WCH_00X_AFIO pinctrl_wch_00x_afio.c)
add_subdirectory(renesas)
if (CONFIG_PINCTRL_BFLB)
zephyr_library_sources(pinctrl_bflb.c)
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_BL60X pinctrl_bflb_bl60x_70x.c)
endif()

View File

@@ -6,40 +6,35 @@
#include <zephyr/kernel.h>
#include <zephyr/drivers/pinctrl.h>
#include <bflb_pinctrl.h>
#include <bflb_glb.h>
#include <bflb_gpio.h>
/* clang-format off */
#include <zephyr/dt-bindings/pinctrl/bflb-common-pinctrl.h>
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
uintptr_t reg)
#if defined(CONFIG_SOC_SERIES_BL60X)
#include <zephyr/dt-bindings/pinctrl/bl60x-pinctrl.h>
#else
#error "Unsupported Platform"
#endif
void pinctrl_bflb_configure_uart(uint8_t pin, uint8_t func);
void pinctrl_bflb_init_pin(pinctrl_soc_pin_t pin);
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
{
GLB_GPIO_Cfg_Type pincfg;
uint8_t i;
ARG_UNUSED(reg);
for (i = 0U; i < pin_cnt; i++) {
pincfg.gpioFun = BFLB_PINMUX_GET_FUN(pins[i]);
pincfg.gpioMode = BFLB_PINMUX_GET_MODE(pins[i]);
pincfg.gpioPin = BFLB_PINMUX_GET_PIN(pins[i]);
pincfg.pullType = BFLB_PINMUX_GET_PULL_MODES(pins[i]);
pincfg.smtCtrl = BFLB_PINMUX_GET_SMT(pins[i]);
pincfg.drive = BFLB_PINMUX_GET_DRIVER_STRENGTH(pins[i]);
if (pincfg.gpioFun == BFLB_PINMUX_FUN_INST_uart0) {
GLB_UART_Fun_Sel(pincfg.gpioPin % 8,
(BFLB_PINMUX_GET_INST(pins[i]))
* 0x4U /* rts, cts, rx, tx */
+ BFLB_PINMUX_GET_SIGNAL(pins[i])
);
if ((BFLB_PINMUX_GET_FUN(pins[i]) & BFLB_PINMUX_FUN_MASK)
== BFLB_PINMUX_FUN_INST_uart0) {
pinctrl_bflb_configure_uart(BFLB_PINMUX_GET_PIN(pins[i]),
BFLB_PINMUX_GET_SIGNAL(pins[i]) + 4 * BFLB_PINMUX_GET_INST(pins[i]));
}
GLB_GPIO_Init(&pincfg);
/* gpio init*/
pinctrl_bflb_init_pin(pins[i]);
}
return 0;
}
/* clang-format on */

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/pinctrl.h>
#include <bflb_soc.h>
#include <glb_reg.h>
#include <zephyr/dt-bindings/pinctrl/bflb-common-pinctrl.h>
#if defined(CONFIG_SOC_SERIES_BL60X)
#include <zephyr/dt-bindings/pinctrl/bl60x-pinctrl.h>
#else
#error "Unsupported Platform"
#endif
void pinctrl_bflb_configure_uart(uint8_t pin, uint8_t func)
{
/* uart func for BL602 and BL702 Only*/
uint32_t regval;
uint8_t sig;
uint8_t sig_pos;
regval = sys_read32(GLB_BASE + GLB_UART_SIG_SEL_0_OFFSET);
sig = pin % 8;
sig_pos = sig << 2;
regval &= (~(0x0f << sig_pos));
regval |= (func << sig_pos);
for (uint8_t i = 0; i < 8; i++) {
/* reset other sigs which are the same with uart_func */
sig_pos = i << 2;
if (((regval & (0x0f << sig_pos)) == (func << sig_pos)) && (i != sig) && (func !=
0x0f)) {
regval &= (~(0x0f << sig_pos));
regval |= (0x0f << sig_pos);
}
}
sys_write32(regval, GLB_BASE + GLB_UART_SIG_SEL_0_OFFSET);
}
void pinctrl_bflb_init_pin(pinctrl_soc_pin_t pin)
{
uint8_t drive;
uint8_t function;
uint16_t mode;
uint32_t regval;
uint8_t real_pin;
uint8_t is_odd = 0;
uint32_t cfg = 0;
uint32_t cfg_address;
real_pin = BFLB_PINMUX_GET_PIN(pin);
function = BFLB_PINMUX_GET_FUN(pin);
mode = BFLB_PINMUX_GET_MODE(pin);
drive = BFLB_PINMUX_GET_DRIVER_STRENGTH(pin);
/* Disable output anyway */
regval = sys_read32(GLB_BASE + GLB_GPIO_CFGCTL34_OFFSET + ((real_pin >> 5) << 2));
regval &= ~(1 << (real_pin & 0x1f));
sys_write32(regval, GLB_BASE + GLB_GPIO_CFGCTL34_OFFSET + ((real_pin >> 5) << 2));
is_odd = real_pin & 1;
cfg_address = GLB_BASE + GLB_GPIO_CFGCTL0_OFFSET + (real_pin / 2 * 4);
cfg = sys_read32(cfg_address);
cfg &= ~(0xffff << (16 * is_odd));
regval = sys_read32(GLB_BASE + GLB_GPIO_CFGCTL34_OFFSET + ((real_pin >> 5) << 2));
if (mode == BFLB_PINMUX_MODE_analog) {
regval &= ~(1 << (real_pin & 0x1f));
function = 10;
} else if (mode == BFLB_PINMUX_MODE_periph) {
cfg |= (1 << (is_odd * 16 + 0));
regval &= ~(1 << (real_pin & 0x1f));
} else {
function = 11;
if (mode == BFLB_PINMUX_MODE_input) {
cfg |= (1 << (is_odd * 16 + 0));
}
if (mode == BFLB_PINMUX_MODE_output) {
regval |= (1 << (real_pin & 0x1f));
}
}
sys_write32(regval, GLB_BASE + GLB_GPIO_CFGCTL34_OFFSET + ((real_pin >> 5) << 2));
uint8_t pull_up = BFLB_PINMUX_GET_PULL_UP(pin);
uint8_t pull_down = BFLB_PINMUX_GET_PULL_DOWN(pin);
if (pull_up) {
cfg |= (1 << (is_odd * 16 + 4));
} else if (pull_down) {
cfg |= (1 << (is_odd * 16 + 5));
} else {
}
if (BFLB_PINMUX_GET_SMT(pin)) {
cfg |= (1 << (is_odd * 16 + 1));
}
cfg |= (drive << (is_odd * 16 + 2));
cfg |= (function << (is_odd * 16 + 8));
sys_write32(cfg, cfg_address);
}

View File

@@ -9,6 +9,5 @@ config UART_BFLB
select PINCTRL
select SERIAL_HAS_DRIVER
select SERIAL_SUPPORT_INTERRUPT
select USE_BFLB_UART
help
This option enables the UART driver for Bouffalo Lab SoC family.

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021-2025 ATL Electronics
* Copyright (c) 2024-2025, MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,28 +10,39 @@
/**
* @brief UART driver for Bouffalo Lab MCU family.
*/
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/pm/device.h>
#include <zephyr/arch/common/sys_io.h>
#include <zephyr/drivers/timer/system_timer.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/irq.h>
#include <zephyr/dt-bindings/clock/bflb_clock_common.h>
#include <soc.h>
#include <bflb_soc.h>
#include <glb_reg.h>
#include <common_defines.h>
#include <bouffalolab/common/uart_reg.h>
#include <bouffalolab/common/bflb_uart.h>
#include <bflb_pinctrl.h>
#include <bflb_uart.h>
#include <bflb_glb.h>
#define UART_CTS_FLOWCONTROL_ENABLE (0)
#define UART_RTS_FLOWCONTROL_ENABLE (0)
#define UART_MSB_FIRST_ENABLE (0)
#define UART_DEFAULT_RTO_TIMEOUT (255)
#define UART_CLOCK_DIV (0)
struct bflb_config {
uint32_t *reg;
const struct pinctrl_dev_config *pinctrl_cfg;
uint32_t periph_id;
UART_CFG_Type uart_cfg;
UART_FifoCfg_Type fifo_cfg;
const struct pinctrl_dev_config *pincfg;
uint32_t baudrate;
uint8_t direction;
uint8_t data_bits;
uint8_t stop_bits;
uint8_t parity;
uint8_t bit_order;
uint8_t flow_ctrl;
uint8_t tx_fifo_threshold;
uint8_t rx_fifo_threshold;
uint32_t base_reg;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_irq_config_func_t irq_config_func;
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
@@ -43,88 +55,100 @@ struct bflb_data {
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};
static int uart_bflb_init(const struct device *dev)
static void uart_bflb_enabled(const struct device *dev, uint32_t enable)
{
const struct bflb_config *cfg = dev->config;
uint32_t rxt = 0;
uint32_t txt = 0;
pinctrl_apply_state(cfg->pinctrl_cfg, PINCTRL_STATE_DEFAULT);
if (enable > 1) {
enable = 1;
}
GLB_Set_UART_CLK(1, HBN_UART_CLK_160M, UART_CLOCK_DIV);
txt = sys_read32(cfg->base_reg + UART_UTX_CONFIG_OFFSET);
txt = (txt & ~UART_CR_UTX_EN) | enable;
rxt = sys_read32(cfg->base_reg + UART_URX_CONFIG_OFFSET);
rxt = (rxt & ~UART_CR_URX_EN) | enable;
sys_write32(rxt, cfg->base_reg + UART_URX_CONFIG_OFFSET);
sys_write32(txt, cfg->base_reg + UART_UTX_CONFIG_OFFSET);
}
UART_IntMask(cfg->periph_id, UART_INT_ALL, 1);
UART_Disable(cfg->periph_id, UART_TXRX);
static uint32_t uart_bflb_get_clock(void)
{
uint32_t uart_divider = 0;
uint32_t uclk;
const struct device *clock_ctrl = DEVICE_DT_GET_ANY(bflb_clock_controller);
#if defined(CONFIG_SOC_SERIES_BL60X)
uart_divider = sys_read32(GLB_BASE + GLB_CLK_CFG2_OFFSET);
uart_divider = (uart_divider & GLB_UART_CLK_DIV_MSK) >> GLB_UART_CLK_DIV_POS;
clock_control_get_rate(clock_ctrl, (void *)BFLB_CLKID_CLK_ROOT, &uclk);
#else
uart_divider = sys_read32(GLB_BASE + GLB_UART_CFG0_OFFSET);
uart_divider = (uart_divider & GLB_UART_CLK_DIV_MSK) >> GLB_UART_CLK_DIV_POS;
clock_control_get_rate(clock_ctrl, (void *)BFLB_CLKID_CLK_BCLK, &uclk);
#endif
return uclk / (uart_divider + 1);
}
UART_Init(cfg->periph_id, (UART_CFG_Type *)&cfg->uart_cfg);
UART_TxFreeRun(cfg->periph_id, 1);
UART_SetRxTimeoutValue(cfg->periph_id, UART_DEFAULT_RTO_TIMEOUT);
UART_FifoConfig(cfg->periph_id, (UART_FifoCfg_Type *)&cfg->fifo_cfg);
UART_Enable(cfg->periph_id, UART_TXRX);
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
cfg->irq_config_func(dev);
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
return 0;
}
static int uart_bflb_poll_in(const struct device *dev, unsigned char *c)
{
const struct bflb_config *cfg = dev->config;
return UART_ReceiveData(cfg->periph_id, (uint8_t *)c, 1) ? 0 : -1;
}
static void uart_bflb_poll_out(const struct device *dev, unsigned char c)
{
const struct bflb_config *cfg = dev->config;
while (UART_GetTxFifoCount(cfg->periph_id) == 0) {
;
}
(void)UART_SendData(cfg->periph_id, (uint8_t *)&c, 1);
}
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static int uart_bflb_err_check(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t status = BL_RD_REG(cfg->reg, UART_INT_STS);
uint32_t clear_mask = 0;
uint32_t status = 0;
uint32_t tmp = 0;
int errors = 0;
if (status & BIT(UART_INT_RX_FER)) {
clear_mask |= BIT(UART_INT_RX_FER);
status = sys_read32(cfg->base_reg + UART_INT_STS_OFFSET);
tmp = sys_read32(cfg->base_reg + UART_INT_CLEAR_OFFSET);
if (status & UART_URX_FER_INT) {
errors |= UART_ERROR_OVERRUN;
}
if (status & BIT(UART_INT_TX_FER)) {
clear_mask |= BIT(UART_INT_TX_FER);
if (status & UART_UTX_FER_INT) {
errors |= UART_ERROR_OVERRUN;
}
if (status & BIT(UART_INT_PCE)) {
clear_mask |= BIT(UART_INT_PCE);
if (status & UART_URX_PCE_INT) {
tmp |= UART_CR_URX_PCE_CLR;
errors |= UART_ERROR_PARITY;
}
if (clear_mask != 0) {
BL_WR_REG(cfg->reg, UART_INT_CLEAR, clear_mask);
}
sys_write32(tmp, cfg->base_reg + UART_INT_CLEAR_OFFSET);
return errors;
}
int uart_bflb_irq_tx_ready(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
tmp = sys_read32(cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET);
return (tmp & UART_TX_FIFO_CNT_MASK) > 0;
}
int uart_bflb_irq_rx_ready(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
tmp = sys_read32(cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET);
return (tmp & UART_RX_FIFO_CNT_MASK) > 0;
}
int uart_bflb_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
{
const struct bflb_config *const cfg = dev->config;
uint8_t num_tx = 0U;
while ((len - num_tx > 0) && (UART_GetTxFifoCount(cfg->periph_id) > 0)) {
BL_WR_BYTE(cfg->reg + UART_FIFO_WDATA_OFFSET, tx_data[num_tx++]);
while (num_tx < len && uart_bflb_irq_tx_ready(dev) > 0) {
sys_write32(tx_data[num_tx++], cfg->base_reg + UART_FIFO_WDATA_OFFSET);
}
return num_tx;
@@ -135,8 +159,8 @@ int uart_bflb_fifo_read(const struct device *dev, uint8_t *rx_data, const int si
const struct bflb_config *const cfg = dev->config;
uint8_t num_rx = 0U;
while ((size - num_rx > 0) && (UART_GetRxFifoCount(cfg->periph_id) > 0)) {
rx_data[num_rx++] = BL_RD_BYTE(cfg->reg + UART_FIFO_RDATA_OFFSET);
while ((num_rx < size) && uart_bflb_irq_rx_ready(dev) > 0) {
rx_data[num_rx++] = sys_read32(cfg->base_reg + UART_FIFO_RDATA_OFFSET);
}
return num_rx;
@@ -145,82 +169,93 @@ int uart_bflb_fifo_read(const struct device *dev, uint8_t *rx_data, const int si
void uart_bflb_irq_tx_enable(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
UART_IntMask(cfg->periph_id, UART_INT_TX_FIFO_REQ, 1);
tmp = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
tmp = tmp & ~UART_CR_UTX_FIFO_MASK;
sys_write32(tmp, cfg->base_reg + UART_INT_MASK_OFFSET);
}
void uart_bflb_irq_tx_disable(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
UART_IntMask(cfg->periph_id, UART_INT_TX_FIFO_REQ, 0);
tmp = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
tmp = tmp | UART_CR_UTX_FIFO_MASK;
sys_write32(tmp, cfg->base_reg + UART_INT_MASK_OFFSET);
}
int uart_bflb_irq_tx_ready(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t maskVal = BL_RD_REG(cfg->reg, UART_INT_MASK);
return (UART_GetTxFifoCount(cfg->periph_id) > 0)
&& BL_IS_REG_BIT_SET(maskVal, UART_CR_UTX_FIFO_MASK);
}
int uart_bflb_irq_tx_complete(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp;
return !UART_GetTxBusBusyStatus(cfg->periph_id);
tmp = sys_read32(cfg->base_reg + UART_STATUS_OFFSET);
if (tmp & UART_STS_UTX_BUS_BUSY) {
return 0;
}
tmp = sys_read32(cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET);
if ((tmp & UART_TX_FIFO_CNT_MASK) >= cfg->tx_fifo_threshold) {
return 1;
}
return 0;
}
void uart_bflb_irq_rx_enable(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
UART_IntMask(cfg->periph_id, UART_INT_RX_FIFO_REQ, 1);
tmp = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
tmp = tmp & ~UART_CR_URX_FIFO_MASK;
sys_write32(tmp, cfg->base_reg + UART_INT_MASK_OFFSET);
}
void uart_bflb_irq_rx_disable(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
UART_IntMask(cfg->periph_id, UART_INT_RX_FIFO_REQ, 0);
}
int uart_bflb_irq_rx_ready(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
return UART_GetRxFifoCount(cfg->periph_id) > 0;
tmp = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
tmp = tmp | UART_CR_URX_FIFO_MASK;
sys_write32(tmp, cfg->base_reg + UART_INT_MASK_OFFSET);
}
void uart_bflb_irq_err_enable(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
UART_IntMask(cfg->periph_id, UART_INT_PCE
| UART_INT_TX_FER
| UART_INT_RX_FER, 1);
tmp = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
tmp = tmp & ~UART_CR_URX_PCE_MASK;
tmp = tmp & ~UART_CR_UTX_FER_MASK;
tmp = tmp & ~UART_CR_URX_FER_MASK;
sys_write32(tmp, cfg->base_reg + UART_INT_MASK_OFFSET);
}
void uart_bflb_irq_err_disable(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
UART_IntMask(cfg->periph_id, UART_INT_PCE
| UART_INT_TX_FER
| UART_INT_RX_FER, 0);
tmp = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
tmp = tmp | UART_CR_URX_PCE_MASK;
tmp = tmp | UART_CR_UTX_FER_MASK;
tmp = tmp | UART_CR_URX_FER_MASK;
sys_write32(tmp, cfg->base_reg + UART_INT_MASK_OFFSET);
}
int uart_bflb_irq_is_pending(const struct device *dev)
{
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = BL_RD_REG(cfg->reg, UART_INT_STS);
uint32_t maskVal = BL_RD_REG(cfg->reg, UART_INT_MASK);
uint32_t tmp = sys_read32(cfg->base_reg + UART_INT_STS_OFFSET);
uint32_t maskVal = sys_read32(cfg->base_reg + UART_INT_MASK_OFFSET);
return ((BL_IS_REG_BIT_SET(tmp, UART_URX_FIFO_INT) &&
BL_IS_REG_BIT_SET(maskVal, UART_CR_URX_FIFO_MASK)) ||
(BL_IS_REG_BIT_SET(tmp, UART_UTX_FIFO_INT) &&
BL_IS_REG_BIT_SET(maskVal, UART_CR_UTX_FIFO_MASK)));
/* only first 8 bits are not reserved */
return (((tmp & ~maskVal) & 0xFF) != 0 ? 1 : 0);
}
int uart_bflb_irq_update(const struct device *dev)
@@ -243,32 +278,219 @@ void uart_bflb_irq_callback_set(const struct device *dev,
static void uart_bflb_isr(const struct device *dev)
{
struct bflb_data *const data = dev->data;
const struct bflb_config *const cfg = dev->config;
uint32_t tmp = 0;
if (data->user_cb) {
data->user_cb(dev, data->user_data);
}
/* clear interrupts that require ack*/
tmp = sys_read32(cfg->base_reg + UART_INT_CLEAR_OFFSET);
tmp = tmp | UART_CR_URX_RTO_CLR;
sys_write32(tmp, cfg->base_reg + UART_INT_CLEAR_OFFSET);
}
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
static int uart_bflb_configure(const struct device *dev)
{
const struct bflb_config *cfg = dev->config;
uint32_t tx_cfg = 0;
uint32_t rx_cfg = 0;
uint32_t divider = 0;
uint32_t tmp = 0;
divider = (uart_bflb_get_clock() * 10 / cfg->baudrate + 5) / 10;
if (divider >= 0xFFFF) {
divider = 0xFFFF - 1;
}
uart_bflb_enabled(dev, 0);
sys_write32(((divider - 1) << 0x10) | ((divider - 1) & 0xFFFF), cfg->base_reg
+ UART_BIT_PRD_OFFSET);
/* Configure Parity */
tx_cfg = sys_read32(cfg->base_reg + UART_UTX_CONFIG_OFFSET);
rx_cfg = sys_read32(cfg->base_reg + UART_URX_CONFIG_OFFSET);
switch (cfg->parity) {
case UART_PARITY_NONE:
tx_cfg &= ~UART_CR_UTX_PRT_EN;
rx_cfg &= ~UART_CR_URX_PRT_EN;
break;
case UART_PARITY_ODD:
tx_cfg |= UART_CR_UTX_PRT_EN;
tx_cfg |= UART_CR_UTX_PRT_SEL;
rx_cfg |= UART_CR_URX_PRT_EN;
rx_cfg |= UART_CR_URX_PRT_SEL;
break;
case UART_PARITY_EVEN:
tx_cfg |= UART_CR_UTX_PRT_EN;
tx_cfg &= ~UART_CR_UTX_PRT_SEL;
rx_cfg |= UART_CR_URX_PRT_EN;
rx_cfg &= ~UART_CR_URX_PRT_SEL;
break;
default:
break;
}
/* Configure data bits */
tx_cfg &= ~UART_CR_UTX_BIT_CNT_D_MASK;
tx_cfg |= (cfg->data_bits + 4) << UART_CR_UTX_BIT_CNT_D_SHIFT;
rx_cfg &= ~UART_CR_URX_BIT_CNT_D_MASK;
rx_cfg |= (cfg->data_bits + 4) << UART_CR_URX_BIT_CNT_D_SHIFT;
/* Configure tx stop bits */
tx_cfg &= ~UART_CR_UTX_BIT_CNT_P_MASK;
tx_cfg |= cfg->stop_bits << UART_CR_UTX_BIT_CNT_P_SHIFT;
/* Configure tx cts flow control function */
if (cfg->flow_ctrl & UART_FLOWCTRL_CTS) {
tx_cfg |= UART_CR_UTX_CTS_EN;
} else {
tx_cfg &= ~UART_CR_UTX_CTS_EN;
}
/* disable de-glitch function */
rx_cfg &= ~UART_CR_URX_DEG_EN;
/* Write config */
sys_write32(tx_cfg, cfg->base_reg + UART_UTX_CONFIG_OFFSET);
sys_write32(rx_cfg, cfg->base_reg + UART_URX_CONFIG_OFFSET);
/* enable hardware control RTS */
#if defined(CONFIG_SOC_SERIES_BL60X)
tmp = sys_read32(cfg->base_reg + UART_URX_CONFIG_OFFSET);
tmp &= ~UART_CR_URX_RTS_SW_MODE;
sys_write32(tmp, cfg->base_reg + UART_URX_CONFIG_OFFSET);
#else
tmp = sys_read32(cfg->base_reg + UART_SW_MODE_OFFSET);
tmp &= ~UART_CR_URX_RTS_SW_MODE;
sys_write32(tmp, cfg->base_reg + UART_SW_MODE_OFFSET);
#endif
/* disable inversion */
tmp = sys_read32(cfg->base_reg + UART_DATA_CONFIG_OFFSET);
tmp &= ~UART_CR_UART_BIT_INV;
sys_write32(tmp, cfg->base_reg + UART_DATA_CONFIG_OFFSET);
/* TX free run enable */
tmp = sys_read32(cfg->base_reg + UART_UTX_CONFIG_OFFSET);
tmp |= UART_CR_UTX_FRM_EN;
sys_write32(tmp, cfg->base_reg + UART_UTX_CONFIG_OFFSET);
/* Configure FIFO thresholds */
tmp = sys_read32(cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET);
tmp &= ~UART_TX_FIFO_TH_MASK;
tmp &= ~UART_RX_FIFO_TH_MASK;
tmp |= (cfg->tx_fifo_threshold << UART_TX_FIFO_TH_SHIFT) & UART_TX_FIFO_TH_MASK;
tmp |= (cfg->rx_fifo_threshold << UART_RX_FIFO_TH_SHIFT) & UART_RX_FIFO_TH_MASK;
sys_write32(tmp, cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET);
/* Clear FIFO */
tmp = sys_read32(cfg->base_reg + UART_FIFO_CONFIG_0_OFFSET);
tmp |= UART_TX_FIFO_CLR;
tmp |= UART_RX_FIFO_CLR;
tmp &= ~UART_DMA_TX_EN;
tmp &= ~UART_DMA_RX_EN;
sys_write32(tmp, cfg->base_reg + UART_FIFO_CONFIG_0_OFFSET);
return 0;
}
static int uart_bflb_init(const struct device *dev)
{
const struct bflb_config *cfg = dev->config;
int rc = 0;
pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
rc = uart_bflb_configure(dev);
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
/* disable all irqs */
sys_write32(0x0, cfg->base_reg + UART_INT_EN_OFFSET);
/* clear all IRQS */
sys_write32(0xFF, cfg->base_reg + UART_INT_CLEAR_OFFSET);
/* mask all IRQs */
sys_write32(0xFFFFFFFFU, cfg->base_reg + UART_INT_MASK_OFFSET);
/* unmask necessary irqs */
uart_bflb_irq_rx_enable(dev);
uart_bflb_irq_err_enable(dev);
/* enable all irqs */
sys_write32(0xFF, cfg->base_reg + UART_INT_EN_OFFSET);
cfg->irq_config_func(dev);
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
uart_bflb_enabled(dev, 1);
return rc;
}
static int uart_bflb_poll_in(const struct device *dev, unsigned char *c)
{
const struct bflb_config *cfg = dev->config;
if ((sys_read32(cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET) & UART_RX_FIFO_CNT_MASK) != 0) {
*c = sys_read8(cfg->base_reg + UART_FIFO_RDATA_OFFSET);
return 0;
}
return -1;
}
static void uart_bflb_poll_out(const struct device *dev, unsigned char c)
{
const struct bflb_config *cfg = dev->config;
while ((sys_read32(cfg->base_reg + UART_FIFO_CONFIG_1_OFFSET) & UART_TX_FIFO_CNT_MASK) ==
0) {
}
sys_write8(c, cfg->base_reg + UART_FIFO_WDATA_OFFSET);
}
#ifdef CONFIG_PM_DEVICE
static int uart_bflb_pm_control(const struct device *dev,
enum pm_device_action action)
{
const struct bflb_config *cfg = dev->config;
uint32_t tmp;
int ret;
switch (action) {
case PM_DEVICE_ACTION_RESUME:
(void)pinctrl_apply_state(cfg->pinctrl_cfg, PINCTRL_STATE_DEFAULT);
UART_Enable(cfg->periph_id, UART_TXRX);
ret = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
return ret;
}
tmp = sys_read32(GLB_BASE + GLB_CGEN_CFG1_OFFSET);
/* Ungate clock to peripheral */
if (cfg->base_reg == UART0_BASE) {
tmp |= (1 << 16);
} else if (cfg->base_reg == UART1_BASE) {
tmp |= (1 << 17);
} else {
return -EINVAL;
}
sys_write32(tmp, GLB_BASE + GLB_CGEN_CFG1_OFFSET);
break;
case PM_DEVICE_ACTION_SUSPEND:
if (pinctrl_apply_state(cfg->pinctrl_cfg, PINCTRL_STATE_SLEEP)) {
return -ENOTSUP;
ret = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_SLEEP);
if (ret < 0) {
return ret;
}
UART_Disable(cfg->periph_id, UART_TXRX);
tmp = sys_read32(GLB_BASE + GLB_CGEN_CFG1_OFFSET);
/* Gate clock to peripheral */
if (cfg->base_reg == UART0_BASE) {
tmp &= ~(1 << 16);
} else if (cfg->base_reg == UART1_BASE) {
tmp &= ~(1 << 17);
} else {
return -EINVAL;
}
sys_write32(tmp, GLB_BASE + GLB_CGEN_CFG1_OFFSET);
break;
default:
return -ENOTSUP;
return -EINVAL;
}
return 0;
@@ -298,55 +520,54 @@ static DEVICE_API(uart, uart_bflb_driver_api) = {
};
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
#define BFLB_UART_IRQ_HANDLER_DECL(n) \
static void uart_bflb_config_func_##n(const struct device *dev) \
#define BFLB_UART_IRQ_HANDLER_DECL(instance) \
static void uart_bflb_config_func_##instance(const struct device *dev);
#define BFLB_UART_IRQ_HANDLER_FUNC(instance) \
.irq_config_func = uart_bflb_config_func_##instance
#define BFLB_UART_IRQ_HANDLER(instance) \
static void uart_bflb_config_func_##instance(const struct device *dev) \
{ \
IRQ_CONNECT(DT_INST_IRQN(n), \
DT_INST_IRQ(n, priority), \
IRQ_CONNECT(DT_INST_IRQN(instance), \
DT_INST_IRQ(instance, priority), \
uart_bflb_isr, \
DEVICE_DT_INST_GET(n), \
DEVICE_DT_INST_GET(instance), \
0); \
irq_enable(DT_INST_IRQN(n)); \
irq_enable(DT_INST_IRQN(instance)); \
}
#define BFLB_UART_IRQ_HANDLER_FUNC(n) \
.irq_config_func = uart_bflb_config_func_##n,
#else /* CONFIG_UART_INTERRUPT_DRIVEN */
#define BFLB_UART_IRQ_HANDLER_DECL(n)
#define BFLB_UART_IRQ_HANDLER_FUNC(n)
#define BFLB_UART_IRQ_HANDLER_DECL(instance)
#define BFLB_UART_IRQ_HANDLER_FUNC(instance)
#define BFLB_UART_IRQ_HANDLER(instance)
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
#define BFLB_UART_INIT(n) \
PINCTRL_DT_INST_DEFINE(n); \
PM_DEVICE_DT_INST_DEFINE(n, uart_bflb_pm_control); \
BFLB_UART_IRQ_HANDLER_DECL(n); \
#define BFLB_UART_INIT(instance) \
PINCTRL_DT_INST_DEFINE(instance); \
PM_DEVICE_DT_INST_DEFINE(instance, uart_bflb_pm_control); \
BFLB_UART_IRQ_HANDLER_DECL(instance) \
static struct bflb_data uart##instance##_bflb_data; \
static const struct bflb_config uart##instance##_bflb_config = { \
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(instance), \
.base_reg = DT_INST_REG_ADDR(instance), \
\
static struct bflb_data bflb_uart##n##_data; \
static const struct bflb_config bflb_uart##n##_config = { \
.reg = (uint32_t *)DT_INST_REG_ADDR(n), \
.pinctrl_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.periph_id = DT_INST_PROP(n, peripheral_id), \
\
.uart_cfg.baudRate = DT_INST_PROP(n, current_speed), \
.uart_cfg.dataBits = UART_DATABITS_8, \
.uart_cfg.stopBits = UART_STOPBITS_1, \
.uart_cfg.parity = UART_PARITY_NONE, \
.uart_cfg.uartClk = SOC_BOUFFALOLAB_BL_PLL160_FREQ_HZ, \
.uart_cfg.ctsFlowControl = UART_CTS_FLOWCONTROL_ENABLE, \
.uart_cfg.rtsSoftwareControl = UART_RTS_FLOWCONTROL_ENABLE, \
.uart_cfg.byteBitInverse = UART_MSB_FIRST_ENABLE, \
\
.fifo_cfg.txFifoDmaThreshold = 1, \
.fifo_cfg.rxFifoDmaThreshold = 1, \
.fifo_cfg.txFifoDmaEnable = 0, \
.fifo_cfg.rxFifoDmaEnable = 0, \
\
BFLB_UART_IRQ_HANDLER_FUNC(n) \
.baudrate = DT_INST_PROP(instance, current_speed), \
.data_bits = UART_DATA_BITS_8, \
.stop_bits = UART_STOP_BITS_1, \
.parity = UART_PARITY_NONE, \
.bit_order = UART_MSB_FIRST, \
.flow_ctrl = UART_FLOWCTRL_NONE, \
/* overflow interrupt threshold, size is 32 bytes*/ \
.tx_fifo_threshold = 8, \
.rx_fifo_threshold = 0, \
BFLB_UART_IRQ_HANDLER_FUNC(instance) \
}; \
DEVICE_DT_INST_DEFINE(n, &uart_bflb_init, \
PM_DEVICE_DT_INST_GET(n), \
&bflb_uart##n##_data, \
&bflb_uart##n##_config, PRE_KERNEL_1, \
DEVICE_DT_INST_DEFINE(instance, &uart_bflb_init, \
PM_DEVICE_DT_INST_GET(instance), \
&uart##instance##_bflb_data, \
&uart##instance##_bflb_config, PRE_KERNEL_1, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&uart_bflb_driver_api);
&uart_bflb_driver_api); \
\
BFLB_UART_IRQ_HANDLER(instance)
DT_INST_FOREACH_STATUS_OKAY(BFLB_UART_INIT)

View File

@@ -0,0 +1,5 @@
description: Bouffalolab Flash Controller
compatible: "bflb,flash-controller"
include: flash-controller.yaml

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2025 MASSDRIVER EI (massdrive.space)
# SPDX-License-Identifier: Apache-2.0
description: RISC-V Core Local Interrupt Controller CLIC Pre-Standard v0.9
compatible: "sifive,clic-draft"
include: [interrupt-controller.yaml, base.yaml]
properties:
reg:
required: true
"#interrupt-cells":
const: 2
interrupt-cells:
- irq
- priority

View File

@@ -13,8 +13,3 @@ include:
properties:
reg:
required: true
peripheral-id:
type: int
description: peripheral ID
required: true

View File

@@ -0,0 +1,8 @@
/*
* Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <bflb/bl60x.dtsi>
#include <dt-bindings/pinctrl/bl602x-pinctrl.h>

View File

@@ -0,0 +1,8 @@
/*
* Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <bflb/bl60x.dtsi>
#include <dt-bindings/pinctrl/bl604x-pinctrl.h>

View File

@@ -7,8 +7,8 @@
#include <freq.h>
#include <mem.h>
#include <dt-bindings/pinctrl/bl60x-pinctrl.h>
#include <dt-bindings/pinctrl/bflb-common-pinctrl.h>
#include <dt-bindings/pinctrl/bl60x-pinctrl.h>
#include <dt-bindings/clock/bflb_bl60x_clock.h>
/ {
@@ -48,7 +48,7 @@
clk_bclk: clk-bclk {
#clock-cells = <0>;
compatible = "bflb,bclk";
divider = <2>;
divider = <4>;
status = "okay";
};
};
@@ -82,7 +82,7 @@
ranges;
clic: clic@2000000 {
compatible = "sifive,clint0";
compatible = "sifive,clic-draft";
reg = <0x2000000 0x10000>;
#address-cells = <0>;
#interrupt-cells = <2>;
@@ -111,7 +111,7 @@
#size-cells = <1>;
status = "okay";
glb: gpio@40000000 {
gpio0: gpio@40000000 {
compatible = "bflb,gpio";
reg = <0x40000000 0x1000>;
#gpio-cells = <2>;
@@ -119,8 +119,8 @@
status = "disabled";
gpio-controller;
interrupts = <1 0>;
interrupt-parent = <&ictrl>;
interrupts = <60 0>;
interrupt-parent = <&clic>;
};
};
@@ -135,7 +135,6 @@
clock-names = "rc32m", "crystal", "root", "bclk",
"pll_192", "pll_160",
"pll_120", "pll_48";
zephyr,deferred-init;
};
efuse: efuse@40007000 {
@@ -148,18 +147,16 @@
uart0: uart@4000a000 {
compatible = "bflb,uart";
reg = <0x4000a000 0x100>;
peripheral-id = <0>;
interrupts = <29 0>;
interrupt-parent = <&ictrl>;
interrupts = <45 0>;
interrupt-parent = <&clic>;
status = "disabled";
};
uart1: uart@4000a100 {
compatible = "bflb,uart";
reg = <0x4000a100 0x100>;
peripheral-id = <1>;
interrupts = <30 0>;
interrupt-parent = <&ictrl>;
interrupts = <46 0>;
interrupt-parent = <&clic>;
status = "disabled";
};
@@ -170,21 +167,19 @@
#size-cells = <0>;
status = "disabled";
peripheral-id = <0>;
interrupts = <27 0>;
interrupt-parent = <&ictrl>;
interrupts = <43 0>;
interrupt-parent = <&clic>;
};
spi1: spi@4000b000 {
compatible = "bflb,qspi";
flashctrl: flash-controller@4000b000 {
compatible = "bflb,flash-controller";
reg = <0x4000b000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
#size-cells = <1>;
status = "disabled";
peripheral-id = <0>;
interrupts = <23 0>;
interrupt-parent = <&ictrl>;
interrupts = <39 0>;
interrupt-parent = <&clic>;
};
retram: memory@40010000 {
@@ -206,12 +201,7 @@
sram0: memory@42020000 {
compatible = "mmio-sram";
reg = <0x42020000 DT_SIZE_K(64)>;
};
sram1: memory@42030000 {
compatible = "mmio-sram";
reg = <0x42030000 DT_SIZE_K(112)>;
reg = <0x42020000 DT_SIZE_K(176)>;
};
};
};

View File

@@ -14,6 +14,7 @@
#include <zephyr/devicetree.h>
#include <zephyr/types.h>
#include <zephyr/dt-bindings/pinctrl/bflb-common-pinctrl.h>
/* clang-format off */

View File

@@ -1,55 +1,9 @@
# Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
# Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
#
# SPDX-License-Identifier: Apache-2.0
if(CONFIG_SOC_FAMILY_BFLB)
zephyr_library_named(hal_bouffalolab)
zephyr_library_compile_definitions(
BFLB_USE_HAL_DRIVER
BFLB_USE_CUSTOM_LD_SECTIONS
)
set(bflb_soc bl602)
set(bflb_drv_dir ${ZEPHYR_HAL_BOUFFALOLAB_MODULE_DIR}/drivers/${bflb_soc}_driver)
set(bflb_common_dir ${ZEPHYR_HAL_BOUFFALOLAB_MODULE_DIR}/common)
set(bflb_drv_src_dir ${bflb_drv_dir}/std_drv/src)
# Global includes
zephyr_include_directories(
include
${ZEPHYR_HAL_BOUFFALOLAB_MODULE_DIR}/include
${bflb_drv_dir}/regs
${bflb_drv_dir}/startup
${bflb_drv_dir}/std_drv/inc
${bflb_common_dir}/misc
)
zephyr_library_include_directories(
${bflb_common_dir}/soft_crc
)
zephyr_library_sources(
${bflb_drv_src_dir}/${bflb_soc}_aon.c
${bflb_drv_src_dir}/${bflb_soc}_ef_ctrl.c
${bflb_drv_src_dir}/${bflb_soc}_glb.c
${bflb_drv_src_dir}/${bflb_soc}_hbn.c
${bflb_drv_src_dir}/${bflb_soc}_l1c.c
${bflb_drv_src_dir}/${bflb_soc}_pds.c
${bflb_drv_src_dir}/${bflb_soc}_romapi.c
${bflb_common_dir}/soft_crc/softcrc.c
)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_ACOMP ${bflb_drv_src_dir}/${bflb_soc}_acomp.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_ADC ${bflb_drv_src_dir}/${bflb_soc}_adc.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_DAC ${bflb_drv_src_dir}/${bflb_soc}_dac.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_DMA ${bflb_drv_src_dir}/${bflb_soc}_dma.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_I2C ${bflb_drv_src_dir}/${bflb_soc}_i2c.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_IR ${bflb_drv_src_dir}/${bflb_soc}_ir.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_PWM ${bflb_drv_src_dir}/${bflb_soc}_pwm.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_SPI ${bflb_drv_src_dir}/${bflb_soc}_spi.c)
zephyr_library_sources_ifdef(CONFIG_USE_BFLB_UART ${bflb_drv_src_dir}/${bflb_soc}_uart.c)
zephyr_include_directories(${ZEPHYR_HAL_BOUFFALOLAB_MODULE_DIR}/include)
zephyr_include_directories(${ZEPHYR_HAL_BOUFFALOLAB_MODULE_DIR}/include/bouffalolab/${SOC_SERIES})
endif() # SOC_FAMILY_BFLB

View File

@@ -1,59 +1,7 @@
# Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
# Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
#
# SPDX-License-Identifier: Apache-2.0
config ZEPHYR_HAL_BOUFFALOLAB_MODULE
bool
config HAS_BFLB_HAL
bool
if HAS_BFLB_HAL
config USE_BFLB_ACOMP
bool
help
Enable BFLB Analog Comparator (ACOMP) HAL module driver
config USE_BFLB_ADC
bool
help
Enable BFLB Analog-to-Digital Converter (ADC) HAL module driver
config USE_BFLB_DAC
bool
help
Enable BFLB Digital-to-Analog Converter (DAC) HAL module driver
config USE_BFLB_DMA
bool
help
Enable BFLB Direct Memory Access controller (DMA) HAL module driver
config USE_BFLB_I2C
bool
help
Enable BFLB Inter-Integrated Circuit Interface (I2C) HAL module driver
config USE_BFLB_IR
bool
help
Enable BFLB Infrared Remote controller (IR) HAL module driver
config USE_BFLB_PWM
bool
help
Enable BFLB Pulse Width Modulation (PMU) HAL module driver
config USE_BFLB_SPI
bool
help
Enable BFLB Serial Peripheral Interface(SPI) HAL module driver
config USE_BFLB_UART
bool
help
Enable BFLB Universal Asynchronous Receiver/Transmitter (UART)
HAL module driver
endif # HAS_BFLB_HAL

View File

@@ -1,14 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_HAL_BFLB_GLB_H_
#define ZEPHYR_HAL_BFLB_GLB_H_
#ifdef CONFIG_SOC_SERIES_BL60X
#include <bl602_glb.h>
#endif
#endif /* ZEPHYR_HAL_BFLB_GLB_H_ */

View File

@@ -1,14 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_HAL_BFLB_GPIO_H_
#define ZEPHYR_HAL_BFLB_GPIO_H_
#ifdef CONFIG_SOC_SERIES_BL60X
#include <bl602_gpio.h>
#endif
#endif /* ZEPHYR_HAL_BFLB_GPIO_H_ */

View File

@@ -1,14 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_HAL_BFLB_HBN_H_
#define ZEPHYR_HAL_BFLB_HBN_H_
#ifdef CONFIG_SOC_SERIES_BL60X
#include <bl602_hbn.h>
#endif
#endif /* ZEPHYR_HAL_BFLB_HBN_H_ */

View File

@@ -1,15 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_HAL_BFLB_PINCTRL_H_
#define ZEPHYR_HAL_BFLB_PINCTRL_H_
#ifdef CONFIG_SOC_SERIES_BL60X
#include <zephyr/dt-bindings/pinctrl/bl60x-pinctrl.h>
#endif
#include <zephyr/dt-bindings/pinctrl/bflb-common-pinctrl.h>
#endif /* ZEPHYR_HAL_BFLB_PINCTRL_H_ */

View File

@@ -1,14 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_HAL_BFLB_UART_H_
#define ZEPHYR_HAL_BFLB_UART_H_
#ifdef CONFIG_SOC_SERIES_BL60X
#include <bl602_uart.h>
#endif
#endif /* ZEPHYR_HAL_BFLB_UART_H_ */

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __BL_LD_SECTIONS_H
#define __BL_LD_SECTIONS_H
#define ATTR_STRINGIFY(x) #x
#define ATTR_TOSTRING(x) ATTR_STRINGIFY(x)
#define ATTR_SECTION(x) __attribute__((section(x)))
#define ATTR_UNI_SYMBOL __FILE__ ATTR_TOSTRING(__LINE__)
#define ATTR_CLOCK_SECTION ATTR_SECTION(".itcm.sclock_rlt_code." ATTR_UNI_SYMBOL)
#define ATTR_CLOCK_CONST_SECTION ATTR_SECTION(".itcm.sclock_rlt_const." ATTR_UNI_SYMBOL)
#define ATTR_TCM_SECTION ATTR_SECTION(".itcm.code." ATTR_UNI_SYMBOL)
#define ATTR_TCM_CONST_SECTION ATTR_SECTION(".itcm.const." ATTR_UNI_SYMBOL)
#define ATTR_DTCM_SECTION ATTR_SECTION(".dtcm.data")
#define ATTR_HSRAM_SECTION ATTR_SECTION(".hsram_code")
#define ATTR_DMA_RAM_SECTION ATTR_SECTION(".system_ram")
#define ATTR_HBN_RAM_SECTION ATTR_SECTION(".hbn_ram_code")
#define ATTR_HBN_RAM_CONST_SECTION ATTR_SECTION(".hbn_ram_data")
#define ATTR_FALLTHROUGH() __attribute__((fallthrough))
#define ATTR_USED __attribute__((__used__))
#define ATTR_EALIGN(x) __aligned(size)
#endif /* __BL_LD_SECTIONS_H */

View File

@@ -2,9 +2,6 @@
#
# SPDX-License-Identifier: Apache-2.0
config SOC_FAMILY_BFLB
select HAS_BFLB_HAL
if SOC_FAMILY_BFLB
rsource "*/Kconfig"

View File

@@ -1,13 +1,16 @@
# Copyright (c) 2021-2025 ATL Electronics
# Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
#
# SPDX-License-Identifier: Apache-2.0
zephyr_include_directories(.)
zephyr_sources(soc.c)
zephyr_linker_sources_ifdef(CONFIG_SOC_SERIES_BL60X RODATA rodata.ld)
set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "")
set(SOC_LINKER_SCRIPT
${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld
CACHE INTERNAL ""
)
zephyr_code_relocate_ifdef(CONFIG_UART_BFLB LIBRARY drivers__serial LOCATION ITCM NOKEEP)
zephyr_code_relocate_ifdef(CONFIG_RISCV_MACHINE_TIMER LIBRARY drivers__timer LOCATION ITCM NOKEEP)
zephyr_code_relocate_ifdef(CONFIG_PINCTRL_BFLB LIBRARY drivers__pinctrl LOCATION ITCM NOKEEP)
zephyr_code_relocate_ifdef(CONFIG_SYSCON_BFLB_EFUSE LIBRARY drivers__syscon LOCATION ITCM NOKEEP)
zephyr_code_relocate_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL60X
LIBRARY drivers__clock_control LOCATION ITCM NOKEEP)

View File

@@ -1,20 +1,30 @@
# Copyright (c) 2021-2025 ATL Electronics
# Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
#
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_BL60X
select ATOMIC_OPERATIONS_C
select CLOCK_CONTROL
select CODE_DATA_RELOCATION
select CPU_HAS_FPU
select FLOAT_HARD
select FPU
select GEN_IRQ_VECTOR_TABLE
select INCLUDE_RESET_VECTOR
select RISCV
select RISCV_HAS_CLIC
select RISCV_MACHINE_TIMER
select RISCV_SOC_HAS_CUSTOM_IRQ_HANDLING
select RISCV_PRIVILEGED
select RISCV_ISA_RV32I
select RISCV_ISA_EXT_M
select RISCV_ISA_EXT_A
select RISCV_ISA_EXT_F
select RISCV_ISA_EXT_C
select RISCV_ISA_EXT_ZICSR
select RISCV_ISA_EXT_ZIFENCEI
select RISCV_VECTORED_MODE
select SOC_EARLY_INIT_HOOK
select SYSCON
select XIP

View File

@@ -4,7 +4,18 @@
if SOC_SERIES_BL60X
# On BL602 and BL604, not all values work, here is a list of some that work:
# 5000, 1000, 100, 10, 1
config SYS_CLOCK_TICKS_PER_SEC
default 5000
config NUM_IRQS
default 80
config ARCH_SW_ISR_TABLE_ALIGN
default 64
config RISCV_MCAUSE_EXCEPTION_MASK
default 0x3FF
endif # SOC_SERIES_BL60X

View File

@@ -1,17 +0,0 @@
/*
* Copyright (c) 2021-2025 ATL Electronics
*
* SPDX-License-Identifier: Apache-2.0
*/
KEEP(*(SORT_NONE( EXCLUDE_FILE( *bl602_glb.o \
*bl602_pds.o \
*bl602_common.o \
*bl602_sf_cfg.o \
*bl602_sf_cfg_ext*.o* \
*bl602_sf_ctrl.o \
*bl602_sflash.o \
*bl602_sflash_ext*.o* \
*bl602_xip_sflash.o \
*bl602_xip_sflash_ext*.o* \
*bl602_ef_ctrl.o) .rodata*)))

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021-2025 ATL Electronics
* Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,41 +10,36 @@
* @brief Bouffalo Lab RISC-V MCU series initialization code
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/irq.h>
#include <bflb_hbn.h>
#include <bflb_glb.h>
#include <clic.h>
#include <bflb_soc.h>
#include <glb_reg.h>
#include <hbn_reg.h>
#include <pds_reg.h>
#define ROOT_FCLK_DIV (0)
#define ROOT_BCLK_DIV (1)
#define ROOT_UART_CLOCK_DIV (0)
/* Set Embedded Flash Pullup */
static void system_bor_init(void)
{
HBN_BOR_CFG_Type borCfg = { 1 /* pu_bor */, 0 /* irq_bor_en */,
1 /* bor_vth */, 1 /* bor_sel */ };
HBN_Set_BOR_Cfg(&borCfg);
}
uint32_t tmp = 0;
static uint32_t mtimer_get_clk_src_div(void)
{
return ((SystemCoreClockGet() / (GLB_Get_BCLK_Div() + 1))
/ 1000 / 1000 - 1);
}
tmp = sys_read32(HBN_BASE + HBN_BOR_CFG_OFFSET);
/* borThreshold = 1 */
tmp = (tmp & HBN_BOR_VTH_UMSK) | ((uint32_t)(1) << HBN_BOR_VTH_POS);
/* enablePorInBor true*/
tmp = (tmp & HBN_BOR_SEL_UMSK) | ((uint32_t)(1) << HBN_BOR_SEL_POS);
/* enableBor true*/
tmp = (tmp & HBN_PU_BOR_UMSK) | ((uint32_t)(1) << HBN_PU_BOR_POS);
sys_write32(tmp, HBN_BASE + HBN_BOR_CFG_OFFSET);
static void system_clock_init(void)
{
GLB_Set_System_CLK(GLB_PLL_XTAL_40M, GLB_SYS_CLK_PLL160M);
GLB_Set_System_CLK_Div(ROOT_FCLK_DIV, ROOT_BCLK_DIV);
GLB_Set_MTimer_CLK(1, GLB_MTIMER_CLK_BCLK, mtimer_get_clk_src_div());
}
static void peripheral_clock_init(void)
{
GLB_Set_UART_CLK(1, HBN_UART_CLK_160M, ROOT_UART_CLOCK_DIV);
/* enableBorInt false */
tmp = sys_read32(HBN_BASE + HBN_IRQ_MODE_OFFSET);
tmp = tmp & HBN_IRQ_BOR_EN_UMSK;
sys_write32(tmp, HBN_BASE + HBN_IRQ_MODE_OFFSET);
}
void soc_early_init_hook(void)
@@ -55,37 +51,37 @@ void soc_early_init_hook(void)
key = irq_lock();
__disable_irq();
/* disable hardware_pullup_pull_down (reg_en_hw_pu_pd = 0) */
tmp = BL_RD_REG(HBN_BASE, HBN_IRQ_MODE);
tmp = BL_CLR_REG_BIT(tmp, HBN_REG_EN_HW_PU_PD);
BL_WR_REG(HBN_BASE, HBN_IRQ_MODE, tmp);
tmp = sys_read32(HBN_BASE + HBN_IRQ_MODE_OFFSET);
/* "BL_CLR_REG_BIT" */
tmp = tmp & HBN_REG_EN_HW_PU_PD_UMSK;
sys_write32(tmp, HBN_BASE + HBN_IRQ_MODE_OFFSET);
/* GLB_Set_EM_Sel(GLB_EM_0KB); */
tmp = BL_RD_REG(GLB_BASE, GLB_SEAM_MISC);
tmp = BL_SET_REG_BITS_VAL(tmp, GLB_EM_SEL, GLB_EM_0KB);
BL_WR_REG(GLB_BASE, GLB_SEAM_MISC, tmp);
/* 'seam' 0kb, undocumented */
tmp = sys_read32(GLB_BASE + GLB_SEAM_MISC_OFFSET);
tmp = (tmp & GLB_EM_SEL_UMSK) | ((uint32_t)(0) << GLB_EM_SEL_POS);
sys_write32(tmp, GLB_BASE + GLB_SEAM_MISC_OFFSET);
/* Fix 26M xtal clkpll_sdmin */
tmp = BL_RD_REG(PDS_BASE, PDS_CLKPLL_SDM);
tmp = sys_read32(PDS_BASE + PDS_CLKPLL_SDM_OFFSET);
if (BL_GET_REG_BITS_VAL(tmp, PDS_CLKPLL_SDMIN) == 0x49D39D) {
tmp = BL_SET_REG_BITS_VAL(tmp, PDS_CLKPLL_SDMIN, 0x49D89E);
BL_WR_REG(PDS_BASE, PDS_CLKPLL_SDM, tmp);
if ((tmp & PDS_CLKPLL_SDMIN_MSK) == 0x49D39D) {
tmp = (tmp & PDS_CLKPLL_SDMIN_UMSK) | (uint32_t)(0x49D89E);
sys_write32(tmp, PDS_BASE + PDS_CLKPLL_SDM_OFFSET);
}
/* Restore default setting*/
/* GLB_UART_Sig_Swap_Set(UART_SIG_SWAP_NONE); */
tmp = BL_RD_REG(GLB_BASE, GLB_PARM);
tmp = BL_SET_REG_BITS_VAL(tmp, GLB_UART_SWAP_SET, UART_SIG_SWAP_NONE);
BL_WR_REG(GLB_BASE, GLB_PARM, tmp);
tmp = sys_read32(GLB_BASE + GLB_PARM_OFFSET);
/* GLB_UART_Sig_Swap_Set(UART_SIG_SWAP_NONE);
* no swap = 0
* see bl602_glb.h for other possible values
*/
tmp = (tmp & GLB_UART_SWAP_SET_UMSK) | ((uint32_t)(0) <<
GLB_UART_SWAP_SET_POS);
/* GLB_JTAG_Sig_Swap_Set(JTAG_SIG_SWAP_NONE); */
tmp = BL_RD_REG(GLB_BASE, GLB_PARM);
tmp = BL_SET_REG_BITS_VAL(tmp, GLB_JTAG_SWAP_SET, JTAG_SIG_SWAP_NONE);
BL_WR_REG(GLB_BASE, GLB_PARM, tmp);
tmp = (tmp & GLB_JTAG_SWAP_SET_UMSK) | ((uint32_t)(0) <<
GLB_JTAG_SWAP_SET_POS);
sys_write32(tmp, GLB_BASE + GLB_PARM_OFFSET);
/* CLear all interrupt */
p = (uint32_t *)(CLIC_HART0_ADDR + CLIC_INTIE);
@@ -102,21 +98,6 @@ void soc_early_init_hook(void)
/* init bor for all platform */
system_bor_init();
/* global IRQ enable */
__enable_irq();
system_clock_init();
peripheral_clock_init();
irq_unlock(key);
}
/* identify flash config automatically */
extern BL_Err_Type flash_init(void);
void System_Post_Init(void)
{
PDS_Trim_RC32M();
HBN_Trim_RC32K();
flash_init();
}

View File

@@ -15,35 +15,12 @@
#define _SOC__H_
#include <zephyr/sys/util.h>
#include <../common/soc_common.h>
#ifndef _ASMLANGUAGE
/* Add include for DTS generated information */
#include <zephyr/devicetree.h>
#if defined(CONFIG_SOC_SERIES_BL60X)
#include <bl602.h>
#else
#error Library does not support the specified device.
#endif
/* clang-format off */
/* RISC-V Machine Timer configuration */
#define RISCV_MTIME_BASE 0x0200BFF8
#define RISCV_MTIMECMP_BASE 0x02004000
/* lib-c hooks required RAM defined variables */
#define RISCV_RAM_BASE DT_SRAM_BASE_ADDRESS
#define RISCV_RAM_SIZE KB(DT_SRAM_SIZE)
#define SOC_BOUFFALOLAB_BL_PLL160_FREQ_HZ (160000000)
#define SOC_BOUFFALOLAB_BL_HCLK_FREQ_HZ \
DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency)
/* clang-format on */
#endif /* !_ASMLANGUAGE */
#endif /* _SOC__H_ */

View File

@@ -4,8 +4,9 @@
zephyr_include_directories(.)
if(CONFIG_SOC_SERIES_BL60X)
zephyr_include_directories(e24)
zephyr_sources(
soc_irq.S
soc_common_irq.c
vector.S
)
e24/soc_irq_privileged.c
e24/intc_clic.S)
endif()

View File

@@ -23,4 +23,12 @@
#define CLIC_INTCFG 0x800
#define CLIC_CFG 0xc00
/* CLIC relative CSR number */
#define CSR_MTVT (0x307)
#define CSR_MNXTI (0x345)
#define CSR_MINTTHRESH (0x347)
#define CSR_MISELECT (0x350)
#define CSR_MIREG (0x351)
#define CSR_MIREG2 (0x352)
#endif /* _SIFIVE_CLIC_H */

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2024 Baumer Electric AG
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief Assembler-hooks specific to RISC-V Core Local Interrupt Controller
*/
#include <zephyr/arch/cpu.h>
#include "clic.h"
/* register-wide load/store based on lw/sw (XLEN = 32) */
.macro lr, rd, mem
lw \rd, \mem
.endm
.macro sr, rs, mem
sw \rs, \mem
.endm
GTEXT(__soc_handle_irq)
/*
* In an CLIC, pending interrupts don't have to be cleared by hand.
* In vectored mode, interrupts are cleared automatically.
* In non-vectored mode, interrupts are cleared when writing the mnxti register (done in
* __soc_handle_all_irqs).
* Thus this function can directly return.
*/
SECTION_FUNC(exception.other, __soc_handle_irq)
ret
GTEXT(__soc_handle_all_irqs)
#ifdef CONFIG_TRACING
/* imports */
GTEXT(sys_trace_isr_enter)
GTEXT(sys_trace_isr_exit)
#endif
/*
* This function services and clears all pending interrupts for an CLIC in non-vectored mode.
*/
SECTION_FUNC(exception.other, __soc_handle_all_irqs)
addi sp, sp, -16
sr ra, 0(sp)
/* Read and clear mnxti to get highest current interrupt and enable interrupts. Will return
* original interrupt if no others appear. */
csrrci a0, CSR_MNXTI, MSTATUS_IEN
beqz a0, irq_done /* Check if original interrupt vanished. */
irq_loop:
#ifdef CONFIG_TRACING_ISR
call sys_trace_isr_enter
#endif
/* Call corresponding registered function in _sw_isr_table. a0 is offset in pointer with
* the mtvt, sw irq table is 2-pointer wide -> shift by one. */
csrr t0, CSR_MTVT
sub a0, a0, t0
la t0, _sw_isr_table
slli a0, a0, (1)
add t0, t0, a0
/* Load argument in a0 register */
lr a0, 0(t0)
/* Load ISR function address in register t1 */
lr t1, RV_REGSIZE(t0)
/* Call ISR function */
jalr ra, t1, 0
#ifdef CONFIG_TRACING_ISR
call sys_trace_isr_exit
#endif
/* Read and clear mnxti to get highest current interrupt and enable interrupts. */
csrrci a0, CSR_MNXTI, MSTATUS_IEN
bnez a0, irq_loop
irq_done:
lr ra, 0(sp)
addi sp, sp, 16
ret

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief interrupt management code for riscv SOCs supporting the SiFive clic
*/
#include <zephyr/irq.h>
#include <soc.h>
#include "clic.h"
#define CLIC_INTCFG_PADDING_BITS 4
void riscv_clic_irq_enable(unsigned int irq)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + irq) = 1;
}
void riscv_clic_irq_disable(unsigned int irq)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + irq) = 0;
}
void riscv_clic_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTCFG + irq) =
(prio & 0xF) << CLIC_INTCFG_PADDING_BITS;
ARG_UNUSED(flags);
}
int riscv_clic_irq_is_enabled(unsigned int irq)
{
return *(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + irq);
}

View File

@@ -1,82 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file interrupt management code for riscv SOCs supporting the SiFive clic
*/
#ifndef __SOC_COMMON_H_
#define __SOC_COMMON_H_
/* clang-format off */
/* IRQ numbers */
#define RISCV_MACHINE_SOFT_IRQ 3 /* Machine Software Interrupt */
#define RISCV_MACHINE_TIMER_IRQ 7 /* Machine Timer Interrupt */
#define RISCV_MACHINE_EXT_IRQ 11 /* Machine External Interrupt */
/* ECALL Exception numbers */
#define SOC_MCAUSE_ECALL_EXP 11 /* Machine ECALL instruction */
#define SOC_MCAUSE_USER_ECALL_EXP 8 /* User ECALL instruction */
/* SOC-specific MCAUSE bitfields */
#ifdef CONFIG_64BIT
/* Interrupt Mask */
#define SOC_MCAUSE_IRQ_MASK (1 << 63)
/* Exception code Mask */
#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFFFFFFFFFF
#else
/* Interrupt Mask */
#define SOC_MCAUSE_IRQ_MASK (1 << 31)
/* Exception code Mask */
#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFF
#endif
/* SOC-Specific EXIT ISR command */
#define SOC_ERET mret
/* CLINT Base Address */
#define CLIC_TIMER_ENABLE_ADDRESS (0x02800407)
/* In mstatus register */
#define SOC_MIE_MSIE (0x1 << 3) /* Machine Software Interrupt Enable */
/* IRQ 0-15 : (exception:interrupt=0) */
#define SOC_IRQ_IAMISALIGNED (0) /* Instruction Address Misaligned */
#define SOC_IRQ_IAFAULT (1) /* Instruction Address Fault */
#define SOC_IRQ_IINSTRUCTION (2) /* Illegal Instruction */
#define SOC_IRQ_BPOINT (3) /* Break Point */
#define SOC_IRQ_LAMISALIGNED (4) /* Load Address Misaligned */
#define SOC_IRQ_LAFAULT (5) /* Load Access Fault */
#define SOC_IRQ_SAMISALIGNED (6) /* Store/AMO Address Misaligned */
#define SOC_IRQ_SAFAULT (7) /* Store/AMO Access Fault */
#define SOC_IRQ_ECALLU (8) /* Environment Call from U-mode */
/* 9-10: Reserved */
#define SOC_IRQ_ECALLM (11) /* Environment Call from M-mode */
/* 12-15: Reserved */
/* IRQ 16- : (async event:interrupt=1) */
#define SOC_IRQ_NUM_BASE (16)
#define SOC_IRQ_ASYNC (16)
/* Machine Software Int */
#define SOC_IRQ_MSOFT (SOC_IRQ_ASYNC + RISCV_MACHINE_SOFT_IRQ)
/* Machine Timer Int */
#define SOC_IRQ_MTIMER (SOC_IRQ_ASYNC + RISCV_MACHINE_TIMER_IRQ)
/* Machine External Int */
#define SOC_IRQ_MEXT (SOC_IRQ_ASYNC + RISCV_MACHINE_EXT_IRQ)
/* Machine Global External Interrupt */
#define SOC_NR_MGEI_IRQS (64)
/* Total number of IRQs */
#define SOC_NR_IRQS (SOC_NR_MGEI_IRQS + SOC_IRQ_NUM_BASE)
/* clang-format on */
#endif /* __SOC_COMMON_H_ */

View File

@@ -1,100 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief interrupt management code for riscv SOCs supporting the SiFive clic
*/
#include <zephyr/irq.h>
#include <soc.h>
#include <clic.h>
/* clang-format off */
static void clic_irq_enable(unsigned int irq)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + irq) = 1;
}
static void clic_irq_disable(unsigned int irq)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + irq) = 0;
}
void arch_irq_enable(unsigned int irq)
{
uint32_t mie;
if (irq == SOC_IRQ_MSOFT) {
/* Read mstatus & set machine software interrupt enable in mie */
__asm__ volatile("csrrs %0, mie, %1"
: "=r"(mie)
: "r"(BIT(RISCV_MACHINE_SOFT_IRQ)));
} else if (irq == SOC_IRQ_MTIMER) {
*(volatile uint8_t *)CLIC_TIMER_ENABLE_ADDRESS = 1;
/* Read mstatus & set machine timer interrupt enable in mie */
__asm__ volatile("csrrs %0, mie, %1"
: "=r"(mie)
: "r"(BIT(RISCV_MACHINE_TIMER_IRQ)
| BIT(RISCV_MACHINE_EXT_IRQ)));
} else {
clic_irq_enable(irq - SOC_IRQ_ASYNC);
}
}
void arch_irq_disable(unsigned int irq)
{
uint32_t mie;
if (irq == SOC_IRQ_MSOFT) {
/* Read mstatus & set machine software interrupt enable in mie */
__asm__ volatile("csrrc %0, mie, %1"
: "=r"(mie)
: "r"(BIT(RISCV_MACHINE_SOFT_IRQ)));
} else if (irq == SOC_IRQ_MTIMER) {
*(volatile uint8_t *)CLIC_TIMER_ENABLE_ADDRESS = 0;
/* Read mstatus & set machine timer interrupt enable in mie */
__asm__ volatile("csrrc %0, mie, %1"
: "=r"(mie)
: "r"(BIT(RISCV_MACHINE_TIMER_IRQ)
| BIT(RISCV_MACHINE_EXT_IRQ)));
} else {
clic_irq_disable(irq - SOC_IRQ_ASYNC);
}
}
void arch_irq_priority_set(unsigned int irq, unsigned int prio)
{
ARG_UNUSED(irq);
ARG_UNUSED(prio);
}
int arch_irq_is_enabled(unsigned int irq)
{
uint32_t mie;
/* Enable MEIE (machine external interrupt enable) */
__asm__ volatile("csrrs %0, mie, %1"
: "=r"(mie)
: "r"(BIT(RISCV_MACHINE_EXT_IRQ)));
/* Read mstatus & set machine interrupt enable (MIE) in mstatus */
__asm__ volatile("csrrs %0, mstatus, %1"
: "=r"(mie)
: "r"(MSTATUS_MIE));
return !!(mie & SOC_MIE_MSIE);
}
/* clang-format on */

View File

@@ -1,58 +0,0 @@
/*
* Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* common interrupt management code for riscv SOCs supporting the riscv
* privileged architecture specification
*/
#include <zephyr/kernel_structs.h>
#include <offsets.h>
#include <zephyr/toolchain.h>
#include <zephyr/linker/sections.h>
#include <soc.h>
/* exports */
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)
/* Clear exception number from CSR mip register */
li t1, 1
sll t0, t1, a0
csrrc t1, mip, t0
/* Return */
jalr x0, ra
/*
* __soc_is_irq is defined as .weak to allow re-implementation by
* SOCs that does not truly follow the riscv privilege specification.
*/
WTEXT(__soc_is_irq)
/*
* SOC-specific function to determine if the exception is the result of a
* an interrupt or an exception
* return 1 (interrupt) or 0 (exception)
*
*/
SECTION_FUNC(exception.other, __soc_is_irq)
/* Read mcause and check if interrupt bit is set */
csrr t0, mcause
li t1, SOC_MCAUSE_IRQ_MASK
and t0, t0, t1
/* If interrupt bit is not set, return with 0 */
addi a0, x0, 0
beqz t0, not_interrupt
addi a0, a0, 1
not_interrupt:
/* return */
jalr x0, ra

View File

@@ -1,39 +0,0 @@
/*
* Copyright (c) 2021-2025 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/toolchain.h>
#include <zephyr/arch/riscv/csr.h>
/* exports */
GTEXT(__start)
/* imports */
GTEXT(__initialize)
GTEXT(_isr_wrapper)
SECTION_FUNC(vectors, __start)
.cfi_startproc
.option norvc
/* Inform the debugger that there is nowhere to backtrace */
.cfi_undefined ra
/* Disable interrupts */
li t0, MSTATUS_MIE
csrc mstatus, t0
/*
* Set mtvec (Machine Trap-Vector Base-Address Register)
* CLINT Direct mode
*/
la t0, _isr_wrapper
csrw mtvec, t0
/* Jump to __initialize */
tail __initialize
.cfi_endproc