From 2214b81836b95ffd988a44e5e4acdfcda2f36c4b Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 18 Sep 2013 13:57:59 +0800 Subject: [PATCH] MLK-11340-27 usb: phy-mxs: Add implementation of nofity_suspend{resume} Implementation of notify_suspend and notify_resume will be different according to mxs_phy_data->flags. Signed-off-by: Peter Chen (cherry picked from commit d1ce766d9aabdfb823131d38056ff67c94e7e20a) --- drivers/usb/phy/phy-mxs-usb.c | 53 ++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 0e2f1a36d315..4333ae3f9cd5 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 Freescale Semiconductor, Inc. + * Copyright 2012-2015 Freescale Semiconductor, Inc. * Copyright (C) 2012 Marek Vasut * 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); -- 2.17.1