MALI: rockchip: adjust code about thermal for kernel 4.4
[firefly-linux-kernel-4.4.55.git] / drivers / phy / phy-twl4030-usb.c
index e2698d29f436848ef7b50a009af0df2a242060b5..f96065a81d1ec6aaeb5ff4fc30401086cdda029f 100644 (file)
 #define PMBR1                          0x0D
 #define GPIO_USB_4PIN_ULPI_2430C       (3 << 0)
 
+/*
+ * If VBUS is valid or ID is ground, then we know a
+ * cable is present and we need to be runtime-enabled
+ */
+static inline bool cable_present(enum omap_musb_vbus_id_status stat)
+{
+       return stat == OMAP_MUSB_VBUS_VALID ||
+               stat == OMAP_MUSB_ID_GROUND;
+}
+
 struct twl4030_usb {
        struct usb_phy          phy;
        struct device           *dev;
@@ -386,8 +396,6 @@ static int twl4030_usb_runtime_suspend(struct device *dev)
        struct twl4030_usb *twl = dev_get_drvdata(dev);
 
        dev_dbg(twl->dev, "%s\n", __func__);
-       if (pm_runtime_suspended(dev))
-               return 0;
 
        __twl4030_phy_power(twl, 0);
        regulator_disable(twl->usb1v5);
@@ -403,8 +411,6 @@ static int twl4030_usb_runtime_resume(struct device *dev)
        int res;
 
        dev_dbg(twl->dev, "%s\n", __func__);
-       if (pm_runtime_active(dev))
-               return 0;
 
        res = regulator_enable(twl->usb3v1);
        if (res)
@@ -536,8 +542,10 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 
        mutex_lock(&twl->lock);
        if (status >= 0 && status != twl->linkstat) {
+               status_changed =
+                       cable_present(twl->linkstat) !=
+                       cable_present(status);
                twl->linkstat = status;
-               status_changed = true;
        }
        mutex_unlock(&twl->lock);
 
@@ -553,15 +561,11 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
                 * USB_LINK_VBUS state.  musb_hdrc won't care until it
                 * starts to handle softconnect right.
                 */
-               if ((status == OMAP_MUSB_VBUS_VALID) ||
-                   (status == OMAP_MUSB_ID_GROUND)) {
-                       if (pm_runtime_suspended(twl->dev))
-                               pm_runtime_get_sync(twl->dev);
+               if (cable_present(status)) {
+                       pm_runtime_get_sync(twl->dev);
                } else {
-                       if (pm_runtime_active(twl->dev)) {
-                               pm_runtime_mark_last_busy(twl->dev);
-                               pm_runtime_put_autosuspend(twl->dev);
-                       }
+                       pm_runtime_mark_last_busy(twl->dev);
+                       pm_runtime_put_autosuspend(twl->dev);
                }
                omap_musb_mailbox(status);
        }
@@ -644,7 +648,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        struct usb_otg          *otg;
        struct device_node      *np = pdev->dev.of_node;
        struct phy_provider     *phy_provider;
-       struct phy_init_data    *init_data = NULL;
 
        twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
        if (!twl)
@@ -655,7 +658,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
                                (enum twl4030_usb_mode *)&twl->usb_mode);
        else if (pdata) {
                twl->usb_mode = pdata->usb_mode;
-               init_data = pdata->init_data;
        } else {
                dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
                return -EINVAL;
@@ -668,7 +670,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        twl->dev                = &pdev->dev;
        twl->irq                = platform_get_irq(pdev, 0);
        twl->vbus_supplied      = false;
-       twl->linkstat           = -EINVAL;
        twl->linkstat           = OMAP_MUSB_UNKNOWN;
 
        twl->phy.dev            = twl->dev;
@@ -680,7 +681,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        otg->set_host           = twl4030_set_host;
        otg->set_peripheral     = twl4030_set_peripheral;
 
-       phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
+       phy = devm_phy_create(twl->dev, NULL, &ops);
        if (IS_ERR(phy)) {
                dev_dbg(&pdev->dev, "Failed to create PHY\n");
                return PTR_ERR(phy);
@@ -733,6 +734,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
                return status;
        }
 
+       if (pdata)
+               err = phy_create_lookup(phy, "usb", "musb-hdrc.0");
+       if (err)
+               return err;
+
        pm_runtime_mark_last_busy(&pdev->dev);
        pm_runtime_put_autosuspend(twl->dev);
 
@@ -745,6 +751,7 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        struct twl4030_usb *twl = platform_get_drvdata(pdev);
        int val;
 
+       usb_remove_phy(&twl->phy);
        pm_runtime_get_sync(twl->dev);
        cancel_delayed_work(&twl->id_workaround_work);
        device_remove_file(twl->dev, &dev_attr_vbus);
@@ -752,6 +759,13 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        /* set transceiver mode to power on defaults */
        twl4030_usb_set_mode(twl, -1);
 
+       /* idle ulpi before powering off */
+       if (cable_present(twl->linkstat))
+               pm_runtime_put_noidle(twl->dev);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put_sync_suspend(twl->dev);
+       pm_runtime_disable(twl->dev);
+
        /* autogate 60MHz ULPI clock,
         * clear dpll clock request for i2c access,
         * disable 32KHz
@@ -765,8 +779,6 @@ static int twl4030_usb_remove(struct platform_device *pdev)
 
        /* disable complete OTG block */
        twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-       pm_runtime_mark_last_busy(twl->dev);
-       pm_runtime_put(twl->dev);
 
        return 0;
 }