USB控制器初始化 Linux,USB——usb host controller driver初始化

概述

本文对USB驱动中的HCD(主机控制器驱动,Host Controller Driver)初始化代码进行分析,梳理总结其中涉及到的重要数据结构和处理流程。HCD驱动代码根据USB标准分为OHCI、UHCI、EHCI和XHCI,本文以EHCI标准为主,进行分析,选取freescale驱动代码

初始化代码分析

HCD驱动是CPU上USB主机控制器的抽象,HCD驱动代码位于driver/usb/host路径下,入口为ehci_hcd.c

static int __init ehci_hcd_init(void)

{

int retval = 0;

set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);

if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||

test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))

printk(KERN_WARNING "Warning! ehci_hcd should always be loaded"

" before uhci_hcd and ohci_hcd, not after\n");

pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",

hcd_name,

sizeof(struct ehci_qh), sizeof(struct ehci_qtd),

sizeof(struct ehci_itd), sizeof(struct ehci_sitd));

#ifdef DEBUG

ehci_debug_root = debugfs_create_dir("ehci", NULL);

if (!ehci_debug_root) {

retval = -ENOENT;

goto err_debug;

}

#endif

#ifdef PLATFORM_DRIVER

retval = platform_driver_register(&PLATFORM_DRIVER);

if (retval < 0)

goto clean0;

#endif

#ifdef PCI_DRIVER

retval = pci_register_driver(&PCI_DRIVER);

if (retval < 0)

goto clean1;

#endif

#ifdef PS3_SYSTEM_BUS_DRIVER

retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);

if (retval < 0)

goto clean2;

#endif

#ifdef OF_PLATFORM_DRIVER

retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);

if (retval < 0)

goto clean3;

#endif

return retval;

#ifdef OF_PLATFORM_DRIVER

/* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */

clean3:

#endif

#ifdef PS3_SYSTEM_BUS_DRIVER

ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);

clean2:

#endif

#ifdef PCI_DRIVER

pci_unregister_driver(&PCI_DRIVER);

clean1:

#endif

#ifdef PLATFORM_DRIVER

platform_driver_unregister(&PLATFORM_DRIVER);

clean0:

#endif

#ifdef DEBUG

debugfs_remove(ehci_debug_root);

ehci_debug_root = NULL;

err_debug:

#endif

clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);

return retval;

}

module_init(ehci_hcd_init);

该函数其实并没有做什么实质性的工作,根据宏定义进入具体设备的驱动程序中,以freescale芯片来分析的话,会调用()向系统注册ehci_fsl_driver驱动,驱动内容如下

static struct platform_driver ehci_fsl_driver = {

.probe = ehci_fsl_drv_probe,

.remove = ehci_fsl_drv_remove,

.shutdown = usb_hcd_platform_shutdown,

.driver = {

.name = "fsl-ehci",

},

};

其probe函数为ehci_fsl_probe,驱动名称为"fsl-ehci"。那么驱动注册了,怎么才会调用probe函数呢?当然是要有设备注册。那么设备是什么时候注册的呢?主机控制器设备属于CPU片上资源,这些片上资源一般都是在内核启动的时候注册到系统的,在arch/powerpc/sysdev/fsl_soc.c文件中,对设备进行了注册操作

usb_dev_mph =

platform_device_register_simple("fsl-ehci", i, r, 2);

if (IS_ERR(usb_dev_mph)) {

ret = PTR_ERR(usb_dev_mph);

goto err;

}

代码中通过调用platform_device_register_simple()向系统中注册名为fsl-ehci的设备。现在就清楚了,不管是设备先注册还是驱动先注册,现在设备和驱动刚好对应起来了,所以ehci_fsl_drv_probe会马上调用起来。

在分析echi_fsl_drv_probe之前,我们先来分析一下设备结构以及内容。fsl_soc.c文件中通过调用fsl_usb_of_init()函数来注册USB主机控制器设备,其设备信息和资源从哪里来的呢?看代码

for_each_compatible_node(np, NULL, "fsl-usb2-mph") {

struct resource r[2];

struct fsl_usb2_platform_data usb_data;

const unsigned char *prop = NULL;

memset(&r, 0, sizeof(r));

memset(&usb_data, 0, sizeof(usb_data));

ret = of_address_to_resource(np, 0, &r[0]);

if (ret)

goto err;

of_irq_to_resource(np, 0, &r[1]);

usb_dev_mph =

platform_device_register_simple("fsl-ehci", i, r, 2);

if (IS_ERR(usb_dev_mph)) {

ret = PTR_ERR(usb_dev_mph);

goto err;

}

这里通过调用for_each_compatible_node(),其实要涉及到linux设备树的概念,这里不展开说明。简单说就是通过平台文件里的一个xxx.dts文件中读取名字为fsl-usb2-mph的设备树结构,从中拿到硬件资源和信息,所以我们主要分析清楚这些资源和信息就行。从arch/powerpc/boot/dts/mpc834x_mds.dts文件中找到这样一段描述

usb@22000 {

compatible = "fsl-usb2-mph";

reg = <0x22000 0x1000>;

#address-cells = <1>;

#size-cells = <0>;

interrupt-parent = ;

interrupts = <39 0x8>;

phy_type = "ulpi";

port1;

};

可以看到寄存器的初始地址为0x22000,长度为1000,中断号为39,有一个port。

HCD probe

下面来分析ehci_fsl_drv_probe()函数,里面返回的是一个usb_hcd_fsl_probe()函数,传递了pdev和一个ehci_fsl_hc_driver

static int ehci_fsl_drv_probe(struct platform_device *pdev)

{

if (usb_disabled())

return -ENODEV;

/* FIXME we only want one one probe() not two */

return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev);

}

pdev就是前面分析的向系统注册的主机控制器设备“fsl-ehci”,但是ehci_fsl_hc_driver又是什么呢?

首先,它的类型是struct hc_driver,然后它是一个static类型的静态变量

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值