dwc3 linux usb3.0 driver架構

 

dwc3 linux usb3.0 driver架構:

 

1. DRD driver

DRD驅動在usb/dwc3

 

1.1 dts

dwc3@44000000 {
    /* Compatible ID used by the Linux driver for this kind of device */
    compatible = "snps,dwc3";
    /* Register bank location: AddressMSB, AddressLSB, SizeMSB, SizeLSB */
    reg = <0x0 0x44000000 0x0 0x100000>;
    interrupts = <0 8 4>;
    dr_mode = "otg";
    extcon = <&extcon_dwc3>;
};


extcon_dwc3: extcon_dwc3 {
    compatible = "linux,extcon-usb-gpio";
    id-gpio = <&porta 1 0>;
};

dr_mode可以配置爲otg、host或者peripheral。

 

1.2 drd driver

usb/dwc3/core.c:

static 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,
    },
};

static const struct of_device_id of_dwc3_match[] = {
    {
        .compatible = "snps,dwc3"
    },
    {
        .compatible = "synopsys,dwc3"
    },
    { },
};

1)首先根據"snps,dwc3"進行dts和driver的匹配,執行dwc3_probe()

2) 在dwc3中先調用 dwc3_get_dr_mode()取得usb mode(dr_mode),這可以是otg、host或者device

3)然後調用 dwc3_core_init()初始化usb PHY interface和usb PHY,usb PHY的初始化參照第4節。

4)最後調用 dwc3_core_init_mode()初始化usb mode:

  • 如果dr_mode爲device,則初始化gadget。

  • 如果dr_mode爲host,需要初始化xHCI驅動。在dwc3_host_init函數的最後調用platform_device_add(xhci)添加platform device(xhci-hcd),用於匹配xHCI driver(xHCI driver爲platform driver),參照第3節。

  • 如果dr_mode爲otg,需要根據extcon來選定一個角色(host或者device)進行初始化,所以還需要extcon驅動的支持,參照第2節。

 

 

2. extcon driver

extcon驅動在drivers/extcon中,利用gpio或其他信號腳提供一種通知機制,控制usb DRD 模式的切換(作爲host或者device)。

 

2.1 driver

extcon/extcon-usb-gpio.c: 

tatic const struct of_device_id usb_extcon_dt_match[] = {
    { .compatible = "linux,extcon-usb-gpio", },
    { /* sentinel */ }
};

static struct platform_driver usb_extcon_driver = {
    .probe        = usb_extcon_probe,
    .remove        = usb_extcon_remove,
    .driver        = {
        .name    = "extcon-usb-gpio",
        .pm    = &usb_extcon_pm_ops,
        .of_match_table = usb_extcon_dt_match,
    },
    .id_table = usb_extcon_platform_ids,
};

1)首先根據"linux,extcon-usb-gpio"進行dts和driver的匹配,執行usb_extcon_probe()

2)在 usb_extcon_probe()中,先調用devm_extcon_dev_register()註冊設備

3)然後爲gpio註冊一箇中斷處理程序,在該中斷處理中處理gpio中斷,並將信息通過通知鏈機制發送給DRD driver

4)DRD driver收到消息後,切換usb的角色,重新初始化usb驅動,作爲device或者host

 

 

3. xHCI driver

xHCI驅動在usb/host中,主要初始化xHCI。xHCI作爲usb host部分的驅動。

3.1 

usb/host/xhci-plat.c:

static struct platform_driver usb_xhci_driver = {
    .probe    = xhci_plat_probe,
    .remove    = xhci_plat_remove,
    .driver    = {
        .name = "xhci-hcd",
        .pm = &xhci_plat_pm_ops,
        .of_match_table = of_match_ptr(usb_xhci_of_match),
        .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
    },
};

static int __init xhci_plat_init(void)
{
    xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides);
    return platform_driver_register(&usb_xhci_driver);
}

1)在xhci_plat_init中調用platform_driver_register(&usb_xhci_driver)註冊platform driver("xhci-hcd")

2)首先根據name="xhci-hcd"匹配到platform device後,執行xhci_plat_probe

3)在xhci_plat_probe中,進行xHCI的初始化,最後添加到usb core中

 

 

4. usb PHY driver

dwc3的PHY初始化主要在 dwc3_core_init中完成,如果確實需要初始化PHY,還需要相關PHY驅動的配合(提供具體的操作函數)。

 

1)synopsys採用femtoPHY,femtoPHY通常情況下無需初始化(設置)其寄存器,只有調試或使用特殊功能時才需要訪問。也就是說,對於femtoPHY,我們可以不寫驅動來進行初始化。

2)雖然不需要初始化PHY,但我們依然需要配置usb controller的PHY interface(PIPE、ULPI、UTMI),這在 dwc3_phy_setup中實現。

3)對於某些類型的PHY,必須要進行初始化,這就需要配置dts設置usb-phy或者phy-names。PHY初始化主要由 dwc3_core_get_phy和 dwc3_core_soft_reset等函數調用。裏面用到的函數指針需要在相關PHY驅動中進行實現並註冊。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章