Skip to content

Commit c88014c

Browse files
richard-bootlinalexandrebelloni
authored andcommitted
rtc: tps6594: Add power management support
Add power management support to the driver. This allows a SoC to wake from suspend using the nINT provided by the RTC. It takes care of the case when the interrupt has not been caught because the kernel has not yet woke up. (This is the case when only edges interrupt are caught) Signed-off-by: Richard Genoud <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Belloni <[email protected]>
1 parent 29bf975 commit c88014c

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

drivers/rtc/rtc-tps6594.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
struct tps6594_rtc {
4646
struct rtc_device *rtc_dev;
47+
int irq;
4748
};
4849

4950
static int tps6594_rtc_alarm_irq_enable(struct device *dev,
@@ -419,6 +420,8 @@ static int tps6594_rtc_probe(struct platform_device *pdev)
419420
if (irq < 0)
420421
return dev_err_probe(dev, irq, "Failed to get irq\n");
421422

423+
rtc->irq = irq;
424+
422425
ret = devm_request_threaded_irq(dev, irq, NULL, tps6594_rtc_interrupt,
423426
IRQF_ONESHOT, TPS6594_IRQ_NAME_ALARM,
424427
dev);
@@ -438,6 +441,49 @@ static int tps6594_rtc_probe(struct platform_device *pdev)
438441
return devm_rtc_register_device(rtc->rtc_dev);
439442
}
440443

444+
static int tps6594_rtc_resume(struct device *dev)
445+
{
446+
struct tps6594 *tps = dev_get_drvdata(dev->parent);
447+
struct tps6594_rtc *rtc = dev_get_drvdata(dev);
448+
int ret;
449+
450+
ret = regmap_test_bits(tps->regmap, TPS6594_REG_INT_STARTUP,
451+
TPS6594_BIT_RTC_INT);
452+
if (ret < 0) {
453+
dev_err(dev, "failed to read REG_INT_STARTUP: %d\n", ret);
454+
goto out;
455+
}
456+
457+
if (ret > 0) {
458+
/*
459+
* If the alarm bit is set, it means that the IRQ has been
460+
* fired. But, the kernel may not have woke up yet when it
461+
* happened. So, we have to clear it.
462+
*/
463+
ret = regmap_write(tps->regmap, TPS6594_REG_RTC_STATUS,
464+
TPS6594_BIT_ALARM);
465+
if (ret < 0)
466+
dev_err(dev, "error clearing alarm bit: %d", ret);
467+
468+
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
469+
}
470+
out:
471+
disable_irq_wake(rtc->irq);
472+
473+
return 0;
474+
}
475+
476+
static int tps6594_rtc_suspend(struct device *dev)
477+
{
478+
struct tps6594_rtc *rtc = dev_get_drvdata(dev);
479+
480+
enable_irq_wake(rtc->irq);
481+
482+
return 0;
483+
}
484+
485+
static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_rtc_pm_ops, tps6594_rtc_suspend, tps6594_rtc_resume);
486+
441487
static const struct platform_device_id tps6594_rtc_id_table[] = {
442488
{ "tps6594-rtc", },
443489
{}
@@ -448,6 +494,7 @@ static struct platform_driver tps6594_rtc_driver = {
448494
.probe = tps6594_rtc_probe,
449495
.driver = {
450496
.name = "tps6594-rtc",
497+
.pm = pm_sleep_ptr(&tps6594_rtc_pm_ops),
451498
},
452499
.id_table = tps6594_rtc_id_table,
453500
};

0 commit comments

Comments
 (0)