@@ -145,15 +145,19 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
- (prev_logic_pwrst == PWRDM_POWER_OFF))
+ (prev_logic_pwrst == PWRDM_POWER_OFF)) {
pwrdm->ret_logic_off_counter++;
+ pwrdm->lost_context = true;
+ }
for (i = 0; i < pwrdm->banks; i++) {
prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) &&
- (prev_mem_pwrst == PWRDM_POWER_OFF))
+ (prev_mem_pwrst == PWRDM_POWER_OFF)) {
pwrdm->ret_mem_off_counter[i]++;
+ pwrdm->lost_context = true;
+ }
}
}
@@ -176,6 +180,8 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
prev = pwrdm_read_prev_pwrst(pwrdm);
if (pwrdm->state != prev)
pwrdm->state_counter[prev]++;
+ if (prev == PWRDM_POWER_OFF)
+ pwrdm->lost_context = true;
if (prev == PWRDM_POWER_RET)
_update_logic_membank_counters(pwrdm);
break;
@@ -197,6 +203,7 @@ static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
{
pwrdm_clear_all_prev_pwrst(pwrdm);
_pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+ pwrdm->lost_context = false;
return 0;
}
@@ -79,6 +79,7 @@ struct omap_device {
int omap_device_enable(struct platform_device *pdev);
int omap_device_idle(struct platform_device *pdev);
int omap_device_shutdown(struct platform_device *pdev);
+bool omap_device_has_lost_context(struct platform_device *pdev);
/* Core code interface */
@@ -102,7 +102,7 @@ struct powerdomain {
unsigned state_counter[PWRDM_MAX_PWRSTS];
unsigned ret_logic_off_counter;
unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
-
+ bool lost_context;
#ifdef CONFIG_PM_DEBUG
s64 timer;
s64 state_timer[PWRDM_MAX_PWRSTS];
@@ -84,6 +84,7 @@
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
+#include <plat/powerdomain.h>
/* These parameters are passed to _omap_device_{de,}activate() */
#define USE_WAKEUP_LAT 0
@@ -579,6 +580,34 @@ int omap_device_shutdown(struct platform_device *pdev)
}
/**
+ * omap_device_has_lost_context() - check if omap_device has lost context
+ * @od: struct omap_device *
+ *
+ * When an omap_device has been deactivated via omap_device_idle() or
+ * omap_device_shutdown() and then (re)activated using omap_device_enable()
+ * This function should be used to determine if the omap_device has
+ * lost context (due to an off-mode transistion)
+ */
+bool omap_device_has_lost_context(struct platform_device *pdev)
+{
+ struct omap_device *od;
+ struct powerdomain *pwrdm;
+
+ od = _find_by_pdev(pdev);
+
+ if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
+ WARN(1, "omap_device: %s.%d: has_lost_context() called "
+ "from invalid state\n", od->pdev.name, od->pdev.id);
+ return -EINVAL;
+ }
+ pwrdm = omap_device_get_pwrdm(od);
+ if (pwrdm)
+ return pwrdm->lost_context;
+
+ return false;
+}
+
+/**
* omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
* @od: struct omap_device *
*