USB系列之Host控制器

版权声明:本文为博主原创文章,未经博主允许不得转载。
https://blog.csdn.net/huangweiqing80/article/details/82998850

USB拓扑

对于每个嵌入式的CPU芯片中一般都会集成一个或多个Host 控制器,每个Host控制器其实就是一个PCI设备,挂载在PCI总线上,在Linux系统中,驱动开发人员应该给Host 控制器提供驱动程序,Host 控制器用usb_hcd结构来表示。该结构体在/include/linux/usb/hcd.h中定义。

每个USB Host控制器都会自带一个USB Hub,被称为跟(Root)Hub。这个根Hub又可以接子(Sub)Hub,每个Hub上又可以挂载USB 设备。从广义上来说,USB Hub也算是USB设备。每个根USB Hub下可以直接或间接地连接127个设备

几种USB控制器类型:OHCI,UHCI,EHCI,xHCI

OHCI、UHCI都是USB1.1的接口标准,而EHCI是对应USB2.0的接口标准,最新的xHCI是USB3.0的接口标准。

  1. OHCI(Open Host Controller Interface)是支持USB1.1的标准,但它不仅仅是针对USB,还支持其他的一些接口,比如它还支持Apple的火线(Firewire,IEEE
    1394)接口。与UHCI相比,OHCI的硬件复杂,硬件做的事情更多,所以实现对应的软件驱动的任务,就相对较简单。主要用于非x86的USB,如扩展卡、嵌入式开发板的USB主控。
  2. UHCI(Universal Host Controller Interface),是Intel主导的对USB1.0、1.1的接口标准,与OHCI不兼容。UHCI的软件驱动的任务重,需要做得比较复杂,但可以使用较便宜、较简单的硬件的USB控制器。Intel和VIA使用UHCI,而其余的硬件提供商使用OHCI。
  3. EHCI(Enhanced Host Controller Interface),是Intel主导的USB2.0的接口标准。EHCI仅提供USB2.0的高速功能,而依靠UHCI或OHCI来提供对全速(full-speed)或低速(low-speed)设备的支持。
  4. xHCI(eXtensible Host Controller Interface),是最新最火的USB3.0的接口标准,它在速度、节能、虚拟化等方面都比前面3中有了较大的提高。xHCI支持所有种类速度的USB设备(USB 3.0 SuperSpeed, USB 2.0 Low-, Full-, and High-speed, USB 1.1 Low- and Full-speed)。xHCI的目的是为了替换前面3中(UHCI/OHCI/EHCI)。

USB主机控制器驱动

顾名思义,主机控制器就是用来控制USB设备与CPU之间通信的。CPU要对设备做什么操作,会先通知主机控制器,而不是直接发送指令给USB设备。主机控制器接收到CPU的命令后,会去指挥USB设备完成相应的任务。这样,CPU把命令传给主机控制器后,就不用管余下的工作了,CPU转向处理其他的事情。

USB主机控制器必须由USB主机控制器驱动程序驱动才能运行。USB主机控制器驱动用hc_driver表示,在计算机系统中的每一个主机控制器都有一个对应的hc_driver结构体,该结构体在/include/linux/usb/hcd.h中定义。

下面我们分析一下USB主机控制器驱动,以usb 3.0 xHCI为例来讲解
xHCI是通过platform平台设备驱动模型来驱动的,同样的他有device和driver。
先看device部分
/driver/usb/dwc3/host.c

int dwc3_host_init(struct dwc3 *dwc)
{
	struct platform_device	*xhci;
	int			ret;

	xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
	if (!xhci) {
		dev_err(dwc->dev, "couldn't allocate xHCI device\n");
		ret = -ENOMEM;
		goto err0;
	}

	dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);

	xhci->dev.parent	= dwc->dev;
	xhci->dev.dma_mask	= dwc->dev->dma_mask;
	xhci->dev.dma_parms	= dwc->dev->dma_parms;

	dwc->xhci = xhci;

	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 err1;
	}

	ret = platform_device_add(xhci);
	if (ret) {
		dev_err(dwc->dev, "failed to register xHCI device\n");
		goto err1;
	}

	return 0;

err1:
	platform_device_put(xhci);

err0:
	return ret;
}

在看driver部分
/drivers/usb/host/xhic.c

static int __init xhci_hcd_init(void)
{
	int retval;

	retval = xhci_register_pci();   //注册到PCI总线上
	if (retval < 0) {
		pr_debug("Problem registering PCI driver.\n");
		return retval;
	}
	retval = xhci_register_plat();    //平台驱动
	if (retval < 0) {
		pr_debug("Problem registering platform driver.\n");
		goto unreg_pci;
	}
	/*
	 * Check the compiler generated sizes of structures that must be laid
	 * out in specific ways for hardware access.
	 */
	BUILD_BUG_ON(sizeof(struct xhci_doorbell_array) != 256*32/8);
	BUILD_BUG_ON(sizeof(struct xhci_slot_ctx) != 8*32/8);
	BUILD_BUG_ON(sizeof(struct xhci_ep_ctx) != 8*32/8);
	/* xhci_device_control has eight fields, and also
	 * embeds one xhci_slot_ctx and 31 xhci_ep_ctx
	 */
	BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
	BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
	BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
	BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 7*32/8);
	BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
	/* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
	BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
	return 0;
unreg_pci:
	xhci_unregister_pci();
	return retval;
}
module_init(xhci_hcd_init);

在来看一下xhci_register_plat这个函数

static struct platform_driver usb_xhci_driver = {
	.probe	= xhci_plat_probe,
	.remove	= xhci_plat_remove,
	.driver	= {
		.name = "xhci-hcd",
		.pm = DEV_PM_OPS,
		.of_match_table = of_match_ptr(usb_xhci_of_match),
	},
};
MODULE_ALIAS("platform:xhci-hcd");

int xhci_register_plat(void)
{
	return platform_driver_register(&usb_xhci_driver);
}

猜你喜欢

转载自blog.csdn.net/huangweiqing80/article/details/82998850