RK3588 kernel-6.1 drivers/usb/dwc2 详细分析:与 USB 2.0 协议的关系及实现方式
1. 文档范围与重要前提
- 目录:
rk3588/kernel-6.1/drivers/usb/dwc2/ - 硬件 IP:Synopsys DesignWare USB 2.0 HS OTG(DWC_otg),内核配置项
CONFIG_USB_DWC2(模块常为dwc2.ko,另有dwc2_platform.ko/dwc2_pci.ko视平台而定)。
1.1 「如何实现 USB 2.0 协议」应怎样理解
USB 2.0 规范涵盖 物理层、链路层事务(TOKEN/DATA/HANDSHAKE)、设备框架(Chapter 9)、Hub、类协议 等多层。
在内核里 分层如下:
| 层级 | 主要由谁完成 |
|---|---|
| 枚举、Hub 拓扑、URB、驱动绑定 | drivers/usb/core(hub.c、hcd.c、urb.c 等) |
| Root Hub IOCTL(端口电源、复位、状态) | DWC2 HCD 通过 hc_driver->hub_control / hub_status_data 与硬件寄存器交互 |
| 将 URB 转为 USB 2.0 事务调度(控制/批量/中断/同步,HS/FS/LS,Split,SOF 对齐) | dwc2 主机代码(hcd*.c、hcd_queue.c、hcd_intr.c、hcd_ddma.c)+ 片内 DWC_otg 硬件 |
| Gadget:作为设备响应主机 | gadget.c + core*.c,对接 usb_gadget |
也就是说:DWC2 驱动并不在用户空间「重写一整份 USB 2.0 规范文档」,而是通过 Linux hc_driver API 与 usbcore 协作,并对 DWC_otg 寄存器/DMA 描述符 编程,使硬件在总线上发出符合 USB 2.0 的 包与事务;设备描述符、SET_ADDRESS、SET_CONFIGURATION 等 逻辑流程 仍以 usbcore 为主。
2. 源码文件与编译关系
依据 Makefile:
| 目标 | 源文件 | 作用概要 |
|---|---|---|
dwc2 |
core.c |
Host/Device 共用:全局寄存器、模式、FIFO、挂起恢复备份、电源相关 等。 |
core_intr.c |
共用中断分发:OTG、模式不匹配、端口、再委托 Host/Device。 | |
platform.c |
platform driver:DT、dr_mode、时钟/复位/PHY、注册 HCD 或 UDC。 |
|
params.c |
硬件参数 / quirks 解析与默认策略。 | |
drd.c(dual-role) |
usb_role_switch:Host/Device 角色切换、GOTGCTL 覆盖等。 |
|
| 主机 | hcd.c |
struct hc_driver 实现:urb_enqueue、Root Hub、端口、启动停止、DMA 映射钩子。 |
hcd_intr.c |
主机中断:SOF、通道完成、NAK、Split、TT clear、帧号。 | |
hcd_queue.c |
QH/QTD、周期带宽位图、主机通道分配与事务入队。 | |
hcd_ddma.c |
Descriptor DMA:描述符链、帧列表(与 dma_desc_enable 等参数相关)。 |
|
| 设备 | gadget.c |
USB Gadget UDC:端点、usb_request、EP0 状态机、DMA/PIO。 |
| 其它 | pci.c |
PCI 绑定 EHCI companion 协调(若启用 USB_DWC2_PCI)。 |
debugfs.c |
调试接口。 | |
hw.h |
寄存器偏移与位域常量(硬件手册级别)。 |
主机与 Gadget 互斥或共存 由 Kconfig 的 USB_DWC2_HOST / PERIPHERAL / DUAL_ROLE 决定。
3. 主机模式:从 URB 到 USB 2.0 事务
3.1 Linux 侧的入口:hc_driver
hcd.c 中 dwc2_hc_driver 声明了 DWC2 作为 USB 2.0 主机控制器 对 usbcore 的回调(节选语义):
1 | static struct hc_driver dwc2_hc_driver = { |
HCD_USB2:向核心声明这是 USB 2.0 主机控制器。urb_enqueue:usb_submit_urb()最终会把 URB 交给这里。hub_*:软件 Root Hub 行为由usbcore的 Hub 逻辑驱动,端口级硬件操作在hub_control里通过 HPRT 等寄存器 完成。
3.2 内部抽象:dwc2_hcd_urb → QH → QTD → Host Channel
hcd.h 中说明:HCD 负责把 USB Driver(此处即 usbcore + 设备驱动) 的请求转换为 DWC_otg 上的动作。
典型链路:
_dwc2_hcd_urb_enqueue()把struct urb包装为struct dwc2_hcd_urb,并挂到dwc2_qh(队列头) 与dwc2_qtd(传输描述)。dwc2_hcd_urb_enqueue()调用dwc2_hcd_qtd_init/dwc2_hcd_qtd_add,必要时触发dwc2_hcd_select_transactions→dwc2_hcd_queue_transactions,把事务发到 主机通道(Host Channel)。struct dwc2_host_chan承载 USB 2.0 事务参数:设备地址、端点号、方向、速度(LS/FS/HS)、传输类型(控制/同步/批量/中断)、max_packet、DATA0/DATA1/SETUP/PING、以及 Split(do_split、hub_addr、hub_port、complete_split、xact_pos)——对应规范里经 Hub TT 访问 低速/全速 设备的 分割事务。
硬件在每个 帧/微帧 内执行通道上的事务;驱动负责 不与周期带宽冲突、正确拆分 Split、处理 NAK/PING/STALL 等。
3.3 SOF 与周期调度
hcd_intr.c 中 dwc2_sof_intr()(注释):SOF 中断到来时更新帧号,把满足 next_active_frame 的周期 QH 从 periodic_sched_inactive 移到 periodic_sched_ready,再 dwc2_hcd_select_transactions / dwc2_hcd_queue_transactions。
这对应 USB 2.0 高速微帧 125µs 下的 中断/同步传输调度;全速/低速则在 1ms 帧 视角下配合 Split。
3.4 周期带宽:hcd_queue.c
dwc2_check_periodic_bandwidth() 等函数按 高速约 80%/帧微帧、全速约 90%/帧 的惯例预留 微秒级带宽(注释中与规范常用比例一致),并用 pmap_schedule() 一类 位图 在多个 interval 上占位,避免周期传输饿死。
3.5 Descriptor DMA:hcd_ddma.c
当 参数启用 Descriptor DMA 时,由 hcd_ddma.c 维护 DMA 描述符链表、帧列表索引 等,减轻 CPU 逐包配置通道的负担;等价的「协议含义」仍是 USB 2.0 事务,只是 提交方式 由硬件扫描描述符完成。
3.6 PIO / Slave 与 Internal DMA
hcd.c 里 dwc2_gahbcfg_init():区分 Slave-only 与 Internal DMA,host_dma 为假时会启用 GINTSTS_RXFLVL 等路径依赖 FIFO 中断搬运——事务语义不变,数据路径不同。
3.7 TT 与 clear_tt_buffer
低速/全速设备挂在高速 Hub 下时,usbcore 维护 usb_tt;DWC2 在 hcd_intr.c(如 dwc2_hc_handle_tt_clear)中与 usb_hub_clear_tt_buffer() 协作,满足规范对 TT 缓冲区 的要求。
4. Root Hub 与端口(与 Chapter 9 / Hub 章节的关系)
- 逻辑枚举(读描述符、SET_ADDRESS、选配置)在
usbcore/hub.c。 - 物理端口(供电、复位、连接检测、速度指示)由
dwc2的hub_control/hub_status_data读HPRT0等完成。 core_intr.c中dwc2_handle_usb_port_intr处理端口相关 PRTINT 状态清除。
因此:协议状态机在软件上层,电气与端口状态在 DWC2 + PHY。
5. Gadget 模式:作为 USB 2.0 设备
gadget.c(历史继承自 Samsung/Openmoko S3C HSOTG)实现 struct usb_gadget:
- EP0:SETUP 解析、状态阶段、与
composite上层协作。 - 其它端点:批量/中断/同步 请求队列,DMA 描述符链(
dwc2_hsotg_ep中的desc_list)或 PIO。 core.h中EP0_MPS_LIMIT等注释反映 硬件对 EP0 IN 长度的限制,属于 实现约束,不是协议重写。
此时 USB 2.0「设备侧」 行为由 硬件 + gadget.c 响应主机令牌与数据阶段。
6. DRD 与 OTG:drd.c、core_intr.c
drd.c 在 dual-role 下配合 usb_role_switch,通过 GOTGCTL 的 override 位强制 A-session/B-session VALID,并 dwc2_force_mode 切换 Host/Device。
core_intr.c 处理 OTG、会话、ID、连接 ID 变化 等与 OTG 补充规范 相关的事件(具体取决于硬件能力与 DTS)。
7. 平台初始化:platform.c、params.c
dwc2_get_dr_mode():对齐 硬件模式 / Kconfig / DTdr_mode(与 DWC3dwc3_get_dr_mode思想类似)。- 时钟、复位、
phy_init、供电 regululator、usb_create_hcd/usb_add_hcd或usb_gadget_register_driver均在platform.c路径串联。
params.c 根据 HWCFG 或 DT 填充 dwc2_core_params(通道数、FIFO、DMA 模式等),直接影响 能否支撑 HS 高带宽同步、Split 等。
8. 小结表:DWC2 与 USB 2.0「协议栈」的对应
| USB 2.0 相关内容 | 主要实现位置 |
|---|---|
| 设备枚举、Hub 树、URB | drivers/usb/core |
| Root Hub 端口寄存器、SOF、通道事务、Split、PING/NAK | dwc2 HCD + DWC_otg 硬件 |
| 描述符 DMA / 帧列表(可选) | hcd_ddma.c |
| PHY、FIFO、时钟 | platform.c、core.c、phy |
| 设备模式 EP0/数据传输 | gadget.c + IP |
| OTG/双角色 | drd.c、core_intr.c |
9. 延伸阅读(本仓库)
| 文档 |
|---|
| drivers-usb-core详细分析.md |
| USB总线枚举匹配与数据传输分析.md |
| drivers-usb目录结构与分层原理.md |
基于 rk3588/kernel-6.1/drivers/usb/dwc2 源码整理;寄存器细节以 Synopsys DWC_otg 数据手册与 SoC TRM 为准。
正在加载留言…