LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

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:显示工作电压。

posted on 2025-05-01 23:59  ArnoldLu  阅读(457)  评论(0)    收藏  举报

导航