dts: arm: st: n6: Use dedicated dts node for NPU cache (aka CACHEAXI)

The new node is called "npu_cache".

This way a possibility is offered to choose - thru an overlay - if to
enable the NPU cache or not.
This new node has a dependency with node "npu", so the NPU cache's
status is taken into account only in case node "npu" has status "okay".

Default status value of "npu_cache" is "okay"
(i.e. enable the NPU cache).

Signed-off-by: Wolfgang Betz <wolfgang.betz@st.com>
This commit is contained in:
Wolfgang Betz
2026-01-13 10:22:51 +01:00
committed by Maureen Helm
parent 92df06bf1d
commit b84bdbcee3
7 changed files with 136 additions and 21 deletions

View File

@@ -1362,14 +1362,19 @@
npu: npu@580e0000 {
compatible = "st,stm32-npu";
reg = <0x580e0000 DT_SIZE_K(128)>;
clocks = <&rcc STM32_CLOCK(AHB5, 31)>,
<&rcc STM32_CLOCK(AHB5, 30)>;
clock-names = "npu", "cacheaxi";
resets = <&rctl STM32_RESET(AHB5, 31)>,
<&rctl STM32_RESET(AHB5, 30)>;
clocks = <&rcc STM32_CLOCK(AHB5, 31)>;
resets = <&rctl STM32_RESET(AHB5, 31)>;
status = "disabled";
};
npu_cache: cache-controller@580dfc00 {
compatible = "st,stm32-npu-cache";
reg = <0x580dfc00 DT_SIZE_K(1)>;
clocks = <&rcc STM32_CLOCK(AHB5, 30)>;
resets = <&rctl STM32_RESET(AHB5, 30)>;
status = "okay";
};
venc: venc@58005000 {
compatible = "st,stm32-venc";
reg = <0x58005000 0x1000>;

View File

@@ -0,0 +1,18 @@
# Copyright (c) 2026 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
description: STM32N6 NPU cache (aka CACHEAXI) block
compatible: "st,stm32-npu-cache"
include: [reset-device.yaml, base.yaml]
properties:
reg:
required: true
clocks:
required: true
resets:
required: true

View File

@@ -7,6 +7,7 @@ zephyr_sources(
zephyr_sources_ifdef(CONFIG_STM32N6_NPU
npu/npu_stm32n6.c
npu/npu_cache_stm32n6.c
)
zephyr_include_directories(.)

View File

@@ -30,12 +30,6 @@ if SOC_SERIES_STM32N6X
config STM32N6_BOOT_SERIAL
bool "Serial boot target (USB)"
config STM32N6_NPU
bool "Neural-ART accelerator (NPU)"
select RESET
default y
depends on DT_HAS_ST_STM32_NPU_ENABLED
config STM32N6_RIF_OPEN
bool "Configure the RIF with all OPEN access"
default y
@@ -45,4 +39,6 @@ config STM32N6_RIF_OPEN
configured during SoC initialization. Zephyr running with Secure privileges has full
access to all SoC resources.
source "soc/st/stm32/stm32n6x/npu/Kconfig"
endif # SOC_SERIES_STM32N6X

View File

@@ -0,0 +1,30 @@
# STMicroelectronics STM32N6 MCU series
# Copyright (c) 2026 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
config STM32N6_NPU
bool "Neural-ART accelerator (NPU)"
select RESET
default y
depends on DT_HAS_ST_STM32_NPU_ENABLED
config STM32N6_NPU_INIT_PRIORITY
int "STM32N6 NPU init priority"
default KERNEL_INIT_PRIORITY_DEFAULT
depends on STM32N6_NPU
help
STM32N6 NPU initialization priority.
Note: This value must have a higher priority (i.e., lower numerical value)
than `STM32N6_NPU_CACHE_INIT_PRIORITY`!
config STM32N6_NPU_CACHE_INIT_PRIORITY
int "STM32N6 NPU cache (aka CACHEAXI) init priority"
default APPLICATION_INIT_PRIORITY
depends on STM32N6_NPU
help
STM32N6 NPU cache (aka CACHEAXI) initialization priority.
Note: This value must have a lower priority (i.e., higher numerical value)
than `STM32N6_NPU_INIT_PRIORITY`!

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2026 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT st_stm32_npu_cache
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <soc.h>
#define NPU_CACHE_NODE DT_DRV_INST(0)
#define NPU_CACHE_BASE DT_REG_ADDR(NPU_CACHE_NODE)
#define NPU_CACHE_CTRL_REG_OFFSET 0x0
#define NPU_CACHE_ERR_IRQ_OFFSET 0x8
#define NPU_CACHE_DISABLE 0x0
#define NPU_CACHE_ENABLE 0x1
#define NPU_CACHE_CNT_ENABLE 0x33330000
#define NPU_CACHE_CNT_RESET 0xCCCC0000
#define NPU_CACHE_ERR_IRQ_ENABLE BIT(2)
/*
* Define npu_cache_stm32_enable and instantiate the device only if both
* the NPU and NPU cache nodes are enabled in the device tree.
* This avoids unused function warnings when the cache is disabled.
*/
#if DT_NODE_HAS_STATUS_OKAY(DT_INST(0, st_stm32_npu)) && \
DT_NODE_HAS_STATUS_OKAY(DT_INST(0, st_stm32_npu_cache))
static int npu_cache_stm32_enable(const struct device *dev)
{
/* Disable cache */
sys_write32(NPU_CACHE_DISABLE, NPU_CACHE_BASE + NPU_CACHE_CTRL_REG_OFFSET);
k_busy_wait(5 * USEC_PER_MSEC); /* 5ms delay */
/* Enable cache */
sys_write32(NPU_CACHE_ENABLE, NPU_CACHE_BASE + NPU_CACHE_CTRL_REG_OFFSET);
/* Enable cache counters */
sys_set_bits(NPU_CACHE_BASE + NPU_CACHE_CTRL_REG_OFFSET, NPU_CACHE_CNT_ENABLE);
/* Reset cache counters */
sys_set_bits(NPU_CACHE_BASE + NPU_CACHE_CTRL_REG_OFFSET, NPU_CACHE_CNT_RESET);
/* Enable cache error interrupt */
sys_write32(NPU_CACHE_ERR_IRQ_ENABLE, NPU_CACHE_BASE + NPU_CACHE_ERR_IRQ_OFFSET);
return 0;
}
DEVICE_DT_INST_DEFINE(0, npu_cache_stm32_enable, NULL, NULL, NULL, POST_KERNEL,
CONFIG_STM32N6_NPU_CACHE_INIT_PRIORITY, NULL);
/*
* Guarantee that initialization priority for the NPU is higher than the one of the NPU cache (aka
* CACHEAXI)
*/
BUILD_ASSERT(CONFIG_STM32N6_NPU_CACHE_INIT_PRIORITY > CONFIG_STM32N6_NPU_INIT_PRIORITY,
"NPU cache initialization must run after NPU driver initialization");
#endif /* st_stm32_npu && st_stm32_npu_cache */

View File

@@ -34,11 +34,11 @@ static int npu_stm32_init(const struct device *dev)
return -ENODEV;
}
if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken_npu) != 0) {
if (clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken_npu) != 0) {
return -EIO;
}
if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken_cacheaxi) != 0) {
if (clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken_cacheaxi) != 0) {
return -EIO;
}
@@ -53,14 +53,16 @@ static int npu_stm32_init(const struct device *dev)
return 0;
}
static const struct npu_stm32_cfg npu_stm32_cfg = {
.pclken_npu = STM32_CLOCK_INFO_BY_NAME(DT_NODELABEL(npu), npu),
.pclken_cacheaxi = STM32_CLOCK_INFO_BY_NAME(DT_NODELABEL(npu), cacheaxi),
.reset_npu = RESET_DT_SPEC_GET_BY_IDX(DT_NODELABEL(npu), 0),
.reset_cacheaxi = RESET_DT_SPEC_GET_BY_IDX(DT_NODELABEL(npu), 1),
.pclken_npu = STM32_DT_INST_CLOCK_INFO(0),
.reset_npu = RESET_DT_SPEC_INST_GET(0),
/*
* Even if npu_cache node is disabled, its clocks must be enabled for NPU operation.
* This is why we need to get clock and reset line from the npu_cache node.
*/
.pclken_cacheaxi = STM32_CLOCK_INFO(0, DT_NODELABEL(npu_cache)),
.reset_cacheaxi = RESET_DT_SPEC_GET(DT_NODELABEL(npu_cache)),
};
DEVICE_DT_DEFINE(DT_NODELABEL(npu), npu_stm32_init, NULL,
NULL, &npu_stm32_cfg, POST_KERNEL,
CONFIG_APPLICATION_INIT_PRIORITY, NULL);
DEVICE_DT_INST_DEFINE(0, npu_stm32_init, NULL, NULL, &npu_stm32_cfg, POST_KERNEL,
CONFIG_STM32N6_NPU_INIT_PRIORITY, NULL);