[PATCH] rtc: tps6594: Add power management support

Richard Genoud posted 1 patch 2 years, 1 month ago
There is a newer version of this series
drivers/rtc/rtc-tps6594.c   | 46 +++++++++++++++++++++++++++++++++++++
include/linux/mfd/tps6594.h |  1 +
2 files changed, 47 insertions(+)
[PATCH] rtc: tps6594: Add power management support
Posted by Richard Genoud 2 years, 1 month ago
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(+)

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;
 };
 
-- 
2.43.0
Re: [PATCH] rtc: tps6594: Add power management support
Posted by kernel test robot 2 years, 1 month ago
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	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki