From 87dea13d05fd867d5ae918718da858a0b36a0db4 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 b02edd2a2ab5..2c7bb58ab596 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 */