]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
thermal/drivers/qcom/tsens: Switch wake IRQ handling to PM callbacks
authorPriyansh Jain <priyansh.jain@oss.qualcomm.com>
Mon, 1 Jun 2026 06:37:56 +0000 (12:07 +0530)
committerDaniel Lezcano <daniel.lezcano@kernel.org>
Wed, 3 Jun 2026 07:13:02 +0000 (09:13 +0200)
This change improves power management by using the standardized PM
framework for wake IRQ handling.

Move wake IRQ control to the PM suspend/resume path:
- store uplow/critical IRQ numbers in struct tsens_priv
- enable wake IRQs in tsens_suspend_common() when wakeup is allowed
- disable wake IRQs in tsens_resume_common()
- mark the device wakeup-capable during probe

This aligns TSENS wake behavior with suspend flow and avoids keeping
wake IRQs permanently enabled during runtime.

Signed-off-by: Priyansh Jain <priyansh.jain@oss.qualcomm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
Link: https://patch.msgid.link/20260601-tsens_interrupt_wake_control-v2-1-ce9570946abd@oss.qualcomm.com
drivers/thermal/qcom/tsens-v2.c
drivers/thermal/qcom/tsens.c
drivers/thermal/qcom/tsens.h

index 8d9698ea3ec4018181e2ee161f607dd6300ea437..e06f8e5802e877ece0a4ac1850c97e1170d5656b 100644 (file)
@@ -263,7 +263,6 @@ static int __init init_tsens_v2_no_rpm(struct tsens_priv *priv)
 static const struct tsens_ops ops_generic_v2 = {
        .init           = init_common,
        .get_temp       = get_temp_tsens_valid,
-       .resume         = tsens_resume_common,
 };
 
 struct tsens_plat_data data_tsens_v2 = {
index cf7fc0d57a5420e4eda74e96c599e218e176d198..78d12c247fb9a6bad41530152895a84f61150828 100644 (file)
@@ -1129,22 +1129,30 @@ static int tsens_get_temp(struct thermal_zone_device *tz, int *temp)
 
 static int  __maybe_unused tsens_suspend(struct device *dev)
 {
+       int ret = 0;
        struct tsens_priv *priv = dev_get_drvdata(dev);
 
-       if (priv->ops && priv->ops->suspend)
-               return priv->ops->suspend(priv);
+       if (priv->ops && priv->ops->suspend) {
+               ret = priv->ops->suspend(priv);
+               if (ret)
+                       return ret;
+       }
 
-       return 0;
+       return tsens_suspend_common(priv);
 }
 
 static int __maybe_unused tsens_resume(struct device *dev)
 {
+       int ret = 0;
        struct tsens_priv *priv = dev_get_drvdata(dev);
 
-       if (priv->ops && priv->ops->resume)
-               return priv->ops->resume(priv);
+       if (priv->ops && priv->ops->resume) {
+               ret = priv->ops->resume(priv);
+               if (ret)
+                       return ret;
+       }
 
-       return 0;
+       return tsens_resume_common(priv);
 }
 
 static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
@@ -1215,7 +1223,7 @@ static const struct thermal_zone_device_ops tsens_of_ops = {
 };
 
 static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
-                             irq_handler_t thread_fn)
+                             irq_handler_t thread_fn, int *irq_num)
 {
        struct platform_device *pdev;
        int ret, irq;
@@ -1248,7 +1256,7 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
                        dev_err(&pdev->dev, "%s: failed to get irq\n",
                                __func__);
                else
-                       enable_irq_wake(irq);
+                       *irq_num = irq;
        }
 
        put_device(&pdev->dev);
@@ -1275,11 +1283,38 @@ static int tsens_reinit(struct tsens_priv *priv)
        return 0;
 }
 
+int tsens_suspend_common(struct tsens_priv *priv)
+{
+       if (!device_may_wakeup(priv->dev))
+               return 0;
+
+       if (priv->feat->combo_int)
+               enable_irq_wake(priv->combined_irq);
+       else {
+               enable_irq_wake(priv->uplow_irq);
+               if (priv->feat->crit_int)
+                       enable_irq_wake(priv->crit_irq);
+       }
+
+       return 0;
+}
+
 int tsens_resume_common(struct tsens_priv *priv)
 {
        if (pm_suspend_target_state == PM_SUSPEND_MEM)
                tsens_reinit(priv);
 
+       if (!device_may_wakeup(priv->dev))
+               return 0;
+
+       if (priv->feat->combo_int)
+               disable_irq_wake(priv->combined_irq);
+       else {
+               disable_irq_wake(priv->uplow_irq);
+               if (priv->feat->crit_int)
+                       disable_irq_wake(priv->crit_irq);
+       }
+
        return 0;
 }
 
@@ -1319,15 +1354,18 @@ static int tsens_register(struct tsens_priv *priv)
 
        if (priv->feat->combo_int) {
                ret = tsens_register_irq(priv, "combined",
-                                        tsens_combined_irq_thread);
+                                        tsens_combined_irq_thread,  &priv->combined_irq);
        } else {
-               ret = tsens_register_irq(priv, "uplow", tsens_irq_thread);
+               ret = tsens_register_irq(priv, "uplow", tsens_irq_thread,
+                                        &priv->uplow_irq);
                if (ret < 0)
                        return ret;
 
-               if (priv->feat->crit_int)
+               if (priv->feat->crit_int) {
                        ret = tsens_register_irq(priv, "critical",
-                                                tsens_critical_irq_thread);
+                                                tsens_critical_irq_thread,
+                                                &priv->crit_irq);
+               }
        }
 
        return ret;
@@ -1386,6 +1424,8 @@ static int tsens_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
+       device_init_wakeup(dev, true);
+
        if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
                return -EINVAL;
 
index ab57ad88c3f7c7984dc29a7082ddfe54d3c162cf..206ee2d5d301d11f7b0de768fcd56013ada5f5cf 100644 (file)
@@ -568,6 +568,9 @@ struct tsens_context {
  * @ops: pointer to list of callbacks supported by this device
  * @debug_root: pointer to debugfs dentry for all tsens
  * @debug: pointer to debugfs dentry for tsens controller
+ * @uplow_irq: IRQ number for uplow (upper/lower) threshold interrupts
+ * @crit_irq: IRQ number for critical threshold interrupts
+ * @combined_irq: IRQ number for combined threshold interrupts
  * @sensor: list of sensors attached to this device
  */
 struct tsens_priv {
@@ -589,6 +592,10 @@ struct tsens_priv {
        struct dentry                   *debug_root;
        struct dentry                   *debug;
 
+       int                             uplow_irq;
+       int                             crit_irq;
+       int                             combined_irq;
+
        struct tsens_sensor             sensor[] __counted_by(num_sensors);
 };
 
@@ -640,8 +647,17 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp);
 int get_temp_common(const struct tsens_sensor *s, int *temp);
 #ifdef CONFIG_SUSPEND
 int tsens_resume_common(struct tsens_priv *priv);
+int tsens_suspend_common(struct tsens_priv *priv);
 #else
-#define tsens_resume_common            NULL
+static inline int tsens_resume_common(struct tsens_priv *priv)
+{
+       return 0;
+}
+
+static inline int tsens_suspend_common(struct tsens_priv *priv)
+{
+       return 0;
+}
 #endif
 
 /* TSENS target */