mfd: fusb302: avoid sending notifier to USB/DP during PM suspend

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>
This commit is contained in:
William Wu
2017-01-04 16:05:21 +08:00
committed by Huang, Tao
parent 1aba3144fc
commit 082f43af91

View 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);
}
}
}