@@ -25,10 +25,20 @@
#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);
}
@@ -12,6 +12,10 @@
#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;
};
/**