RK3588+Deepseek(2):RKNNP驱动
RNNNP的驱动将RKNPU作为一个DRM设备,同时支持IOMMU以及devfreq进行动态调频。
上层应用通过对RKNPU DRM设备进行控制,发起NNP命令执行和数据搬运。

1 RKNNP硬件框架
RKNN包括3个NPU,可以单核、双核、3核模式下工作,每个核2T算力,共6T。支持TensorFlow、Caffe、Tflite、PyTorch、Onnx NN、Android NN等。

每个核架构如下:

- Memory Interface AXI:负责NPU与其他系统组件之间的数据传输。
- CNA:执行权重解压缩、零跳过和数据加载以优化神经网络计算。
- Weight Decompress:对权重数据进行解压缩以减少内存占用和加速数据传输。
- Zero-Skipping:在计算过程中识别并跳过零值,以提高计算效率。
- Weight Data Load:将解压缩后的权重数据加载到NPU内存中以供计算使用。
- Feature Data Load:将输入特征数据加载到NPU内存中,准备进行神经网络计算。
- 384KB Buffer:临时存储数据以支持快速读取和写入。
- Sequence Controller:控制数据处理顺序和管理数据流。
- MAC Array:执行乘累加运算,是神经网络计算的核心步骤。
- Accumulator:累加计算结果,生成最终输出。
- DPU (Data Process Unit):执行主要数据处理任务,如卷积运算。
- PPU (Planar Process Unit):执行平面处理任务,如矩阵乘法。
- Register File Fetch:从寄存器文件获取指令或配置信息。
- Register File/Interrupt Control:管理寄存器文件的写入和中断控制。
- Config Interface (AHB):提供配置接口,用于设置NPU的操作参数。
2 RKNNP dts配置
RKNNP的dts配置是由硬件决定的,包括:
- 寄存器,每个NPU一个地址空间。
- 中断、时钟、复位、电源域每个核独立。
- OPP列表。
- iommu配置。
rknpu: npu@fdab0000 { compatible = "rockchip,rk3588-rknpu"; reg = <0x0 0xfdab0000 0x0 0x10000>, <0x0 0xfdac0000 0x0 0x10000>, <0x0 0xfdad0000 0x0 0x10000>; interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "npu0_irq", "npu1_irq", "npu2_irq";--每个核一个中断。 clocks = <&scmi_clk SCMI_CLK_NPU>, <&cru ACLK_NPU0>, <&cru ACLK_NPU1>, <&cru ACLK_NPU2>, <&cru HCLK_NPU0>, <&cru HCLK_NPU1>, <&cru HCLK_NPU2>, <&cru PCLK_NPU_ROOT>; clock-names = "clk_npu", "aclk0",--每个NPU核包含两个时钟:AHB clock核AXI clock。 "aclk1", "aclk2", "hclk0", "hclk1", "hclk2", "pclk"; assigned-clocks = <&scmi_clk SCMI_CLK_NPU>; assigned-clock-rates = <200000000>; resets = <&cru SRST_A_RKNN0>, <&cru SRST_A_RKNN1>, <&cru SRST_A_RKNN2>, <&cru SRST_H_RKNN0>, <&cru SRST_H_RKNN1>, <&cru SRST_H_RKNN2>; reset-names = "srst_a0", "srst_a1", "srst_a2",--每个核包含两个复位信号:AXI接口下模块复位核AHB接口复位。 "srst_h0", "srst_h1", "srst_h2"; power-domains = <&power RK3588_PD_NPUTOP>, <&power RK3588_PD_NPU1>, <&power RK3588_PD_NPU2>; power-domain-names = "npu0", "npu1", "npu2";--每个核一个电源域。 operating-points-v2 = <&npu_opp_table>; iommus = <&rknpu_mmu>; status = "disabled"; };
3 RKNPU驱动
3.1 RKNPU驱动文件
drivers/rknpu/
├── include │ ├── rknpu_debugger.h │ ├── rknpu_devfreq.h │ ├── rknpu_drv.h │ ├── rknpu_fence.h │ ├── rknpu_gem.h │ ├── rknpu_ioctl.h │ ├── rknpu_iommu.h │ ├── rknpu_job.h │ ├── rknpu_mem.h │ ├── rknpu_mm.h │ └── rknpu_reset.h ├── Kconfig ├── Makefile ├── rknpu_debugger.c--实现 NPU 的调试功能,包括版本信息显示、负载显示、电源状态显示、频率和电压显示、重置控制等。 ├── rknpu_devfreq.c--实现 NPU 的动态频率和电压调整(DVFS)功能。 ├── rknpu_drv.c--NPU 驱动的核心文件,负责设备初始化、电源管理、中断注册、设备树解析等。 ├── rknpu_fence.c--实现 NPU 的同步机制,通过 DMA Fence 提供硬件同步功能。 ├── rknpu_gem.c--管理 NPU 的内存对象(GEM,Graphics Execution Manager),支持内存分配、映射和同步。 ├── rknpu_iommu.c--实现 NPU 的 IOMMU(输入/输出内存管理单元)支持,用于内存保护和地址转换。 ├── rknpu_job.c--管理 NPU 的任务调度和执行,包括任务提交、中断处理和完成通知。 ├── rknpu_mem.c--提供用户空间的内存管理接口,支持内存分配、释放和同步。 ├── rknpu_mm.c--实现一个简单的内存管理模块,用于管理 SRAM 或其他固定大小的内存区域。 └── rknpu_reset.c--实现 NPU 的软重置功能。
3.2 RNNPU初始化
rknpu_init()进行RKNNP设备初始化,rknpu_probe()探测设备:
- RKNPU设备匹配,以及配置获取。
- 检查是否支持IOMMU。
- 时钟、电源、中断、寄存器映射。
- 注册作为DRM设备。
- 电源域和功耗管理。
- 注册作为devfreq设备,以及OPP设置。
- 创建延迟关闭电源的工作队列。
- 调试信息、定时器等创建。
rknpu_init
platform_driver_register--rknpu_driver为RKNPU的驱动,低功耗管理为rknpu_pm_ops。
rknpu_probe--通过rknpu_of_match匹配。
of_match_device
of_device_get_match_data--获取匹配设备的私有数据,即rk3588_rknpu_config。
rknpu_get_invalid_core_mask
rknpu_is_iommu_enable--判断是否是能iommu。
rknpu_reset_get--获取设备复位信号。
devm_clk_bulk_get_all
devm_regulator_get_optional--获取rknpu和mem的regulator。
platform_get_resource--获取每个NPU的地址空间并且映射。
devm_ioremap_resource
rknpu_register_irq
platform_get_resource_byname--分别获取npu0/1/2_irq中断号。
devm_request_irq--注册中断。
rknpu_drm_probe
misc_register--操作函数及为rknpu_fops。
pm_runtime_enable
dev_pm_domain_attach_by_name--根据名称获取PowerDomain设备。
rknpu_power_on
regulator_enable--打开rknpu和mem两个regulator。
clk_bulk_prepare_enable
rknpu_devfreq_lock
pm_runtime_resume_and_get--打开3个npu domain。
pm_runtime_get_sync
rknpu_devfreq_unlock
rknpu_devfreq_init
create_freezable_workqueue--创建rknpu_power_off_wq workqueue。
INIT_DEFERRABLE_WORK--创建一个work,用于关闭RKNPU供电。
rknpu_power_off_delay_work
rknpu_power_off
rknpu_devfreq_lock
pm_runtime_put_sync
pm_runtime_put_sync
rknpu_devfreq_unlock
clk_bulk_disable_unprepare
regulator_disable--关闭Regulator。
rknpu_find_sram_resource
rknpu_mm_create
rknpu_iommu_init_domain
rknpu_power_off
rknpu_debugger_init
rknpu_debugfs_init
debugfs_create_dir--创建/sys/kernel/debug/rknpu目录。
rknpu_debugfs_create_files--在/sys/kernel/debug/rknpu目录下创建rknpu_debugger_root_list列表中的节点,用于调试。
rknpu_init_timer
完成后创建的设备节点如下:
fdab0000.npu/ ├── devfreq │ └── fdab0000.npu │ ├── available_frequencies │ ├── available_governors │ ├── cur_freq │ ├── device -> ../../../fdab0000.npu │ ├── governor │ ├── load │ ├── max_freq │ ├── min_freq │ ├── name │ ├── polling_interval │ ├── power │ │ ├── async │ │ ├── autosuspend_delay_ms │ │ ├── control │ │ ├── runtime_active_kids │ │ ├── runtime_active_time │ │ ├── runtime_enabled │ │ ├── runtime_status │ │ ├── runtime_suspended_time │ │ └── runtime_usage │ ├── subsystem -> ../../../../../class/devfreq │ ├── target_freq │ ├── timer │ ├── trans_stat │ └── uevent ├── driver -> ../../../bus/platform/drivers/RKNPU ├── driver_override ├── drm │ ├── card1 │ │ ├── dev │ │ ├── device -> ../../../fdab0000.npu │ │ ├── power │ │ │ ├── async │ │ │ ├── autosuspend_delay_ms │ │ │ ├── control │ │ │ ├── runtime_active_kids │ │ │ ├── runtime_active_time │ │ │ ├── runtime_enabled │ │ │ ├── runtime_status │ │ │ ├── runtime_suspended_time │ │ │ └── runtime_usage │ │ ├── subsystem -> ../../../../../class/drm │ │ └── uevent │ └── renderD129 │ ├── dev │ ├── device -> ../../../fdab0000.npu │ ├── power │ │ ├── async │ │ ├── autosuspend_delay_ms │ │ ├── control │ │ ├── runtime_active_kids │ │ ├── runtime_active_time │ │ ├── runtime_enabled │ │ ├── runtime_status │ │ ├── runtime_suspended_time │ │ └── runtime_usage │ ├── subsystem -> ../../../../../class/drm │ └── uevent ├── iommu -> ../fdab9000.iommu/iommu/fdab9000.iommu ├── iommu_group -> ../../../kernel/iommu_groups/0 ├── modalias ├── of_node -> ../../../firmware/devicetree/base/npu@fdab0000 ├── power │ ├── async │ ├── autosuspend_delay_ms │ ├── control │ ├── runtime_active_kids │ ├── runtime_active_time │ ├── runtime_enabled │ ├── runtime_status │ ├── runtime_suspended_time │ └── runtime_usage ├── subsystem -> ../../../bus/platform ├── supplier:i2c:1-0042 -> ../../virtual/devlink/i2c:1-0042--platform:fdab0000.npu ├── supplier:platform:fd8d8000.power-management:power-controller -> ../../virtual/devlink/platform:fd8d8000.power-management:power-controller--platform:fdab0000.npu ├── supplier:platform:fdab9000.iommu -> ../../virtual/devlink/platform:fdab9000.iommu--platform:fdab0000.npu ├── supplier:platform:firmware:scmi -> ../../virtual/devlink/platform:firmware:scmi--platform:fdab0000.npu ├── supplier:regulator:regulator.30 -> ../../virtual/devlink/regulator:regulator.30--platform:fdab0000.npu └── uevent
3.3 DRM
rknpu_drm_probe将NPU作为一个DRM设备:
rknpu_drm_probe drm_dev_alloc--分配一个drm设备,驱动为rknpu_drm_driver。 drm_dev_register--生成一个DRM设备/dev/dri/cardx。 drm_fake_dev_register platform_device_register_full--添加一个名为rknpu_dev的platform device。
参照drm_driver说明,DRM设备的驱动包含DRM特有的驱动接口,还提供设备文件操作函数集,以及DRM驱动特有的ioctl命令:
static struct drm_driver rknpu_drm_driver = { #if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE .driver_features = DRIVER_GEM | DRIVER_RENDER, #else .driver_features = DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER,--设置 DRM 驱动支持的功能,包括 GEM、PRIME 和渲染功能。 #endif #if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE .gem_free_object_unlocked = rknpu_gem_free_object, .gem_vm_ops = &rknpu_gem_vm_ops, .dumb_destroy = drm_gem_dumb_destroy, .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = rknpu_gem_prime_get_sg_table, .gem_prime_vmap = rknpu_gem_prime_vmap, .gem_prime_vunmap = rknpu_gem_prime_vunmap, #endif .dumb_create = rknpu_gem_dumb_create, #if KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE .dumb_map_offset = rknpu_gem_dumb_map_offset, #else .dumb_map_offset = drm_gem_dumb_map_offset, #endif .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE .gem_prime_import = rknpu_gem_prime_import, #else .gem_prime_import = drm_gem_prime_import, #endif .gem_prime_import_sg_table = rknpu_gem_prime_import_sg_table, #if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE .gem_prime_mmap = drm_gem_prime_mmap, #else .gem_prime_mmap = rknpu_gem_prime_mmap, #endif .ioctls = rknpu_ioctls, .num_ioctls = ARRAY_SIZE(rknpu_ioctls), .fops = &rknpu_drm_driver_fops,--DRM设备的操作函数集。 .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, };
DRM设备文件操作函数集为:
static const struct file_operations rknpu_drm_driver_fops = { .owner = THIS_MODULE, .open = drm_open, .mmap = rknpu_gem_mmap, .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl,--支持的ioctl命令包括drm_ioctls和drm_driver的ioctls命令(比如rknpu_ioctls)。 #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif .release = drm_release, .llseek = noop_llseek, }; static const struct drm_ioctl_desc rknpu_ioctls[] = { DRM_IOCTL_DEF_DRV(RKNPU_ACTION, __rknpu_action_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(RKNPU_SUBMIT, __rknpu_submit_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(RKNPU_MEM_CREATE, __rknpu_gem_create_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(RKNPU_MEM_MAP, __rknpu_gem_map_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(RKNPU_MEM_DESTROY, __rknpu_gem_destroy_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(RKNPU_MEM_SYNC, __rknpu_gem_sync_ioctl, DRM_RENDER_ALLOW), };
下面是RKNPU驱动私有ioctl命令函数:
rknpu_action_ioctl
rknpu_action--获取版本号、获取频率核电压、复位、iommu等配置。
rknpu_submit_ioctl
rknpu_submit
rknpu_job_alloc
rknpu_gem_create_ioctl
rknpu_gem_object_find
drm_gem_object_lookup
rknpu_gem_object_put
rknpu_gem_object_create
rknpu_gem_init
drm_gem_object_init
mapping_gfp_mask
mapping_set_gfp_mask
rknpu_iommu_domain_get_and_switch
rknpu_gem_alloc_buf_with_cache
rknpu_gem_alloc_buf
rknpu_iommu_domain_put
rknpu_gem_handle_create
drm_gem_handle_create
rknpu_gem_object_put
rknpu_gem_map_ioctl
drm_gem_dumb_map_offset
rknpu_gem_destroy_ioctl
rknpu_gem_object_find
rknpu_iommu_domain_get_and_switch
rknpu_gem_handle_destroy
rknpu_iommu_domain_put
rknpu_gem_sync_ioctl
rknpu_iommu_domain_get_and_switch
rknpu_iommu_domain_put
3.4 devfreq opp
npu_opp_table给出了RKNPU不同频率点的描述:
npu_opp_table: npu-opp-table { compatible = "operating-points-v2"; nvmem-cells = <&npu_leakage>, <&npu_opp_info>, <&specification_serial_number>; nvmem-cell-names = "leakage", "opp-info", "specification_serial_number"; rockchip,supported-hw; rockchip,pvtm-hw = <0x06>; rockchip,pvtm-voltage-sel-hw = < 0 799 0 800 819 1 820 844 2 845 869 3 870 894 4 895 9999 5 >; rockchip,pvtm-voltage-sel = < 0 815 0 816 835 1 836 860 2 861 885 3 886 910 4 911 9999 5 >; rockchip,pvtm-pvtpll; rockchip,pvtm-offset = <0x50>; rockchip,pvtm-sample-time = <1100>; rockchip,pvtm-freq = <800000>; rockchip,pvtm-volt = <750000>; rockchip,pvtm-ref-temp = <25>; rockchip,pvtm-temp-prop = <(-113) (-113)>; rockchip,pvtm-thermal-zone = "npu-thermal"; rockchip,opp-clocks = <&cru PCLK_NPU_GRF>, <&cru HCLK_NPU_ROOT>; rockchip,grf = <&npu_grf>; volt-mem-read-margin = < 855000 1 765000 2 675000 3 495000 4 >; low-volt-mem-read-margin = <4>; intermediate-threshold-freq = <500000>; /* KHz*/ rockchip,init-freq = <1000000>; /* KHz */ rockchip,temp-hysteresis = <5000>; rockchip,low-temp = <10000>; rockchip,low-temp-min-volt = <750000>; rockchip,high-temp = <85000>; rockchip,high-temp-max-freq = <800000>; /* RK3588 npu OPPs */ opp-300000000 {--定义了NPU在不同工作频率下的电压和硬件支持情况。 opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <300000000>;--工作频率。 opp-microvolt = <700000 700000 850000>,--定义不同电压域的电压。 <700000 700000 850000>; opp-microvolt-L1 = <687500 687500 850000>, <687500 687500 850000>; opp-microvolt-L2 = <675000 675000 850000>, <675000 675000 850000>; opp-microvolt-L3 = <675000 675000 850000>, <675000 675000 850000>; opp-microvolt-L4 = <675000 675000 850000>, <675000 675000 850000>; opp-microvolt-L5 = <675000 675000 850000>, <675000 675000 850000>; }; ... opp-1000000000 { opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <850000 850000 850000>, <850000 850000 850000>; opp-microvolt-L1 = <837500 837500 850000>, <837500 837500 850000>; opp-microvolt-L2 = <825000 825000 850000>, <825000 825000 850000>; opp-microvolt-L3 = <812500 812500 850000>, <812500 812500 850000>; opp-microvolt-L4 = <800000 800000 850000>, <800000 800000 850000>; opp-microvolt-L5 = <787500 787500 850000>, <787500 787500 850000>; }; ... };
rknpu_devfrreq_init解析opp表,添加devfreq governor,注册devfreq设备,创建虚拟monitor_dev设备进行opp选择:
rknpu_devfreq_init
dev_pm_opp_set_regulator
rockchip_get_opp_data
rockchip_init_opp_table
clk_get_rate--获取当前时钟频率。
devfreq_recommended_opp--根据频率从opp表中找到合适的opp配置。
devfreq_add_governor--向devfreq框架添加devfreq_rknpu_ondemand governor。 devm_devfreq_add_device--向devfreq框架添加一个设备,并且和rknpu_ondemand关联。 rockchip_system_monitor_register--创建npu_mdevp一个虚拟设备,加入到system monitor设备列表上。根据system monitor的温度进行频率控制。 rockchip_ipa_power_model_init of_devfreq_cooling_register_power
3.5 IOMMU
rknpu_mmu节点描述了IOMMU:
rknpu_mmu: iommu@fdab9000 { compatible = "rockchip,iommu-v2"; reg = <0x0 0xfdab9000 0x0 0x100>, <0x0 0xfdaba000 0x0 0x100>, <0x0 0xfdaca000 0x0 0x100>, <0x0 0xfdada000 0x0 0x100>; interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "npu0_mmu", "npu1_mmu", "npu2_mmu"; clocks = <&cru ACLK_NPU0>, <&cru ACLK_NPU1>, <&cru ACLK_NPU2>, <&cru HCLK_NPU0>, <&cru HCLK_NPU1>, <&cru HCLK_NPU2>; clock-names = "aclk0", "aclk1", "aclk2", "iface0", "iface1", "iface2"; #iommu-cells = <0>; status = "disabled"; };
rk_iommu_init初始化iommu,作为其他设备的子节点:
rk_iommu_init
platform_driver_register--注册驱动rk_iommu_driver,当和rk_iommu_dt_ids中compatible匹配后执行probe。
rk_iommu_probe
of_device_get_match_data--获取设备私有数据,对应iommu_data_ops_v2,里面包含iommu的操作函数。
platform_get_resource
devm_ioremap_resource
platform_irq_count--获取平台设备的中断数量。
devm_clk_buld_get_all
clk_buld_prepare
iommu_group_alloc
iommu_device_sysfs_add--将 IOMMU 设备添加到 sysfs 文件系统,以便用户空间可以访问和管理。
iommu_device_set_ops--设置 IOMMU 设备的操作函数集rk_iommu_ops,这些函数用于管理 IOMMU 的具体操作。
iommu_device_set_fwnode--将 IOMMU 设备与设备树中的固件节点关联起来。
iommu_device_register--注册 IOMMU 设备到内核,使其可以被其他内核组件使用。
bus_set_iommu--为platform总线设置 IOMMU 操作函数,以便总线上的设备可以使用这些操作函数。
pm_runtime_enable--启用设备的电源管理功能,允许设备在空闲时进入低功耗状态。
platform_get_irq
devm_request_irq
rk_iommu_irq--IOMMU 设备的中断处理函数,处理 IOMMU 相关的中断事件。
dma_set_mask_and_coherent--设置设备的 DMA 掩码和一致性内存掩码,确保设备可以正确进行 DMA 操作。
当dts中节点匹配之后,获取到对应的rk iommu私有数据:
static const struct of_device_id rk_iommu_dt_ids[] = { ... { .compatible = "rockchip,iommu-v2", .data = &iommu_data_ops_v2, }, ... }; static struct rk_iommu_ops iommu_data_ops_v2 = { .pt_address = &rk_dte_pt_address_v2, .mk_dtentries = &rk_mk_dte_v2, .mk_ptentries = &rk_mk_pte_v2, .dte_addr_phys = &rk_dte_addr_phys_v2, .dma_addr_dte = &rk_dma_addr_dte_v2, .dma_bit_mask = DMA_BIT_MASK(40), };
rk_iommu_ops定义了一组回调函数,允许内核与 IOMMU 驱动程序交互,从而实现内存地址转换、设备隔离和 DMA 保护等功能:
static const struct iommu_ops rk_iommu_ops = { .domain_alloc = rk_iommu_domain_alloc,--创建一个新的 IOMMU 域,用于管理设备的内存访问。 .domain_free = rk_iommu_domain_free,--释放不再需要的 IOMMU 域,释放相关资源。 .attach_dev = rk_iommu_attach_device,--将设备与 IOMMU 域关联,使设备可以使用该域进行内存访问。 .detach_dev = rk_iommu_detach_device,--解除设备与 IOMMU 域的关联,设备不再使用该域进行内存访问。 .map = rk_iommu_map,--将物理地址映射到 IOMMU 的 IOVA(I/O 虚拟地址),以便设备可以访问内存。 .unmap = rk_iommu_unmap,--取消 IOVA 的映射,释放相关资源。 .flush_iotlb_all = rk_iommu_flush_tlb_all,--取消 IOVA 的映射,释放相关资源。 .probe_device = rk_iommu_probe_device,--检查设备是否支持 IOMMU 功能,初始化设备的 IOMMU 资源。 .release_device = rk_iommu_release_device,--释放设备占用的 IOMMU 资源,通常在设备移除时调用。 .iova_to_phys = rk_iommu_iova_to_phys,--将 IOMMU 的 IOVA 转换为实际的物理地址,用于调试和诊断。 .is_attach_deferred = rk_iommu_is_attach_deferred,--检查设备的 IOMMU 附加是否被延迟,通常用于处理复杂的设备初始化顺序。 .device_group = rk_iommu_device_group,--获取设备所属的 IOMMU 组,用于管理设备的 IOMMU 操作。 .pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,--定义 IOMMU 支持的页面大小,用于内存分配和映射。 .of_xlate = rk_iommu_of_xlate,--解析设备树中的 IOMMU 相关信息,设置设备的 IOMMU 域。 };
rknpu_iommu_init_domain初始化第一个struct iommu_domain资源:
rknpu_iommu_init_domain
iommu_get_domain_for_dev
iommu_group_get--获取设备所在的iommu_group,进而获得iommu_domain返回。
rknpu_iommu_domain_get_and_switch根据domain_id获取对应的struct iommu_domain资源:
rknpu_iommu_domain_get_and_switch
rknpu_iommu_switch_domain
iommu_get_domain_for_dev--获取与指定设备关联的 IOMMU 域。
iommu_domain_alloc--为指定的总线类型分配一个新的 IOMMU 域。
iommu_get_dma_cookie--为指定的 IOMMU 域获取 DMA cookie。
iommu_detach_device--将设备从指定的 IOMMU 域中分离。
iommu_attach_device--将设备附加到指定的 IOMMU 域。
iommu_setup_dma_ops--为设备设置 DMA 操作。
3.6 debugfs调试节点
在/sys/kernel/debug/rknpu/提供了一系列调试节点:
- delayms:设置power_off_work延迟执行时间。
- freq:显示/设置当前时钟频率。
- load:显示每个核的占用率。
- power:设置/显示电源on/off状态。
- reset:显示/设置复位状态。
- version:驱动版本号。
- volt:显示工作电压。
浙公网安备 33010602011771号