Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

accel/rocket: Add a new driver for Rockchip's NPU

This initial version supports the NPU as shipped in the RK3588 SoC and
described in the first part of its TRM, in Chapter 36.

This NPU contains 3 independent cores that the driver can submit jobs
to.

This commit adds just hardware initialization and power management.

v2:
- Split cores and IOMMUs as independent devices (Sebastian Reichel)
- Add some documentation (Jeffrey Hugo)
- Be more explicit in the Kconfig documentation (Jeffrey Hugo)
- Remove resets, as these haven't been found useful so far (Zenghui Yu)
- Repack structs (Jeffrey Hugo)
- Use DEFINE_DRM_ACCEL_FOPS (Jeffrey Hugo)
- Use devm_drm_dev_alloc (Jeffrey Hugo)
- Use probe log helper (Jeffrey Hugo)
- Introduce UABI header in a later patch (Jeffrey Hugo)

v3:
- Adapt to a split of the register block in the DT bindings (Nicolas
Frattaroli)
- Move registers header to its own commit (Thomas Zimmermann)
- Misc. cleanups (Thomas Zimmermann and Jeff Hugo)
- Make use of GPL-2.0-only for the copyright notice (Jeff Hugo)
- PM improvements (Nicolas Frattaroli)

v4:
- Use bulk clk API (Krzysztof Kozlowski)

v6:
- Remove mention to NVDLA, as the hardware is only incidentally related
(Kever Yang)
- Use calloc instead of GFP_ZERO (Jeff Hugo)
- Explicitly include linux/container_of.h (Jeff Hugo)
- pclk and npu clocks are now needed by all cores (Rob Herring)

v7:
- Assign its own IOMMU domain to each client, for isolation (Daniel
Stone and Robin Murphy)

v8:
- Kconfig: fix depends to be more explicit about Rockchip, and remove
superfluous selects (Robin Murphy)
- Use reset lines to reset the cores (Robin Murphy)
- Reference count the module
- Set dma_set_max_seg_size
- Correctly acquire a reference to the IOMMU (Robin Murphy)
- Remove notion of top core (Robin Murphy)

Reviewed-by: Robert Foss <rfoss@kernel.org>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Signed-off-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
Signed-off-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250721-6-10-rocket-v9-2-77ebd484941e@tomeuvizoso.net

authored by

Tomeu Vizoso and committed by
Jeff Hugo
ed98261b 5fc2bfdd

+581
+1
Documentation/accel/index.rst
··· 10 10 introduction 11 11 amdxdna/index 12 12 qaic/index 13 + rocket/index 13 14 14 15 .. only:: subproject and html 15 16
+19
Documentation/accel/rocket/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-only 2 + 3 + ===================================== 4 + accel/rocket Rockchip NPU driver 5 + ===================================== 6 + 7 + The accel/rocket driver supports the Neural Processing Units (NPUs) inside some 8 + Rockchip SoCs such as the RK3588. Rockchip calls it RKNN and sometimes RKNPU. 9 + 10 + The hardware is described in chapter 36 in the RK3588 TRM. 11 + 12 + This driver just powers the hardware on and off, allocates and maps buffers to 13 + the device and submits jobs to the frontend unit. Everything else is done in 14 + userspace, as a Gallium driver (also called rocket) that is part of the Mesa3D 15 + project. 16 + 17 + Hardware currently supported: 18 + 19 + * RK3588
+10
MAINTAINERS
··· 7393 7393 F: drivers/accel/ivpu/ 7394 7394 F: include/uapi/drm/ivpu_accel.h 7395 7395 7396 + DRM ACCEL DRIVER FOR ROCKCHIP NPU 7397 + M: Tomeu Vizoso <tomeu@tomeuvizoso.net> 7398 + L: dri-devel@lists.freedesktop.org 7399 + S: Supported 7400 + T: git https://gitlab.freedesktop.org/drm/misc/kernel.git 7401 + F: Documentation/accel/rocket/ 7402 + F: Documentation/devicetree/bindings/npu/rockchip,rknn-core.yaml 7403 + F: drivers/accel/rocket/ 7404 + F: include/uapi/drm/rocket_accel.h 7405 + 7396 7406 DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK 7397 7407 M: Oded Gabbay <ogabbay@kernel.org> 7398 7408 L: dri-devel@lists.freedesktop.org
+1
drivers/accel/Kconfig
··· 28 28 source "drivers/accel/habanalabs/Kconfig" 29 29 source "drivers/accel/ivpu/Kconfig" 30 30 source "drivers/accel/qaic/Kconfig" 31 + source "drivers/accel/rocket/Kconfig" 31 32 32 33 endif
+1
drivers/accel/Makefile
··· 4 4 obj-$(CONFIG_DRM_ACCEL_HABANALABS) += habanalabs/ 5 5 obj-$(CONFIG_DRM_ACCEL_IVPU) += ivpu/ 6 6 obj-$(CONFIG_DRM_ACCEL_QAIC) += qaic/ 7 + obj-$(CONFIG_DRM_ACCEL_ROCKET) += rocket/
+24
drivers/accel/rocket/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + config DRM_ACCEL_ROCKET 4 + tristate "Rocket (support for Rockchip NPUs)" 5 + depends on DRM 6 + depends on (ARCH_ROCKCHIP && ARM64) || COMPILE_TEST 7 + depends on ROCKCHIP_IOMMU || COMPILE_TEST 8 + depends on MMU 9 + select DRM_SCHED 10 + select DRM_GEM_SHMEM_HELPER 11 + help 12 + Choose this option if you have a Rockchip SoC that contains a 13 + compatible Neural Processing Unit (NPU), such as the RK3588. Called by 14 + Rockchip either RKNN or RKNPU, it accelerates inference of neural 15 + networks. 16 + 17 + The interface exposed to userspace is described in 18 + include/uapi/drm/rocket_accel.h and is used by the Rocket userspace 19 + driver in Mesa3D. 20 + 21 + If unsure, say N. 22 + 23 + To compile this driver as a module, choose M here: the 24 + module will be called rocket.
+8
drivers/accel/rocket/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + obj-$(CONFIG_DRM_ACCEL_ROCKET) := rocket.o 4 + 5 + rocket-y := \ 6 + rocket_core.o \ 7 + rocket_device.o \ 8 + rocket_drv.o
+100
drivers/accel/rocket/rocket_core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */ 3 + 4 + #include <linux/clk.h> 5 + #include <linux/delay.h> 6 + #include <linux/dev_printk.h> 7 + #include <linux/dma-mapping.h> 8 + #include <linux/err.h> 9 + #include <linux/iommu.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/pm_runtime.h> 12 + #include <linux/reset.h> 13 + 14 + #include "rocket_core.h" 15 + 16 + int rocket_core_init(struct rocket_core *core) 17 + { 18 + struct device *dev = core->dev; 19 + struct platform_device *pdev = to_platform_device(dev); 20 + u32 version; 21 + int err = 0; 22 + 23 + core->resets[0].id = "srst_a"; 24 + core->resets[1].id = "srst_h"; 25 + err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets), 26 + core->resets); 27 + if (err) 28 + return dev_err_probe(dev, err, "failed to get resets for core %d\n", core->index); 29 + 30 + err = devm_clk_bulk_get(dev, ARRAY_SIZE(core->clks), core->clks); 31 + if (err) 32 + return dev_err_probe(dev, err, "failed to get clocks for core %d\n", core->index); 33 + 34 + core->pc_iomem = devm_platform_ioremap_resource_byname(pdev, "pc"); 35 + if (IS_ERR(core->pc_iomem)) { 36 + dev_err(dev, "couldn't find PC registers %ld\n", PTR_ERR(core->pc_iomem)); 37 + return PTR_ERR(core->pc_iomem); 38 + } 39 + 40 + core->cna_iomem = devm_platform_ioremap_resource_byname(pdev, "cna"); 41 + if (IS_ERR(core->cna_iomem)) { 42 + dev_err(dev, "couldn't find CNA registers %ld\n", PTR_ERR(core->cna_iomem)); 43 + return PTR_ERR(core->cna_iomem); 44 + } 45 + 46 + core->core_iomem = devm_platform_ioremap_resource_byname(pdev, "core"); 47 + if (IS_ERR(core->core_iomem)) { 48 + dev_err(dev, "couldn't find CORE registers %ld\n", PTR_ERR(core->core_iomem)); 49 + return PTR_ERR(core->core_iomem); 50 + } 51 + 52 + dma_set_max_seg_size(dev, UINT_MAX); 53 + 54 + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 55 + if (err) 56 + return err; 57 + 58 + core->iommu_group = iommu_group_get(dev); 59 + 60 + pm_runtime_use_autosuspend(dev); 61 + 62 + /* 63 + * As this NPU will be most often used as part of a media pipeline that 64 + * ends presenting in a display, choose 50 ms (~3 frames at 60Hz) as an 65 + * autosuspend delay as that will keep the device powered up while the 66 + * pipeline is running. 67 + */ 68 + pm_runtime_set_autosuspend_delay(dev, 50); 69 + 70 + pm_runtime_enable(dev); 71 + 72 + err = pm_runtime_get_sync(dev); 73 + 74 + version = rocket_pc_readl(core, VERSION); 75 + version += rocket_pc_readl(core, VERSION_NUM) & 0xffff; 76 + 77 + pm_runtime_mark_last_busy(dev); 78 + pm_runtime_put_autosuspend(dev); 79 + 80 + dev_info(dev, "Rockchip NPU core %d version: %d\n", core->index, version); 81 + 82 + return 0; 83 + } 84 + 85 + void rocket_core_fini(struct rocket_core *core) 86 + { 87 + pm_runtime_dont_use_autosuspend(core->dev); 88 + pm_runtime_disable(core->dev); 89 + iommu_group_put(core->iommu_group); 90 + core->iommu_group = NULL; 91 + } 92 + 93 + void rocket_core_reset(struct rocket_core *core) 94 + { 95 + reset_control_bulk_assert(ARRAY_SIZE(core->resets), core->resets); 96 + 97 + udelay(10); 98 + 99 + reset_control_bulk_deassert(ARRAY_SIZE(core->resets), core->resets); 100 + }
+49
drivers/accel/rocket/rocket_core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */ 3 + 4 + #ifndef __ROCKET_CORE_H__ 5 + #define __ROCKET_CORE_H__ 6 + 7 + #include <drm/gpu_scheduler.h> 8 + #include <linux/clk.h> 9 + #include <linux/io.h> 10 + #include <linux/mutex_types.h> 11 + #include <linux/reset.h> 12 + 13 + #include "rocket_registers.h" 14 + 15 + #define rocket_pc_readl(core, reg) \ 16 + readl((core)->pc_iomem + (REG_PC_##reg)) 17 + #define rocket_pc_writel(core, reg, value) \ 18 + writel(value, (core)->pc_iomem + (REG_PC_##reg)) 19 + 20 + #define rocket_cna_readl(core, reg) \ 21 + readl((core)->cna_iomem + (REG_CNA_##reg) - REG_CNA_S_STATUS) 22 + #define rocket_cna_writel(core, reg, value) \ 23 + writel(value, (core)->cna_iomem + (REG_CNA_##reg) - REG_CNA_S_STATUS) 24 + 25 + #define rocket_core_readl(core, reg) \ 26 + readl((core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS) 27 + #define rocket_core_writel(core, reg, value) \ 28 + writel(value, (core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS) 29 + 30 + struct rocket_core { 31 + struct device *dev; 32 + struct rocket_device *rdev; 33 + unsigned int index; 34 + 35 + int irq; 36 + void __iomem *pc_iomem; 37 + void __iomem *cna_iomem; 38 + void __iomem *core_iomem; 39 + struct clk_bulk_data clks[4]; 40 + struct reset_control_bulk_data resets[2]; 41 + 42 + struct iommu_group *iommu_group; 43 + }; 44 + 45 + int rocket_core_init(struct rocket_core *core); 46 + void rocket_core_fini(struct rocket_core *core); 47 + void rocket_core_reset(struct rocket_core *core); 48 + 49 + #endif
+56
drivers/accel/rocket/rocket_device.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */ 3 + 4 + #include <drm/drm_drv.h> 5 + #include <linux/array_size.h> 6 + #include <linux/clk.h> 7 + #include <linux/dma-mapping.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/of.h> 10 + 11 + #include "rocket_device.h" 12 + 13 + struct rocket_device *rocket_device_init(struct platform_device *pdev, 14 + const struct drm_driver *rocket_drm_driver) 15 + { 16 + struct device *dev = &pdev->dev; 17 + struct device_node *core_node; 18 + struct rocket_device *rdev; 19 + struct drm_device *ddev; 20 + unsigned int num_cores = 0; 21 + int err; 22 + 23 + rdev = devm_drm_dev_alloc(dev, rocket_drm_driver, struct rocket_device, ddev); 24 + if (IS_ERR(rdev)) 25 + return rdev; 26 + 27 + ddev = &rdev->ddev; 28 + dev_set_drvdata(dev, rdev); 29 + 30 + for_each_compatible_node(core_node, NULL, "rockchip,rk3588-rknn-core") 31 + if (of_device_is_available(core_node)) 32 + num_cores++; 33 + 34 + rdev->cores = devm_kcalloc(dev, num_cores, sizeof(*rdev->cores), GFP_KERNEL); 35 + if (!rdev->cores) 36 + return ERR_PTR(-ENOMEM); 37 + 38 + dma_set_max_seg_size(dev, UINT_MAX); 39 + 40 + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 41 + if (err) 42 + return ERR_PTR(err); 43 + 44 + err = drm_dev_register(ddev, 0); 45 + if (err) 46 + return ERR_PTR(err); 47 + 48 + return rdev; 49 + } 50 + 51 + void rocket_device_fini(struct rocket_device *rdev) 52 + { 53 + WARN_ON(rdev->num_cores > 0); 54 + 55 + drm_dev_unregister(&rdev->ddev); 56 + }
+28
drivers/accel/rocket/rocket_device.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */ 3 + 4 + #ifndef __ROCKET_DEVICE_H__ 5 + #define __ROCKET_DEVICE_H__ 6 + 7 + #include <drm/drm_device.h> 8 + #include <linux/clk.h> 9 + #include <linux/container_of.h> 10 + #include <linux/iommu.h> 11 + #include <linux/platform_device.h> 12 + 13 + #include "rocket_core.h" 14 + 15 + struct rocket_device { 16 + struct drm_device ddev; 17 + 18 + struct rocket_core *cores; 19 + unsigned int num_cores; 20 + }; 21 + 22 + struct rocket_device *rocket_device_init(struct platform_device *pdev, 23 + const struct drm_driver *rocket_drm_driver); 24 + void rocket_device_fini(struct rocket_device *rdev); 25 + #define to_rocket_device(drm_dev) \ 26 + ((struct rocket_device *)(container_of((drm_dev), struct rocket_device, ddev))) 27 + 28 + #endif /* __ROCKET_DEVICE_H__ */
+261
drivers/accel/rocket/rocket_drv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */ 3 + 4 + #include <drm/drm_accel.h> 5 + #include <drm/drm_drv.h> 6 + #include <drm/drm_gem.h> 7 + #include <drm/drm_ioctl.h> 8 + #include <linux/clk.h> 9 + #include <linux/err.h> 10 + #include <linux/iommu.h> 11 + #include <linux/of.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/pm_runtime.h> 14 + 15 + #include "rocket_drv.h" 16 + 17 + /* 18 + * Facade device, used to expose a single DRM device to userspace, that 19 + * schedules jobs to any RKNN cores in the system. 20 + */ 21 + static struct platform_device *drm_dev; 22 + static struct rocket_device *rdev; 23 + 24 + static void 25 + rocket_iommu_domain_destroy(struct kref *kref) 26 + { 27 + struct rocket_iommu_domain *domain = container_of(kref, struct rocket_iommu_domain, kref); 28 + 29 + iommu_domain_free(domain->domain); 30 + domain->domain = NULL; 31 + kfree(domain); 32 + } 33 + 34 + static struct rocket_iommu_domain* 35 + rocket_iommu_domain_create(struct device *dev) 36 + { 37 + struct rocket_iommu_domain *domain = kmalloc(sizeof(*domain), GFP_KERNEL); 38 + void *err; 39 + 40 + if (!domain) 41 + return ERR_PTR(-ENOMEM); 42 + 43 + domain->domain = iommu_paging_domain_alloc(dev); 44 + if (IS_ERR(domain->domain)) { 45 + err = ERR_CAST(domain->domain); 46 + kfree(domain); 47 + return err; 48 + } 49 + kref_init(&domain->kref); 50 + 51 + return domain; 52 + } 53 + 54 + struct rocket_iommu_domain * 55 + rocket_iommu_domain_get(struct rocket_file_priv *rocket_priv) 56 + { 57 + kref_get(&rocket_priv->domain->kref); 58 + return rocket_priv->domain; 59 + } 60 + 61 + void 62 + rocket_iommu_domain_put(struct rocket_iommu_domain *domain) 63 + { 64 + kref_put(&domain->kref, rocket_iommu_domain_destroy); 65 + } 66 + 67 + static int 68 + rocket_open(struct drm_device *dev, struct drm_file *file) 69 + { 70 + struct rocket_device *rdev = to_rocket_device(dev); 71 + struct rocket_file_priv *rocket_priv; 72 + int ret; 73 + 74 + if (!try_module_get(THIS_MODULE)) 75 + return -EINVAL; 76 + 77 + rocket_priv = kzalloc(sizeof(*rocket_priv), GFP_KERNEL); 78 + if (!rocket_priv) { 79 + ret = -ENOMEM; 80 + goto err_put_mod; 81 + } 82 + 83 + rocket_priv->rdev = rdev; 84 + rocket_priv->domain = rocket_iommu_domain_create(rdev->cores[0].dev); 85 + if (IS_ERR(rocket_priv->domain)) { 86 + ret = PTR_ERR(rocket_priv->domain); 87 + goto err_free; 88 + } 89 + 90 + file->driver_priv = rocket_priv; 91 + 92 + return 0; 93 + 94 + err_free: 95 + kfree(rocket_priv); 96 + err_put_mod: 97 + module_put(THIS_MODULE); 98 + return ret; 99 + } 100 + 101 + static void 102 + rocket_postclose(struct drm_device *dev, struct drm_file *file) 103 + { 104 + struct rocket_file_priv *rocket_priv = file->driver_priv; 105 + 106 + rocket_iommu_domain_put(rocket_priv->domain); 107 + kfree(rocket_priv); 108 + module_put(THIS_MODULE); 109 + } 110 + 111 + static const struct drm_ioctl_desc rocket_drm_driver_ioctls[] = { 112 + #define ROCKET_IOCTL(n, func) \ 113 + DRM_IOCTL_DEF_DRV(ROCKET_##n, rocket_ioctl_##func, 0) 114 + }; 115 + 116 + DEFINE_DRM_ACCEL_FOPS(rocket_accel_driver_fops); 117 + 118 + /* 119 + * Rocket driver version: 120 + * - 1.0 - initial interface 121 + */ 122 + static const struct drm_driver rocket_drm_driver = { 123 + .driver_features = DRIVER_COMPUTE_ACCEL, 124 + .open = rocket_open, 125 + .postclose = rocket_postclose, 126 + .ioctls = rocket_drm_driver_ioctls, 127 + .num_ioctls = ARRAY_SIZE(rocket_drm_driver_ioctls), 128 + .fops = &rocket_accel_driver_fops, 129 + .name = "rocket", 130 + .desc = "rocket DRM", 131 + }; 132 + 133 + static int rocket_probe(struct platform_device *pdev) 134 + { 135 + if (rdev == NULL) { 136 + /* First core probing, initialize DRM device. */ 137 + rdev = rocket_device_init(drm_dev, &rocket_drm_driver); 138 + if (IS_ERR(rdev)) { 139 + dev_err(&pdev->dev, "failed to initialize rocket device\n"); 140 + return PTR_ERR(rdev); 141 + } 142 + } 143 + 144 + unsigned int core = rdev->num_cores; 145 + 146 + dev_set_drvdata(&pdev->dev, rdev); 147 + 148 + rdev->cores[core].rdev = rdev; 149 + rdev->cores[core].dev = &pdev->dev; 150 + rdev->cores[core].index = core; 151 + 152 + rdev->num_cores++; 153 + 154 + return rocket_core_init(&rdev->cores[core]); 155 + } 156 + 157 + static void rocket_remove(struct platform_device *pdev) 158 + { 159 + struct device *dev = &pdev->dev; 160 + 161 + for (unsigned int core = 0; core < rdev->num_cores; core++) { 162 + if (rdev->cores[core].dev == dev) { 163 + rocket_core_fini(&rdev->cores[core]); 164 + rdev->num_cores--; 165 + break; 166 + } 167 + } 168 + 169 + if (rdev->num_cores == 0) { 170 + /* Last core removed, deinitialize DRM device. */ 171 + rocket_device_fini(rdev); 172 + rdev = NULL; 173 + } 174 + } 175 + 176 + static const struct of_device_id dt_match[] = { 177 + { .compatible = "rockchip,rk3588-rknn-core" }, 178 + {} 179 + }; 180 + MODULE_DEVICE_TABLE(of, dt_match); 181 + 182 + static int find_core_for_dev(struct device *dev) 183 + { 184 + struct rocket_device *rdev = dev_get_drvdata(dev); 185 + 186 + for (unsigned int core = 0; core < rdev->num_cores; core++) { 187 + if (dev == rdev->cores[core].dev) 188 + return core; 189 + } 190 + 191 + return -1; 192 + } 193 + 194 + static int rocket_device_runtime_resume(struct device *dev) 195 + { 196 + struct rocket_device *rdev = dev_get_drvdata(dev); 197 + int core = find_core_for_dev(dev); 198 + int err = 0; 199 + 200 + if (core < 0) 201 + return -ENODEV; 202 + 203 + err = clk_bulk_prepare_enable(ARRAY_SIZE(rdev->cores[core].clks), rdev->cores[core].clks); 204 + if (err) { 205 + dev_err(dev, "failed to enable (%d) clocks for core %d\n", err, core); 206 + return err; 207 + } 208 + 209 + return 0; 210 + } 211 + 212 + static int rocket_device_runtime_suspend(struct device *dev) 213 + { 214 + struct rocket_device *rdev = dev_get_drvdata(dev); 215 + int core = find_core_for_dev(dev); 216 + 217 + if (core < 0) 218 + return -ENODEV; 219 + 220 + clk_bulk_disable_unprepare(ARRAY_SIZE(rdev->cores[core].clks), rdev->cores[core].clks); 221 + 222 + return 0; 223 + } 224 + 225 + EXPORT_GPL_DEV_PM_OPS(rocket_pm_ops) = { 226 + RUNTIME_PM_OPS(rocket_device_runtime_suspend, rocket_device_runtime_resume, NULL) 227 + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 228 + }; 229 + 230 + static struct platform_driver rocket_driver = { 231 + .probe = rocket_probe, 232 + .remove = rocket_remove, 233 + .driver = { 234 + .name = "rocket", 235 + .pm = pm_ptr(&rocket_pm_ops), 236 + .of_match_table = dt_match, 237 + }, 238 + }; 239 + 240 + static int __init rocket_register(void) 241 + { 242 + drm_dev = platform_device_register_simple("rknn", -1, NULL, 0); 243 + if (IS_ERR(drm_dev)) 244 + return PTR_ERR(drm_dev); 245 + 246 + return platform_driver_register(&rocket_driver); 247 + } 248 + 249 + static void __exit rocket_unregister(void) 250 + { 251 + platform_driver_unregister(&rocket_driver); 252 + 253 + platform_device_unregister(drm_dev); 254 + } 255 + 256 + module_init(rocket_register); 257 + module_exit(rocket_unregister); 258 + 259 + MODULE_LICENSE("GPL"); 260 + MODULE_DESCRIPTION("DRM driver for the Rockchip NPU IP"); 261 + MODULE_AUTHOR("Tomeu Vizoso");
+23
drivers/accel/rocket/rocket_drv.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */ 3 + 4 + #ifndef __ROCKET_DRV_H__ 5 + #define __ROCKET_DRV_H__ 6 + 7 + #include "rocket_device.h" 8 + 9 + struct rocket_iommu_domain { 10 + struct iommu_domain *domain; 11 + struct kref kref; 12 + }; 13 + 14 + struct rocket_file_priv { 15 + struct rocket_device *rdev; 16 + 17 + struct rocket_iommu_domain *domain; 18 + }; 19 + 20 + struct rocket_iommu_domain *rocket_iommu_domain_get(struct rocket_file_priv *rocket_priv); 21 + void rocket_iommu_domain_put(struct rocket_iommu_domain *domain); 22 + 23 + #endif