MLK-11340-27 usb: phy-mxs: Add implementation of nofity_suspend{resume}
authorPeter Chen <peter.chen@freescale.com>
Wed, 18 Sep 2013 05:57:59 +0000 (13:57 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:47:00 +0000 (14:47 -0500)
Implementation of notify_suspend and notify_resume will be different
according to mxs_phy_data->flags.

Signed-off-by: Peter Chen <peter.chen@freescale.com>
(cherry picked from commit d1ce766d9aabdfb823131d38056ff67c94e7e20a)

drivers/usb/phy/phy-mxs-usb.c

index 0e2f1a3..4333ae3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2014 Freescale Semiconductor, Inc.
+ * Copyright 2012-2015 Freescale Semiconductor, Inc.
  * Copyright (C) 2012 Marek Vasut <marex@denx.de>
  * on behalf of DENX Software Engineering GmbH
  *
@@ -479,6 +479,48 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,
        return 0;
 }
 
+static int mxs_phy_on_suspend(struct usb_phy *phy,
+               enum usb_device_speed speed)
+{
+       struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
+       dev_dbg(phy->dev, "%s device has suspended\n",
+               (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
+
+       /* delay 4ms to wait bus entering idle */
+       usleep_range(4000, 5000);
+
+       if (mxs_phy->data->flags & MXS_PHY_ABNORMAL_IN_SUSPEND) {
+               writel_relaxed(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
+               writel_relaxed(0, phy->io_priv + HW_USBPHY_PWD);
+       }
+
+       if (speed == USB_SPEED_HIGH)
+               writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+                               phy->io_priv + HW_USBPHY_CTRL_CLR);
+
+       return 0;
+}
+
+/*
+ * The resume signal must be finished here.
+ */
+static int mxs_phy_on_resume(struct usb_phy *phy,
+               enum usb_device_speed speed)
+{
+       dev_dbg(phy->dev, "%s device has resumed\n",
+               (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
+
+       if (speed == USB_SPEED_HIGH) {
+               /* Make sure the device has switched to High-Speed mode */
+               udelay(500);
+               writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+                               phy->io_priv + HW_USBPHY_CTRL_SET);
+       }
+
+       return 0;
+}
+
 static int mxs_phy_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -556,6 +598,8 @@ static int mxs_phy_probe(struct platform_device *pdev)
        if (ret < 0)
                dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);
        mxs_phy->port_id = ret;
+       mxs_phy->clk = clk;
+       mxs_phy->data = of_id->data;
 
        mxs_phy->phy.io_priv            = base;
        mxs_phy->phy.dev                = &pdev->dev;
@@ -567,9 +611,10 @@ static int mxs_phy_probe(struct platform_device *pdev)
        mxs_phy->phy.notify_disconnect  = mxs_phy_on_disconnect;
        mxs_phy->phy.type               = USB_PHY_TYPE_USB2;
        mxs_phy->phy.set_wakeup         = mxs_phy_set_wakeup;
-
-       mxs_phy->clk = clk;
-       mxs_phy->data = of_id->data;
+       if (mxs_phy->data->flags & MXS_PHY_SENDING_SOF_TOO_FAST) {
+               mxs_phy->phy.notify_suspend = mxs_phy_on_suspend;
+               mxs_phy->phy.notify_resume = mxs_phy_on_resume;
+       }
 
        platform_set_drvdata(pdev, mxs_phy);