MLK-13125 usb: phy: phy-mxs-usb: enable weak 1p1 regulator for imx6ul during suspend
authorPeter Chen <peter.chen@nxp.com>
Wed, 7 Sep 2016 04:16:59 +0000 (12:16 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:52:15 +0000 (14:52 -0500)
For imx6ul PHY, when the system enters suspend, its 1p1 is off by default,
that may cause the PHY get inaccurate USB DP/DM value. If the USB wakeup
is enabled at this time, the unexpected wakeup may occur when the system
enters suspend.

In this patch, when the vbus is there, we enable weak 1p1 during the PHY
suspend API, in that case, the USB DP/DM will be accurate for USB PHY,
then unexpected usb wakeup will not be occurred, especially for the USB
charger is connected scenario. The user needs to enable PHY wakeup for
USB wakeup function using below setting.

echo enabled > /sys/devices/platform/soc/2000000.aips-bus/20c9000.usbphy
/power/wakeup

Cc: Shaojun Wang <shaojun.wang@nxp.com>
Cc: Anson Huang <anson.huang@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
drivers/usb/phy/phy-mxs-usb.c

index 20ca0e6..5cdf06e 100644 (file)
@@ -64,6 +64,9 @@
 #define BM_USBPHY_DEBUG_CLKGATE                        BIT(30)
 
 /* Anatop Registers */
+#define ANADIG_REG_1P1_SET                     0x114
+#define ANADIG_REG_1P1_CLR                     0x118
+
 #define ANADIG_ANA_MISC0                       0x150
 #define ANADIG_ANA_MISC0_SET                   0x154
 #define ANADIG_ANA_MISC0_CLR                   0x158
@@ -95,6 +98,9 @@
 #define BM_ANADIG_USB2_MISC_RX_VPIN_FS         BIT(29)
 #define BM_ANADIG_USB2_MISC_RX_VMIN_FS         BIT(28)
 
+#define BM_ANADIG_REG_1P1_ENABLE_WEAK_LINREG   BIT(18)
+#define BM_ANADIG_REG_1P1_TRACK_VDD_SOC_CAP    BIT(19)
+
 #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
 
 /* Do disconnection between PHY and controller without vbus */
@@ -169,7 +175,8 @@ static const struct mxs_phy_data imx6sx_phy_data = {
 };
 
 static const struct mxs_phy_data imx6ul_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 of_device_id mxs_phy_dt_ids[] = {
@@ -206,6 +213,11 @@ static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
        return mxs_phy->data == &imx6sl_phy_data;
 }
 
+static inline bool is_imx6ul_phy(struct mxs_phy *mxs_phy)
+{
+       return mxs_phy->data == &imx6ul_phy_data;
+}
+
 /*
  * PHY needs some 32K cycles to switch from 32K clock to
  * bus (such as AHB/AXI, etc) clock.
@@ -687,18 +699,30 @@ static int mxs_phy_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
 {
-       unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
+       unsigned int reg;
+       u32 value;
 
        /* If the SoCs don't have anatop, quit */
        if (!mxs_phy->regmap_anatop)
                return;
 
-       if (is_imx6q_phy(mxs_phy))
+       if (is_imx6q_phy(mxs_phy)) {
+               reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
                regmap_write(mxs_phy->regmap_anatop, reg,
                        BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
-       else if (is_imx6sl_phy(mxs_phy))
+       } else if (is_imx6sl_phy(mxs_phy)) {
+               reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
                regmap_write(mxs_phy->regmap_anatop,
                        reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
+       } else if (is_imx6ul_phy(mxs_phy)) {
+               reg = on ? ANADIG_REG_1P1_SET : ANADIG_REG_1P1_CLR;
+               value = BM_ANADIG_REG_1P1_ENABLE_WEAK_LINREG |
+                       BM_ANADIG_REG_1P1_TRACK_VDD_SOC_CAP;
+               if (mxs_phy_get_vbus_status(mxs_phy) && on)
+                       regmap_write(mxs_phy->regmap_anatop, reg, value);
+               else if (!on)
+                       regmap_write(mxs_phy->regmap_anatop, reg, value);
+       }
 }
 
 static int mxs_phy_system_suspend(struct device *dev)