RK3588 kernel-6.1 drivers/usb/dwc2 详细分析:与 USB 2.0 协议的关系及实现方式

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/corehub.chcd.curb.c 等)
Root Hub IOCTL(端口电源、复位、状态) DWC2 HCD 通过 hc_driver->hub_control / hub_status_data 与硬件寄存器交互
将 URB 转为 USB 2.0 事务调度(控制/批量/中断/同步,HS/FS/LS,Split,SOF 对齐) dwc2 主机代码hcd*.chcd_queue.chcd_intr.chcd_ddma.c)+ 片内 DWC_otg 硬件
Gadget:作为设备响应主机 gadget.c + core*.c,对接 usb_gadget

也就是说:DWC2 驱动并不在用户空间「重写一整份 USB 2.0 规范文档」,而是通过 Linux hc_driver APIusbcore 协作,并对 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 互斥或共存KconfigUSB_DWC2_HOST / PERIPHERAL / DUAL_ROLE 决定。


3. 主机模式:从 URB 到 USB 2.0 事务

3.1 Linux 侧的入口:hc_driver

hcd.cdwc2_hc_driver 声明了 DWC2 作为 USB 2.0 主机控制器usbcore 的回调(节选语义):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static struct hc_driver dwc2_hc_driver = {
.description = "dwc2_hsotg",
.product_desc = "DWC OTG Controller",
.hcd_priv_size = sizeof(struct wrapper_priv_data),

.irq = _dwc2_hcd_irq,
.flags = HCD_MEMORY | HCD_USB2 | HCD_BH,

.start = _dwc2_hcd_start,
.stop = _dwc2_hcd_stop,
.urb_enqueue = _dwc2_hcd_urb_enqueue,
.urb_dequeue = _dwc2_hcd_urb_dequeue,
.endpoint_disable = _dwc2_hcd_endpoint_disable,
.endpoint_reset = _dwc2_hcd_endpoint_reset,
.get_frame_number = _dwc2_hcd_get_frame_number,

.hub_status_data = _dwc2_hcd_hub_status_data,
.hub_control = _dwc2_hcd_hub_control,
.clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete,
...
.map_urb_for_dma = dwc2_map_urb_for_dma,
.unmap_urb_for_dma = dwc2_unmap_urb_for_dma,
};
  • HCD_USB2:向核心声明这是 USB 2.0 主机控制器。
  • urb_enqueueusb_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 上的动作。

典型链路:

  1. _dwc2_hcd_urb_enqueue()struct urb 包装为 struct dwc2_hcd_urb,并挂到 dwc2_qh(队列头)dwc2_qtd(传输描述)
  2. dwc2_hcd_urb_enqueue() 调用 dwc2_hcd_qtd_init / dwc2_hcd_qtd_add,必要时触发 dwc2_hcd_select_transactionsdwc2_hcd_queue_transactions,把事务发到 主机通道(Host Channel)
  3. struct dwc2_host_chan 承载 USB 2.0 事务参数:设备地址、端点号、方向、速度(LS/FS/HS)传输类型(控制/同步/批量/中断)max_packetDATA0/DATA1/SETUP/PING、以及 Splitdo_splithub_addrhub_portcomplete_splitxact_pos)——对应规范里经 Hub TT 访问 低速/全速 设备的 分割事务

硬件在每个 帧/微帧 内执行通道上的事务;驱动负责 不与周期带宽冲突正确拆分 Split、处理 NAK/PING/STALL 等。

3.3 SOF 与周期调度

hcd_intr.cdwc2_sof_intr()(注释):SOF 中断到来时更新帧号,把满足 next_active_frame 的周期 QHperiodic_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.cdwc2_gahbcfg_init():区分 Slave-onlyInternal DMAhost_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
  • 物理端口(供电、复位、连接检测、速度指示)由 dwc2hub_control/hub_status_dataHPRT0 等完成。
  • core_intr.cdwc2_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.hEP0_MPS_LIMIT 等注释反映 硬件对 EP0 IN 长度的限制,属于 实现约束,不是协议重写。

此时 USB 2.0「设备侧」 行为由 硬件 + gadget.c 响应主机令牌与数据阶段。


6. DRD 与 OTG:drd.ccore_intr.c

drd.cdual-role 下配合 usb_role_switch,通过 GOTGCTLoverride 位强制 A-session/B-session VALID,并 dwc2_force_mode 切换 Host/Device。

core_intr.c 处理 OTG、会话、ID、连接 ID 变化 等与 OTG 补充规范 相关的事件(具体取决于硬件能力与 DTS)。


7. 平台初始化:platform.cparams.c

  • dwc2_get_dr_mode():对齐 硬件模式 / Kconfig / DT dr_mode(与 DWC3 dwc3_get_dr_mode 思想类似)。
  • 时钟、复位、phy_init供电 regululatorusb_create_hcd / usb_add_hcdusb_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.ccore.cphy
设备模式 EP0/数据传输 gadget.c + IP
OTG/双角色 drd.ccore_intr.c

9. 延伸阅读(本仓库)

文档
drivers-usb-core详细分析.md
USB总线枚举匹配与数据传输分析.md
drivers-usb目录结构与分层原理.md

基于 rk3588/kernel-6.1/drivers/usb/dwc2 源码整理;寄存器细节以 Synopsys DWC_otg 数据手册与 SoC TRM 为准。

文章互动

阅读 --

留言

0 条留言

正在加载留言…