linux 内核 usb驱动分析

布满荆棘的人生 2024-04-19 15:21 137阅读 0赞

本文基于ti的am5728平台,4.14.79版本内核,DesignWare USB3.0方案,xhci主机控制器。简单分析 USB 主机控制器驱动 根 Hub 的注册过程,以及 USB设备的枚举过程,并不涉及USB协议,单纯分析驱动框架流程。无论是hub还是普通的usb设备,它们注册到 usb_bus_type 都会经历两次 Match ,因为第一次注册进来时,是将整个设备作为一个 device 注册,然后在通用的 devices 驱动程序 usb_generic_driver 的 generic_probe 函数中,将该设备的所有接口进行设置并将这些接口注册到 usb_bus_type 。如果是Hub设备的接口,则会调用 hub_probe,如果是其他设备则调用 xx_probe 函数。如果是 Hub 的话,usb主机会监测hub端口变化,如果有变化会分配一个usb_devices 注册到 usb_bus_type 重复前边的步骤。

omap dwc3设备树节点

  1. omap_dwc3_1: omap_dwc3_1@48880000 {
  2. compatible = "ti,dwc3";
  3. ti,hwmods = "usb_otg_ss1";
  4. reg = <0x48880000 0x10000>;
  5. interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
  6. #address-cells = <1>;
  7. #size-cells = <1>;
  8. utmi-mode = <2>;
  9. ranges;
  10. usb1: usb@48890000 {
  11. compatible = "snps,dwc3";
  12. reg = <0x48890000 0x17000>;
  13. interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
  14. <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
  15. <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
  16. interrupt-names = "peripheral",
  17. "host",
  18. "otg";
  19. phys = <&usb2_phy1>, <&usb3_phy1>;
  20. phy-names = "usb2-phy", "usb3-phy";
  21. maximum-speed = "super-speed";
  22. dr_mode = "host";
  23. snps,dis_u3_susphy_quirk;
  24. snps,dis_u2_susphy_quirk;
  25. };
  26. };

流程图:watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3oxMDI2NTQ0Njgy_size_16_color_FFFFFF_t_70

  1. 主机控制器驱动的注册。先从设备树解析注册omap_dwc3节点,与dwc3_omap_driver匹配并调用dwc3_omap_probe,dwc3_omap_probe里再解析omap_dwc3节点下的子节点usb@48890000,与dwc3_driver匹配后调用dwc3_probe,会根据usb节点配置的模式再去注册真正的usb控制器。如果是host模式,则会调用dwc3_host_init函数注册xhci主机控制器设备,与usb_xhci_driver匹配并调用xhci_plat_probe.

  2. usb主机控制器驱动的probe过程,分配usb_hcd,然后添加到系统中,一个主控制器对应一条usb总线,一个主控制器绑定着一个root hub,一个root hub对应于一个usb_device,然后注册此root hub,主要是调用usb_new_device。每个usb设备(usb_device)有一种或多种配置,每种配置有一个或多个接口,一个接口有一种或多种设置,一种设置有一个或多个端点。为了获取并解析这些描述符,usb_new_device调用usb_configure_device,然后将设备添加到内核。每个usb设备都有一个控制端点。它通常用于配置设备,获取设备信息,发送命令到设备,或者获取设备的状态报告,usb_new_device中调用了函数usb_create_ep_devs。

  3. 当root hub这个usb_device添加到系统中时,系统中也有一个usb_device_driver(注意,不是usb_driver,一个是对应usb设备,一个对应usb接口)叫做usb_generic_driver,匹配上之后就会调用generic_probe,在这个函数里面调用usb_choose_configuration为设备选择一个合理的配置,到此就可以用选定配置下的所有描述符进行设备配置了。函数usb_set_configuration就是完成此项功能。在函数usb_set_configuration中将设备的所有接口都添加到内核device_add(&intf->dev)。这些接口设备的总线类型也是usb_bus_type,不过设备类型为usb_if_device_type。

  4. 接口添加到系统中了,当然要匹配接口驱动。恰好系统中有一个usb_driver为hub_driver,它是为hub接口准备的。接口又分为hub的接口和usb设备的接口。如果是设备的接口,如果匹配上了后就调用probe函数,做相应的初始化、设备模型建立等工作,例如usb storage驱动,usb hid驱动。如果是hub的接口,就调用hub_probe。

参考:
USB主机控制器驱动——OHCI分析:https://blog.csdn.net/lizuobin2/article/details/51931161
USB驱动框架分析1:https://blog.csdn.net/xuao20060793/article/details/46530481

发表评论

表情:
评论列表 (有 0 条评论,137人围观)

还没有评论,来说两句吧...

相关阅读

    相关 USB OTG驱动分析(一)

    前一段时间弄了 2 个礼拜的 OTG 驱动调试,感觉精神疲惫啊。主要原因还是自己对 OTG 功能不了解造成的。现在终于完成但是对实质原理还有些模糊。所以 自己重新总结一下。因为