Synopsys DesignWare Core SuperSpeed USB 3.0 控制器¶
- 作者:
Felipe Balbi <felipe.balbi@linux.intel.com>
- 日期:
2017 年 4 月
简介¶
Synopsys DesignWare Core SuperSpeed USB 3.0 控制器(以下简称 DWC3)是符合 USB 超高速标准的控制器,可以通过以下 4 种方式之一进行配置
仅限外围设备配置
仅限主机配置
双重角色配置
集线器配置
Linux 目前支持此控制器的多个版本。 您 SoC 中的版本很可能已受支持。 在撰写本文时,已知测试版本范围从 2.02a 到 3.10a。 根据经验,任何高于 2.02a 的版本都应该可以可靠地工作。
目前,我们有很多此驱动程序的已知用户。 按字母顺序排列
Cavium
英特尔公司
高通
瑞芯微
意法半导体
三星
德州仪器
赛灵思
功能概述¶
有关您的 DWC3 版本支持的功能的详细信息,请咨询您的 IP 团队和/或 Synopsys DesignWare Core SuperSpeed USB 3.0 控制器数据手册。 以下是撰写本文时驱动程序支持的功能列表
这些功能都已通过许多 树内 设备驱动程序进行过测试。 我们已验证 ConfigFS [4] 和旧版设备驱动程序。
驱动程序设计¶
DWC3 驱动程序位于 drivers/usb/dwc3/ 目录中。 与此驱动程序相关的所有文件都在这一个目录中。 这使新手可以轻松阅读代码并了解其行为方式。
由于 DWC3 的配置灵活性,该驱动程序在某些地方有点复杂,但应该很容易理解。
驱动程序的最大部分涉及 Gadget API。
已知限制¶
与任何其他硬件一样,DWC3 也有其自身的限制。 为了避免关于此类问题的不断提问,我们决定在此处记录它们,并提供一个我们可以向用户指明的单一位置。
OUT 传输大小要求¶
根据 Synopsys 数据手册,所有 OUT 传输 TRB [1] 的 size 字段必须设置为可被端点的 wMaxPacketSize 整除的值。 这意味着,例如,为了接收大容量存储 CBW [5],req->length 必须设置为可被 wMaxPacketSize 整除的值(超高速为 1024,高速为 512,等等),否则 DWC3 驱动程序必须添加一个指向剩余长度的抛弃缓冲区的链式 TRB。 如果不这样做,OUT 传输将 不 会启动。
请注意,在撰写本文时,这不会成为问题,因为 DWC3 完全能够为剩余长度附加一个链式 TRB,并完全向设备驱动程序隐藏此细节。 仍然值得一提,因为这似乎是关于 DWC3 和非工作传输的最大查询来源。
TRB 环大小限制¶
目前,我们对每个端点有 256 个 TRB [1] 的硬限制,最后一个 TRB 是指向第一个 TRB 的链接 TRB [2]。此限制是任意的,但它的好处是加起来正好是 4096 字节或 1 页。
DWC3 驱动程序将尽力处理超过 255 个请求,并且在大多数情况下,它应该正常工作。 但是,这不是经常测试的功能。 如果您遇到任何问题,请参阅下面的“报告错误”部分。
报告错误¶
每当您遇到 DWC3 的问题时,首先应确保
您正在运行来自 Linus 的树的最新标签
您可以在不对 DWC3 进行任何树外更改的情况下重现该错误
您已检查过这是否不是主机上的故障
验证所有这些后,下面是如何捕获足够的信息,以便我们为您提供帮助。
所需信息¶
DWC3 完全依赖于用于调试的跟踪事件。 所有内容都在那里公开,一些额外的位会公开到 DebugFS [3]。
为了捕获 DWC3 的跟踪事件,您应该在将 USB 电缆插入主机 之前 运行以下命令
# mkdir -p /d
# mkdir -p /t
# mount -t debugfs none /d
# mount -t tracefs none /t
# echo 81920 > /t/buffer_size_kb
# echo 1 > /t/events/dwc3/enable
完成此操作后,您可以连接 USB 电缆并重现该问题。 重现故障后,请复制文件 trace
和 regdump
,如下所示
# cp /t/trace /root/trace.txt
# cat /d/*dwc3*/regdump > /root/regdump.txt
请确保将 trace.txt
和 regdump.txt
压缩到 tarball 中,并通过电子邮件发送给 我,并将 linux-usb 添加到抄送列表中。 如果您想格外确保我会帮助您,请按以下格式编写您的主题行
[错误报告] usb:dwc3:在执行 XYZ 时出现错误
在电子邮件正文中,请务必详细说明您在做什么、您正在使用的设备驱动程序、如何重现问题、您正在使用的 SoC 以及主机上运行的操作系统(及其版本)。
有了所有这些信息,我们应该能够了解发生了什么并为您提供帮助。
调试¶
首先声明一下
DISCLAIMER: The information available on DebugFS and/or TraceFS can
change at any time at any Major Linux Kernel Release. If writing
scripts, do **NOT** assume information to be available in the
current format.
解决了这个问题,我们继续。
如果您愿意调试自己的问题,您应该得到热烈的掌声 :-)
无论如何,除了跟踪事件对于弄清楚 DWC3 的问题非常有帮助之外,这里没什么好说的。 此外,在这种情况下,访问 Synopsys 数据手册将 非常 有价值。
USB 嗅探器有时可能会有帮助,但并非完全必要,即使不看连接线,也可以理解很多内容。
如果您需要任何帮助,请随时通过电子邮件发送给 我 并抄送 linux-usb。
DebugFS
¶
DebugFS
非常适合收集 DWC3 和/或任何端点正在发生的事情的快照。
在 DWC3 的 DebugFS
目录中,您将找到以下文件和目录
ep[0..15]{in,out}/
link_state
regdump
testmode
link_state
¶
读取时,link_state
将打印出以下状态之一: U0
、U1
、U2
、U3
、SS.Disabled
、RX.Detect
、SS.Inactive
、Polling
、Recovery
、Hot Reset
、Compliance
、Loopback
、Reset
、Resume
或 UNKNOWN link state
。
也可以写入此文件以强制链接到上述状态之一。
regdump
¶
文件名是不言自明的。读取时,regdump
将打印出 DWC3 的寄存器转储。 请注意,可以使用 grep 命令从此文件中查找所需的信息。
testmode
¶
读取时,testmode
将打印出指定的 USB 2.0 测试模式之一的名称(test_j
、test_k
、test_se0_nak
、test_packet
、test_force_enable
),如果当前没有执行任何测试,则打印字符串 no test
。
为了启动任何这些测试模式,可以将相同的字符串写入文件,DWC3 将进入请求的测试模式。
ep[0..15]{in,out}
¶
对于每个端点,我们公开一个遵循命名约定 ep$num$dir
(ep0in, ep0out, ep1in, ...) 的目录。在每个目录中,您将找到以下文件:
descriptor_fetch_queue
event_queue
rx_fifo_queue
rx_info_queue
rx_request_queue
transfer_type
trb_ring
tx_fifo_queue
tx_request_queue
通过访问 Synopsys Databook,您可以解码它们上的信息。
transfer_type
¶
读取时,transfer_type
将根据端点描述符的内容打印出 control
、bulk
、interrupt
或 isochronous
之一。如果尚未启用端点,则将打印 --
。
trb_ring
¶
读取时,trb_ring
将打印出有关环上所有 TRB 的详细信息。它还将告诉您我们的入队和出队指针在环中的位置。
buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,512,normal,1,0,1,0,0,1 D
0000000000000000,0,UNKNOWN,0,0,0,0,0,0 E
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
00000000381ab000,0,link,0,0,0,0,0,1
跟踪事件¶
DWC3 还提供了几个跟踪事件,这些事件有助于我们收集有关驱动程序在运行时行为的信息。
为了使用这些事件,您必须在内核配置中启用 CONFIG_FTRACE
。
有关如何启用 DWC3 事件的详细信息,请参阅 报告错误 部分。
以下小节将详细介绍 DWC3 定义的每个事件类和每个事件。
MMIO¶
有时,在查找错误时,查看每个 MMIO 访问会很有用。因此,DWC3 提供了两个跟踪事件(一个用于 dwc3_readl(),另一个用于 dwc3_writel())。以下是 TP_printk
格式:
TP_printk("addr %p value %08x", __entry->base + __entry->offset,
__entry->value)
中断事件¶
每个 IRQ 事件都可以记录并解码为人类可读的字符串。因为每个事件都会有所不同,所以我们不提供 TP_printk
格式以外的示例:
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event, __entry->ep0state))
控制请求¶
每个 USB 控制请求都可以记录到跟踪缓冲区。输出格式为:
TP_printk("%s", dwc3_decode_ctrl(__entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
请注意,标准控制请求将被解码为具有各自参数的人类可读字符串。类和供应商请求将以 8 字节的十六进制格式打印出来。
struct usb_request
的生命周期¶
可以在跟踪缓冲区中跟踪 struct usb_request
的整个生命周期。我们为每个分配、释放、排队、出队和返回都有一个事件。输出格式为:
TP_printk("%s: req %p length %u/%u %s%s%s ==> %d",
__get_str(name), __entry->req, __entry->actual, __entry->length,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
__entry->no_interrupt ? "i" : "I",
__entry->status
)
通用命令¶
我们可以记录和解码每个通用命令及其完成代码。格式为:
TP_printk("cmd '%s' [%x] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
)
端点命令¶
端点命令也可以与完成代码一起记录。格式为:
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2,
dwc3_ep_cmd_status_string(__entry->cmd_status)
)
TRB
的生命周期¶
TRB
的生命周期很简单。我们要么准备 TRB
,要么完成它。通过这两个事件,我们可以看到 TRB
如何随时间变化。格式为:
TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
({char *s;
int pcm = ((__entry->size >> 24) & 3) + 1;
switch (__entry->type) {
case USB_ENDPOINT_XFER_INT:
case USB_ENDPOINT_XFER_ISOC:
switch (pcm) {
case 1:
s = "1x ";
break;
case 2:
s = "2x ";
break;
case 3:
s = "3x ";
break;
}
default:
s = "";
} s; }),
DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl))
)
端点的生命周期¶
端点的生命周期通过启用和禁用操作来总结,这两个操作都可以被跟踪。格式为:
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
__entry->trb_dequeue,
__entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
__entry->flags & DWC3_EP_STALL ? 'S' : 's',
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
结构、方法和定义¶
-
struct dwc3_event_buffer¶
软件事件缓冲区表示
定义:
struct dwc3_event_buffer {
void *buf;
void *cache;
unsigned int length;
unsigned int lpos;
unsigned int count;
unsigned int flags;
#define DWC3_EVENT_PENDING BIT(0);
dma_addr_t dma;
struct dwc3 *dwc;
};
成员
buf
_THE_ 缓冲区
cache
线程中断中使用的缓冲区缓存
length
此缓冲区的大小
lpos
事件偏移量
count
上次读取的事件计数寄存器的缓存
flags
与此事件缓冲区相关的标志
dma
dma_addr_t
dwc
指向 DWC 控制器的指针
-
struct dwc3_ep¶
设备侧端点表示
定义:
struct dwc3_ep {
struct usb_ep endpoint;
struct list_head cancelled_list;
struct list_head pending_list;
struct list_head started_list;
void __iomem *regs;
struct dwc3_trb *trb_pool;
dma_addr_t trb_pool_dma;
struct dwc3 *dwc;
u32 saved_state;
unsigned int flags;
#define DWC3_EP_ENABLED BIT(0);
#define DWC3_EP_STALL BIT(1);
#define DWC3_EP_WEDGE BIT(2);
#define DWC3_EP_TRANSFER_STARTED BIT(3);
#define DWC3_EP_END_TRANSFER_PENDING BIT(4);
#define DWC3_EP_PENDING_REQUEST BIT(5);
#define DWC3_EP_DELAY_START BIT(6);
#define DWC3_EP_WAIT_TRANSFER_COMPLETE BIT(7);
#define DWC3_EP_IGNORE_NEXT_NOSTREAM BIT(8);
#define DWC3_EP_FORCE_RESTART_STREAM BIT(9);
#define DWC3_EP_FIRST_STREAM_PRIMED BIT(10);
#define DWC3_EP_PENDING_CLEAR_STALL BIT(11);
#define DWC3_EP_TXFIFO_RESIZED BIT(12);
#define DWC3_EP_DELAY_STOP BIT(13);
#define DWC3_EP_RESOURCE_ALLOCATED BIT(14);
#define DWC3_EP0_DIR_IN BIT(31);
u8 trb_enqueue;
u8 trb_dequeue;
u8 number;
u8 type;
u8 resource_index;
u32 frame_number;
u32 interval;
char name[20];
unsigned direction:1;
unsigned stream_capable:1;
u8 combo_num;
int start_cmd_status;
};
成员
endpoint
usb 端点
cancelled_list
此端点已取消的请求列表
pending_list
此端点待处理的请求列表
started_list
在此端点上已启动的请求列表
regs
指向第一个端点寄存器的指针
trb_pool
事务缓冲区数组
trb_pool_dma
trb_pool 的 DMA 地址
dwc
指向 DWC 控制器的指针
saved_state
休眠期间保存的 ep 状态
flags
端点标志(楔入、停止、...)
trb_enqueue
TRB 数组的入队“指针”
trb_dequeue
TRB 数组的出队“指针”
number
端点号 (1 - 15)
type
设置为 bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
resource_index
资源传输索引
frame_number
设置为我们希望此传输开始的帧号 (ISOC)
interval
ISOC 传输开始的间隔
name
人类可读的名称,例如 ep1out-bulk
direction
对于 TX 为真,对于 RX 为假
stream_capable
启用流时为真
combo_num
用于测试同步启动传输命令失败解决方法,帧号的测试组合 BIT[15:14]
start_cmd_status
使用 combo_num = ‘b00 测试启动传输命令的状态
-
struct dwc3_trb¶
传输请求块(硬件格式)
定义:
struct dwc3_trb {
u32 bpl;
u32 bph;
u32 size;
u32 ctrl;
};
成员
bpl
DW0-3
bph
DW4-7
size
DW8-B
ctrl
DWC-F
-
struct dwc3_hwparams¶
HWPARAMS 寄存器的副本
定义:
struct dwc3_hwparams {
u32 hwparams0;
u32 hwparams1;
u32 hwparams2;
u32 hwparams3;
u32 hwparams4;
u32 hwparams5;
u32 hwparams6;
u32 hwparams7;
u32 hwparams8;
u32 hwparams9;
};
成员
hwparams0
GHWPARAMS0
hwparams1
GHWPARAMS1
hwparams2
GHWPARAMS2
hwparams3
GHWPARAMS3
hwparams4
GHWPARAMS4
hwparams5
GHWPARAMS5
hwparams6
GHWPARAMS6
hwparams7
GHWPARAMS7
hwparams8
GHWPARAMS8
hwparams9
GHWPARAMS9
-
struct dwc3_request¶
传输请求的表示
定义:
struct dwc3_request {
struct usb_request request;
struct list_head list;
struct dwc3_ep *dep;
struct scatterlist *sg;
struct scatterlist *start_sg;
unsigned int num_pending_sgs;
unsigned int remaining;
unsigned int status;
#define DWC3_REQUEST_STATUS_QUEUED 0;
#define DWC3_REQUEST_STATUS_STARTED 1;
#define DWC3_REQUEST_STATUS_DISCONNECTED 2;
#define DWC3_REQUEST_STATUS_DEQUEUED 3;
#define DWC3_REQUEST_STATUS_STALLED 4;
#define DWC3_REQUEST_STATUS_COMPLETED 5;
#define DWC3_REQUEST_STATUS_UNKNOWN -1;
u8 epnum;
struct dwc3_trb *trb;
dma_addr_t trb_dma;
unsigned int num_trbs;
unsigned int direction:1;
unsigned int mapped:1;
};
成员
request
要传输的
struct usb_request
list
用于请求排队的 list_head
dep
拥有此请求的
struct dwc3_ep
start_sg
指向下一个应排队的 sg 的指针
num_pending_sgs
待处理的 sg 的计数器
remaining
剩余数据量
status
内部 dwc3 请求状态跟踪
epnum
此请求指向的端点号
trb
指向
struct dwc3_trb
的指针trb_dma
trb 的 DMA 地址
num_trbs
此请求使用的 TRB 数量
direction
IN 或 OUT 方向标志
mapped
当请求已被 dma 映射时为 true
-
struct dwc3¶
我们控制器的表示
定义:
struct dwc3 {
struct work_struct drd_work;
struct dwc3_trb *ep0_trb;
void *bounce;
u8 *setup_buf;
dma_addr_t ep0_trb_addr;
dma_addr_t bounce_addr;
struct dwc3_request ep0_usb_req;
struct completion ep0_in_setup;
spinlock_t lock;
struct mutex mutex;
struct device *dev;
struct device *sysdev;
struct platform_device *xhci;
struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
struct dwc3_event_buffer *ev_buf;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
struct usb_gadget *gadget;
struct usb_gadget_driver *gadget_driver;
struct clk *bus_clk;
struct clk *ref_clk;
struct clk *susp_clk;
struct clk *utmi_clk;
struct clk *pipe_clk;
struct reset_control *reset;
struct usb_phy *usb2_phy;
struct usb_phy *usb3_phy;
struct phy *usb2_generic_phy[DWC3_USB2_MAX_PORTS];
struct phy *usb3_generic_phy[DWC3_USB3_MAX_PORTS];
u8 num_usb2_ports;
u8 num_usb3_ports;
bool phys_ready;
struct ulpi *ulpi;
bool ulpi_ready;
void __iomem *regs;
size_t regs_size;
enum usb_dr_mode dr_mode;
u32 current_dr_role;
u32 desired_dr_role;
struct extcon_dev *edev;
struct notifier_block edev_nb;
enum usb_phy_interface hsphy_mode;
struct usb_role_switch *role_sw;
enum usb_dr_mode role_switch_default_mode;
struct power_supply *usb_psy;
u32 fladj;
u32 ref_clk_per;
u32 irq_gadget;
u32 otg_irq;
u32 current_otg_role;
u32 desired_otg_role;
bool otg_restart_host;
u32 u1u2;
u32 maximum_speed;
u32 gadget_max_speed;
enum usb_ssp_rate max_ssp_rate;
enum usb_ssp_rate gadget_ssp_rate;
u32 ip;
#define DWC3_IP 0x5533;
#define DWC31_IP 0x3331;
#define DWC32_IP 0x3332;
u32 revision;
#define DWC3_REVISION_ANY 0x0;
#define DWC3_REVISION_173A 0x5533173a;
#define DWC3_REVISION_175A 0x5533175a;
#define DWC3_REVISION_180A 0x5533180a;
#define DWC3_REVISION_183A 0x5533183a;
#define DWC3_REVISION_185A 0x5533185a;
#define DWC3_REVISION_187A 0x5533187a;
#define DWC3_REVISION_188A 0x5533188a;
#define DWC3_REVISION_190A 0x5533190a;
#define DWC3_REVISION_194A 0x5533194a;
#define DWC3_REVISION_200A 0x5533200a;
#define DWC3_REVISION_202A 0x5533202a;
#define DWC3_REVISION_210A 0x5533210a;
#define DWC3_REVISION_220A 0x5533220a;
#define DWC3_REVISION_230A 0x5533230a;
#define DWC3_REVISION_240A 0x5533240a;
#define DWC3_REVISION_250A 0x5533250a;
#define DWC3_REVISION_260A 0x5533260a;
#define DWC3_REVISION_270A 0x5533270a;
#define DWC3_REVISION_280A 0x5533280a;
#define DWC3_REVISION_290A 0x5533290a;
#define DWC3_REVISION_300A 0x5533300a;
#define DWC3_REVISION_310A 0x5533310a;
#define DWC3_REVISION_320A 0x5533320a;
#define DWC3_REVISION_330A 0x5533330a;
#define DWC31_REVISION_ANY 0x0;
#define DWC31_REVISION_110A 0x3131302a;
#define DWC31_REVISION_120A 0x3132302a;
#define DWC31_REVISION_160A 0x3136302a;
#define DWC31_REVISION_170A 0x3137302a;
#define DWC31_REVISION_180A 0x3138302a;
#define DWC31_REVISION_190A 0x3139302a;
#define DWC31_REVISION_200A 0x3230302a;
#define DWC32_REVISION_ANY 0x0;
#define DWC32_REVISION_100A 0x3130302a;
u32 version_type;
#define DWC31_VERSIONTYPE_ANY 0x0;
#define DWC31_VERSIONTYPE_EA01 0x65613031;
#define DWC31_VERSIONTYPE_EA02 0x65613032;
#define DWC31_VERSIONTYPE_EA03 0x65613033;
#define DWC31_VERSIONTYPE_EA04 0x65613034;
#define DWC31_VERSIONTYPE_EA05 0x65613035;
#define DWC31_VERSIONTYPE_EA06 0x65613036;
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state;
u16 u2sel;
u16 u2pel;
u8 u1sel;
u8 u1pel;
u8 speed;
u8 num_eps;
struct dwc3_hwparams hwparams;
struct debugfs_regset32 *regset;
u32 dbg_lsp_select;
u8 test_mode;
u8 test_mode_nr;
u8 lpm_nyet_threshold;
u8 hird_threshold;
u8 rx_thr_num_pkt;
u8 rx_max_burst;
u8 tx_thr_num_pkt;
u8 tx_max_burst;
u8 rx_thr_num_pkt_prd;
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
u8 tx_fifo_resize_max_num;
u8 clear_stall_protocol;
const char *hsphy_interface;
unsigned connected:1;
unsigned softconnect:1;
unsigned delayed_status:1;
unsigned ep0_bounced:1;
unsigned ep0_expect_in:1;
unsigned sysdev_is_parent:1;
unsigned has_lpm_erratum:1;
unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1;
unsigned pending_events:1;
unsigned do_fifo_resize:1;
unsigned pullups_connected:1;
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
unsigned dis_start_transfer_quirk:1;
unsigned usb3_lpm_capable:1;
unsigned usb2_lpm_disable:1;
unsigned usb2_gadget_lpm_disable:1;
unsigned disable_scramble_quirk:1;
unsigned u2exit_lfps_quirk:1;
unsigned u2ss_inp3_quirk:1;
unsigned req_p1p2p3_quirk:1;
unsigned del_p1p2p3_quirk:1;
unsigned del_phy_power_chg_quirk:1;
unsigned lfps_filter_quirk:1;
unsigned rx_detect_poll_quirk:1;
unsigned dis_u3_susphy_quirk:1;
unsigned dis_u2_susphy_quirk:1;
unsigned dis_enblslpm_quirk:1;
unsigned dis_u1_entry_quirk:1;
unsigned dis_u2_entry_quirk:1;
unsigned dis_rxdet_inp3_quirk:1;
unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_quirk:1;
unsigned dis_tx_ipgap_linecheck_quirk:1;
unsigned resume_hs_terminations:1;
unsigned ulpi_ext_vbus_drv:1;
unsigned parkmode_disable_ss_quirk:1;
unsigned parkmode_disable_hs_quirk:1;
unsigned gfladj_refclk_lpm_sel:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
unsigned dis_metastability_quirk:1;
unsigned dis_split_quirk:1;
unsigned async_callbacks:1;
unsigned sys_wakeup:1;
unsigned wakeup_configured:1;
unsigned suspended:1;
unsigned susphy_state:1;
u16 imod_interval;
int max_cfg_eps;
int last_fifo_depth;
int num_ep_resized;
struct dentry *debug_root;
u32 gsbuscfg0_reqinfo;
};
成员
drd_work
用于角色切换的工作队列
ep0_trb
用于 ctrl_req 的 trb
bounce
反弹缓冲区的地址
setup_buf
在处理标准 USB 请求时使用
ep0_trb_addr
ep0_trb 的 dma 地址
bounce_addr
bounce 的 dma 地址
ep0_usb_req
处理标准 USB 请求时使用的虚拟请求
ep0_in_setup
一个控制传输完成并进入设置阶段
lock
用于同步
mutex
用于模式切换
dev
指向我们的
struct device
的指针sysdev
指向支持 DMA 的设备的指针
xhci
指向我们的 xHCI 子设备的指针
xhci_resources
我们 xhci 子设备的结构资源
ev_buf
eps
端点数组
gadget
外围控制器的设备端表示
gadget_driver
指向 gadget 驱动程序的指针
bus_clk
用于访问寄存器的时钟
ref_clk
参考时钟
susp_clk
当 SS phy 处于低功耗(S3)状态时使用的时钟
utmi_clk
用于 USB2 PHY 通信的时钟
pipe_clk
用于 USB3 PHY 通信的时钟
reset
复位控制
usb2_phy
指向 USB2 PHY 的指针
usb3_phy
指向 USB3 PHY 的指针
usb2_generic_phy
指向 USB2 PHY 数组的指针
usb3_generic_phy
指向 USB3 PHY 数组的指针
num_usb2_ports
USB2 端口数
num_usb3_ports
USB3 端口数
phys_ready
指示 PHY 已准备就绪的标志
ulpi
指向 ulpi 接口的指针
ulpi_ready
指示 ULPI 已初始化的标志
regs
我们寄存器的基地址
regs_size
地址空间大小
dr_mode
请求的操作模式
current_dr_role
在双角色模式下的当前操作角色
desired_dr_role
在双角色模式下期望的操作角色
edev
extcon 句柄
edev_nb
extcon 通知程序
hsphy_mode
UTMI phy 模式,以下之一:- USBPHY_INTERFACE_MODE_UTMI - USBPHY_INTERFACE_MODE_UTMIW
role_sw
usb_role_switch 句柄
role_switch_default_mode
当 usb 角色为 USB_ROLE_NONE 时,控制器的默认操作模式。
usb_psy
指向电源接口的指针。
fladj
帧长度调整
ref_clk_per
参考时钟周期配置
irq_gadget
外围控制器的 IRQ 号
otg_irq
OTG IRQ 的 IRQ 号
current_otg_role
使用 OTG 块时的当前操作角色
desired_otg_role
使用 OTG 块时期望的操作角色
otg_restart_host
OTG 控制器需要重启主机的标志
u1u2
仅用于修订版 <1.83a 的解决方法
maximum_speed
请求的最大速度(主要用于测试目的)
gadget_max_speed
请求的最大 gadget 速度
max_ssp_rate
SuperSpeed Plus 最大信号速率和通道数
gadget_ssp_rate
Gadget 驱动程序支持的最大 SuperSpeed Plus 信号速率和通道数。
ip
控制器的 ID
revision
控制器 IP 版本
version_type
VERSIONTYPE 寄存器内容,修订版的子版本
ep0_next_event
保持下一个预期事件
ep0state
零号端点的状态
link_state
链路状态
u2sel
来自 Set SEL 请求的参数。
u2pel
来自 Set SEL 请求的参数。
u1sel
来自 Set SEL 请求的参数。
u1pel
来自 Set SEL 请求的参数。
speed
设备速度(超速、高速、全速、低速)
num_eps
端点数
hwparams
hwparams 寄存器的副本
regset
指向 regdump 文件的 debugfs 指针
dbg_lsp_select
当前的调试 lsp 多路复用器寄存器选择
test_mode
当我们进入 USB 测试模式时为 true
test_mode_nr
测试功能选择器
lpm_nyet_threshold
LPM NYET 响应阈值
hird_threshold
HIRD 阈值
rx_thr_num_pkt
USB 接收数据包计数
rx_max_burst
最大 USB 接收突发大小
tx_thr_num_pkt
USB 发送数据包计数
tx_max_burst
最大 USB 发送突发大小
rx_thr_num_pkt_prd
周期性 ESS 接收数据包计数
rx_max_burst_prd
最大周期性 ESS 接收突发大小
tx_thr_num_pkt_prd
周期性 ESS 发送数据包计数
tx_max_burst_prd
最大周期性 ESS 发送突发大小
tx_fifo_resize_max_num
在 txfifo 调整大小期间分配的最大 fifo 数
clear_stall_protocol
需要延迟状态阶段的端点号
hsphy_interface
“utmi” 或 “ulpi”
connected
当我们连接到主机时为 true,否则为 false
softconnect
当调用 gadget 连接时为 true,当断开连接运行时为 false
delayed_status
当 gadget 驱动程序请求延迟状态时为 true
ep0_bounced
当我们使用反弹缓冲区时为 true
ep0_expect_in
当我们期望 DATA IN 传输时为 true
sysdev_is_parent
当 dwc3 设备具有父驱动程序时为 true
has_lpm_erratum
当核心配置了 LPM 勘误时为 true。请注意,现在没有办法让软件在运行时检测到这一点。
is_utmi_l1_suspend
核心断言输出信号 0 - utmi_sleep_n 1 - utmi_l1_suspend_n
is_fpga
当我们使用 FPGA 板时为 true
pending_events
当我们有待处理的 IRQ 需要处理时为 true
do_fifo_resize
当为 dwc3 端点启用 txfifo 调整大小时为 true
pullups_connected
当设置 Run/Stop 位时为 true
setup_packet_pending
当 FIFO 中有 Setup 数据包时为 true。解决方法
three_stage_setup
如果我们执行三阶段设置,则设置
dis_start_transfer_quirk
如果 DWC_usb31 版本 1.70a-ea06 及更低版本不需要 start_transfer 失败 SW 解决方法,则设置
usb3_lpm_capable
如果硬件支持链路电源管理,则设置
usb2_lpm_disable
设置为禁用主机的 usb2 lpm
usb2_gadget_lpm_disable
设置为禁用 gadget 的 usb2 lpm
disable_scramble_quirk
如果我们启用禁用扰码怪癖,则设置
u2exit_lfps_quirk
如果我们启用 u2exit lfps 怪癖,则设置
u2ss_inp3_quirk
如果我们为 U2/SS Inactive 启用 P3 OK,则设置
req_p1p2p3_quirk
如果我们启用请求 p1p2p3 怪癖,则设置
del_p1p2p3_quirk
如果我们启用延迟 p1p2p3 怪癖,则设置
del_phy_power_chg_quirk
如果我们启用延迟 phy 电源更改怪癖,则设置
lfps_filter_quirk
如果我们启用 LFPS 过滤器怪癖,则设置
rx_detect_poll_quirk
如果我们启用 rx_detect 以轮询 lfps 怪癖,则设置
dis_u3_susphy_quirk
如果我们禁用 usb3 暂停 phy,则设置
dis_u2_susphy_quirk
如果我们禁用 usb2 暂停 phy,则设置
dis_enblslpm_quirk
如果我们在 GUSB2PHYCFG 中清除 enblslpm,则设置,禁用到 PHY 的暂停信号。
dis_u1_entry_quirk
如果需要禁用进入 U1 状态的链接,则设置。
dis_u2_entry_quirk
如果需要禁用进入 U2 状态的链接,则设置。
dis_rxdet_inp3_quirk
如果我们在 P3 中禁用 Rx.Detect,则设置
dis_u2_freeclk_exists_quirk
如果我们在 GUSB2PHYCFG 中清除 u2_freeclk_exists,则设置,指定 USB2 PHY 不提供自由运行的 PHY 时钟。
dis_del_phy_power_chg_quirk
如果我们禁用延迟 phy 电源更改怪癖,则设置。
dis_tx_ipgap_linecheck_quirk
如果我们在 HS 发送期间禁用 u2mac 行状态检查,则设置。
resume_hs_terminations
如果我们在从暂停恢复后启用怪癖以修复不正确的 crc 生成,则设置。
ulpi_ext_vbus_drv
设置为将 upli 芯片配置为使用外部电源驱动 CPEN 引脚 VBUS。
parkmode_disable_ss_quirk
如果我们需要禁用停放模式下的所有 SuperSpeed 实例,则设置。
parkmode_disable_hs_quirk
如果我们需要禁用停放模式下的所有 HighSpeed 实例,则设置。
gfladj_refclk_lpm_sel
如果我们需要启用基于 ref_clk 运行的 SOF/ITP 计数器,则设置
tx_de_emphasis_quirk
如果我们启用 Tx 预加重怪癖,则设置
tx_de_emphasis
Tx 预加重值 0 - -6dB 预加重 1 - -3.5dB 预加重 2 - 无预加重 3 - 保留
dis_metastability_quirk
设置为禁用亚稳定性怪癖。
dis_split_quirk
设置为禁用拆分边界。
async_callbacks
如果设置,则表示将使用异步回调。
sys_wakeup
如果设备可以进行系统唤醒,则设置。
wakeup_configured
如果设备配置为远程唤醒,则设置。
suspended
设置为跟踪由于 U3/L2 导致的暂停事件。
susphy_state
PM 暂停之前的 DWC3_GUSB2PHYCFG_SUSPHY + DWC3_GUSB3PIPECTL_SUSPHY 的状态。
imod_interval
以 250ns 增量设置中断缓解间隔,或设置为 0 以禁用。
max_cfg_eps
在所有 USB 配置中使用的当前最大 IN ep 数。
last_fifo_depth
用于确定下一个 fifo ram 起始地址的最后一个 fifo 深度。
num_ep_resized
携带当前已调整其 tx fifo 大小的端点数。
debug_root
此设备的根 debugfs 目录,用于将其文件放入其中。
gsbuscfg0_reqinfo
存储从胶合驱动程序传递的 GSBUSCFG0.DATRDREQINFO、DESRDREQINFO、DATWRREQINFO 和 DESWRREQINFO 值。
-
struct dwc3_event_depevt¶
设备端点事件
定义:
struct dwc3_event_depevt {
u32 one_bit:1;
u32 endpoint_number:5;
u32 endpoint_event:4;
u32 reserved11_10:2;
u32 status:4;
#define DEPEVT_STATUS_TRANSFER_ACTIVE BIT(3);
#define DEPEVT_STATUS_BUSERR BIT(0);
#define DEPEVT_STATUS_SHORT BIT(1);
#define DEPEVT_STATUS_IOC BIT(2);
#define DEPEVT_STATUS_LST BIT(3) ;
#define DEPEVT_STATUS_MISSED_ISOC BIT(3) ;
#define DEPEVT_STREAMEVT_FOUND 1;
#define DEPEVT_STREAMEVT_NOTFOUND 2;
#define DEPEVT_STREAM_PRIME 0xfffe;
#define DEPEVT_STREAM_NOSTREAM 0x0;
#define DEPEVT_STATUS_CONTROL_DATA 1;
#define DEPEVT_STATUS_CONTROL_STATUS 2;
#define DEPEVT_STATUS_CONTROL_PHASE(n) ((n) & 3);
#define DEPEVT_TRANSFER_NO_RESOURCE 1;
#define DEPEVT_TRANSFER_BUS_EXPIRY 2;
u32 parameters:16;
#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8);
};
成员
one_bit
指示这是一个端点事件(未使用)
endpoint_number
端点的数量
endpoint_event
我们拥有的事件:0x00 - 保留 0x01 - XferComplete 0x02 - XferInProgress 0x03 - XferNotReady 0x04 - RxTxFifoEvt (IN->下溢,OUT->溢出) 0x05 - 保留 0x06 - StreamEvt 0x07 - EPCmdCmplt
reserved11_10
保留,请勿使用。
status
指示事件的状态。有关更多信息,请参阅数据手册。
parameters
当前事件的参数。有关更多信息,请参阅数据手册。
-
struct dwc3_event_devt¶
设备事件
定义:
struct dwc3_event_devt {
u32 one_bit:1;
u32 device_event:7;
u32 type:4;
u32 reserved15_12:4;
u32 event_info:9;
u32 reserved31_25:7;
};
成员
one_bit
指示这是一个非端点事件(未使用)
device_event
指示它是一个设备事件。应读取为 0x00
type
指示设备事件的类型。0 - DisconnEvt(断开连接事件) 1 - USBRst(USB 重置) 2 - ConnectDone(连接完成) 3 - ULStChng(上行链路状态更改) 4 - WkUpEvt(唤醒事件) 5 - 保留 6 - Suspend(挂起,在 2.10a 及更早版本中为 EOPF) 7 - SOF(帧开始) 8 - 保留 9 - ErrticErr(错误) 10 - CmdCmplt(命令完成) 11 - EvntOverflow(事件溢出) 12 - VndrDevTstRcved(接收到供应商设备测试)
reserved15_12(保留位 15-12)
保留,未使用
event_info(事件信息)
关于此事件的信息
reserved31_25(保留位 31-25)
保留,未使用
-
struct dwc3_event_gevt¶
其他核心事件
定义:
struct dwc3_event_gevt {
u32 one_bit:1;
u32 device_event:7;
u32 phy_port_number:4;
u32 reserved31_12:20;
};
成员
one_bit
指示这是一个非端点事件(未使用)
device_event
指示它是 (0x03) Carkit 事件还是 (0x04) I2C 事件。
phy_port_number(物理端口号)
不言自明
reserved31_12(保留位 31-12)
保留,未使用。
-
union dwc3_event¶
事件缓冲区内容的表示
定义:
union dwc3_event {
u32 raw;
struct dwc3_event_type type;
struct dwc3_event_depevt depevt;
struct dwc3_event_devt devt;
struct dwc3_event_gevt gevt;
};
成员
raw(原始)
原始 32 位事件
type
事件的类型
depevt
设备端点事件
devt
设备事件
gevt
全局事件
-
struct dwc3_gadget_ep_cmd_params¶
端点命令参数的表示
定义:
struct dwc3_gadget_ep_cmd_params {
u32 param2;
u32 param1;
u32 param0;
};
成员
param2
第三个参数
param1
第二个参数
param0
第一个参数
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
描述
以位为单位返回 MDWIDTH 配置值。
-
struct dwc3_request *next_request(struct list_head *list)¶
获取给定列表中的下一个请求
参数
struct list_head *list
要操作的请求列表
描述
调用者应注意加锁。此函数返回 NULL
或 **list** 中可用的第一个请求。
-
void dwc3_gadget_move_started_request(struct dwc3_request *req)¶
将 **req** 移动到 started_list
参数
struct dwc3_request *req
要移动的请求
描述
调用者应注意加锁。此函数将把 **req** 从其当前列表移动到端点的 started_list。
-
void dwc3_gadget_move_cancelled_request(struct dwc3_request *req, unsigned int reason)¶
将 **req** 移动到 cancelled_list
参数
struct dwc3_request *req
要移动的请求
unsigned int reason
dwc3 请求的取消原因
描述
调用者应注意加锁。此函数将把 **req** 从其当前列表移动到端点的 cancelled_list。
参数
struct dwc3_ep *dep
dwc3 端点
描述
调用者应注意加锁。返回给定端点的传输资源索引。
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
u32 value
要写入 DCTL 的值
描述
在对 DCTL 进行读取-修改-写入时使用此函数。它不会发送链路状态更改请求。
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
int mode
要设置的模式(J、K、SE0、NAK、强制启用)
描述
调用者应注意加锁。如果传递了错误的测试选择器,此函数将返回 0 表示成功,或返回 -EINVAL。
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
描述
调用者应注意加锁。此函数将在成功时返回链路状态 (>= 0) 或返回 -ETIMEDOUT。
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
enum dwc3_link_state state
要将链路置于的状态
描述
调用者应注意加锁。此函数将在成功时返回 0 或返回 -ETIMEDOUT。
-
void dwc3_ep_inc_trb(u8 *index)¶
递增 trb 索引。
参数
u8 *index
指向要递增的 TRB 索引的指针。
描述
该索引绝不应指向链接 TRB。递增后,如果它指向链接 TRB,则回绕到开头。链接 TRB 始终位于最后一个 TRB 条目。
参数
struct dwc3_ep *dep
我们要递增入队指针的端点
参数
struct dwc3_ep *dep
我们要递增入队指针的端点
-
void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status)¶
调用
struct usb_request
的 ->complete 回调
参数
struct dwc3_ep *dep
请求所属的端点
struct dwc3_request *req
我们要返回的请求
int status
请求的完成代码
描述
必须在持有控制器锁且禁用中断的情况下调用。此函数将取消映射 **req** 并调用其 ->complete() 回调以通知上层它已完成。
参数
struct dwc3 *dwc
指向控制器上下文的指针
unsigned int cmd
要发送的命令
u32 param
命令参数
描述
调用者应负责锁定。向 dwc 发送 cmd 命令以及给定的 param 参数,并等待其完成。
-
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, struct dwc3_gadget_ep_cmd_params *params)¶
发送一个端点命令
参数
struct dwc3_ep *dep
要发送命令的端点
unsigned int cmd
要发送的命令
struct dwc3_gadget_ep_cmd_params *params
命令的参数
描述
调用者应负责锁定。此函数将向 dep 发送 cmd 命令以及给定的 params 参数,并等待其完成。
根据编程指南,如果链路状态为 L1/L2/U3,则发送启动传输命令可能无法完成。编程指南建议在发送命令之前,通过执行远程唤醒将链路状态恢复为 ON/U0。但是,当用户/功能未通过唤醒操作发送唤醒请求时,不要启动远程唤醒。当允许时发送命令。
对于 L2 或 U3 链路状态,设备处于 USB 挂起状态。发送启动传输命令时应注意确保在 USB 恢复后执行。
注意
对于 L1 链路状态,发送命令需要清除 GUSB2PHYCFG.SUSPENDUSB2,这将打开完成给定命令所需的信号(通常在 50us 内)。这应在驱动程序设置的命令超时时间内发生。无需其他步骤。
参数
struct dwc3 *dwc
指向 DWC3 上下文的指针
unsigned int resource_index
DEPSTARTCFG.XferRscIdx 值(必须为 0 或 2)
描述
设置 resource_index=0 以重置所有端点的资源分配。在电源开启/软重置初始化期间执行此操作。
设置 resource_index=2 以仅重置非控制端点的资源。在接收到 SET_CONFIGURATION 请求或休眠恢复时执行此操作。
参数
struct dwc3 *dwc
指向 DWC3 上下文的指针
int mult
计算 fifo_size 时要使用的乘数
描述
根据以下公式计算大小值
DWC3 修订版 280A 及更早版本:fifo_size = mult * (max_packet / mdwidth) + 1;
DWC3 修订版 290A 及更高版本:fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
最大数据包大小设置为 1024,因为 txfifo 要求主要适用于超高速 USB 用例。但是,为其他场景(即高速 USB)高估 fifo 分配是安全的。
参数
struct dwc3 *dwc
指向 DWC3 上下文的指针
参数
struct dwc3 *dwc
指向 DWC3 上下文的指针
描述
遍历所有端点寄存器并清除之前的 txfifo 分配。
参数
struct dwc3_ep *dep
要初始化的端点
unsigned int action
INIT、MODIFY 或 RESTORE 之一
描述
调用者应负责锁定。执行所有必要的命令以初始化硬件端点,以便设备驱动程序可以使用它。
参数
struct dwc3_ep *dep
要禁用的端点
描述
此函数撤消 __dwc3_gadget_ep_enable 所做的工作,并删除当前正在由硬件处理的请求以及尚未调度的请求。
调用者应负责锁定。
参数
struct dwc3_ep *dep
具有 TRB 环的端点
u8 index
环中当前 TRB 的索引
描述
返回索引所指向的 TRB 之前的 TRB。如果索引为 0,我们将向后回绕,跳过链接 TRB,并返回紧接其之前的 TRB。
-
void dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_request *req, unsigned int trb_length, unsigned int chain, unsigned int node, bool use_bounce_buffer, bool must_interrupt)¶
从一个请求设置一个 TRB
参数
struct dwc3_ep *dep
为其准备此请求的端点
struct dwc3_request *req
dwc3_request 指针
unsigned int trb_length
TRB 的缓冲区大小
unsigned int chain
此 TRB 是否应链接到下一个 TRB?
unsigned int node
仅适用于等时端点。第一个 TRB 需要不同的类型。
bool use_bounce_buffer
设置为使用反弹缓冲区
bool must_interrupt
设置为在 TRB 完成时中断
-
int dwc3_prepare_last_sg(struct dwc3_ep *dep, struct dwc3_request *req, unsigned int entry_length, unsigned int node)¶
为最后一个 SG 条目准备 TRB
参数
struct dwc3_ep *dep
请求所属的端点
struct dwc3_request *req
要准备的请求
unsigned int entry_length
最后一个 SG 条目的大小
unsigned int node
指示这是否不是第一个条目(仅用于等时传输)
描述
返回已准备好的 TRB 的数量。
参数
struct dwc3_ep *dep
等时端点
bool force
在命令中设置 forcerm 位
bool interrupt
结束传输命令后的命令完成中断
描述
设置 force 时,将设置 ForceRM 位。在这种情况下,控制器不会在命令完成时更新 TRB 进度。它也不会清除 TRB 中的 HWO 位。在这种情况下,该命令也不会立即完成。
参数
struct dwc3_ep *dep
等时端点
描述
此函数测试从 XferNotReady 事件报告的 16 位微帧号的 BIT[15:14] 的正确组合,以获取启动等时传输的未来帧号。
在 DWC_usb31 版本 1.70a-ea06 及更早版本中,对于高速和全速等时 IN,XferNotReady 事件报告的 16 位微帧号的 BIT[15:14] 无效。驱动程序使用此数字来调度等时传输并将其传递给 START TRANSFER 命令。由于此数字无效,该命令可能会失败。如果 BIT[15:14] 与内部 16 位微帧匹配,则 START TRANSFER 命令将通过,并且传输将在计划的时间开始;如果相差 1,则命令仍将通过,但传输将在 2 秒后开始。对于所有其他情况,START TRANSFER 命令将因总线过期而失败。
为了解决此问题,我们可以通过发送具有不同 BIT[15:14] 值的 START TRANSFER 命令来测试 BIT[15:14] 的正确组合:‘b00、‘b01、‘b10 和 ‘b11。每个组合相隔 2^14 个 uframe(或 2 秒)。未来 4 秒会导致总线过期状态。因此,在 BIT[15:14] 的 4 个可能组合中,将会有 2 个成功的 START COMMAND 状态和 2 个失败的 START COMMAND 状态。2 个成功的命令状态之一将导致延迟 2 秒开始。较小的 BIT[15:14] 值是正确的组合。
由于只有 4 个结果且结果已排序,我们可以简单地测试 2 个带有 BIT[15:14] 组合 ‘b00 和 ‘b01 的 START TRANSFER 命令,以推断较小的成功组合。
设 test0 = 组合 ‘b00 的测试状态,test1 = BIT[15:14] 的 ‘b01 的测试状态。正确的组合如下:
如果 test0 失败且 test1 通过,则 BIT[15:14] 为 ‘b01;如果 test0 失败且 test1 失败,则 BIT[15:14] 为 ‘b10;如果 test0 通过且 test1 失败,则 BIT[15:14] 为 ‘b11;如果 test0 通过且 test1 通过,则 BIT[15:14] 为 ‘b00
Synopsys STAR 9001202023:等时 IN 端点的微帧号错误。
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
描述
以下内容看起来很复杂,但实际上非常简单。为了计算我们可以在 OUT 传输中一次突发的包的数量,我们将使用 RxFIFO 大小。
要计算 RxFIFO 大小,我们需要两个数字:MDWIDTH = 内部内存总线的以位为单位的大小,RAM2_DEPTH = 内部 RAM2(RxFIFO 所在的位置)的 MDWIDTH 深度
有了这两个数字,公式很简单
RxFIFO 大小 = (RAM2_DEPTH * MDWIDTH / 8) - 24 - 16;
24 字节用于 3 个 SETUP 数据包,16 字节是时钟域交叉容差
给定 RxFIFO 大小,NUMP = RxFIFOSize / 1024;
-
int dwc3_gadget_check_config(struct usb_gadget *g)¶
确保 dwc3 可以支持 USB 配置
参数
struct usb_gadget *g
指向 USB gadget 的指针
描述
用于记录 USB 复合设备中使用的最大端点数量。(跨所有配置)这将在调整单个端点的内部内存大小时用于计算 TXFIFO 大小。它将有助于确保调整大小的逻辑为至少一个最大数据包保留足够的空间。
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
描述
成功时返回 0,否则返回负 errno。
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
参数
struct dwc3 *dwc
指向我们的上下文结构的指针
-
void dwc3_ref_clk_period(struct dwc3 *dwc)¶
参考时钟周期配置 默认参考时钟周期取决于硬件配置。对于参考时钟与默认值不同的系统,这将在 DWC3_GUCTL 寄存器中设置时钟周期。
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
-
void dwc3_free_one_event_buffer(struct dwc3 *dwc, struct dwc3_event_buffer *evt)¶
释放一个事件缓冲区
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
struct dwc3_event_buffer *evt
指向要释放的事件缓冲区的指针
-
struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned int length)¶
分配一个事件缓冲区结构
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
unsigned int length
事件缓冲区的大小
描述
成功时返回指向已分配的事件缓冲区结构的指针,否则返回 ERR_PTR(errno)。
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
unsigned int length
事件缓冲区的大小
描述
成功时返回 0,否则返回负的错误码 errno。在错误情况下,dwc 可能包含一些已分配的缓冲区,但并非所有请求的缓冲区都已分配。
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
描述
成功时返回 0,否则返回负 errno。
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
描述
成功时返回 0。USB PHY 接口已配置但未初始化。PHY 接口和 PHY 将在 dwc3_core_init 中与核心一起初始化。
参数
struct dwc3 *dwc
指向我们的控制器上下文结构的指针
描述
成功时返回 0,否则返回负 errno。