Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
18b6acd
accel/rocket: initialize job domain before cleanup paths
shuv-amp Jul 1, 2026
4ac54d3
accel/rocket: fix NULL dereference and integer overflow in rocket_job…
May 24, 2026
ac54abe
accel/rocket: Fix error path handling in rocket_job_run()
ZhaoJM2022 Jun 10, 2026
66b4ca1
pmdomain: rockchip: Add a regulator to the RK3568 NPU power domain
MidG971 Jul 8, 2026
2730490
accel/rocket: request the core clocks by name
sky-rk3588 Jul 29, 2026
62da95c
accel/rocket: take the completion register writes under job_lock
gahingwoo Aug 12, 2026
1c8263a
accel/rocket: wait for a running IRQ handler before resetting a core
gahingwoo Aug 17, 2026
5b34309
accel/rocket: let the core suspend after a reset
gahingwoo Aug 19, 2026
8493b8b
accel/rocket: factor the completion tail out of the IRQ handler
gahingwoo Aug 17, 2026
ab4b974
dt-bindings: npu: rockchip: add rockchip,rk3576-rknn-core
gahingwoo Aug 6, 2026
4e77c28
dt-bindings: power: rockchip: allow resets in a power domain node
gahingwoo Aug 17, 2026
9e3933a
dt-bindings: iommu: rockchip: describe the RK3576 NPU MMU
gahingwoo Aug 17, 2026
d36e48d
pmdomain/rockchip: add optional per-domain power-on settle delay
gahingwoo Jul 31, 2026
f31bd3b
pmdomain/rockchip: cycle optional power-domain resets on power-on
gahingwoo Aug 6, 2026
c7f9420
accel/rocket: select the per-core clock and reset counts from match data
gahingwoo Aug 6, 2026
1ddfbda
accel/rocket: add RK3576 NPU (RKNN) support
gahingwoo Aug 6, 2026
dc039b0
arm64: dts: rockchip: rk3576: add NPU (RKNN) nodes
gahingwoo Aug 6, 2026
5d00ea3
arm64: dts: rockchip: flipper-one: Enable the NPU
Notnurb Aug 26, 2026
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
28 changes: 28 additions & 0 deletions Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ properties:
- items:
- enum:
- rockchip,rk3576-iommu
- rockchip,rk3576-npu-iommu
- rockchip,rk3588-iommu
- const: rockchip,rk3568-iommu

Expand All @@ -42,14 +43,22 @@ properties:
minItems: 1

clocks:
minItems: 2
items:
- description: Core clock
- description: Interface clock
- description: Compute clock
- description: Convolution buffer core clock
- description: Convolution buffer interface clock

clock-names:
minItems: 2
items:
- const: aclk
- const: iface
- const: npu
- const: aclk_cbuf
- const: hclk_cbuf

"#iommu-cells":
const: 0
Expand All @@ -72,6 +81,25 @@ required:
- clock-names
- "#iommu-cells"

allOf:
- if:
properties:
compatible:
contains:
const: rockchip,rk3576-npu-iommu
then:
properties:
clocks:
minItems: 5
clock-names:
minItems: 5
else:
properties:
clocks:
maxItems: 2
clock-names:
maxItems: 2

additionalProperties: false

examples:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ properties:

compatible:
enum:
- rockchip,rk3576-rknn-core
- rockchip,rk3588-rknn-core

reg:
Expand All @@ -33,14 +34,18 @@ properties:
- const: core # Main NPU core processing unit registers

clocks:
maxItems: 4
minItems: 4
maxItems: 6

clock-names:
minItems: 4
items:
- const: aclk
- const: hclk
- const: npu
- const: pclk
- const: aclk_cbuf
- const: hclk_cbuf

interrupts:
maxItems: 1
Expand All @@ -51,12 +56,15 @@ properties:
npu-supply: true

power-domains:
maxItems: 1
minItems: 1
maxItems: 2

resets:
minItems: 1
maxItems: 2

reset-names:
minItems: 1
items:
- const: srst_a
- const: srst_h
Expand All @@ -75,7 +83,40 @@ required:
- resets
- reset-names
- npu-supply
- sram-supply

allOf:
- if:
properties:
compatible:
contains:
const: rockchip,rk3588-rknn-core
then:
properties:
clocks:
maxItems: 4
clock-names:
maxItems: 4
power-domains:
maxItems: 1
resets:
minItems: 2
reset-names:
minItems: 2
required:
- sram-supply
else:
properties:
clocks:
minItems: 6
clock-names:
minItems: 6
power-domains:
minItems: 2
resets:
maxItems: 1
reset-names:
maxItems: 1
sram-supply: false

additionalProperties: false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ $defs:
A number of phandles to clocks that need to be enabled
while power domain switches state.

resets:
maxItems: 1
description:
A phandle to a reset that needs to be cycled once the power domain has
been switched on, for domains whose logic does not come up in a usable
state by itself.

domain-supply:
description: domain regulator supply.

Expand Down Expand Up @@ -216,6 +223,7 @@ examples:
reg = <RK3399_PD_IEP>;
clocks = <&cru ACLK_IEP>,
<&cru HCLK_IEP>;
resets = <&cru SRST_A_IEP>;
pm_qos = <&qos_iep>;
#power-domain-cells = <0>;
};
Expand Down
13 changes: 13 additions & 0 deletions arch/arm64/boot/dts/rockchip/rk3576-flipper-one.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,10 @@
status = "okay";
};

&pd_npu {
domain-supply = <&vdd_npu_s0>;
};

&pinctrl {
camera {
cam_pdn: cam-pdn {
Expand Down Expand Up @@ -1470,6 +1474,15 @@
};
};

&rknn_core_0 {
npu-supply = <&vdd_npu_s0>;
status = "okay";
};

&rknn_mmu_0 {
status = "okay";
};

&sai0 {
/* Serial audio for M.2 WWAN */
pinctrl-names = "default";
Expand Down
82 changes: 79 additions & 3 deletions arch/arm64/boot/dts/rockchip/rk3576.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,7 @@
#address-cells = <1>;
#size-cells = <0>;

power-domain@RK3576_PD_NPU {
pd_npu: power-domain@RK3576_PD_NPU {
reg = <RK3576_PD_NPU>;
#power-domain-cells = <1>;
#address-cells = <1>;
Expand Down Expand Up @@ -1185,14 +1185,22 @@
power-domain@RK3576_PD_NPU0 {
reg = <RK3576_PD_NPU0>;
clocks = <&cru HCLK_RKNN_ROOT>,
<&cru ACLK_RKNN0>;
<&cru ACLK_RKNN0>,
<&cru CLK_RKNN_DSU0>,
<&cru ACLK_RKNN_CBUF>,
<&cru HCLK_RKNN_CBUF>;
resets = <&cru SRST_A_RKNN0_BIU>;
pm_qos = <&qos_npu_m0>;
#power-domain-cells = <0>;
};
power-domain@RK3576_PD_NPU1 {
reg = <RK3576_PD_NPU1>;
clocks = <&cru HCLK_RKNN_ROOT>,
<&cru ACLK_RKNN1>;
<&cru ACLK_RKNN1>,
<&cru CLK_RKNN_DSU0>,
<&cru ACLK_RKNN_CBUF>,
<&cru HCLK_RKNN_CBUF>;
resets = <&cru SRST_A_RKNN1_BIU>;
pm_qos = <&qos_npu_m1>;
#power-domain-cells = <0>;
};
Expand Down Expand Up @@ -1376,6 +1384,74 @@
};
};

rknn_core_0: npu@27700000 {
compatible = "rockchip,rk3576-rknn-core";
reg = <0x0 0x27700000 0x0 0x1000>,
<0x0 0x27701000 0x0 0x1000>,
<0x0 0x27703000 0x0 0x1000>;
reg-names = "pc", "cna", "core";
interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_RKNN0>, <&cru HCLK_RKNN_ROOT>,
<&cru CLK_RKNN_DSU0>, <&cru PCLK_NPUTOP_ROOT>,
<&cru ACLK_RKNN_CBUF>, <&cru HCLK_RKNN_CBUF>;
clock-names = "aclk", "hclk", "npu", "pclk",
"aclk_cbuf", "hclk_cbuf";
resets = <&cru SRST_A_RKNN0>;
reset-names = "srst_a";
power-domains = <&power RK3576_PD_NPU0>, <&power RK3576_PD_NPU1>;
iommus = <&rknn_mmu_0>;
status = "disabled";
};

rknn_mmu_0: iommu@27702000 {
compatible = "rockchip,rk3576-npu-iommu", "rockchip,rk3568-iommu";
reg = <0x0 0x27702000 0x0 0x100>,
<0x0 0x27702100 0x0 0x100>;
interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_RKNN0>, <&cru HCLK_RKNN_ROOT>,
<&cru CLK_RKNN_DSU0>, <&cru ACLK_RKNN_CBUF>,
<&cru HCLK_RKNN_CBUF>;
clock-names = "aclk", "iface", "npu",
"aclk_cbuf", "hclk_cbuf";
#iommu-cells = <0>;
power-domains = <&power RK3576_PD_NPU0>;
status = "disabled";
};

rknn_core_1: npu@27708000 {
compatible = "rockchip,rk3576-rknn-core";
reg = <0x0 0x27708000 0x0 0x1000>,
<0x0 0x27709000 0x0 0x1000>,
<0x0 0x2770b000 0x0 0x1000>;
reg-names = "pc", "cna", "core";
interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_RKNN1>, <&cru HCLK_RKNN_ROOT>,
<&cru CLK_RKNN_DSU0>, <&cru PCLK_NPUTOP_ROOT>,
<&cru ACLK_RKNN_CBUF>, <&cru HCLK_RKNN_CBUF>;
clock-names = "aclk", "hclk", "npu", "pclk",
"aclk_cbuf", "hclk_cbuf";
resets = <&cru SRST_A_RKNN1>;
reset-names = "srst_a";
power-domains = <&power RK3576_PD_NPU1>, <&power RK3576_PD_NPU0>;
iommus = <&rknn_mmu_1>;
status = "disabled";
};

rknn_mmu_1: iommu@2770a000 {
compatible = "rockchip,rk3576-npu-iommu", "rockchip,rk3568-iommu";
reg = <0x0 0x2770a000 0x0 0x100>,
<0x0 0x2770a100 0x0 0x100>;
interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_RKNN1>, <&cru HCLK_RKNN_ROOT>,
<&cru CLK_RKNN_DSU0>, <&cru ACLK_RKNN_CBUF>,
<&cru HCLK_RKNN_CBUF>;
clock-names = "aclk", "iface", "npu",
"aclk_cbuf", "hclk_cbuf";
#iommu-cells = <0>;
power-domains = <&power RK3576_PD_NPU1>;
status = "disabled";
};

gpu: gpu@27800000 {
compatible = "rockchip,rk3576-mali", "arm,mali-bifrost";
reg = <0x0 0x27800000 0x0 0x20000>;
Expand Down
32 changes: 28 additions & 4 deletions drivers/accel/rocket/rocket_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/iommu.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>

Expand All @@ -21,14 +22,22 @@ int rocket_core_init(struct rocket_core *core)
u32 version;
int err = 0;

/* RK3576 has no per-core hclk reset, so it takes srst_a alone. */
core->resets[0].id = "srst_a";
core->resets[1].id = "srst_h";
err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets),
err = devm_reset_control_bulk_get_exclusive(&pdev->dev, core->soc->num_resets,
core->resets);
if (err)
return dev_err_probe(dev, err, "failed to get resets for core %d\n", core->index);

err = devm_clk_bulk_get(dev, ARRAY_SIZE(core->clks), core->clks);
core->clks[0].id = "aclk";
core->clks[1].id = "hclk";
core->clks[2].id = "npu";
core->clks[3].id = "pclk";
/* RK3576 clocks the CBUF separately; the compute path stalls without these. */
core->clks[4].id = "aclk_cbuf";
core->clks[5].id = "hclk_cbuf";
err = devm_clk_bulk_get(dev, core->soc->num_clks, core->clks);
if (err)
return dev_err_probe(dev, err, "failed to get clocks for core %d\n", core->index);

Expand Down Expand Up @@ -56,6 +65,21 @@ int rocket_core_init(struct rocket_core *core)
if (err)
return err;

/*
* RK3576 spans two power domains, and a multi-domain device is skipped
* by the driver-core single-domain auto-attach, so attach the list here.
* This goes before the first thing that would have to be unwound, so a
* failure can simply return.
*/
if (core->soc->multi_power_domain) {
struct dev_pm_domain_list *pd_list;

err = devm_pm_domain_attach_list(dev, NULL, &pd_list);
if (err < 0)
return dev_err_probe(dev, err,
"failed to attach NPU power domains\n");
}

core->iommu_group = iommu_group_get(dev);

err = rocket_job_init(core);
Expand Down Expand Up @@ -105,9 +129,9 @@ void rocket_core_fini(struct rocket_core *core)

void rocket_core_reset(struct rocket_core *core)
{
reset_control_bulk_assert(ARRAY_SIZE(core->resets), core->resets);
reset_control_bulk_assert(core->soc->num_resets, core->resets);

udelay(10);

reset_control_bulk_deassert(ARRAY_SIZE(core->resets), core->resets);
reset_control_bulk_deassert(core->soc->num_resets, core->resets);
}
11 changes: 10 additions & 1 deletion drivers/accel/rocket/rocket_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,25 @@
#define rocket_core_writel(core, reg, value) \
writel(value, (core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS)

/* Per-SoC differences, selected by the of_device_id match data. */
struct rocket_soc_data {
unsigned int num_clks; /* clk_bulk count: 4 base, 6 with CBUF */
unsigned int num_resets; /* reset_bulk count: 2 base, 1 on RK3576 */
bool multi_power_domain; /* device spans more than one PM domain */
bool task_con_16bit; /* PC_TASK_CON uses the 16-bit task number */
};

struct rocket_core {
struct device *dev;
struct rocket_device *rdev;
const struct rocket_soc_data *soc;
unsigned int index;

int irq;
void __iomem *pc_iomem;
void __iomem *cna_iomem;
void __iomem *core_iomem;
struct clk_bulk_data clks[4];
struct clk_bulk_data clks[6];
struct reset_control_bulk_data resets[2];

struct iommu_group *iommu_group;
Expand Down
Loading