From c00cc673bf2d8e47d90db14258944d4e42d632ed Mon Sep 17 00:00:00 2001 From: Bin Yang Date: Fri, 26 Jul 2019 16:09:18 +0800 Subject: [PATCH] mfd/fusb302: Add fusb302 suspend/resume functions We found that the Type-C OTG cable was plugged in while the system was suspending, it may fail to detect the Type-C OTG cable after resume. That's because the fusb302 registers will fail to operate during suspend, this will cause the fusb302 CC logic to be abnormal. So we should not operate queue_work function while the suspend. Change-Id: Idc675c25de5452ec39513eb484cfaa75534790cd Signed-off-by: Bin Yang --- drivers/mfd/fusb302.c | 31 ++++++++++++++++++++++++++++++- drivers/mfd/fusb302.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/fusb302.c b/drivers/mfd/fusb302.c index 28888fe1296d..a120e5764ecc 100644 --- a/drivers/mfd/fusb302.c +++ b/drivers/mfd/fusb302.c @@ -3287,7 +3287,8 @@ static void fusb302_work_func(struct work_struct *work) struct fusb30x_chip *chip; chip = container_of(work, struct fusb30x_chip, work); - state_machine_typec(chip); + if (!chip->suspended) + state_machine_typec(chip); } static int fusb30x_probe(struct i2c_client *client, @@ -3523,6 +3524,33 @@ static void fusb30x_shutdown(struct i2c_client *client) } } +static int fusb30x_pm_suspend(struct device *dev) +{ + struct fusb30x_chip *chip = dev_get_drvdata(dev); + + fusb_irq_disable(chip); + chip->suspended = true; + cancel_work_sync(&chip->work); + + return 0; +} + +static int fusb30x_pm_resume(struct device *dev) +{ + struct fusb30x_chip *chip = dev_get_drvdata(dev); + + fusb_irq_enable(chip); + chip->suspended = false; + queue_work(chip->fusb30x_wq, &chip->work); + + return 0; +} + +static const struct dev_pm_ops fusb30x_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(fusb30x_pm_suspend, + fusb30x_pm_resume) +}; + static const struct of_device_id fusb30x_dt_match[] = { { .compatible = FUSB30X_I2C_DEVICETREE_NAME }, {}, @@ -3539,6 +3567,7 @@ static struct i2c_driver fusb30x_driver = { .driver = { .name = FUSB30X_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(fusb30x_dt_match), + .pm = &fusb30x_pm_ops, }, .probe = fusb30x_probe, .remove = fusb30x_remove, diff --git a/drivers/mfd/fusb302.h b/drivers/mfd/fusb302.h index 9f629e54dec7..749bff859775 100644 --- a/drivers/mfd/fusb302.h +++ b/drivers/mfd/fusb302.h @@ -555,6 +555,7 @@ struct fusb30x_chip { bool try_role_complete; enum role_mode try_role; struct input_dev *input; + bool suspended; }; #endif /* FUSB302_H */