Linux USB 3.0驱动分析(六)

您所在的位置:网站首页 432623355368738 Linux USB 3.0驱动分析(六)

Linux USB 3.0驱动分析(六)

#Linux USB 3.0驱动分析(六)| 来源: 网络整理| 查看: 265

一.USB主机控制器HCD(Host Controller Device)简介

USB的主机控制器(HCD),出现了多种不同的类型,即OHCI和UHCI,EHCI,和xHCI,不同USB控制器类型OHCI,UHCI,EHCI,xHCI的区别和联系

USB采用树形拓扑结构,主机侧和设备侧的USB控制器分别称为主机控制器(Host Controller)和USB设备控制器(UDC),每条总线上只有一个主机控制器,负责协调主机和设备间的通信,设备不能主动向主机发送任何消息。

1.usb phy

二.USB主机控制器驱动

1.分析的usb主机控制器硬件情况

USB Host带有Root Hub,第一个USB设备是一个根集线器(Root_hub)它控制连接到其上的整个USB总线。

鉴于现在大部分设备都已经支持usb3.0, 我们来分析xHCI主机控制器驱动代码。

我手里的设备是imx8mq,用的DWC3 USB控制芯片

USB设备分为HOST(主设备)和SLAVE(从设备),只有当一台HOST与一台SLAVE连接时才能实现数据的传输,而OTG设备既能充当HOST,亦能充当SLAVE,也即DRD(Dual-role-devices).我现在只分析当主设备的情况。2.usb主机控制器驱动分析代码位置: drivers\usb\dwc3\Core.c首先是platform驱动的加载, 会通过of_dwc3_match配置dtsstatic struct platform_driver dwc3_driver = { .probe = dwc3_probe, .remove = dwc3_remove, .driver = { .name = "dwc3", .of_match_table = of_match_ptr(of_dwc3_match), .acpi_match_table = ACPI_PTR(dwc3_acpi_match), .pm = &dwc3_dev_pm_ops, }, }; module_platform_driver(dwc3_driver);匹配成功后,会进入dwc3_probe函数。主要进行一些资源的分配,硬件的初始化等,这里化简一下static int dwc3_probe(struct platform_device *pdev) { dwc3_get_properties(dwc); //获取一些属性,主要是读取dts里面的配置,比如dr_mode可以配置为otg、host或者peripheral。 dwc3_cache_hwparams(dwc); //读取一些硬件参数 ret = dwc3_core_init(dwc); //这里面是最重要的初始化,一些硬件初始化,包括USB PHY if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "failed to initialize core: %d\n", ret); goto err4; } ret = dwc3_core_init_mode(dwc); //根据不同的模式进行初始化 if (ret) goto err5; dwc3_debugfs_init(dwc); //调试节点,/sys/kernel/debug/38100000.usb/ }dwc3_core_init_mode里面会进行不同模式的初始化,包括otg、host或者peripheral。static int dwc3_core_init_mode(struct dwc3 *dwc) { switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: //外围模式,也就是当从设备 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, false); phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "failed to initialize gadget\n"); return ret; } break; case USB_DR_MODE_HOST: //主机模式,也就是当主设备 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, true); phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); ret = dwc3_host_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "failed to initialize host\n"); return ret; } break; case USB_DR_MODE_OTG: //otg模式,OTG控制器可以做host,也能做device INIT_WORK(&dwc->drd_work, __dwc3_set_mode); ret = dwc3_drd_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "failed to initialize dual-role\n"); return ret; } break; default: dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); return -EINVAL; } return 0; }只做从设备的情况比较少,只做host或者otg的情况比较多。我们先来分析当做host的情况int dwc3_host_init(struct dwc3 *dwc) { xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); //创建一个平台设备,名字是xhci-hcd if (!xhci) { dev_err(dwc->dev, "couldn't allocate xHCI device\n"); return -ENOMEM; } ret = platform_device_add_resources(xhci, dwc->xhci_resources, DWC3_XHCI_RESOURCES_NUM); //添加资源到这个平台设备 if (ret) { dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); goto err; } /** * WORKAROUND: dwc3 revisions uses_new_polling ? HCD_POLL_RH(hcd) : //这里hcd->uses_new_polling=1 HCD_POLL_RH(hcd)如果不等于0,会一直调用mod_timer (length == 0 && hcd->status_urb != NULL)) //此时开启rh_timer.rh_timer的处理函数rh_timer_func,实际就是usb_hcd_poll_rh_status。 mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); }

参考:

USB驱动框架_WuYujun's blog-CSDN博客_usb驱动框架

USB PHY芯片



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3