Skip to content

rkojedzinszky/rknpu-dkms

Repository files navigation

RKNPU DKMS Module

Out-of-tree DKMS module for the Rockchip NPU (RKNPU) driver, extracted from the Rockchip kernel (6.6.y). Enables NPU hardware on Rockchip SoCs when using a vanilla/mainline kernel.

Supported SoCs

SoC Compatible String Cores
RK3566 / RK3568 rockchip,rknpu / rockchip,rk3568-rknpu 1
RK3562 rockchip,rk3562-rknpu 1
RK3576 rockchip,rk3576-rknpu 2
RK3588 / RK3583 rockchip,rk3588-rknpu 3 / 2
RV1106 rockchip,rv1106-rknpu 1

Requirements

  • Linux kernel 6.1.y - 6.12.y (arm64) with the following enabled:
    • CONFIG_DRM=m or CONFIG_DRM=y
    • CONFIG_IOMMU_API=y
    • CONFIG_ROCKCHIP_IOMMU=y
    • CONFIG_SYNC_FILE=y
    • CONFIG_PROC_FS=y
  • Appropriate device tree with RKNPU node and IOMMU phandle
  • Kernel headers installed (for DKMS build)

Installation (DKMS)

# Copy to DKMS source directory
sudo cp -r . /usr/src/rknpu-0.9.8

# Add and build
sudo dkms add rknpu/0.9.8
sudo dkms build rknpu/0.9.8
sudo dkms install rknpu/0.9.8

# Load the module
sudo modprobe rknpu

Manual Build

# Native build
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

# Cross-compile for aarch64
make -C <kernel-source> ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=$(pwd) modules

Architecture

The driver registers as a DRM render node (/dev/dri/renderD*) and exposes custom ioctls for NPU job submission and memory management via DRM GEM.

Features Enabled

  • DRM GEM memory management — standard kernel DRM subsystem
  • DMA fence support — for synchronization between CPU and NPU
  • procfs interface/proc/rknpu/ for status, load, freq, power monitoring

Features Disabled (require Rockchip-proprietary kernel patches)

  • devfreq / DVFS — requires Rockchip OPP framework (rockchip_opp_select.h)
  • SRAM allocation — requires CONFIG_NO_GKI (Rockchip-specific)
  • DMA Heap backend — requires rk-dma-heap (Rockchip-specific)
  • debugfs — not critical; enable CONFIG_DEBUG_FS in kernel if desired

Compatibility Notes

This module provides stub headers under compat/ for Rockchip-specific kernel APIs that don't exist in vanilla kernels:

  • soc/rockchip/rockchip_opp_select.h — OPP/DVFS stubs
  • soc/rockchip/rockchip_system_monitor.h — thermal monitor stubs
  • soc/rockchip/rockchip_ipa.h — IPA power model stubs
  • soc/rockchip/rockchip_iommu.h — IOMMU helper stubs
  • linux/version_compat_defs.hvm_flags_set/clear compat for pre-6.3

The driver will function correctly for NPU inference workloads. Dynamic frequency/voltage scaling will not be available without the Rockchip OPP framework — the NPU runs at whatever frequency is set by the bootloader or device tree.

Device Tree Patches (RK3566 / RK3568)

Upstream kernels do not include the NPU or its IOMMU device-tree nodes. You need to patch two layers: the SoC DTSI (rk356x.dtsi) shared by all RK3566/RK3568 boards, then one small addition in the board DTS to wire the supply regulator and enable the node.

Important — NPU supply regulator must be always-on. The upstream rockchip-pm-domain driver has no per-domain regulator support (unlike the Radxa/Rockchip vendor kernel). When the genpd framework powers on PD_NPU during driver probe, the NPU silicon must already be receiving voltage. If the supply regulator (vdd_npu on most boards) is not enabled, the NIU bus interconnect cannot leave its idle state and a subsequent QoS register write triggers an SError / kernel panic. Adding regulator-always-on; regulator-boot-on; to the NPU supply regulator in the board DTS prevents this.

To quickly extract the patches, run:

sed -n -e '/^```diff/,/^```/{/^```/d; p}' README.md

1. Shared SoC patch — rk356x.dtsi

Apply this to arch/arm64/boot/dts/rockchip/rk356x.dtsi:

--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -550,6 +550,14 @@ power: power-controller {
 			#address-cells = <1>;
 			#size-cells = <0>;

+			/* These power domains are grouped by VD_NPU */
+			power-domain@RK3568_PD_NPU {
+				reg = <RK3568_PD_NPU>;
+				clocks = <&cru ACLK_NPU_PRE>,
+					 <&cru HCLK_NPU_PRE>,
+					 <&cru PCLK_NPU_PRE>;
+				pm_qos = <&qos_npu>;
+			};
 			/* These power domains are grouped by VD_GPU */
 			power-domain@RK3568_PD_GPU {
 				reg = <RK3568_PD_GPU>;
@@ -619,6 +627,33 @@ power-domain@RK3568_PD_RKVENC {
 		};
 	};

+	rknpu: npu@fde40000 {
+		compatible = "rockchip,rk3568-rknpu", "rockchip,rknpu";
+		reg = <0x0 0xfde40000 0x0 0x10000>;
+		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&scmi_clk 2>, <&cru CLK_NPU>,
+			 <&cru ACLK_NPU>, <&cru HCLK_NPU>;
+		clock-names = "scmi_clk", "clk", "aclk", "hclk";
+		assigned-clocks = <&cru CLK_NPU>;
+		assigned-clock-rates = <600000000>;
+		resets = <&cru SRST_A_NPU>, <&cru SRST_H_NPU>;
+		reset-names = "srst_a", "srst_h";
+		power-domains = <&power RK3568_PD_NPU>;
+		iommus = <&rknpu_mmu>;
+		status = "disabled";
+	};
+
+	rknpu_mmu: iommu@fde4b000 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xfde4b000 0x0 0x40>;
+		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_NPU>, <&cru HCLK_NPU>;
+		clock-names = "aclk", "iface";
+		power-domains = <&power RK3568_PD_NPU>;
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
 	gpu: gpu@fde60000 {
 		compatible = "rockchip,rk3568-mali", "arm,mali-bifrost";
 		reg = <0x0 0xfde60000 0x0 0x4000>;

2a. Board patch — ROCK 3A (rk3568-rock-3a.dts)

The &vdd_npu override ensures the NPU power rail (DCDC_REG4 on the RK809 PMIC) is enabled at boot so PD_NPU can power on without an SError.

--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
@@ -867,3 +867,42 @@ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
 		remote-endpoint = <&hdmi_in_vp0>;
 	};
 };
+
+&vdd_npu {
+	regulator-always-on;
+	regulator-boot-on;
+};
+
+&rknpu {
+	rknpu-supply = <&vdd_npu>;
+	status = "okay";
+};
+
+&rknpu_mmu {
+	status = "okay";
+};
+
+// These are only necessary for 6.6.y and later. See README.md
+&vpu {
+	status = "disabled";
+};
+
+&vdpu_mmu {
+	status = "disabled";
+};
+
+&vepu {
+	status = "disabled";
+};
+
+&vepu_mmu {
+	status = "disabled";
+};
+
+&vop {
+	status = "disabled";
+};
+
+&vop_mmu {
+	status = "disabled";
+};

2b. Board patch — ROCK 3C (rk3566-rock-3c.dts)

Same regulator fix as Rock 3A — vdd_npu is DCDC_REG4 on the RK809 PMIC.

--- a/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
@@ -725,3 +725,42 @@ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
 		remote-endpoint = <&hdmi_in_vp0>;
 	};
 };
+
+&vdd_npu {
+	regulator-always-on;
+	regulator-boot-on;
+};
+
+&rknpu {
+	rknpu-supply = <&vdd_npu>;
+	status = "okay";
+};
+
+&rknpu_mmu {
+	status = "okay";
+};
+
+// These are only necessary for 6.6.y and later. See README.md
+&vpu {
+	status = "disabled";
+};
+
+&vdpu_mmu {
+	status = "disabled";
+};
+
+&vepu {
+	status = "disabled";
+};
+
+&vepu_mmu {
+	status = "disabled";
+};
+
+&vop {
+	status = "disabled";
+};
+
+&vop_mmu {
+	status = "disabled";
+};

2c. Board patch — Radxa ZERO 3E (rk3566-radxa-zero-3e.dts)

The ZERO 3E shares its GPU/NPU supply rail (vdd_gpu, DCDC_REG2 on the RK817 PMIC). This regulator is typically already regulator-always-on in the board DTS (since it also powers the GPU), so no extra override is needed.

--- a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3e.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3e.dts
@@ -50,3 +50,37 @@ gmac1_rstn: gmac1-rstn {
 		};
 	};
 };
+
+&rknpu {
+	rknpu-supply = <&vdd_gpu_npu>;
+	status = "okay";
+};
+
+&rknpu_mmu {
+	status = "okay";
+};
+
+// These are only necessary for 6.6.y and later. See README.md
+&vpu {
+	status = "disabled";
+};
+
+&vdpu_mmu {
+	status = "disabled";
+};
+
+&vepu {
+	status = "disabled";
+};
+
+&vepu_mmu {
+	status = "disabled";
+};
+
+&vop {
+	status = "disabled";
+};
+
+&vop_mmu {
+	status = "disabled";
+};

Building the patched device tree

# From the kernel source tree, after applying the patches above:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs

# Copy the resulting DTB to your board:
scp arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dtb root@board:/boot/dtbs/

Replace the DTB your bootloader loads (path depends on distro) and reboot.

Kernel Version Notes

6.6.y — DRM GEM prime function compilation errors

Some intermediate 6.6.y kernel versions made drm_gem_prime_handle_to_fd and drm_gem_prime_fd_to_handle private symbols, causing compilation errors on those specific versions. Later 6.6.y releases made these functions public again. If you encounter such errors, they are transitory and a newer 6.6.y kernel version should resolve them.

RK356x on 6.6.y and later — IOMMU v2 breaks the NPU

Important: On kernel 6.6 and later, the Rockchip 356x NPU IOMMU only works reliably with the v1 compatible string, rockchip,iommu.

A commit enables IOMMU page table allocations above the 32 bit address space. The lack of NPU documentation and the available kernel driver suggests that the NPU cannot access memory above the 32 bit address space. The Rockchip iommu-v1 and iommu-v2 drivers page table handling is equivalent for addresses in the 32 bit space. Thus using the v1 compatible string (rockchip,iommu) for the NPU MMU node forces the Rockchip IOMMU driver to allocate page tables from the 32-bit region, which matches the apparent NPU limitation. In other words, rockchip,iommu is required here not because the NPU needs an older page-table format, but because it ensures the page tables land in address space the NPU can actually reach.

The problem is that the current upstream rockchip-iommu driver does not allow multiple Rockchip IOMMU variants to coexist in the same system. Once the NPU is switched to rockchip,iommu, the other Rockchip IOMMU devices and their devices must be turned off (i.e. disabled).

In practice this means that using NPU is exclusive with other IOMMU subsystems (VOP, VEPU, VDPU).

License

GPL-2.0 — see source file headers for details.

Origin

Extracted from Rockchip's kernel tree (drivers/rknpu/), version 0.9.8 (2024-08-28).

About

Rockchip rknpu driver in DKMS

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors