|
@@ -14,6 +14,7 @@
|
|
|
*/
|
|
|
#undef DEBUG
|
|
|
|
|
|
+#include <linux/cpu_pm.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/types.h>
|
|
|
#include <linux/list.h>
|
|
@@ -39,6 +40,9 @@
|
|
|
|
|
|
#define PWRDM_TRACE_STATES_FLAG (1<<31)
|
|
|
|
|
|
+void pwrdms_save_context(void);
|
|
|
+void pwrdms_restore_context(void);
|
|
|
+
|
|
|
enum {
|
|
|
PWRDM_STATE_NOW = 0,
|
|
|
PWRDM_STATE_PREV,
|
|
@@ -333,6 +337,22 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
|
|
|
+{
|
|
|
+ switch (cmd) {
|
|
|
+ case CPU_CLUSTER_PM_ENTER:
|
|
|
+ if (enable_off_mode)
|
|
|
+ pwrdms_save_context();
|
|
|
+ break;
|
|
|
+ case CPU_CLUSTER_PM_EXIT:
|
|
|
+ if (enable_off_mode)
|
|
|
+ pwrdms_restore_context();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NOTIFY_OK;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* pwrdm_complete_init - set up the powerdomain layer
|
|
|
*
|
|
@@ -347,6 +367,7 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
|
|
|
int pwrdm_complete_init(void)
|
|
|
{
|
|
|
struct powerdomain *temp_p;
|
|
|
+ static struct notifier_block nb;
|
|
|
|
|
|
if (list_empty(&pwrdm_list))
|
|
|
return -EACCES;
|
|
@@ -354,6 +375,12 @@ int pwrdm_complete_init(void)
|
|
|
list_for_each_entry(temp_p, &pwrdm_list, node)
|
|
|
pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
|
|
|
|
|
|
+ /* Only AM43XX can lose pwrdm context during rtc-ddr suspend */
|
|
|
+ if (soc_is_am43xx()) {
|
|
|
+ nb.notifier_call = cpu_notifier;
|
|
|
+ cpu_pm_register_notifier(&nb);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|