diff mbox series

rtc: tps6594: Add power management support

Message ID 20240513162942.68484-1-richard.genoud@bootlin.com
State New
Headers show
Series rtc: tps6594: Add power management support | expand

Commit Message

Richard Genoud May 13, 2024, 4:29 p.m. UTC
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 <richard.genoud@bootlin.com>
---
 drivers/rtc/rtc-tps6594.c   | 46 +++++++++++++++++++++++++++++++++++++
 include/linux/mfd/tps6594.h |  1 +
 2 files changed, 47 insertions(+)

Comments

kernel test robot May 14, 2024, 7:09 a.m. UTC | #1
Hi Richard,

kernel test robot noticed the following build warnings:

[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on lee-mfd/for-mfd-next lee-leds/for-leds-next lee-mfd/for-mfd-fixes linus/master v6.9 next-20240513]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Richard-Genoud/rtc-tps6594-Add-power-management-support/20240514-003053
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link:    https://lore.kernel.org/r/20240513162942.68484-1-richard.genoud%40bootlin.com
patch subject: [PATCH] rtc: tps6594: Add power management support
config: sparc-randconfig-r081-20240514 (https://download.01.org/0day-ci/archive/20240514/202405141408.o5jSp8nU-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240514/202405141408.o5jSp8nU-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405141408.o5jSp8nU-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/rtc/rtc-tps6594.c:471:12: warning: 'tps6594_rtc_suspend' defined but not used [-Wunused-function]
     471 | static int tps6594_rtc_suspend(struct device *dev)
         |            ^~~~~~~~~~~~~~~~~~~
>> drivers/rtc/rtc-tps6594.c:439:12: warning: 'tps6594_rtc_resume' defined but not used [-Wunused-function]
     439 | static int tps6594_rtc_resume(struct device *dev)
         |            ^~~~~~~~~~~~~~~~~~


vim +/tps6594_rtc_suspend +471 drivers/rtc/rtc-tps6594.c

   438	
 > 439	static int tps6594_rtc_resume(struct device *dev)
   440	{
   441		struct tps6594 *tps = dev_get_drvdata(dev->parent);
   442		struct rtc_device *rtc_dev = dev_get_drvdata(dev);
   443		int ret;
   444	
   445		ret = regmap_test_bits(tps->regmap, TPS6594_REG_INT_STARTUP,
   446				       TPS6594_BIT_RTC_INT);
   447		if (ret < 0) {
   448			dev_err(dev, "failed to read REG_INT_STARTUP: %d\n", ret);
   449			goto out;
   450		}
   451	
   452		if (ret > 0) {
   453			/*
   454			 * If the alarm bit is set, it means that the IRQ has been
   455			 * fired. But, the kernel may not have woke up yet when it
   456			 * happened. So, we have to clear it.
   457			 */
   458			ret = regmap_write(tps->regmap, TPS6594_REG_RTC_STATUS,
   459					   TPS6594_BIT_ALARM);
   460			if (ret < 0)
   461				dev_err(dev, "error clearing alarm bit: %d", ret);
   462	
   463			rtc_update_irq(rtc_dev, 1, RTC_IRQF | RTC_AF);
   464		}
   465	out:
   466		disable_irq_wake(tps->irq_rtc);
   467	
   468		return 0;
   469	}
   470	
 > 471	static int tps6594_rtc_suspend(struct device *dev)
   472	{
   473		struct tps6594 *tps = dev_get_drvdata(dev->parent);
   474	
   475		enable_irq_wake(tps->irq_rtc);
   476	
   477		return 0;
   478	}
   479
diff mbox series

Patch

diff --git a/drivers/rtc/rtc-tps6594.c b/drivers/rtc/rtc-tps6594.c
index 838ae8562a35..b769d120c624 100644
--- a/drivers/rtc/rtc-tps6594.c
+++ b/drivers/rtc/rtc-tps6594.c
@@ -415,6 +415,8 @@  static int tps6594_rtc_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return dev_err_probe(dev, irq, "Failed to get irq\n");
 
+	tps->irq_rtc = irq;
+
 	ret = devm_request_threaded_irq(dev, irq, NULL, tps6594_rtc_interrupt,
 					IRQF_ONESHOT, TPS6594_IRQ_NAME_ALARM,
 					dev);
@@ -434,6 +436,49 @@  static int tps6594_rtc_probe(struct platform_device *pdev)
 	return devm_rtc_register_device(rtc);
 }
 
+static int tps6594_rtc_resume(struct device *dev)
+{
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	struct rtc_device *rtc_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regmap_test_bits(tps->regmap, TPS6594_REG_INT_STARTUP,
+			       TPS6594_BIT_RTC_INT);
+	if (ret < 0) {
+		dev_err(dev, "failed to read REG_INT_STARTUP: %d\n", ret);
+		goto out;
+	}
+
+	if (ret > 0) {
+		/*
+		 * If the alarm bit is set, it means that the IRQ has been
+		 * fired. But, the kernel may not have woke up yet when it
+		 * happened. So, we have to clear it.
+		 */
+		ret = regmap_write(tps->regmap, TPS6594_REG_RTC_STATUS,
+				   TPS6594_BIT_ALARM);
+		if (ret < 0)
+			dev_err(dev, "error clearing alarm bit: %d", ret);
+
+		rtc_update_irq(rtc_dev, 1, RTC_IRQF | RTC_AF);
+	}
+out:
+	disable_irq_wake(tps->irq_rtc);
+
+	return 0;
+}
+
+static int tps6594_rtc_suspend(struct device *dev)
+{
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+
+	enable_irq_wake(tps->irq_rtc);
+
+	return 0;
+}
+
+SIMPLE_DEV_PM_OPS(tps6594_rtc_pm_ops, tps6594_rtc_suspend, tps6594_rtc_resume);
+
 static const struct platform_device_id tps6594_rtc_id_table[] = {
 	{ "tps6594-rtc", },
 	{}
@@ -444,6 +489,7 @@  static struct platform_driver tps6594_rtc_driver = {
 	.probe		= tps6594_rtc_probe,
 	.driver		= {
 		.name	= "tps6594-rtc",
+		.pm = pm_sleep_ptr(&tps6594_rtc_pm_ops),
 	},
 	.id_table = tps6594_rtc_id_table,
 };
diff --git a/include/linux/mfd/tps6594.h b/include/linux/mfd/tps6594.h
index 3f7c5e23cd4c..85933f1519c4 100644
--- a/include/linux/mfd/tps6594.h
+++ b/include/linux/mfd/tps6594.h
@@ -1011,6 +1011,7 @@  struct tps6594 {
 	bool use_crc;
 	struct regmap *regmap;
 	int irq;
+	int irq_rtc;
 	struct regmap_irq_chip_data *irq_data;
 };