[RK3288][Android6.0] USB ECHI 驱动小结

来源:互联网 发布:mac和max 编辑:程序博客网 时间:2024/05/05 16:51
Platform: RK3288
OS: Android 6.0
Kernel: 3.10.92

usbdev_rk32.c:
rk3288平台的usb host controller接口实现都在这里.
echi-hcd.c:
linux通用echi hcd驱动.
echi-rockchip.c:
平台echi驱动.

rk3288平台总共有5个usb host controller(hcd), 每个usb口都分别使用不同的hcd, 对应的配置在文件rk3288.dtsi中
usb0: usb@ff580000 {
        compatible = "rockchip,rk3288_usb20_otg";
        reg = <0xff580000 0x40000>;
        interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clk_gates13 4>, <&clk_gates7 4>;
        clock-names = "clk_usbphy0", "hclk_usb0";
        resets = <&reset RK3288_SOFT_RST_USBOTG_H>,
             <&reset RK3288_SOFT_RST_USBOTGPHY>,
             <&reset RK3288_SOFT_RST_USBOTGC>;
        reset-names = "otg_ahb", "otg_phy", "otg_controller";
        /*0 - Normal, 1 - Force Host, 2 - Force Device*/
        rockchip,usb-mode = <0>;
    };

    usb1: usb@ff540000 {
        compatible = "rockchip,rk3288_usb20_host";
        reg = <0xff540000 0x40000>;
        interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clk_gates13 6>, <&clk_gates7 7>,
             <&usbphy_480m>;
        clock-names = "clk_usbphy1", "hclk_usb1",
                  "usbphy_480m";
        resets = <&reset RK3288_SOFT_RST_USBHOST1_H>,
             <&reset RK3288_SOFT_RST_USBHOST1PHY>,
             <&reset RK3288_SOFT_RST_USBHOST1C>;
        reset-names = "host1_ahb", "host1_phy", "host1_controller";
    };

    usb2: usb@ff500000 {
        compatible = "rockchip,rk3288_rk_ehci_host";
        reg = <0xff500000 0x20000>;
        interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clk_gates13 5>, <&clk_gates7 6>;
        clock-names = "clk_usbphy2", "hclk_usb2";
        resets = <&reset RK3288_SOFT_RST_USBHOST0_H>,
             <&reset RK3288_SOFT_RST_USBHOST0PHY>,
             <&reset RK3288_SOFT_RST_USBHOST0C>,
             <&reset RK3288_SOFT_RST_USB_HOST0>;
        reset-names = "ehci_ahb", "ehci_phy", "ehci_controller", "ehci";
    };

    usb3: usb@ff520000 {
        compatible = "rockchip,rk3288_rk_ohci_host";
        reg = <0xff520000 0x20000>;
        interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clk_gates13 5>, <&clk_gates7 6>;
        clock-names = "clk_usbphy3", "hclk_usb3";
        status = "okay";
    };

    usb4: usb@ff5c0000 {
        compatible = "rockchip,rk3288_rk_ehci1_host";
        reg = <0xff5c0000 0x40000>;
        interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&ehci1phy_480m>, <&clk_gates7 8>,
             <&ehci1phy_12m>, <&usbphy_480m>,
             <&otgphy1_480m>, <&otgphy2_480m>;
        clock-names = "ehci1phy_480m", "hclk_ehci1",
                  "ehci1phy_12m", "usbphy_480m",
                  "ehci1_usbphy1", "ehci1_usbphy2";
        resets = <&reset RK3288_SOFT_RST_EHCI1>,
             <&reset RK3288_SOFT_RST_EHCI1_AUX>,
             <&reset RK3288_SOFT_RST_EHCI1PHY>;
        reset-names = "ehci1_ahb", "ehci1_aux", "ehci1_phy";
    };

各个控制器的驱动大同小异, 这里以echi驱动为例, 看完下面流程会发现各usb controller需要实现的是struct rkehci_platform_data.

ehci_rk_init ->  echi-rockchip.c
    ehci_init_driver    ehci-hcd.c //使用标准ehci驱动配置
    platform_driver_register ->    //driver name是rockchip,rk3288_rk_ehci_host, data是struct rkehci_platform_data rkehci_pdata_rk3288
        ehci_rk_probe ->
            usb_create_hcd    //标准创建hcd方法
            pldata->hw_init    ->    //调用的是rkehci_pdata_rk3288里的函数
                rk_ehci_hw_init     usbdev_rk32.c
            pldata->clock_init ->
                rk_ehci_clock_init
            pldata->clock_enable ->
                rk_ehci_clock_enable
            pldata->phy_suspend ->
                rk_ehci_phy_suspend
            pldata->soft_reset ->
                rk_ehci_soft_reset
            usb_add_hcd    //标准添加hcd方法
            rk_ehci->connect_detect_timer.function = rk_ehci_hcd_connect_detect    //timer实现函数,2秒调用一次
            INIT_DELAYED_WORK(&rk_ehci->host_enable_work, rk_ehci_hcd_enable);    //work函数会在定时器函数中被调用.
    
定时器回调函数:
rk_ehci_hcd_connect_detect ->
    pldata->get_status ->
        rk_ehci_get_status
        schedule_delayed_work ->    //如果usb处于enable状态就调用work queue
            rk_ehci_hcd_enable ->
                pldata->phy_suspend    ->
                    rk_ehci_phy_suspend    //通过此接口来开关硬件host controller
        mod_timer(&rk_ehci->connect_detect_timer, jiffies + (HZ << 1));    //定时器的下一次工作需要自己设置.
        

1 0