一 整体概述
1.1 程序文件位置分布
RTOS中DSMC代码,dsmc-controller.c是控制器初始化代码,dsmc-host.c是主机驱动代码
dsmc-lb-device.c是总线设备用户接口驱动程序,dsmc-lb-slave.c是从机程序
SDK/GA3506_Linux_Source/kernel-6.1/drivers/memory/rockchip/dsmc-controller.c
SDK/GA3506_Linux_Source/kernel-6.1/drivers/memory/rockchip/dsmc-host.c
SDK/GA3506_Linux_Source/kernel-6.1/drivers/memory/rockchip/dsmc-lb-device.c
SDK/GA3506_Linux_Source/kernel-6.1/drivers/memory/rockchip/dsmc-lb-slave.c
1.2 四个文件整体之间的关系
四个文件尽管分为控制器、主机、接口、从机四部分,但总体来说,从功能上来看只有主机和从机两个部分主机dsmc-host.c依赖dsmc-controller.c和dsmc-lb-device.c完成整体功能从机不依赖其他DSMC文件,只在dsmc-lb-slave.c里写寄存器配置DSMC,处理中断等
主机端Host
dsmc-host.c 注册 platform 驱动,probe 时会:
调用 dsmc-controller.c 的底层初始化接口rockchip_dsmc_ctrller_init,完成控制器硬件初始化
调用 dsmc-lb-device.c 注册 Local Bus 设备,创建 /dev/dsmc/... 字符设备节点,提供用户空间访问接口
注册 DMA 和中断,做好数据搬运准备
用户程序通过 /dev/dsmc/ 下的设备节点,发起 DMA 读写请求open/ioctl
ioctl 处理,配置 DMA 参数,调用 dma_memcpy_init/dma_memcpy_trans_start
通过 dsmc-host.c 提供的 ops 接口,最终调用 dsmc-controller.c 的底层 DMA 函数发送出去从机端Slave
dsmc-lb-slave.c 注册 platform 驱动,probe 时:
解析 dts,获取资源和内存映射
初始化寄存器,配置为 slave 模式
申请中断,等待主机端的中断操作通知
收到中断(如 S2H),进入中断服务函数 rockchip_dsmc_lb_slave_irq
调用 dsmc_lb_slave_dma_trigger(),触发本地 DMA 硬件搬运
搬运完成后清除中断,等待下一次操作二 控制器驱动代码解析
2.1 控制器驱动初始化 dsmc-controller.c
dsmc-controller.c主要负责 DSMC 控制器的底层硬件初始化、PSRAM检测与配置、延迟线训练、DMA 触发、寄存器操作等功能。它是整个 DSMC 总线主控端驱动的底层核心,直接操作硬件寄存器,完成对存储器和总线的初始化和管理。在RTOS中与其对应的是HAL_DSMC_HOST_Init中部分内容
延迟线(DLL)训练:是为总线采样时钟增加适当延时,使得数据到达时间一致性
主要结构体
struct rockchip_dsmc:DSMC控制器的核心结构体,包含寄存器基址、配置参数等
struct dsmc_config_cs:描述每个chip select的配置信息,时序、宽度、延迟等
struct dsmc_map:映射的内存区域信息
下列函数通过 EXPORT_SYMBOL 导出,可以被其他内核模块调用,比如dsmc-host.c等
rockchip_dsmc_dll_training:延迟线训练
rockchip_dsmc_lb_dma_trigger_by_host:主控触发 DMA
rockchip_dsmc_lb_dma_hw_mode_dis:关闭 DMA 硬件模式
rockchip_dsmc_ctrller_init:主控控制器初始化
rockchip_dsmc_lb_init:本地总线初始化
rockchip_dsmc_psram_reinit:PSRAM 重新初始化
rockchip_dsmc_device_dectect:设备检测大致调用流程:参考dsmc-host.c
1调用rockchip_dsmc_ctrller_init初始化控制器
2调用rockchip_dsmc_device_dectect检测并识别PSRAM
3调用rockchip_dsmc_dll_training进行延迟线训练
4调用rockchip_dsmc_psram_reinit可重新初始化PSRAM参数三 主机驱动代码解析
3.1 主机驱动初始化代码流向
模块加载 → 驱动注册 → probe资源申请 → dts参数解析 → 控制器/设备初始化 → 内存映射 → DMA/中断注册 → 对外API注册 → 正常工作 → 释放资源 → 注销驱动
rk_dsmc_init -> platform_driver_register(&rk_dsmc_driver) -> rk_dsmc_probe -> dsmc_parse_dt ->
dsmc_init -> dsmc_mem_remap ->rockchip_dsmc_dma_request -> priv->ops = &rockchip_dsmc_ops ->
正常工作(上层ops调用等)-> rk_dsmc_remove -> platform_driver_unregister(&rk_dsmc_driver)-> rk_dsmc_exit
3.2 主机驱动代码框架
结构体
struct rockchip_dsmc:主控结构体,包含寄存器映射、配置参数、DMA、中断等
struct dsmc_ctrl_config:控制器配置,包括各chip select的参数
struct dsmc_transfer:DMA传输相关参数与状态
rk_dsmc_init():类与平台驱动注册,创建DSMC类,通常用于sysfs、热插拔等管理
platform_driver_register():注册平台驱动,关联 .probe = rk_dsmc_probe,设备树匹配到 compatible 节点后会自动调用 probe
rk_dsmc_probe():平台驱动探测函数probe资源申请(malloc),DMA申请与时钟初始化等
dsmc_parse_dt():dts参数解析,读取slave/psram/lb-slave等节点参数,解析物理内存、时序、属性等
dsmc_init():DSMC控制器初始化,内部会调用dsmc-controller.c里面的函数,实现控制器底层初始化
dsmc_mem_remap():内存空间映射与设备注册,RTS可以直接访问物理地址,Linux下必须做虚拟地址映射
priv->ops = &rockchip_dsmc_ops:ops对外操作函数集注册,提供标准的 read、write、copy_from、copy_to 等接口给上层调用
用户获取DSMC设备指针,通过 ops 中的API进行寄存器读写、DMA数据搬运等操作
rk_dsmc_remove:关闭并释放时钟、DMA、内存映射、local bus设备等资源
rk_dsmc_exit:注销平台驱动,销毁DSMC类。
四 DSMC Local Bus(LB)设备驱动代码解析 dsmc-lb-device.c
此文件负责DSMC控制器驱动 Local Bus 的字符设备节点注册、DMA 操作、用户接口的实现,由主驱动调用,用于实现用户空间访问和数据交换。
4.1 驱动初始化代码流向
rockchip_dsmc_lb_class_create / rockchip_dsmc_lb_class_destroy
创建/销毁 dsmc_class,用于 device_create。
rockchip_dsmc_register_lb_device / rockchip_dsmc_unregister_lb_device
注册/注销 Local Bus 字符设备节点,分配 cdev,生成 /dev/dsmc/csX/regionY 设备文件。
dsmc_fops:dma操作集
dsmc_ioctl:支持 DMA 配置、启动、获取时间、释放等命令。
dma_memcpy_init:申请并配置 DMA 通道
dma_memcpy_trans_start:提交 DMA 任务,等待完成
dma_cb_isr:DMA 传输完成回调
在 dsmc-host.c 或 dsmc-controller.c 里,初始化 Local Bus 设备时,会调用:
rockchip_dsmc_lb_class_create()→ 创建 class
rockchip_dsmc_register_lb_device()→ 为每个 cs/region 注册字符设备节点
卸载时调用:
rockchip_dsmc_unregister_lb_device()
rockchip_dsmc_lb_class_destroy()4.2 驱动代码调用细节
主驱动dsmc-host.c在 probe 时调用rockchip_dsmc_lb_class_create()创建 class,用于后续设备节点挂载
rockchip_dsmc_register_lb_device(dev, cs)为每个 cs(chip select)下的每个 region 注册字符设备节点(/dev/dsmc/csX/regionY)
用户程序通过 /dev/dsmc/csX/regionY 设备节点进行操作如下:
open("/dev/dsmc/csX/regionY", ...)//打开设备接口
→ 内核调用 dsmc_open()
打开 dsmc 设备,分配DMA
ioctl(fd, DMA_MEMCPY_SETUP, ¶ms) 发送参数
→ 内核调用 dsmc_ioctl()
从用户空间拷贝参数到 rw_dsmc_params
分配一块 DMA 一致性内存(dma_alloc_coherent)
设置 DMA 源/目的物理地址,虚拟地址等
调用 dma_memcpy_init() 申请并配置 DMA 通道
ioctl(fd, DMA_MEMCPY_START)
→ 内核调用 dsmc_ioctl(DMA_MEMCPY_START, ...)
调用 dma_memcpy_trans_start()
配置 DMA 描述符
设置回调(dma_cb_isr)
提交并启动 DMA
阻塞等待传输完成(wait_for_completion)
ioctl(fd, DMA_MEMCPY_GET_TIME)
→ 内核调用 dsmc_ioctl(DMA_MEMCPY_GET_TIME, ...)
如果上次 DMA 完成,返回耗时(write_time)
fd.close()
→ 内核调用 dsmc_release()
释放 DMA 结构体五 从机驱动代码解析dsmc-lb-slave.c
此文件 是 DSMC Local Bus 的Slave端驱动,用于管理从设备的寄存器、时钟和总线协议相关配置
主机端Host通过 DSMC 通道发起 DMA 操作从机端Slave收到中断后,触发硬件 DMA 拷贝,完成数据交互
5.1 系统如何启动驱动?
设备树匹配 → probe 初始化 → 寄存器初始化 → 申请中断 → 中断触发时,启动 DMA 传输 → 中断清除,等待下一次传输
5.2 从机驱动初始化代码流向
struct rockchip_dsmc_lb_slave
保存了 slave 端的所有硬件资源指针和内存映射信息
module_platform_driver(rk_dsmc_lb_slave_driver):注册 platform 驱动,驱动入口与设备匹配驱动入口与设备匹配
rk_dsmc_lb_slave_driver:指定 probe/remove、of_match_table
rk_dsmc_lb_slave_probe():分配并初始化 rockchip_dsmc_lb_slave 结构体
解析 dts 的 memory-region,获取 slave 端映射内存物理地址和大小
调用 dsmc_lb_slave_init() 做寄存器初始化,申请中断,绑定 rockchip_dsmc_lb_slave_irq
dsmc_lb_slave_init():寄存器初始化,使能slave模式
rockchip_dsmc_lb_slave_irq():检查中断状态,调用 dsmc_lb_slave_dma_trigger()触发 DMA 传输,清除所有 H2S 中断
dsmc_lb_slave_dma_trigger():检查 DMA 中断状态,等待清空,通过写寄存器触发 slave 到 host 的 DMA 硬件拷贝
rk_dsmc_lb_slave_remove():关闭并释放时钟
评论