msm: mpm: Configure wakeup time via virtual MPM on RPM.
On 8974 targets, the sleep code programs the wakeup time directly into
the virtual MPM driver on the RPM. The sleep code passes in the
scheduled wakeup time. The existing msm_mpm_enter_sleep API is
modified to accept the sclk timer value. On earlier targets, the mpm
driver would ignore this parameter.
Change-Id: If3d512f46ac8aadadf3e524a5c0e368afb362dfb
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/mpm.h b/arch/arm/mach-msm/include/mach/mpm.h
index 76f1ea6..fabaa09 100644
--- a/arch/arm/mach-msm/include/mach/mpm.h
+++ b/arch/arm/mach-msm/include/mach/mpm.h
@@ -109,13 +109,14 @@
/**
* msm_mpm_enter_sleep() -Called from PM code before entering low power mode
*
+ * @sclk_count: wakeup time in sclk counts for programmed RPM wakeup
* @from_idle: indicates if the sytem is entering low power mode as a part of
* suspend/idle task.
*
* Low power management code calls into this API to configure the MPM to
* monitor the active irqs before going to sleep.
*/
-void msm_mpm_enter_sleep(bool from_idle);
+void msm_mpm_enter_sleep(uint32_t sclk_count, bool from_idle);
/**
* msm_mpm_exit_sleep() -Called from PM code after resuming from low power mode
*
@@ -158,11 +159,8 @@
{ return false; }
static inline bool msm_mpm_gpio_irqs_detectable(bool from_idle)
{ return false; }
-static inline void msm_mpm_enter_sleep(bool from_idle) {}
+static inline void msm_mpm_enter_sleep(uint32_t sclk_count, bool from_idle) {}
static inline void msm_mpm_exit_sleep(bool from_idle) {}
static inline void __init of_mpm_init(struct device_node *node) {}
#endif
-
-
-
#endif /* __ARCH_ARM_MACH_MSM_MPM_H */
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index be59d7c..f7456ef 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -41,6 +41,7 @@
bool from_idle, bool notify_rpm)
{
int ret = 0;
+ struct msm_rpmrs_limits *l = (struct msm_rpmrs_limits *)limits;
ret = msm_rpm_enter_sleep();
if (ret) {
@@ -48,8 +49,7 @@
__func__, ret);
goto bail;
}
- ret = msm_lpmrs_enter_sleep((struct msm_rpmrs_limits *)limits,
- from_idle, notify_rpm);
+ ret = msm_lpmrs_enter_sleep(sclk_count, l, from_idle, notify_rpm);
bail:
return ret;
}
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index ebcbd26..0758651 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -619,12 +619,10 @@
msm_lpm_notify_common(rpm_notifier_cb, rs);
}
-/* MPM
-static bool msm_lpm_use_mpm(struct msm_rpmrs_limits *limits)
+static inline bool msm_lpm_use_mpm(struct msm_rpmrs_limits *limits)
{
- return ((limits->pxo == MSM_LPM_PXO_OFF) ||
- (limits->vdd_dig_lower_bound <= VDD_DIG_RET_HIGH));
-}*/
+ return (limits->pxo == MSM_LPM_PXO_OFF);
+}
/* LPM levels interface */
bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
@@ -647,7 +645,7 @@
return beyond_limit;
}
-int msm_lpmrs_enter_sleep(struct msm_rpmrs_limits *limits,
+int msm_lpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
bool from_idle, bool notify_rpm)
{
int ret = 0;
@@ -668,9 +666,8 @@
}
msm_lpm_get_rpm_notif = true;
- /* MPM Enter sleep
if (msm_lpm_use_mpm(limits))
- msm_mpm_enter_sleep(from_idle);*/
+ msm_mpm_enter_sleep(sclk_count, from_idle);
return ret;
}
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index bc06d7b..120832f 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -71,6 +71,7 @@
* on the low power mode being entered. L2 low power mode is also set in
* this function.
+ * @sclk_count: wakeup counter for RPM.
* @limits: pointer to the resource limits of the low power mode being entered.
* @from_idle: bool to determine if this call being made as a part of
* idle power collapse.
@@ -78,7 +79,7 @@
*
* returns 0 on success.
*/
-int msm_lpmrs_enter_sleep(struct msm_rpmrs_limits *limits,
+int msm_lpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
bool from_idle, bool notify_rpm);
/**
@@ -106,8 +107,8 @@
return true;
}
-static inline int msm_lpmrs_enter_sleep(struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm)
+static inline int msm_lpmrs_enter_sleep(uint32_t sclk_count,
+ struct msm_rpmrs_limits *limits, bool from_idle, bool notify_rpm)
{
return 0;
}
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index f98c0f2..e4c0e4e 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/hardware/gic.h>
+#include <asm/arch_timer.h>
#include <mach/gpio.h>
#include <mach/mpm.h>
@@ -70,7 +71,8 @@
#define MSM_MPM_DETECT_CTL_SHIFT(irq) ((irq % 16) * 2)
#define hashfn(val) (val % MSM_MPM_NR_MPM_IRQS)
-
+#define SCLK_HZ (32768)
+#define ARCH_TIMER_HZ (19200000)
static struct msm_mpm_device_data msm_mpm_dev_data;
enum mpm_reg_offsets {
@@ -152,14 +154,20 @@
return IRQ_HANDLED;
}
-static void msm_mpm_set(bool wakeset)
+static void msm_mpm_set(cycle_t wakeup, bool wakeset)
{
uint32_t *irqs;
unsigned int reg;
int i;
+ uint32_t *expiry_timer;
+
+ expiry_timer = (uint32_t *)&wakeup;
irqs = wakeset ? msm_mpm_wake_irq : msm_mpm_enabled_irq;
for (i = 0; i < MSM_MPM_REG_WIDTH; i++) {
+ reg = MSM_MPM_REG_WAKEUP;
+ msm_mpm_write(reg, i, expiry_timer[i]);
+
reg = MSM_MPM_REG_ENABLE;
msm_mpm_write(reg, i, irqs[i]);
@@ -448,14 +456,23 @@
return true;
}
-void msm_mpm_enter_sleep(bool from_idle)
+void msm_mpm_enter_sleep(uint32_t sclk_count, bool from_idle)
{
+ cycle_t wakeup = (u64)sclk_count * ARCH_TIMER_HZ;
+
if (!msm_mpm_is_initialized()) {
pr_err("%s(): MPM not initialized\n", __func__);
return;
}
- msm_mpm_set(!from_idle);
+ if (sclk_count) {
+ do_div(wakeup, SCLK_HZ);
+ wakeup += arch_counter_get_cntpct();
+ } else {
+ wakeup = (~0ULL);
+ }
+
+ msm_mpm_set(wakeup, !from_idle);
}
void msm_mpm_exit_sleep(bool from_idle)
diff --git a/arch/arm/mach-msm/mpm.c b/arch/arm/mach-msm/mpm.c
index b395b61..1c39415 100644
--- a/arch/arm/mach-msm/mpm.c
+++ b/arch/arm/mach-msm/mpm.c
@@ -421,7 +421,7 @@
MSM_MPM_NR_APPS_IRQS);
}
-void msm_mpm_enter_sleep(bool from_idle)
+void msm_mpm_enter_sleep(uint32_t sclk_count, bool from_idle)
{
msm_mpm_set(!from_idle);
}
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index a88e42e..9d794e7 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -967,7 +967,7 @@
return rc;
if (msm_rpmrs_use_mpm(limits))
- msm_mpm_enter_sleep(from_idle);
+ msm_mpm_enter_sleep(sclk_count, from_idle);
}
rc = msm_rpmrs_flush_L2(limits, notify_rpm);