usb PHY linux驱动

 

本文以imx6ul SoC为例。

 

涉及目录及文件:

  • dts: linux-4.14.141\arch\arm\boot\dts\imx6ul.dtsi

  • controller: drivers\usb\chipidea

  • phy: drivers\usb\phy

 

几点说明:

1)4.13 kernel

2)4.13内核中全部是usb2.0的PHY驱动,没有usb3.0的驱动。也许usb3.0的PHY都不需要初始化,直接就可以使用,如femtoPHY。

3)imx6ul的usb controller和phy都集成在SoC中

 

 

 

1. dts配置

\linux-4.14.141\arch\arm\boot\dts\imx6ul.dtsi

usbotg1: usb@02184000 {
    compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
    reg = <0x02184000 0x200>;
    interrupts = ;
    clocks = <&clks IMX6UL_CLK_USBOH3>;
    fsl,usbphy = <&usbphy1>;
    fsl,usbmisc = <&usbmisc 0>;
    fsl,anatop = <&anatop>;
    ahb-burst-config = <0x0>;
    tx-burst-size-dword = <0x10>;
    rx-burst-size-dword = <0x10>;
    status = "disabled";
};

usbphy1: usbphy@020c9000 {
    compatible = "fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
    reg = <0x020c9000 0x1000>;
    interrupts = ;
    clocks = <&clks IMX6UL_CLK_USBPHY1>;
    phy-3p0-supply = <®_3p0>;
    fsl,anatop = <&anatop>;
};

 

 

 

2. usb controller

drivers/usb/chipidea/ci_hdrc_imx.c

static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
    { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
    { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
    ......
    { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
    { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
    { /* sentinel */ }
};

static struct platform_driver ci_hdrc_imx_driver = {
    .probe = ci_hdrc_imx_probe,
    .remove = ci_hdrc_imx_remove,
    .shutdown = ci_hdrc_imx_shutdown,
    .driver = {
        .name = "imx_usb",
        .of_match_table = ci_hdrc_imx_dt_ids,
        .pm = &ci_hdrc_imx_pm_ops,
     },
};

drivers/usb/chipidea/core.c

static struct platform_driver ci_hdrc_driver = {
    .probe    = ci_hdrc_probe,
    .remove    = ci_hdrc_remove,
    .driver    = {
        .name    = "ci_hdrc",
        .pm    = &ci_pm_ops,
    },
};

 

2.1 首先根据"fsl,imx6ul-usb"进行dts match,执行ci_hdrc_imx_probe。在此函数中:

1)首先获得devm_usb_get_phy_by_phandle("fsl,usbphy") 获得phy,"fsl,usbphy"在dts中有定义

2)然后调用ci_hdrc_add_device添加platform device ("ci_hdrc"),下一步会match 相应的platform driver

函数流程如下:

chipidea/ci_hdrc_imx.c: ci_hdrc_imx_probe -> devm_usb_get_phy_by_phandle | ci_hdrc_add_device -> chipidea/core.c: platform_device_add("ci_hdrc")

 

2.2 初始化PHY

1)上述添加platform device ("ci_hdrc")后,会match到相应的platform driver,然后执行ci_hdrc_probe

2)在ci_hdrc_probe中初始化usb phy

函数流程如下:

chipidea/core.c: ci_hdrc_probe -> ci_usb_phy_init -> phy.h: usb_phy_init -> (phy->init)

 

 

3.  usb PHY

drivers/usb/phy/phy-mxs-usb.c

在该文件中主要实现PHY的相关操作函数,然后被controller调用进行初始化。

 

1)根据"fsl,imx6ul-usbphy"进行dts match,match到后执行mxs_phy_probe

static const struct of_device_id mxs_phy_dt_ids[] = {
    { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
    { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
    { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
    { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
    { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
    { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
    { /* sentinel */ }
};

 

2)在mxs_phy_probe中先设置phy的相关操作函数

    mxs_phy->phy.io_priv        = base;
    mxs_phy->phy.dev        = &pdev->dev;
    mxs_phy->phy.label        = DRIVER_NAME;
    mxs_phy->phy.init        = mxs_phy_init;
    mxs_phy->phy.shutdown        = mxs_phy_shutdown;
    mxs_phy->phy.set_suspend    = mxs_phy_suspend;
    mxs_phy->phy.notify_connect    = mxs_phy_on_connect;
    mxs_phy->phy.notify_disconnect    = mxs_phy_on_disconnect;
    mxs_phy->phy.type        = USB_PHY_TYPE_USB2;
    mxs_phy->phy.set_wakeup        = mxs_phy_set_wakeup;

 

3)最后通过usb_add_phy_dev(&mxs_phy->phy)添加usb PHY,被host或device controller driver使用。

 

 

4. register

4.1 usb phy

1)usb phy register base address 

usb PHY linux驱动_第1张图片

从上面可以得出usb phy及地址是020c_9000,这也符合dts中的地址定义

 

2)在phy-mxs-usb.c中定义的寄存器地址偏移

#define HW_USBPHY_PWD                0x00
#define HW_USBPHY_TX                0x10
#define HW_USBPHY_CTRL                0x30
#define HW_USBPHY_CTRL_SET            0x34
#define HW_USBPHY_CTRL_CLR            0x38
#define HW_USBPHY_DEBUG_SET            0x54
#define HW_USBPHY_DEBUG_CLR            0x58
#define HW_USBPHY_IP                0x90
#define HW_USBPHY_IP_SET            0x94
#define HW_USBPHY_IP_CLR            0x98

 

4.2 usb controller

1)usb controller register base address 

usb PHY linux驱动_第2张图片

从上面可以得出usb phy及地址是0218_4000,这也符合dts中的地址定义

 

2)在chipidea/ci.h中定义的寄存器地址偏移

#define ID_ID                0x0
#define ID_HWGENERAL            0x4
#define ID_HWHOST            0x8
#define ID_HWDEVICE            0xc
#define ID_HWTXBUF            0x10
#define ID_HWRXBUF            0x14
#define ID_SBUSCFG            0x90

 

 

 

你可能感兴趣的:(USB开发,Linux,Driver,usb,PHY,kernel,driver)