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 SuperSpeed 标准的控制器,可以配置为以下 4 种方式之一
仅限外设配置
仅限主机配置
双重角色配置
集线器配置
Linux 目前支持此控制器的多个版本。 在所有可能性中,您的 SoC 中的版本已被支持。 在撰写本文时,已知的经过测试的版本范围从 2.02a 到 3.10a。 根据经验,高于 2.02a 的任何版本都应能可靠地工作。
目前,我们有很多已知的此驱动程序的用户。 按字母顺序排列
Cavium
英特尔公司
高通
瑞芯微
ST
三星
德州仪器
赛灵思
功能概述¶
有关 DWC3 版本的支持的功能的详细信息,请咨询您的 IP 团队和/或 _Synopsys DesignWare Core SuperSpeed USB 3.0 控制器数据手册_。 以下是撰写本文时驱动程序支持的功能列表
这些功能已通过许多树内小工具驱动程序进行了测试。 我们已经验证了 ConfigFS [4] 和旧版小工具驱动程序。
驱动程序设计¶
DWC3 驱动程序位于 _drivers/usb/dwc3/_ 目录中。 与此驱动程序相关的所有文件都在这一个目录中。 这使得新手可以轻松阅读代码并了解其行为方式。
由于 DWC3 的配置灵活性,驱动程序在某些地方有点复杂,但应该很容易理解。
驱动程序的最大部分是指小工具 API。
已知限制¶
与其他任何硬件一样,DWC3 也有其自身的局限性。 为了避免不断地询问此类问题,我们决定在此处记录它们,并拥有一个可以指向用户的单一位置。
OUT 传输大小要求¶
根据 Synopsys 数据手册,所有 OUT 传输 TRB [1] 必须将其 _size_ 字段设置为整数,该整数可被端点的 _wMaxPacketSize_ 整除。 这意味着,_例如_,为了接收大容量存储 _CBW_ [5],req->length 必须设置为可被 _wMaxPacketSize_ 整除的值(在 SuperSpeed 上为 1024,在 HighSpeed 上为 512,等等),或者 DWC3 驱动程序必须添加一个链接的 TRB,指向剩余长度的抛弃型缓冲区。 没有这个,OUT 传输将不会启动。
请注意,截至撰写本文时,这不会成为问题,因为 DWC3 完全能够为剩余长度附加一个链接的 TRB,并从小工具驱动程序中完全隐藏此细节。 仍然值得一提,因为这似乎是关于 DWC3 和 _无法正常传输_ 的查询的最大来源。
TRB 环大小限制¶
我们目前对每个端点有 256 个 TRB [1] 的硬性限制,最后一个 TRB 是一个链接 TRB [2],指回第一个。 此限制是任意的,但它的好处是总计正好 4096 字节,或 1 页。
DWC3 驱动程序将尽最大努力处理超过 255 个请求,并且在大多数情况下,它应该正常工作。 但是,这并不是经常进行的。 如果您遇到任何问题,请参阅下面的报告错误部分。
报告错误¶
每当您遇到 DWC3 问题时,首先也是最重要的,您应该确保
您正在运行来自 Linus’ tree 的最新标签
您可以在没有任何对 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。 如果您想格外确保我会帮助您,请按以下格式编写您的主题行
[BUG REPORT] usb: dwc3: Bug while doing 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 Sniffer 有时会有所帮助,但并非完全必需,无需查看电线即可理解很多内容。
如果您需要任何帮助,请随时通过电子邮件发送给 我,并在抄送中包含 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 数据手册,您可以解码其中的信息。
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与此事件缓冲区相关的标志
dmadma_addr_t
dwc指向 DWC 控制器的指针
-
struct dwc3_ep¶
设备侧端点表示
定义:
struct dwc3_ep {
struct usb_ep endpoint;
struct delayed_work nostream_work;
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_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;
};
成员
endpointusb 端点
nostream_work用于处理批量 NoStream 的工作
cancelled_list此端点已取消的请求的列表
pending_list此端点的挂起请求的列表
started_list此端点上已启动的请求的列表
regs指向第一个端点寄存器的指针
trb_pool事务缓冲区数组
trb_pool_dmatrb_pool 的 DMA 地址
dwc指向 DWC 控制器的指针
saved_state休眠期间保存的 ep 状态
flags端点标志(楔入、停止...)
trb_enqueueTRB 数组中的入队“指针”
trb_dequeueTRB 数组中的出队“指针”
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_statuscombo_num = ‘b00 测试 START TRANSFER 命令的状态
-
struct dwc3_trb¶
传输请求块(硬件格式)
定义:
struct dwc3_trb {
u32 bpl;
u32 bph;
u32 size;
u32 ctrl;
};
成员
bplDW0-3
bphDW4-7
sizeDW8-B
ctrlDWC-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;
};
成员
hwparams0GHWPARAMS0
hwparams1GHWPARAMS1
hwparams2GHWPARAMS2
hwparams3GHWPARAMS3
hwparams4GHWPARAMS4
hwparams5GHWPARAMS5
hwparams6GHWPARAMS6
hwparams7GHWPARAMS7
hwparams8GHWPARAMS8
hwparams9GHWPARAMS9
-
struct dwc3_request¶
传输请求的表示
定义:
struct dwc3_request {
struct usb_request request;
struct list_head list;
struct dwc3_ep *dep;
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_requestlist用于请求排队的 list_head
dep拥有此请求的
struct dwc3_epstart_sg指向接下来应排队的 sg 的指针
num_pending_sgs待处理 sg 的计数器
remaining剩余数据量
status内部 dwc3 请求状态跟踪
epnum此请求引用的端点号
trb指向
struct dwc3_trb的指针trb_dmatrb 的 DMA 地址
num_trbs此请求使用的 TRB 数量
directionIN 或 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;
u16 num_hc_interrupters;
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;
u32 wakeup_pending_funcs;
};
成员
drd_work用于角色切换的工作队列
ep0_trb用于 ctrl_req 的 trb
bouncebounce 缓冲区的地址
setup_buf在处理 STD USB 请求时使用
ep0_trb_addrep0_trb 的 dma 地址
bounce_addrbounce 的 dma 地址
ep0_usb_req处理 STD USB 请求时使用的虚拟请求
ep0_in_setup一个控制传输已完成并进入设置阶段
lock用于同步
mutex用于模式切换
dev指向我们的
struct device的指针sysdev指向支持 DMA 的设备的指针
xhci指向我们的 xHCI 子设备的指针
xhci_resources我们的 xhci 子设备的结构资源
ev_bufeps端点数组
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_portsUSB2 端口的数量
num_usb3_portsUSB3 端口的数量
phys_ready指示 PHY 已准备就绪的标志
ulpi指向 ulpi 接口的指针
ulpi_ready指示 ULPI 已初始化的标志
regs我们寄存器的基本地址
regs_size地址空间大小
dr_mode请求的操作模式
current_dr_role处于双角色模式时的当前操作角色
desired_dr_role处于双角色模式时所需的操作角色
edevextcon 句柄
edev_nbextcon 通知器
hsphy_modeUTMI phy 模式,以下之一: - USBPHY_INTERFACE_MODE_UTMI - USBPHY_INTERFACE_MODE_UTMIW
role_swusb_role_switch 句柄
role_switch_default_mode当 usb 角色为 USB_ROLE_NONE 时,控制器的默认操作模式。
usb_psy指向电源接口的指针。
fladj帧长度调整
ref_clk_per参考时钟周期配置
irq_gadget外围控制器的 IRQ 号
otg_irqOTG IRQ 的 IRQ 号
current_otg_role使用 OTG 块时的当前操作角色
desired_otg_role使用 OTG 块时所需的操作角色
otg_restart_hostOTG 控制器需要重新启动主机的标志
u1u2仅用于修订版 <1.83a 以进行解决方法
maximum_speed请求的最大速度(主要用于测试目的)
gadget_max_speed请求的最大 gadget 速度
max_ssp_rateSuperSpeed Plus 最大信令速率和通道数
gadget_ssp_rateGadget 驱动程序支持的最大 SuperSpeed Plus 信令速率和通道数。
ip控制器的 ID
revisionIP 控制器的版本
version_typeVERSIONTYPE 寄存器内容,修订版的子版本
ep0_next_event保存下一个预期事件
ep0state端点零的状态
link_state链路状态
u2sel来自 Set SEL 请求的参数。
u2pel来自 Set SEL 请求的参数。
u1sel来自 Set SEL 请求的参数。
u1pel来自 Set SEL 请求的参数。
speed设备速度(super、high、full、low)
num_eps端点数
hwparamshwparams 寄存器的副本
regset指向 regdump 文件的 debugfs 指针
dbg_lsp_select当前调试 lsp 多路复用器寄存器选择
test_mode当我们进入 USB 测试模式时为 true
test_mode_nr测试功能选择器
lpm_nyet_thresholdLPM NYET 响应阈值
hird_thresholdHIRD 阈值
rx_thr_num_pktUSB 接收数据包计数
rx_max_burst最大 USB 接收突发大小
tx_thr_num_pktUSB 传输数据包计数
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_numtxfifo 大小调整期间分配的最大 fifo 数量
clear_stall_protocol需要延迟状态阶段的端点号
num_hc_interrupters主机控制器中断器的数量
hsphy_interface“utmi” 或 “ulpi”
connected当我们连接到主机时为 true,否则为 false
softconnect调用 gadget connect 时为 true,运行 disconnect 时为 false
delayed_status当 gadget 驱动程序请求延迟状态时为 true
ep0_bounced当我们使用 bounce 缓冲区时为 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如果启用 P3 OK for U2/SS Inactive 怪癖,则设置
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如果我们需要禁用 park 模式下的所有 SuperSpeed 实例,则设置。
parkmode_disable_hs_quirk如果我们需要禁用 park 模式下的所有 HishSpeed 实例,则设置。
gfladj_refclk_lpm_sel如果我们需要启用基于 ref_clk 运行的 SOF/ITP 计数器,则设置
tx_de_emphasis_quirk如果启用 Tx 去加重怪癖,则设置
tx_de_emphasisTx 去加重值 0 - -6dB 去加重 1 - -3.5dB 去加重 2 - 无去加重 3 - 保留
dis_metastability_quirk设置为禁用亚稳态怪癖。
dis_split_quirk设置为禁用拆分边界。
async_callbacks如果设置,指示将使用异步回调。
sys_wakeup如果设备可以执行系统唤醒,则设置。
wakeup_configured如果设备配置为远程唤醒,则设置。
suspended设置为跟踪由于 U3/L2 导致的挂起事件。
susphy_statePM 挂起之前 DWC3_GUSB2PHYCFG_SUSPHY + DWC3_GUSB3PIPECTL_SUSPHY 的状态。
imod_interval以 250ns 增量设置中断调节间隔,或设置为 0 以禁用。
max_cfg_eps所有 USB 配置中使用的当前最大 IN 端点数。
last_fifo_depth用于确定下一个 fifo ram 起始地址的最后一个 fifo 深度。
num_ep_resized携带当前已调整其 tx fifo 大小的端点数。
debug_root此设备的根 debugfs 目录,用于放置其文件。
gsbuscfg0_reqinfo存储从 glue 驱动程序传递的 GSBUSCFG0.DATRDREQINFO、DESRDREQINFO、DATWRREQINFO 和 DESWRREQINFO 值。
wakeup_pending_funcs指示是否任何接口已请求以位图格式进行函数唤醒,其中位位置表示 interface_id。
-
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->Underrun, OUT->Overrun) 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 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保留,未使用
event_info有关此事件的信息
reserved31_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保留,未使用。
-
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 reasondwc3 请求的取消原因
描述
调用者应注意锁定。此函数会将 **req** 从其当前列表移动到端点的 cancelled_list。
参数
struct dwc3_ep *depdwc3 端点
描述
调用者应注意锁定。 返回给定端点的传输资源索引。
参数
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命令参数
描述
调用者应注意锁定。 将带有给定 **param** 的 **cmd** 发送到 **dwc** 并等待其完成。
-
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命令的参数
描述
调用者应处理锁定。 此函数将带有给定 **params** 的 **cmd** 发送到 **dep** 并等待其完成。
根据编程指南,如果链路状态为 L1/L2/U3,则发送“启动传输”命令可能无法完成。 编程指南建议通过在发送命令之前执行远程唤醒来将链路状态恢复为 ON/U0。 但是,当用户/函数未通过唤醒操作发送唤醒请求时,请勿启动远程唤醒。 在允许时发送命令。
对于 L2 或 U3 链路状态,设备处于 USB 挂起状态。 发送“启动传输”命令时,应注意确保在 USB 恢复后完成该操作。
注释
对于 L1 链路状态,发出命令需要清除 GUSB2PHYCFG.SUSPENDUSB2,这会打开完成给定命令所需的信号(通常在 50us 内)。 这应在驱动程序设置的命令超时内发生。 无需其他步骤。
参数
struct dwc3 *dwc指向 DWC3 上下文的指针
unsigned int resource_indexDEPSTARTCFG.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 actionINIT、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 *reqdwc3_request 指针
unsigned int trb_lengthTRB 的缓冲区大小
unsigned int chain此 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指示这是否不是第一个条目(仅适用于 isoc)
描述
返回准备好的 TRB 的数量。
参数
struct dwc3_ep *depisoc 端点
bool force在命令中设置 forcerm 位
bool interrupt在结束传输命令后,命令完成中断
描述
设置 force 时,将设置 ForceRM 位。在这种情况下,控制器不会在命令完成时更新 TRB 进度。它也不会清除 TRB 中的 HWO 位。在这种情况下,该命令也不会立即完成。
参数
struct dwc3_ep *depisoc 端点
描述
此函数测试来自 XferNotReady 事件报告的 16 位微帧号的 BIT[15:14] 的正确组合,以用于启动 isoc 传输的未来帧号。
在 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 个成功的和 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 的深度(以 MDWIDTH 为单位)(RxFIFO 位于此处)
有了这两个数字,公式很简单
RxFIFO Size = (RAM2_DEPTH * MDWIDTH / 8) - 24 - 16;
24 字节用于 3x SETUP 数据包,16 字节是时钟域交叉容差
给定 RxFIFO Size,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。