usb: dwc_otg: fix problems of commit 058d627
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / dwc_otg_driver.c
index d20173159647d44dc96ef0cd419f642d2a7e5a58..16a4464dc51d6bfca7cfdbec05a08d761f8198e1 100755 (executable)
@@ -86,6 +86,14 @@ static struct usb20otg_pdata_id usb20otg_pdata[] = {
         .name = "rk3288-usb20otg",
         .pdata = &usb20otg_pdata_rk3288,
         },
+       {
+        .name = "rk3036-usb20otg",
+        .pdata = &usb20otg_pdata_rk3036,
+        },
+       {
+        .name = "rk3126-usb20otg",
+        .pdata = &usb20otg_pdata_rk3126,
+        },
        {},
 };
 #endif
@@ -100,13 +108,19 @@ static struct usb20host_pdata_id usb20host_pdata[] = {
         .name = "rk3288-usb20host",
         .pdata = &usb20host_pdata_rk3288,
         },
+       {
+        .name = "rk3036-usb20host",
+        .pdata = &usb20host_pdata_rk3036,
+        },
+       {
+        .name = "rk3126-usb20host",
+        .pdata = &usb20host_pdata_rk3126,
+        },
        {},
 };
 #endif
 
-#ifdef CONFIG_RK_USB_UART
 static u32 usb_to_uart_status;
-#endif
 /*-------------------------------------------------------------------------*/
 /* Encapsulate the module parameter settings */
 
@@ -433,28 +447,6 @@ void dwc_otg_force_device(dwc_otg_core_if_t *core_if)
        local_irq_restore(flags);
 }
 
-static void dwc_otg_set_force_mode(dwc_otg_core_if_t *core_if, int mode)
-{
-       gusbcfg_data_t usbcfg = {.d32 = 0 };
-       printk("!!!dwc_otg_set_force_mode\n");
-       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
-       switch (mode) {
-       case USB_MODE_FORCE_HOST:
-               usbcfg.b.force_host_mode = 1;
-               usbcfg.b.force_dev_mode = 0;
-               break;
-       case USB_MODE_FORCE_DEVICE:
-               usbcfg.b.force_host_mode = 0;
-               usbcfg.b.force_dev_mode = 1;
-               break;
-       case USB_MODE_NORMAL:
-               usbcfg.b.force_host_mode = 0;
-               usbcfg.b.force_dev_mode = 0;
-               break;
-       }
-       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
-}
-
 static ssize_t force_usb_mode_show(struct device_driver *drv, char *buf)
 {
        dwc_otg_device_t *otg_dev = g_otgdev;
@@ -570,6 +562,43 @@ static ssize_t dwc_otg_conn_en_store(struct device_driver *_drv,
 static DRIVER_ATTR(dwc_otg_conn_en, S_IRUGO | S_IWUSR, dwc_otg_conn_en_show,
                   dwc_otg_conn_en_store);
 
+/* used for product vbus power control, SDK not need.
+ * If dwc_otg is host mode, enable vbus power.
+ * If dwc_otg is device mode, disable vbus power.
+ * return 1 - host mode, 0 - device mode.
+ */
+int dwc_otg_usb_state(void)
+{
+       dwc_otg_device_t *otg_dev = g_otgdev;
+
+       if (otg_dev) {
+               /* op_state is A_HOST */
+               if (1 == otg_dev->core_if->op_state)
+                       return 1;
+               /* op_state is B_PERIPHERAL */
+               else if (4 == otg_dev->core_if->op_state)
+                       return 0;
+               else
+                       return 0;
+       } else {
+               DWC_WARN("g_otgdev is NULL, maybe otg probe is failed!\n");
+               return 0;
+       }
+}
+EXPORT_SYMBOL(dwc_otg_usb_state);
+
+static ssize_t dwc_otg_op_state_show(struct device_driver *_drv, char *_buf)
+{
+       dwc_otg_device_t *otg_dev = g_otgdev;
+
+       if (otg_dev) {
+               return sprintf(_buf, "%d\n", otg_dev->core_if->op_state);
+       } else {
+               return sprintf(_buf, "%d\n", 0);
+       }
+}
+static DRIVER_ATTR(op_state, S_IRUGO, dwc_otg_op_state_show, NULL);
+
 static ssize_t vbus_status_show(struct device_driver *_drv, char *_buf)
 {
        dwc_otg_device_t *otg_dev = g_otgdev;
@@ -935,6 +964,14 @@ static const struct of_device_id usb20_host_of_match[] = {
         .compatible = "rockchip,rk3288_usb20_host",
         .data = &usb20host_pdata[RK3288_USB_CTLR],
         },
+       {
+        .compatible = "rockchip,rk3036_usb20_host",
+        .data = &usb20host_pdata[RK3036_USB_CTLR],
+        },
+       {
+        .compatible = "rockchip,rk3126_usb20_host",
+        .data = &usb20host_pdata[RK3126_USB_CTLR],
+        },
        {},
 };
 
@@ -992,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);
 
@@ -1156,12 +1193,18 @@ static int dwc_otg_driver_resume(struct platform_device *_dev)
 static void dwc_otg_driver_shutdown(struct platform_device *_dev)
 {
        struct device *dev = &_dev->dev;
+       struct dwc_otg_platform_data *pldata = dev->platform_data;
        dwc_otg_device_t *otg_dev = dev->platform_data;
        dwc_otg_core_if_t *core_if = otg_dev->core_if;
        dctl_data_t dctl = {.d32 = 0 };
 
        DWC_PRINTF("%s: disconnect USB %s mode\n", __func__,
                   dwc_otg_is_host_mode(core_if) ? "host" : "device");
+
+    if( pldata->dwc_otg_uart_mode != NULL)
+        pldata->dwc_otg_uart_mode( pldata, PHY_USB_MODE);
+    if(pldata->phy_suspend != NULL)
+        pldata->phy_suspend(pldata, USB_PHY_ENABLED);
        if (dwc_otg_is_host_mode(core_if)) {
                if (core_if->hcd_cb && core_if->hcd_cb->stop)
                        core_if->hcd_cb->stop(core_if->hcd_cb_p);
@@ -1289,6 +1332,14 @@ static const struct of_device_id usb20_otg_of_match[] = {
         .compatible = "rockchip,rk3288_usb20_otg",
         .data = &usb20otg_pdata[RK3288_USB_CTLR],
         },
+       {
+        .compatible = "rockchip,rk3036_usb20_otg",
+        .data = &usb20otg_pdata[RK3036_USB_CTLR],
+        },
+       {
+        .compatible = "rockchip,rk3126_usb20_otg",
+        .data = &usb20otg_pdata[RK3126_USB_CTLR],
+        },
        {
         },
 };
@@ -1545,7 +1596,11 @@ void rk_usb_power_up(void)
        struct dwc_otg_platform_data *pldata_otg;
        struct dwc_otg_platform_data *pldata_host;
        struct rkehci_platform_data *pldata_ehci;
-
+       if (cpu_is_rk312x()) {
+               pldata_otg = &usb20otg_pdata_rk3126;
+               if (usb_to_uart_status)
+                       pldata_otg->dwc_otg_uart_mode(pldata_otg, PHY_UART_MODE);
+       }
        if (cpu_is_rk3288()) {
 #ifdef CONFIG_RK_USB_UART
                /* enable USB bypass UART function  */
@@ -1591,6 +1646,11 @@ void rk_usb_power_down(void)
        struct dwc_otg_platform_data *pldata_host;
        struct rkehci_platform_data *pldata_ehci;
 
+       if (cpu_is_rk312x()) {
+               pldata_otg = &usb20otg_pdata_rk3126;
+               usb_to_uart_status = pldata_otg->get_status(USB_STATUS_UARTMODE);
+               pldata_otg->dwc_otg_uart_mode(pldata_otg, PHY_USB_MODE);
+       }
        if (cpu_is_rk3288()) {
 #ifdef CONFIG_RK_USB_UART
                /* disable USB bypass UART function */
@@ -1678,6 +1738,9 @@ static int __init dwc_otg_driver_init(void)
        error =
            driver_create_file(&dwc_otg_driver.driver,
                               &driver_attr_force_usb_mode);
+       error =
+           driver_create_file(&dwc_otg_driver.driver,
+                              &driver_attr_op_state);
 
 #endif
 
@@ -1729,6 +1792,7 @@ static void __exit dwc_otg_driver_cleanup(void)
        driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
        driver_remove_file(&dwc_otg_driver.driver, &driver_attr_vbus_status);
        driver_remove_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode);
+       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_op_state);
        platform_driver_unregister(&dwc_otg_driver);
        printk(KERN_INFO "%s module removed\n", dwc_otg20_driver_name);
 #endif