MLK-10170 usb: phy: mxs: keep USBPHY2's clk always on
authorPeter Chen <peter.chen@freescale.com>
Tue, 3 Feb 2015 08:13:31 +0000 (16:13 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:47:04 +0000 (14:47 -0500)
Per IC engineer request, we need to keep USBPHY2's clk always on,
in this way, the USBPHY2 (PLL7) power can be controlled by
hardware suspend signal totally. It is benefit of USB remote wakeup
case which needs the resume signal be sent out as soon as
possible (without software interfere).

It is intended to fix the issue which this ticket describes, the
reason for this issue is the host does not send resume in time.

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

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

index 8d79bcf..0670ee8 100644 (file)
 #define MXS_PHY_TX_D_CAL_MIN                   79
 #define MXS_PHY_TX_D_CAL_MAX                   119
 
+/*
+ * At some versions, the PHY2's clock is controlled by hardware directly,
+ * eg, according to PHY's suspend status. In these PHYs, we only need to
+ * open the clock at the initialization and close it at its shutdown routine.
+ * It will be benefit for remote wakeup case which needs to send resume
+ * signal as soon as possible, and in this case, the resume signal can be sent
+ * out without software interfere.
+ */
+#define MXS_PHY_HARDWARE_CONTROL_PHY2_CLK      BIT(4)
+
 struct mxs_phy_data {
        unsigned int flags;
 };
@@ -138,12 +148,14 @@ static const struct mxs_phy_data imx23_phy_data = {
 static const struct mxs_phy_data imx6q_phy_data = {
        .flags = MXS_PHY_SENDING_SOF_TOO_FAST |
                MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
-               MXS_PHY_NEED_IP_FIX,
+               MXS_PHY_NEED_IP_FIX |
+               MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
 };
 
 static const struct mxs_phy_data imx6sl_phy_data = {
        .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
-               MXS_PHY_NEED_IP_FIX,
+               MXS_PHY_NEED_IP_FIX |
+               MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
 };
 
 static const struct mxs_phy_data vf610_phy_data = {
@@ -152,7 +164,8 @@ static const struct mxs_phy_data vf610_phy_data = {
 };
 
 static const struct mxs_phy_data imx6sx_phy_data = {
-       .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+       .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
+               MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
 };
 
 static const struct mxs_phy_data imx6ul_phy_data = {
@@ -179,6 +192,7 @@ struct mxs_phy {
        u32 tx_reg_set;
        u32 tx_reg_mask;
        struct regulator *phy_3p0;
+       bool hardware_control_phy2_clk;
 };
 
 static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
@@ -435,12 +449,17 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend)
                }
                writel(BM_USBPHY_CTRL_CLKGATE,
                       x->io_priv + HW_USBPHY_CTRL_SET);
-               clk_disable_unprepare(mxs_phy->clk);
+               if (!(mxs_phy->port_id == 1 &&
+                               mxs_phy->hardware_control_phy2_clk))
+                       clk_disable_unprepare(mxs_phy->clk);
        } else {
                mxs_phy_clock_switch_delay();
-               ret = clk_prepare_enable(mxs_phy->clk);
-               if (ret)
-                       return ret;
+               if (!(mxs_phy->port_id == 1 &&
+                               mxs_phy->hardware_control_phy2_clk)) {
+                       ret = clk_prepare_enable(mxs_phy->clk);
+                       if (ret)
+                               return ret;
+               }
                writel(BM_USBPHY_CTRL_CLKGATE,
                       x->io_priv + HW_USBPHY_CTRL_CLR);
                writel(0, x->io_priv + HW_USBPHY_PWD);
@@ -645,6 +664,9 @@ static int mxs_phy_probe(struct platform_device *pdev)
        if (mxs_phy->phy_3p0)
                regulator_set_voltage(mxs_phy->phy_3p0, 3200000, 3200000);
 
+       if (mxs_phy->data->flags & MXS_PHY_HARDWARE_CONTROL_PHY2_CLK)
+               mxs_phy->hardware_control_phy2_clk = true;
+
        platform_set_drvdata(pdev, mxs_phy);
 
        device_set_wakeup_capable(&pdev->dev, true);