USB总线-Linux内核USB3.0主机控制器驱动初始化流程分析(十三)

news/2024/9/19 3:10:19/文章来源:https://www.cnblogs.com/linhaostudy/p/18414684

1.概述

RK3588有2个USB3.0 DRD控制器,2个USB2.0 Host控制器。USB3.0 DRD控制器既可以做Host,也可以做Device,向下兼容USB2.0和USB1.0。USB3.0 DRD控制器的内部结构如下图所示;总线接口为AXI或AHB;USB3.0和USB2.0及USB1.0硬件上独立;USB3.0控制器数字逻辑部分对应SS MAC,PHY接口为PIPE,PHY为USBDP PHY,和DP使用同一个PHY;USB2.0和USB1.0控制器数字逻辑部分对应HS/FS/LS MAC,PHY接口为UTMI+,PHY为USB2.0 PHY。

USB3.0 DRD控制器作为Host的主要特性如下:

  1. 兼容USB3.0 Revision 1.0规范,兼容USB2.0规范,兼容xHCI Revision 1.1规范。
  2. 支持Control/Bulk (including stream)/Interrupt/Isochronous传输。
  3. USB3.0同时进行输入和输出传输,最大可达到8Gbps带宽。
  4. 具有描述符缓存和数据预取功能,可以改善高延迟系统的性能。
  5. USB2.0支持LPM低功耗协议,USB3.0支持U0、U1、U2、U3四种低功耗状态。
  6. 端点具有动态FIFO memory分配能力。
  7. LS模式具有Keep-Alive特性,HS/FS模式具有(micro-)SOFs特性。
  8. 支持AXI Master和AHB Slave接口。
  9. 最大支持64个设备。
  10. 支持1个中断。
  11. 支持USB2.0 port和USB3.0 port。
  12. 支持标准的和开源的xHCI和USB类驱动。
  13. USB2.0 PHY支持充电检测。
  14. 支持USB Type-C和DP Alt模式。

2.设备树

usbdrd3_1设备树定义如下,默认模式为Host。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
/ {......usbdrd3_1: usbdrd3_1 {compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3";clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>,<&cru ACLK_USB3OTG1>;clock-names = "ref", "suspend", "bus";#address-cells = <2>;#size-cells = <2>;ranges;status = "disabled";usbdrd_dwc3_1: usb@fc400000 {compatible = "snps,dwc3";reg = <0x0 0xfc400000 0x0 0x400000>;interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;power-domains = <&power RK3588_PD_USB>;resets = <&cru SRST_A_USB3OTG1>;reset-names = "usb3-otg";/* USB模式,host:主机,otg:otg模式,peripheral:设备 */dr_mode = "host";/*   USB2.0和USB1.0 PHY      USB3.0 PHY */phys = <&u2phy1_otg>, <&usbdp_phy1_u3>;phy-names = "usb2-phy", "usb3-phy";phy_type = "utmi_wide"; /* USB2.0 PHY接口 *//* When set clears the enblslpm in GUSB2PHYCFG,* disabling the suspend signal to the PHY*/snps,dis_enblslpm_quirk;/* When set, clear the u2_freeclk_exists in GUSB2PHYCFG,* specify that USB2 PHY doesn't provide a free-running* PHY clock.*/snps,dis-u2-freeclk-exists-quirk;/* When set core will change PHY power from P0 to* P1/P2/P3 without delay.*/snps,dis-del-phy-power-chg-quirk;/* When set, disable u2mac linestate check during HS transmit */snps,dis-tx-ipgap-linecheck-quirk;status = "disabled";};};
};[arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi]
&usbdrd3_1 {status = "okay";
};

3.DWC3驱动初始化

在xhci驱动初始化之前,需要dwc3驱动做一些底层的初始化,主要是非XHCI协议的硬件初始化,如模式、时钟、PHY等。dwc3驱动的主要工作如下:

  1. 首先初始化的是外围的rockchip驱动,内部的dwc3驱动由rockchip驱动进行匹配。

  2. 接着进入dwc3的驱动初始化流程,工作流程如下:解复位控制器。

  3. 获取控制器硬件配置的模式,并和软件配置的模式进行比较,起到校验作用

  4. dwc3核心初始化,包括配置PHY接口、初始化PHY、给PHY上电、调整帧长度、使能Auto retry Feature等。

  5. 根据配置的模式,进入对应的模式。若是Host,则需要将USB2.0 PHY和USB3.0 PHY设置为PHY_MODE_USB_HOST,然后注册xhci的platform_device

4.xHCI驱动初始化

dwc3驱动将设备树中的USB Host设备节点转换成platform_device,并将其name设置为"xhci-hcd",然后调用platform_device_add注册到系统中。USB Host驱动通过platform_driver实现,通过xhci_plat_init和xhci_plat_exit注册和注销。当USB Host设备或USB Host驱动注册的时候,都会调用platform_match去匹配对方,若匹配成功,则会调用USB Host驱动中的probe函数,即usb_xhci_driver中的xhci_plat_probe函数。

[drivers/usb/host/xhci-plat.c]
static struct platform_driver usb_xhci_driver = {.probe	= xhci_plat_probe,.remove	= xhci_plat_remove,.shutdown = usb_hcd_platform_shutdown,.driver	= {.name = "xhci-hcd",.pm = &xhci_plat_pm_ops,.of_match_table = of_match_ptr(usb_xhci_of_match),.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),},
};
MODULE_ALIAS("platform:xhci-hcd");static int __init xhci_plat_init(void)
{xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides);return platform_driver_register(&usb_xhci_driver);
}
module_init(xhci_plat_init);static void __exit xhci_plat_exit(void)
{platform_driver_unregister(&usb_xhci_driver);
}
module_exit(xhci_plat_exit);

xhci_plat_probe函数中会注册xHCI控制器的硬件操作函数集合,即xhci_hc_driver数据结构,如下所示。

[drivers/usb/host/xhci.c]
static const struct hc_driver xhci_hc_driver = {.description   =  "xhci-hcd",.product_desc  =  "xHCI Host Controller",.hcd_priv_size =  sizeof(struct xhci_hcd),/* generic hardware linkage */.irq      = xhci_irq,.flags    = HCD_MEMORY | HCD_DMA | HCD_USB3 | HCD_SHARED | HCD_BH,/* basic lifecycle operations */.reset    = NULL,     /* xhci_plat_setup */.start    = xhci_run, /* xhci_plat_start */.stop     = xhci_stop,.shutdown = xhci_shutdown,/* managing i/o requests and associated device resources */.map_urb_for_dma    =     xhci_map_urb_for_dma,.urb_enqueue        =     xhci_urb_enqueue,.urb_dequeue        =     xhci_urb_dequeue,.alloc_dev          =     xhci_alloc_dev,.free_dev           =     xhci_free_dev,.alloc_streams      =     xhci_alloc_streams,.free_streams       =     xhci_free_streams,.add_endpoint       =     xhci_add_endpoint,.drop_endpoint      =     xhci_drop_endpoint,.endpoint_disable   =     xhci_endpoint_disable,.endpoint_reset     =     xhci_endpoint_reset,.check_bandwidth    =     xhci_check_bandwidth,.reset_bandwidth    =     xhci_reset_bandwidth,.address_device     =     xhci_address_device,.enable_device      =     xhci_enable_device,.update_hub_device  =     xhci_update_hub_device,.reset_device       =     xhci_discover_or_reset_device,/* scheduling support */.get_frame_number         =   xhci_get_frame,/* root hub support */.hub_control              =   xhci_hub_control,.hub_status_data          =   xhci_hub_status_data,.bus_suspend              =   xhci_bus_suspend,.bus_resume               =   xhci_bus_resume,.get_resuming_ports       =   xhci_get_resuming_ports,/* call back when device connected and addressed */.update_device            =   xhci_update_device,.set_usb2_hw_lpm          =   xhci_set_usb2_hardware_lpm,.enable_usb3_lpm_timeout  =   xhci_enable_usb3_lpm_timeout,.disable_usb3_lpm_timeout =   xhci_disable_usb3_lpm_timeout,.find_raw_port_number     =   xhci_find_raw_port_number,.clear_tt_buffer_complete =   xhci_clear_tt_buffer_complete,
};

USB主机驱动的初始化过程如下图所示,具体的流程如下:

  1. USB主机的设备和驱动通过platform_match匹配,匹配成功后,驱动的xhci_plat_probe函数被调用。
  2. 调用__usb_create_hcd函数 创建USB主机数据结构,即main_hcd(primary_hcd)和shared_hcd,前者为USB2.0,后者为USB3.0;创建USB主机数据结构的时候会初始化一个非常重要的定时器rh_timer,到期会调用rh_timer_func函数,该定时器的作用是轮询Hub的状态,检测USB设备连接、断开等情况。
  3. 调用usb_add_hcd注册USB2.0和USB3.0主机控制器,USB主机驱动的核心初始化工作在注册控制器时完成。
    1. 注册USB总线。
    2. 分配root hub的数据结构usb_device(root hub不是一个真实的USB设备,无需调用xhci_alloc_dev分配主机控制器资源);设置总线类型、设备类型和属性,总线类型usb_bus_type中的usb_device_match函数用于匹配USB设备和USB设备驱动,具体的匹配过程后面分析;使能使能root hub端点0,即将端点0的数据结构usb_host_endpoint放到usb_device输入输出端点的数组中,便于后续和USB设备通信。
    3. 调用xhci_plat_setup通过读取控制器的hcs_params寄存器获取寄存器地址、能力等信息,然后复位复位控制器,最后初始化xHCI需要的数据结构。
    4. 初始化root hub的tasklets,设置回调函数为usb_giveback_urb_bh,当root hub的port状态变化时,会调用usb_giveback_urb_bh处理。
    5. 注册USB2.0控制器的中断处理函数usb_hcd_irq(中断只需要注册一次,2.0和3.0公用),usb_hcd_irq内部会调用xhci_irq,该中断用于处理控制器传输数据、事件。
    6. 调用xhci_run使能xHCI控制器。
    7. 调用register_root_hub注册root hub。root hub虽然不是真实的USB设备,但也需要获取描述符,走枚举的流程。
      1. 获取设备描述符。使用控制传输,调用usb_control_msg
      2. 初始化root hub。主要是获取配置描述符(获取配置描述符时,会一并获取该配置下的接口描述符、端点描述符等)。
      3. 枚举成功后,打印root hub的设备信息(需要开启对应的选项,否则不打印)。
      4. 注册USB设备。内部会调用usb_device_match匹配USB设备驱动,对于hub,则会匹配到hub_driver,调用hub_probe函数。
    8. 当设置uses_new_pollingHCD_POLL_RH(hcd)标志时,内核会调用usb_hcd_poll_rh_status函数轮询hub状态,以此探测设备的连接、断开等状态变化。详细的轮询过程在下一节分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/797207.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

作业2:个人项目

个人项目-论文查重 一、课程信息这个作业属于哪个课程 班级的链接这个作业要求在哪里 作业要求的链接这个作业的目标 熟悉软件开发以及工具的使用、算法的设计、资料的搜集GitHub地址 二、开发环境开发工具 IDEA 2021.3.2项目构建工具 maven单元测试 Junit分词依赖包 hanlp三、…

Linkedin-SRE-中文教程-二-

Linkedin SRE 中文教程(二)原文:School of SRE 协议:CC BY-NC-SA 4.0一些 Python 概念原文:https://linkedin.github.io/school-of-sre/level101/python_web/python-concepts/虽然期望您了解 python 及其基本语法,但是让我们讨论一些基本概念,这将帮助您更好地理解 pyth…

分析负数取模与取余的规则

目录负数"取模"基本概念修正定义取整规则决定商的值取模和取余不一样. 负数"取模"基本概念如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r,且0 <= r < d。其中,q 被称为商,r 被称为余数。 //对应代码 int mai…

Openwrt挂载大容量NTFS磁盘,解决默认挂载不能写入问题,实现samba共享

1. 目的 在OpenWRT上挂载上大容量磁盘(NTFS文件系统),支持读写操作。解决默认挂载仅能读取,不能写入问题。 配置Samba36,实现局域网文件夹共享。 2. 环境架构 ARMv7 Processor rev 1 (v7l)固件版本 OpenWrt 19.07.7内核版本 3.10.33安装插件smbd -v # 检查是否安装了smb …

使用MySQL Workbench进行数据库备份

1、打开MySQL Workbench2、进行数据库连接配置 如果之前连过,会有历史记录,直接点击需要备份的连接即可3、进入主界面后,选择左侧的Administration选项卡,然后点击Data Export;或者点击工具栏的Server——Data Export4、选择要备份的数据库,默认选择所有的表,在objects …

Mininet安装记录

安装环境: Ubuntu虚拟机版本:14.04 Mininet版本:2.3.1b1 1、更改软件镜像源 在设置中进行如下操作:选择国内的镜像站点,如阿里云。 点击关闭后,在弹出的窗口中点击重新载入,等待缓存更新完成。2、下载git 在终端中执行如下命令: sudo apt-get install git没有报错的话,…

Redis运维之监控指标,性能监控,监控方式,响应慢分析

目录1 Redis监控1.1 Redis监控指标1.1.1 性能指标: Performance1.1.2 内存指标: Memory1.1.3 基本活动指标:Basic activity1.1.4 持久性指标: Persistence1.1.5 错误指标:Error1.2 监控方式1.2.1 info1.2.2 性能监控1.2.3 内存监控1.2.4 基本活动指标1.2.5 持久性指标1.2.6 错…

代码随想录算法 - 二叉树4

题目1 654. 最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。返回 nums 构建的 …

图的连通性小记

前言 DFS 树 无向图 DFS 树 定义:DFS树 是在图或树结构上进行深度优先搜索时形成的树。在 DFS 过程中,从一个顶点开始,尽可能深地搜索图的分支,直到达到一个没有未访问邻居的顶点,然后回溯到上一个顶点继续搜索。 从点 \(r\) 开始搜索,每次进入一个点 \(i\) 对应的边 \((…

前端项目通过 Nginx 发布至 Linux,并通过 rewrite 配置访问后端接口

本文通过将 arco 框架的前端项目,部署至 CentOS 7,并访问同服务器的 WebAPI 接口,来简单演示一下,如何将前端项目发布至 Linux 系统。〇、前言 本文通过将 arco 框架的前端项目,部署至 CentOS 7,并访问同服务器的 WebAPI 接口,来简单演示一下,如何将前端项目发布至 Lin…

练习第四周8.31

作业: 1、安装burp并实现抓取HTTP站点的数据包(HTTPS站点暂时不要求)2、练习Tomcat PUT方法任意写文件漏洞(CVE-2017-12615),提供蚁剑连接成功截图3、练习S2-048 远程代码执行漏洞(CVE-2017-9791),提供命令执行截图 4、练习JBoss 5.x/6.x 反序列化漏洞(CVE-2017-1214…