usb: update soft reset
authorlyz <lyz@rock-chips.com>
Mon, 7 Jul 2014 11:24:02 +0000 (19:24 +0800)
committerlyz <lyz@rock-chips.com>
Wed, 9 Jul 2014 02:52:49 +0000 (10:52 +0800)
1.add rst_flag to distinguish different reset cases
2.use new reset framework APIs

arch/arm/boot/dts/rk3288.dtsi
drivers/usb/dwc_otg_310/dwc_otg_driver.c
drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c
drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c
drivers/usb/dwc_otg_310/usbdev_rk.h
drivers/usb/dwc_otg_310/usbdev_rk30.c
drivers/usb/dwc_otg_310/usbdev_rk32.c
drivers/usb/host/ehci-rkhsic.c
drivers/usb/host/ehci-rockchip.c

index 2c250835ecf013e8a912905c90ec40cb46c25c78..438ae0d567d914aa016e539048082d2ac0462dd0 100755 (executable)
                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>;
        };
                         <&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 {
                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 {
                clock-names = "hsicphy_480m", "hclk_hsic",
                              "hsicphy_12m", "usbphy_480m",
                              "hsic_usbphy1", "hsic_usbphy2";
+               resets = <&reset RK3288_SOFT_RST_HSIC>, <&reset RK3288_SOFT_RST_HSIC_AUX>,
+                               <&reset RK3288_SOFT_RST_HSICPHY>;
+               reset-names = "hsic_ahb", "hsic_aux", "hsic_phy";
        };
 
        gmac: eth@ff290000 {
index 74deafef62f1f6843076b9fa65daa1d5a420284a..3afba4084333f0474c65466660b59ba0e8642a36 100755 (executable)
@@ -1029,7 +1029,7 @@ static int host20_driver_probe(struct platform_device *_dev)
                pldata->phy_suspend(pldata, USB_PHY_ENABLED);
 
        if (pldata->soft_reset)
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_POR);
 
        res_base = platform_get_resource(_dev, IORESOURCE_MEM, 0);
 
index 7da1cd71e0d67b472d278b44d6e2c02dfa507451..42c3dc1349d7c4ecff30187ff17facfa3d547ee3 100755 (executable)
@@ -376,7 +376,7 @@ static void dwc_otg_hcd_enable(struct work_struct *work)
                        _core_if->hcd_cb->disconnect(_core_if->hcd_cb->p);
                }
 #endif
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_RECNT);
                dwc_otg_disable_host_interrupts(core_if);
                if (pldata->phy_suspend)
                        pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
index def6e719d969c395b02d97371f959579802caafe..6a733ddf0117512db0026fde0a13d7f1e5db9324 100755 (executable)
@@ -1479,7 +1479,7 @@ static void dwc_phy_reconnect(struct work_struct *work)
 
        if (gctrl.b.bsesvld) {
                pcd->conn_status++;
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_RECNT);
                dwc_pcd_reset(pcd);
                /*
                 * Enable the global interrupt after all the interrupt
index f79adac1563f15b9af8ccec7c6307c03e5d8ff0f..0c6e48a57d9812482ec4d16e1add619b84cfb963 100755 (executable)
@@ -18,6 +18,7 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/reset.h>
 #include <linux/rockchip/cru.h>
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/cpu.h>
 #define USB_REMOTE_WAKEUP     (6)
 #define USB_IRQ_WAKEUP        (7)
 
+enum rkusb_rst_flag {
+       RST_POR = 0, /* Reset power-on */
+       RST_RECNT,      /* Reset re-connect */
+       RST_CHN_HALT, /* Reset a channel halt has been detected */
+       RST_OTHER,
+};
+
 extern int rk_usb_charger_status;
 extern void rk_send_wakeup_key(void);
 /* rk3188 platform data */
@@ -63,7 +71,7 @@ struct dwc_otg_platform_data {
        int phy_status;
        void (*hw_init) (void);
        void (*phy_suspend) (void *pdata, int suspend);
-       void (*soft_reset) (void);
+       void (*soft_reset) (void *pdata, enum rkusb_rst_flag rst_type);
        void (*clock_init) (void *pdata);
        void (*clock_enable) (void *pdata, int enable);
        void (*power_enable) (int enable);
@@ -83,7 +91,7 @@ struct rkehci_platform_data {
        void (*clock_init) (void *pdata);
        void (*clock_enable) (void *pdata, int enable);
        void (*phy_suspend) (void *pdata, int suspend);
-       void (*soft_reset) (void);
+       void (*soft_reset) (void *pdata, enum rkusb_rst_flag rst_type);
        int (*get_status) (int id);
        int clk_status;
        int phy_status;
index 0f3c134c9e55b7c705b5af904f2200cd867d2994..dcdfb7d38e24ab6ccc21a10456b31acf85a0439e 100755 (executable)
@@ -43,7 +43,7 @@ static void usb20otg_phy_suspend(void *pdata, int suspend)
        }
 }
 
-static void usb20otg_soft_reset(void)
+static void usb20otg_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
 }
 
@@ -192,7 +192,7 @@ static void usb20host_phy_suspend(void *pdata, int suspend)
        }
 }
 
-static void usb20host_soft_reset(void)
+static void usb20host_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
 }
 
@@ -368,7 +368,7 @@ static void rk_hsic_clock_enable(void *pdata, int enable)
        }
 }
 
-static void rk_hsic_soft_reset(void)
+static void rk_hsic_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
 
 }
index d1a9406fe3f910acfa3935c600da1476b0a3e38c..97675201256b881d0f38f8aaf19c3b3b0b7a17a6 100755 (executable)
@@ -43,16 +43,26 @@ static void usb20otg_phy_suspend(void *pdata, int suspend)
        }
 }
 
-static void usb20otg_soft_reset(void)
+static void usb20otg_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTG_H, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGPHY, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGC, true);
-       udelay(5);
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct reset_control *rst_otg_h, *rst_otg_p, *rst_otg_c;
+
+       rst_otg_h = devm_reset_control_get(usbpdata->dev, "otg_ahb");
+       rst_otg_p = devm_reset_control_get(usbpdata->dev, "otg_phy");
+       rst_otg_c = devm_reset_control_get(usbpdata->dev, "otg_controller");
+       if (IS_ERR(rst_otg_h) || IS_ERR(rst_otg_p) || IS_ERR(rst_otg_c)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
 
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTG_H, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGPHY, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBOTGC, false);
+       reset_control_assert(rst_otg_h);
+       reset_control_assert(rst_otg_p);
+       reset_control_assert(rst_otg_c);
+       udelay(5);
+       reset_control_deassert(rst_otg_h);
+       reset_control_deassert(rst_otg_p);
+       reset_control_deassert(rst_otg_c);
        mdelay(2);
 }
 
@@ -206,16 +216,26 @@ static void usb20host_phy_suspend(void *pdata, int suspend)
        }
 }
 
-static void usb20host_soft_reset(void)
+static void usb20host_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1_H, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1PHY, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1C, true);
-       udelay(5);
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct reset_control *rst_host1_h, *rst_host1_p, *rst_host1_c;
 
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1_H, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1PHY, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST1C, false);
+       rst_host1_h = devm_reset_control_get(usbpdata->dev, "host1_ahb");
+       rst_host1_p = devm_reset_control_get(usbpdata->dev, "host1_phy");
+       rst_host1_c = devm_reset_control_get(usbpdata->dev, "host1_controller");
+       if (IS_ERR(rst_host1_h) || IS_ERR(rst_host1_p) || IS_ERR(rst_host1_c)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
+
+       reset_control_assert(rst_host1_h);
+       reset_control_assert(rst_host1_p);
+       reset_control_assert(rst_host1_c);
+       udelay(5);
+       reset_control_deassert(rst_host1_h);
+       reset_control_deassert(rst_host1_p);
+       reset_control_deassert(rst_host1_c);
        mdelay(2);
 }
 
@@ -392,16 +412,22 @@ static void rk_hsic_clock_enable(void *pdata, int enable)
        }
 }
 
-static void rk_hsic_soft_reset(void)
+static void rk_hsic_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC_AUX, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSICPHY, true);
-       udelay(5);
+       struct rkehci_platform_data *usbpdata = pdata;
+       struct reset_control *rst_hsic_h, rst_hsic_a, rst_hsic_p;
 
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSIC_AUX, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_HSICPHY, false);
+       rst_hsic_h = devm_reset_control_get(usbpdata->dev, "hsic_ahb");
+       rst_hsic_a = devm_reset_control_get(usbpdata->dev, "hsic_aux");
+       rst_hsic_p = devm_reset_control_get(usbpdata->dev, "hsic_phy");
+
+       reset_control_assert(rst_hsic_h);
+       reset_control_assert(rst_hsic_a);
+       reset_control_assert(rst_hsic_p);
+       udelay(5);
+       reset_control_deassert(rst_hsic_h);
+       reset_control_deassert(rst_hsic_a);
+       reset_control_deassert(rst_hsic_p);
        mdelay(2);
 
        /* HSIC per-port reset */
@@ -491,18 +517,31 @@ static void rk_ehci_clock_enable(void *pdata, int enable)
        }
 }
 
-static void rk_ehci_soft_reset(void)
+static void rk_ehci_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0_H, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0PHY, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0C, true);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USB_HOST0, true);
-       udelay(5);
+       struct rkehci_platform_data *usbpdata = pdata;
+       struct reset_control *rst_host0_h, *rst_host0_p,
+                            *rst_host0_c , *rst_host0;
+
+       rst_host0_h = devm_reset_control_get(usbpdata->dev, "ehci_ahb");
+       rst_host0_p = devm_reset_control_get(usbpdata->dev, "ehci_phy");
+       rst_host0_c = devm_reset_control_get(usbpdata->dev, "ehci_controller");
+       rst_host0 = devm_reset_control_get(usbpdata->dev, "ehci");
+       if (IS_ERR(rst_host0_h) || IS_ERR(rst_host0_p) ||
+           IS_ERR(rst_host0_c) || IS_ERR(rst_host0)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
 
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0_H, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0PHY, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USBHOST0C, false);
-       rk3288_cru_set_soft_reset(RK3288_SOFT_RST_USB_HOST0, false);
+       reset_control_assert(rst_host0_h);
+       reset_control_assert(rst_host0_p);
+       reset_control_assert(rst_host0_c);
+       reset_control_assert(rst_host0);
+       udelay(5);
+       reset_control_deassert(rst_host0_h);
+       reset_control_deassert(rst_host0_p);
+       reset_control_deassert(rst_host0_c);
+       reset_control_deassert(rst_host0);
        mdelay(2);
 }
 
@@ -595,7 +634,7 @@ static void rk_ohci_clock_enable(void *pdata, int enable)
        }
 }
 
-static void rk_ohci_soft_reset(void)
+static void rk_ohci_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
 {
 }
 
@@ -725,34 +764,29 @@ static int otg_irq_detect_init(struct platform_device *pdev)
 
        /*register otg_bvalid irq */
        irq = platform_get_irq_byname(pdev, "otg_bvalid");
-       if (irq > 0) {
-               ret =
-                   request_irq(irq, bvalid_irq_handler, 0, "otg_bvalid", NULL);
+       if ((irq > 0) && control_usb->usb_irq_wakeup) {
+               ret = request_irq(irq, bvalid_irq_handler,
+                                 0, "otg_bvalid", NULL);
                if (ret < 0) {
                        dev_err(&pdev->dev, "request_irq %d failed!\n", irq);
-                       return ret;
                } else {
                        /* enable bvalid irq  */
                        control_usb->grf_uoc0_base->CON4 = 0x000c000c;
-                       if (control_usb->usb_irq_wakeup)
-                               enable_irq_wake(irq);
                }
        }
 
        /*register otg_id irq */
        irq = platform_get_irq_byname(pdev, "otg_id");
-       if (irq > 0) {
+       if ((irq > 0) && control_usb->usb_irq_wakeup) {
                ret = request_irq(irq, id_irq_handler, 0, "otg_id", NULL);
                if (ret < 0) {
                        dev_err(&pdev->dev, "request_irq %d failed!\n", irq);
-                       return ret;
                } else {
+                       /* enable otg_id irq */
                        control_usb->grf_uoc0_base->CON4 = 0x00f000f0;
-                       if (control_usb->usb_irq_wakeup)
-                               enable_irq_wake(irq);
                }
        }
-#ifdef USB_LINESTATE_IRQ
+#if 0
        /*register otg_linestate irq */
        irq = platform_get_irq_byname(pdev, "otg_linestate");
        if (irq > 0) {
index 72495a8c8291f5a88de9cb16cd5d59e1fb7e9d39..659bcf0fd41481e167180964aa456d2fefb1eaea 100755 (executable)
@@ -142,7 +142,7 @@ static ssize_t ehci_rkhsic_power_store(struct device *_dev,
                usb_remove_hcd(hcd);
                break;
        case 1: /* power on */
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_POR);
                usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);
 
                ehci_rkhsic_port_power(ehci, 1);
@@ -275,7 +275,7 @@ static int ehci_rkhsic_probe(struct platform_device *pdev)
        }
 
        if (pldata->soft_reset)
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_POR);;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
index 74fd0b786d537af39579ae42a7d12d0254de38ea..03217cd22e7ea9e67f155db8db77737ae5138490 100755 (executable)
@@ -97,7 +97,7 @@ static void rk_ehci_hcd_enable(struct work_struct *work)
                usb_remove_hcd(hcd);
 
                /* reset cru and reinitialize EHCI controller */
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_RECNT);
                usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);
                if (pldata->phy_suspend)
                        pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
@@ -228,7 +228,7 @@ static ssize_t ehci_power_store(struct device *_dev,
                usb_remove_hcd(hcd);
                break;
        case 1: /*  power on */
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_POR);
                usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);
                ehci_port_power(ehci, 1);
                break;
@@ -357,7 +357,7 @@ static int ehci_rk_probe(struct platform_device *pdev)
                pldata->phy_suspend(pldata, USB_PHY_ENABLED);
 
        if (pldata->soft_reset)
-               pldata->soft_reset();
+               pldata->soft_reset(pldata, RST_POR);;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {