Skip to content

stm32n6: Provide npu driver #93591

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion drivers/misc/stm32n6_axisram/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
config STM32N6_AXISRAM
bool
select USE_STM32_HAL_RAMCFG
default y if DT_HAS_ST_STM32N6_RAMCFG_ENABLED
default y if $(dt_nodelabel_enabled,axisram3) || \
$(dt_nodelabel_enabled,axisram4) || \
$(dt_nodelabel_enabled,axisram5) || \
$(dt_nodelabel_enabled,axisram6)
8 changes: 8 additions & 0 deletions dts/arm/st/n6/stm32n6.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,14 @@
resets = <&rctl STM32_RESET(APB5, 1)>;
status = "disabled";
};

npu: npu@580c0000 {
compatible = "st,stm32-npu";
reg = <0x580c0000 0x1000>;
clocks = <&rcc STM32_CLOCK(AHB5, 31)>;
resets = <&rctl STM32_RESET(AHB5, 31)>;
status = "disabled";
};
};
};

Expand Down
2 changes: 1 addition & 1 deletion dts/arm/st/n6/stm32n657X0.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
ramcfg@42023100 {
axisram3: memory@34200000 {
reg = <0x34200000 DT_SIZE_K(448)>;
status = "okay";
status = "disabled";
};
};

Expand Down
18 changes: 18 additions & 0 deletions dts/bindings/misc/st,stm32-npu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0

description: STM32 Neural-ART accelerator

compatible: "st,stm32-npu"

include: [reset-device.yaml, base.yaml]

properties:
reg:
required: true

clocks:
required: true

resets:
required: true
4 changes: 4 additions & 0 deletions soc/st/stm32/stm32n6x/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ zephyr_sources(
soc.c
)

zephyr_sources_ifdef(CONFIG_STM32N6_NPU
npu/npu_stm32n6.c
)

zephyr_include_directories(.)

set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")
Expand Down
5 changes: 5 additions & 0 deletions soc/st/stm32/stm32n6x/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ config SOC_SERIES_STM32N6X

config STM32N6_BOOT_SERIAL
bool "Serial boot target (USB)"

config STM32N6_NPU
bool "Neural-ART accelerator (NPU)"
select USE_STM32_HAL_RIF
Copy link

@avolmat-st avolmat-st Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to mention select RESET here as well ?
I faced an issue with another driver which didn't have select RESET, leading to failure to initialized once I disabled the CONFIG_SERIAL, cf #94041

default y if DT_HAS_ST_STM32_NPU_ENABLED
73 changes: 73 additions & 0 deletions soc/st/stm32/stm32n6x/npu/npu_stm32n6.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2025 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT st_stm32_npu

#include <errno.h>

#include <zephyr/device.h>
#include <zephyr/drivers/reset.h>
#include <zephyr/init.h>
#include <soc.h>

#include <zephyr/drivers/clock_control/stm32_clock_control.h>

/* Read-only driver configuration */
struct npu_stm32_cfg {
/* Clock configuration. */
struct stm32_pclken pclken;
/* Reset configuration */
const struct reset_dt_spec reset;
};

static void npu_risaf_config(void)
{
RIMC_MasterConfig_t RIMC_master = {0};

RIMC_master.MasterCID = RIF_CID_1;
RIMC_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;
HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_NPU, &RIMC_master);
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_NPU,
RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
}

static int npu_stm32_init(const struct device *dev)
{
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
const struct npu_stm32_cfg *cfg = dev->config;

if (!device_is_ready(clk)) {
return -ENODEV;
}

if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken) != 0) {
return -EIO;
}

if (!device_is_ready(cfg->reset.dev)) {
return -ENODEV;
}

/* Reset timer to default state using RCC */
(void)reset_line_toggle_dt(&cfg->reset);

npu_risaf_config();

return 0;
}


static const struct npu_stm32_cfg npu_stm32_cfg = {
.pclken = {
.enr = DT_CLOCKS_CELL(DT_NODELABEL(npu), bits),
.bus = DT_CLOCKS_CELL(DT_NODELABEL(npu), bus),
},
.reset = RESET_DT_SPEC_GET(DT_NODELABEL(npu)),
};

DEVICE_DT_DEFINE(DT_NODELABEL(npu), npu_stm32_init, NULL,
NULL, &npu_stm32_cfg, POST_KERNEL,
CONFIG_APPLICATION_INIT_PRIORITY, NULL);