diff options
-rw-r--r-- | drivers/mfd/sec-core.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index b31824c33e15..cca0f990d287 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -323,6 +323,8 @@ static int sec_pmic_probe(struct i2c_client *i2c, if (ret) goto err; + device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); + return ret; err: @@ -341,6 +343,43 @@ static int sec_pmic_remove(struct i2c_client *i2c) return 0; } +static int sec_pmic_suspend(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) { + enable_irq_wake(sec_pmic->irq); + /* + * PMIC IRQ must be disabled during suspend for RTC alarm + * to work properly. + * When device is woken up from suspend by RTC Alarm, an + * interrupt occurs before resuming I2C bus controller. + * The interrupt is handled by regmap_irq_thread which tries + * to read RTC registers. This read fails (I2C is still + * suspended) and RTC Alarm interrupt is disabled. + */ + disable_irq(sec_pmic->irq); + } + + return 0; +} + +static int sec_pmic_resume(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) { + disable_irq_wake(sec_pmic->irq); + enable_irq(sec_pmic->irq); + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); + static const struct i2c_device_id sec_pmic_id[] = { { "sec_pmic", 0 }, { } @@ -351,6 +390,7 @@ static struct i2c_driver sec_pmic_driver = { .driver = { .name = "sec_pmic", .owner = THIS_MODULE, + .pm = &sec_pmic_pm_ops, .of_match_table = of_match_ptr(sec_dt_match), }, .probe = sec_pmic_probe, |