thermal: ti-soc-thermal: Enable addition power management
authorAdam Ford <aford173@gmail.com>
Fri, 11 Sep 2020 12:31:56 +0000 (07:31 -0500)
committerDaniel Lezcano <daniel.lezcano@linaro.org>
Mon, 12 Oct 2020 10:08:36 +0000 (12:08 +0200)
The bandgap sensor can be idled when the processor is too, but it
isn't currently being done, so the power consumption of OMAP3
boards can elevated if the bangap sensor is enabled.

This patch attempts to use some additional power management
to idle the clock to the bandgap when not needed.

Signed-off-by: Adam Ford <aford173@gmail.com>
Reported-by: kernel test robot <lkp@intel.com>
Tested-by: Andreas Kemnade <andreas@kemnade.info> # GTA04
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20200911123157.759379-1-aford173@gmail.com
drivers/thermal/ti-soc-thermal/ti-bandgap.c
drivers/thermal/ti-soc-thermal/ti-bandgap.h

index ab19ceff6e2a73ff87c16e97a515e4dc32f1314d..5e596168ba73b5ba218ea98a719e122a00b8bf0c 100644 (file)
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/io.h>
+#include <linux/cpu_pm.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include "ti-bandgap.h"
 
 static int ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id);
+#ifdef CONFIG_PM_SLEEP
+static int bandgap_omap_cpu_notifier(struct notifier_block *nb,
+                                 unsigned long cmd, void *v);
+#endif
 
 /***   Helper functions to access registers and their bitfields   ***/
 
@@ -1008,6 +1018,11 @@ int ti_bandgap_probe(struct platform_device *pdev)
                }
        }
 
+#ifdef CONFIG_PM_SLEEP
+       bgp->nb.notifier_call = bandgap_omap_cpu_notifier;
+       cpu_pm_register_notifier(&bgp->nb);
+#endif
+
        return 0;
 
 remove_last_cooling:
@@ -1041,7 +1056,9 @@ int ti_bandgap_remove(struct platform_device *pdev)
        struct ti_bandgap *bgp = platform_get_drvdata(pdev);
        int i;
 
-       /* First thing is to remove sensor interfaces */
+       cpu_pm_unregister_notifier(&bgp->nb);
+
+       /* Remove sensor interfaces */
        for (i = 0; i < bgp->conf->sensor_count; i++) {
                if (bgp->conf->sensors[i].unregister_cooling)
                        bgp->conf->sensors[i].unregister_cooling(bgp, i);
@@ -1150,9 +1167,43 @@ static int ti_bandgap_suspend(struct device *dev)
        if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
                clk_disable_unprepare(bgp->fclock);
 
+       bgp->is_suspended = true;
+
        return err;
 }
 
+static int bandgap_omap_cpu_notifier(struct notifier_block *nb,
+                                 unsigned long cmd, void *v)
+{
+       struct ti_bandgap *bgp;
+
+       bgp = container_of(nb, struct ti_bandgap, nb);
+
+       spin_lock(&bgp->lock);
+       switch (cmd) {
+       case CPU_CLUSTER_PM_ENTER:
+               if (bgp->is_suspended)
+                       break;
+               ti_bandgap_save_ctxt(bgp);
+               ti_bandgap_power(bgp, false);
+               if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+                       clk_disable(bgp->fclock);
+               break;
+       case CPU_CLUSTER_PM_ENTER_FAILED:
+       case CPU_CLUSTER_PM_EXIT:
+               if (bgp->is_suspended)
+                       break;
+               if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+                       clk_enable(bgp->fclock);
+               ti_bandgap_power(bgp, true);
+               ti_bandgap_restore_ctxt(bgp);
+               break;
+       }
+       spin_unlock(&bgp->lock);
+
+       return NOTIFY_OK;
+}
+
 static int ti_bandgap_resume(struct device *dev)
 {
        struct ti_bandgap *bgp = dev_get_drvdata(dev);
@@ -1161,6 +1212,7 @@ static int ti_bandgap_resume(struct device *dev)
                clk_prepare_enable(bgp->fclock);
 
        ti_bandgap_power(bgp, true);
+       bgp->is_suspended = false;
 
        return ti_bandgap_restore_ctxt(bgp);
 }
index fce4657e94862a9ac16053b592f70f50ebc6db50..ed0ea4b17b256c24b1252c3c8a4f2933a24b1c11 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/err.h>
+#include <linux/cpu_pm.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm.h>
 
 struct gpio_desc;
 
@@ -203,6 +207,8 @@ struct ti_bandgap {
        int                             irq;
        struct gpio_desc                *tshut_gpiod;
        u32                             clk_rate;
+       struct notifier_block           nb;
+       unsigned int is_suspended:1;
 };
 
 /**