mfd: fusb302: avoid sending notifier to USB/DP during PM suspend
authorWilliam Wu <wulf@rock-chips.com>
Wed, 4 Jan 2017 08:05:21 +0000 (16:05 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 6 Jan 2017 10:27:36 +0000 (18:27 +0800)
When system enter PM suspend, it will use a flag genpd->suspend_
power_off to disable device power domain operations, and device
can't enable its power domain until complete PM resume, or rather,
until call pm_genpd_complete() to clear suspend_power_off flag.

In some case, e.g. plug in Type-C PD adapter during system suspend,
and then wakeup system, the fusb302 may send notifier to USB/DP
before USB/DP complete PM resume, this may cause USB/DP fail to
enable their power domain.

I don't find a way to make sure USB/DP PM resume, fortunately,
the PM framework provides a flag pm_freezing to indicate that
complete PM resume all of devices.

Change-Id: I5c9a467691956250c1fa99b7a83f5fe306c0730a
Signed-off-by: William Wu <wulf@rock-chips.com>
drivers/mfd/fusb302.c

index 6f07904718e48721ef4e3ef9d19b0ddd70b5c9d4..3201a17fa53d7d92525315b59005f4a22cc013f9 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/delay.h>
 #include <linux/extcon.h>
+#include <linux/freezer.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -248,6 +249,32 @@ static void platform_fusb_notify(struct fusb30x_chip *chip)
                        usb_ss = 1;
                }
 
+               if (chip->notify.power_role == 0 &&
+                   chip->notify.is_pd_connected &&
+                   chip->pd_output_vol > 0 && chip->pd_output_cur > 0) {
+                       extcon_set_state(chip->extcon, EXTCON_CHG_USB_FAST,
+                                        true);
+                       property.intval =
+                               (chip->pd_output_cur << 15 |
+                                chip->pd_output_vol);
+                       extcon_set_property(chip->extcon, EXTCON_CHG_USB_FAST,
+                                           EXTCON_PROP_USB_TYPEC_POLARITY,
+                                           property);
+                       extcon_sync(chip->extcon, EXTCON_CHG_USB_FAST);
+               }
+
+#ifdef CONFIG_FREEZER
+               /*
+                * If system enter PM suspend, we need to wait until
+                * PM resume all of devices completion, then the flag
+                * pm_freezing will be set to false, and we can send
+                * notifier to USB/DP module safety, it make sure that
+                * USB/DP can enable power domain successfully.
+                */
+               while (pm_freezing)
+                       usleep_range(10000, 11000);
+#endif
+
                property.intval = flip;
                extcon_set_property(chip->extcon, EXTCON_USB,
                                    EXTCON_PROP_USB_TYPEC_POLARITY, property);
@@ -269,18 +296,6 @@ static void platform_fusb_notify(struct fusb30x_chip *chip)
                extcon_sync(chip->extcon, EXTCON_USB);
                extcon_sync(chip->extcon, EXTCON_USB_HOST);
                extcon_sync(chip->extcon, EXTCON_DISP_DP);
-               if (chip->notify.power_role == 0 &&
-                   chip->notify.is_pd_connected &&
-                   chip->pd_output_vol > 0 && chip->pd_output_cur > 0) {
-                       extcon_set_state(chip->extcon, EXTCON_CHG_USB_FAST, true);
-                       property.intval =
-                               (chip->pd_output_cur << 15 |
-                                chip->pd_output_vol);
-                       extcon_set_property(chip->extcon, EXTCON_CHG_USB_FAST,
-                                           EXTCON_PROP_USB_TYPEC_POLARITY,
-                                           property);
-                       extcon_sync(chip->extcon, EXTCON_CHG_USB_FAST);
-               }
        }
 }