usb: dwc_otg_310: fix usb vbus power controlled by pmic
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / usbdev_rk3368.c
index ebd263004117b5ad3c1ac16d38df52f667df5a81..833671c1e1e51f24a1194b35122ab0b9151a97a2 100644 (file)
@@ -131,7 +131,7 @@ static void usb20otg_clock_enable(void *pdata, int enable)
 static int usb20otg_get_status(int id)
 {
        int ret = -1;
-       u32 soc_status15 = uoc_read(0x4bc);
+       u32 soc_status15 = uoc_read(control_usb->grf_otg_st_offset);
 
        switch (id) {
        case USB_STATUS_BVABLID:
@@ -186,15 +186,17 @@ static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode)
 static void usb20otg_power_enable(int enable)
 {
        if (0 == enable) {
-               rk_battery_charger_detect_cb(USB_OTG_POWER_OFF);
                /* disable otg_drv power */
                if (gpio_is_valid(control_usb->otg_gpios->gpio))
                        gpio_set_value(control_usb->otg_gpios->gpio, 0);
+               else if (usb20otg_get_status(USB_STATUS_BVABLID))
+                       rk_battery_charger_detect_cb(USB_OTG_POWER_OFF);
        } else if (1 == enable) {
-               rk_battery_charger_detect_cb(USB_OTG_POWER_ON);
                /* enable otg_drv power */
                if (gpio_is_valid(control_usb->otg_gpios->gpio))
                        gpio_set_value(control_usb->otg_gpios->gpio, 1);
+               else if (!usb20otg_get_status(USB_STATUS_BVABLID))
+                       rk_battery_charger_detect_cb(USB_OTG_POWER_ON);
        }
 }
 
@@ -402,6 +404,7 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
        struct clk *hclk_usb_peri;
        struct regmap *grf;
        int gpio, ret = 0;
+       u32 offset;
 
        control_usb = devm_kzalloc(dev, sizeof(*control_usb), GFP_KERNEL);
        if (!control_usb) {
@@ -417,6 +420,14 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
        }
        control_usb->grf = grf;
 
+       /* get the reg offset of GRF_SOC_STATUS for USB2.0 OTG */
+       if (of_property_read_u32(np, "grf-offset", &offset)) {
+               dev_err(&pdev->dev, "missing reg property in node %s\n",
+                       np->name);
+               return -EINVAL;
+       }
+       control_usb->grf_otg_st_offset = offset;
+
        /* Init Vbus-drv GPIOs */
        control_usb->host_gpios =
            devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
@@ -466,8 +477,8 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
        /* Init hclk_usb_peri */
        hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri");
        if (IS_ERR(hclk_usb_peri)) {
-               dev_err(&pdev->dev, "Failed to get hclk_usb_peri\n");
-               return PTR_ERR(hclk_usb_peri);
+               dev_info(&pdev->dev, "no hclk_usb_peri clk specified\n");
+               hclk_usb_peri = NULL;
        }
        control_usb->hclk_usb_peri = hclk_usb_peri;
        clk_prepare_enable(hclk_usb_peri);