Merge branch develop-3.10 into develop-3.10-next
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / usbdev_rk32.c
index d1a9406fe3f910acfa3935c600da1476b0a3e38c..84894be0ed0aa1b37c511b74e683f9e776bb4281 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;
 
-       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);
+       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;
+       }
+
+       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);
 }
 
@@ -124,9 +134,27 @@ static int usb20otg_get_status(int id)
 }
 
 #ifdef CONFIG_RK_USB_UART
+/**
+ *  dwc_otg_uart_enabled - check if a usb-uart bypass func is enabled in DT
+ *
+ *  Returns true if the status property of node "usb_uart" is set to "okay"
+ *  or "ok", if this property is absent it will use the default status "ok"
+ *  0 otherwise
+ */
+static bool dwc_otg_uart_enabled(void)
+{
+       struct device_node *np;
+
+       np = of_find_node_by_name(NULL, "usb_uart");
+       if (np && of_device_is_available(np))
+               return true;
+
+       return false;
+}
+
 static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode)
 {
-       if (1 == enter_usb_uart_mode) {
+       if ((1 == enter_usb_uart_mode) && dwc_otg_uart_enabled()) {
                /* bypass dm, enter uart mode */
                control_usb->grf_uoc0_base->CON3 = (0x00c0 | (0x00c0 << 16));
 
@@ -135,6 +163,10 @@ static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode)
                control_usb->grf_uoc0_base->CON3 = (0x00c0 << 16);
        }
 }
+#else
+static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode)
+{
+}
 #endif
 
 static void usb20otg_power_enable(int enable)
@@ -162,10 +194,8 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3288 = {
        .clock_enable = usb20otg_clock_enable,
        .get_status = usb20otg_get_status,
        .power_enable = usb20otg_power_enable,
-#ifdef CONFIG_RK_USB_UART
        .dwc_otg_uart_mode = dwc_otg_uart_mode,
-#endif
-       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+       .bc_detect_cb = rk_battery_charger_detect_cb,
 };
 
 #endif
@@ -206,16 +236,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;
+
+       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;
+       }
 
-       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);
+       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);
 }
 
@@ -297,7 +337,8 @@ static void usb20host_power_enable(int enable)
 {
        if (0 == enable) {
                /* disable host_drv power */
-               /* do not disable power in default */
+               if (gpio_is_valid(control_usb->host_gpios->gpio))
+                       gpio_set_value(control_usb->host_gpios->gpio, 0);
        } else if (1 == enable) {
                /* enable host_drv power */
                if (gpio_is_valid(control_usb->host_gpios->gpio))
@@ -392,16 +433,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 +538,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 +655,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)
 {
 }
 
@@ -623,7 +683,7 @@ static inline void do_wakeup(struct work_struct *work)
 
 static void usb_battery_charger_detect_work(struct work_struct *work)
 {
-       rk_usb_charger_status = usb_battery_charger_detect(0);
+       rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
 }
 
 /********** handler for bvalid irq **********/
@@ -632,10 +692,8 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
        /* clear irq */
        control_usb->grf_uoc0_base->CON4 = (0x0008 | (0x0008 << 16));
 
-#ifdef CONFIG_RK_USB_UART
        /* usb otg dp/dm switch to usb phy */
        dwc_otg_uart_mode(NULL, PHY_USB_MODE);
-#endif
 
        if (control_usb->usb_irq_wakeup) {
                wake_lock_timeout(&control_usb->usb_wakelock,
@@ -643,8 +701,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
                schedule_delayed_work(&control_usb->usb_det_wakeup_work,
                                      HZ / 10);
        }
-
-       rk_usb_charger_status = USB_BC_TYPE_SDP;
        schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
 
        return IRQ_HANDLED;
@@ -666,10 +722,8 @@ static irqreturn_t id_irq_handler(int irq, void *dev_id)
 
        /* id fall */
        if (uoc_con & (1 << 7)) {
-#ifdef CONFIG_RK_USB_UART
                /* usb otg dp/dm switch to usb phy */
                dwc_otg_uart_mode(NULL, PHY_USB_MODE);
-#endif
                /* clear id fall irq pandding */
                control_usb->grf_uoc0_base->CON4 = ((1 << 7) | (1 << 23));
        }
@@ -716,7 +770,6 @@ static int otg_irq_detect_init(struct platform_device *pdev)
 {
        int ret = 0;
        int irq = 0;
-
        if (control_usb->usb_irq_wakeup) {
                wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND,
                               "usb_detect");
@@ -725,34 +778,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) {
@@ -1062,11 +1110,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
                goto err2;
        }
 #ifdef CONFIG_USB20_OTG
-       if (usb20otg_get_status(USB_STATUS_BVABLID)) {
-               rk_usb_charger_status = USB_BC_TYPE_SDP;
+       if (usb20otg_get_status(USB_STATUS_BVABLID))
                schedule_delayed_work(&control_usb->usb_charger_det_work,
                                      HZ / 10);
-       }
 #endif
 
        ret = otg_irq_detect_init(pdev);