uboot usb驱动模型

9 篇文章 1 订阅

关于uboot驱动模型,这篇文章讲得很好,不再描述:
[uboot] (番外篇)uboot 驱动模型_ooonebook的博客-CSDN博客

U-Boot Driver Model领域模型设计 
 

linux usb总线架构:
Linux USB总线架构_ZhY_Rening的博客-CSDN博客

uboot版本:uboot2018.01
平台:ti-am5728
usb控制器:xhci-dwc3

usb 命令:cmd/usb.c
usb uclass:drivers/usb/host/usb-uclass.c
usb 控制器驱动:drivers/usb/host/xhci-dwc3.c
usb hub驱动:common/usb_hub.c
usb存储驱动:common/usb_storage.c

uboot DM驱动模型图:

DMä¸çæ¥å£è°ç¨æµç¨

注:图来自网络,是以serial驱动为例,其他驱动也是一样的。


这里涉及到的uclass有 UCLASS_USB,UCLASS_USB_HUB,UCLASS_MASS_STORAGE。

对于UCLASS_USB:一个udevice对应一个 usb控制器(bus、root hub)。udevice从设备树解析,driver在驱动程序里定义。
对于UCLASS_USB_HUB:一个udevice对应一个 usb hub(非root hub)。udevice在父设备(usb或usb hub)扫描时创建并和驱动程序match,driver在驱动程序里定义。
对于UCLASS_MASS_STORAGE:一个udevice对应一个 mass 存储设备。udevice在父设备(usb或usb hub)扫描时创建并和驱动程序match,driver在驱动程序里定义。

这三种udevice的关系如下:
一个usb控制器有且仅有一个root hub设备(和控制器作为一个整体),这个根Hub下可以接多级的Hub(以child udevice的形式),每个子Hub又可以接子Hub。每个USB设备作为一个节点接在不同级别的Hub上。 每条USB总线上最多可以接127个设备。mass storage是一种usb设备。

è¿éåå¾çæè¿°

1.usb控制器驱动(以xhci-dwc3为例):

U_BOOT_DRIVER(xhci_dwc3) = {
	.name = "xhci-dwc3",
	.id = UCLASS_USB,
	.of_match = xhci_dwc3_ids,
	.probe = xhci_dwc3_probe,
	.remove = xhci_dwc3_remove,
	.ops = &xhci_usb_ops,
	.priv_auto_alloc_size = sizeof(struct xhci_ctrl),
	.platdata_auto_alloc_size = sizeof(struct xhci_dwc3_platdata),
	.flags = DM_FLAG_ALLOC_PRIV_DMA,
};

2.usb控制器设备树节点:

usb1: usb@48890000 {
				compatible = "snps,dwc3";
				reg = <0x48890000 0x17000>;
				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
				interrupt-names = "peripheral",
						  "host",
						  "otg";
				phys = <&usb2_phy1>, <&usb3_phy1>;
				phy-names = "usb2-phy", "usb3-phy";
				maximum-speed = "super-speed";
				dr_mode = "host";
				snps,dis_u3_susphy_quirk;
				snps,dis_u2_susphy_quirk;
			};

3.usb uclass驱动:

UCLASS_DRIVER(usb) = {
	.id		= UCLASS_USB,
	.name		= "usb",
	.flags		= DM_UC_FLAG_SEQ_ALIAS,
	.post_bind	= dm_scan_fdt_dev,
	.priv_auto_alloc_size = sizeof(struct usb_uclass_priv),
	.per_child_auto_alloc_size = sizeof(struct usb_device),
	.per_device_auto_alloc_size = sizeof(struct usb_bus_priv),
	.child_post_bind = usb_child_post_bind,
	.child_pre_probe = usb_child_pre_probe,
	.per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
};

4.usb hub 设备驱动和 uclass驱动:

U_BOOT_DRIVER(usb_generic_hub) = {
	.name	= "usb_hub",
	.id	= UCLASS_USB_HUB,
	.of_match = usb_hub_ids,
	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
};

UCLASS_DRIVER(usb_hub) = {
	.id		= UCLASS_USB_HUB,
	.name		= "usb_hub",
	.post_bind	= dm_scan_fdt_dev,
	.post_probe	= usb_hub_post_probe,
	.child_pre_probe	= usb_child_pre_probe,
	.per_child_auto_alloc_size = sizeof(struct usb_device),
	.per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
	.per_device_auto_alloc_size = sizeof(struct usb_hub_device),
};

5.usb mass storage 设备驱动和uclass驱动:

U_BOOT_DRIVER(usb_mass_storage) = {
	.name	= "usb_mass_storage",
	.id	= UCLASS_MASS_STORAGE,
	.of_match = usb_mass_storage_ids,
	.probe = usb_mass_storage_probe,
#ifdef CONFIG_BLK
	.platdata_auto_alloc_size	= sizeof(struct us_data),
#endif
};

UCLASS_DRIVER(usb_mass_storage) = {
	.id		= UCLASS_MASS_STORAGE,
	.name		= "usb_mass_storage",
};

6.usb start过程:

do_usb
  do_usb_start
    usb_init    //drivers/usb/host/usb-uclass.c
      uclass_get(UCLASS_USB, &uc);    //根据uclass id获取usb uclass
      uclass_foreach_dev(bus, uc) {    //遍历 probe uclass下的udevice(控制器)
        device_probe(bus);    //drivers/core/device.c
          device_probe(dev->parent);    //递归probe父节点
            uclass_resolve_seq//父节点都probe之后,会分配一个seq给该设备
            dev->flags |= DM_FLAG_ACTIVATED//设置该设备的flag为激活状态
            pinctrl_select_state(dev, "default")//和引脚相关的初始化设置
            uclass_pre_probe_device    //uc_drv->pre_probe
            dev->parent->driver->child_pre_probe(dev)//执行父节点驱动的child_pre_probe
            drv->ofdata_to_platdata(dev)//执行设备驱动的ofdata_to_platdata接口函数
            clk_set_defaults(dev)//设备时钟相关的设置
            drv->probe(dev)//调用设备驱动的probe接口函数
            uclass_post_probe_device(dev)//调用所属CLASS驱动的post_probe接口函数
      }
      uclass_foreach_dev(bus, uc) {    //遍历 扫描 uclass下的udevice(控制器)
        if (!device_active(bus))    //跳过active的设备
			continue;
        usb_scan_bus(bus, true);    //扫描bus(usb控制器)下的设备
          usb_scan_device(bus, 0, USB_SPEED_FULL, &dev);
            struct usb_device *parent_udev;    //定义usb_devide
            usb_setup_device        //配置设备
              usb_prepare_device    //设置地址和描述符
              usb_select_config     //选择设备的配置
            usb_find_child    //寻找子设备
            usb_find_and_bind_driver //遍历usb驱动(hub、keyboard、storage)并和子设备绑定
            device_probe    //子设备probe,最终会调用子设备驱动里面的方法,如果是hub就递归扫描,如果是storage就初始化并获取描述符等。


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值