msm: pm-8x60: Refactor to remove dependencies on rpm_resources.c
With 8974 family of chipsets, lpm_levels replaces the functionality
provided by rpm_resources. Expose function pointers that can be
overwritten by respective resource drivers at probe time.
Change-Id: Ifd577f9aca6457c0caad6205bcaf562e0162a2e2
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 48cf3f7..80b82cb 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -19,18 +19,19 @@
#include <linux/of.h>
#include <mach/mpm.h>
#include "rpm_resources.h"
+#include "pm.h"
static struct msm_rpmrs_level *msm_lpm_levels;
static int msm_lpm_level_count;
-int msm_rpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
+static int msm_lpm_enter_sleep(uint32_t sclk_count, void *limits,
bool from_idle, bool notify_rpm)
{
/* TODO */
return 0;
}
-void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits, bool from_idle,
+static void msm_lpm_exit_sleep(void *limits, bool from_idle,
bool notify_rpm, bool collapsed)
{
/* TODO */
@@ -50,14 +51,15 @@
return;
}
-struct msm_rpmrs_limits *msm_rpmrs_lowest_limits(
- bool from_idle, enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us)
+static void *msm_lpm_lowest_limits(bool from_idle,
+ enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
+ uint32_t sleep_us, uint32_t *power)
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
bool irqs_detectable = false;
bool gpio_detectable = false;
+ uint32_t pwr;
int i;
if (!msm_lpm_levels)
@@ -70,7 +72,6 @@
for (i = 0; i < msm_lpm_level_count; i++) {
struct msm_rpmrs_level *level = &msm_lpm_levels[i];
- uint32_t power;
if (!level->available)
continue;
@@ -86,28 +87,36 @@
continue;
if (sleep_us <= 1) {
- power = level->energy_overhead;
+ pwr = level->energy_overhead;
} else if (sleep_us <= level->time_overhead_us) {
- power = level->energy_overhead / sleep_us;
+ pwr = level->energy_overhead / sleep_us;
} else if ((sleep_us >> 10) > level->time_overhead_us) {
- power = level->steady_state_power;
+ pwr = level->steady_state_power;
} else {
- power = level->steady_state_power;
- power -= (level->time_overhead_us *
+ pwr = level->steady_state_power;
+ pwr -= (level->time_overhead_us *
level->steady_state_power)/sleep_us;
- power += level->energy_overhead / sleep_us;
+ pwr += level->energy_overhead / sleep_us;
}
- if (!best_level ||
- best_level->rs_limits.power[cpu] >= power) {
+ if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
+
level->rs_limits.latency_us[cpu] = level->latency_us;
- level->rs_limits.power[cpu] = power;
+ level->rs_limits.power[cpu] = pwr;
best_level = level;
+
+ if (power)
+ *power = pwr;
}
}
return best_level ? &best_level->rs_limits : NULL;
}
+static struct msm_pm_sleep_ops msm_lpm_ops = {
+ .lowest_limits = msm_lpm_lowest_limits,
+ .enter_sleep = msm_lpm_enter_sleep,
+ .exit_sleep = msm_lpm_exit_sleep,
+};
static int __devinit msm_lpm_levels_probe(struct platform_device *pdev)
{
@@ -204,6 +213,8 @@
msm_lpm_levels = levels;
msm_lpm_level_count = idx;
+ msm_pm_set_sleep_ops(&msm_lpm_ops);
+
return 0;
fail:
pr_err("%s: Error in name %s key %s\n", __func__, node->full_name, key);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 070e2c5..6f68c8b 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -44,7 +44,6 @@
#include <mach/cpuidle.h>
#include "idle.h"
#include "pm.h"
-#include "rpm_resources.h"
#include "scm-boot.h"
#include "spm.h"
#include "timer.h"
@@ -109,6 +108,7 @@
"standalone_power_collapse",
};
+static struct msm_pm_sleep_ops pm_sleep_ops;
/*
* Write out the attribute.
*/
@@ -396,7 +396,7 @@
*
*****************************************************************************/
-static struct msm_rpmrs_limits *msm_pm_idle_rs_limits;
+static void *msm_pm_idle_rs_limits;
static bool msm_pm_use_qtimer;
static void msm_pm_swfi(void)
@@ -644,7 +644,8 @@
struct cpuidle_state *state = &dev->states[i];
enum msm_pm_sleep_mode mode;
bool allow;
- struct msm_rpmrs_limits *rs_limits = NULL;
+ void *rs_limits = NULL;
+ uint32_t power;
int idx;
mode = (enum msm_pm_sleep_mode) state->driver_data;
@@ -673,12 +674,6 @@
case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
if (!allow)
break;
-
- if (!dev->cpu &&
- msm_rpm_local_request_is_outstanding()) {
- allow = false;
- break;
- }
/* fall through */
case MSM_PM_SLEEP_MODE_RETENTION:
@@ -690,8 +685,10 @@
if (!allow)
break;
- rs_limits = msm_rpmrs_lowest_limits(true,
- mode, latency_us, sleep_us);
+ if (pm_sleep_ops.lowest_limits)
+ rs_limits = pm_sleep_ops.lowest_limits(true,
+ mode, latency_us, sleep_us,
+ &power);
if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
pr_info("CPU%u: %s: %s, latency %uus, "
@@ -699,17 +696,6 @@
dev->cpu, __func__, state->desc,
latency_us, sleep_us, rs_limits);
- if ((MSM_PM_DEBUG_IDLE_LIMITS & msm_pm_debug_mask) &&
- rs_limits)
- pr_info("CPU%u: %s: limit %p: "
- "pxo %d, l2_cache %d, "
- "vdd_mem %d, vdd_dig %d\n",
- dev->cpu, __func__, rs_limits,
- rs_limits->pxo,
- rs_limits->l2_cache,
- rs_limits->vdd_mem,
- rs_limits->vdd_dig);
-
if (!rs_limits)
allow = false;
break;
@@ -727,7 +713,7 @@
state->flags &= ~CPUIDLE_FLAG_IGNORE;
state->target_residency = 0;
state->exit_latency = 0;
- state->power_usage = rs_limits->power[dev->cpu];
+ state->power_usage = power;
if (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == mode)
msm_pm_idle_rs_limits = rs_limits;
@@ -770,7 +756,7 @@
int64_t timer_expiration = 0;
bool timer_halted = false;
uint32_t sleep_delay;
- int ret;
+ int ret = -ENODEV;
int notify_rpm =
(sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE);
int collapsed;
@@ -785,14 +771,17 @@
if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
clock_debug_print_enabled();
- ret = msm_rpmrs_enter_sleep(
- sleep_delay, msm_pm_idle_rs_limits, true, notify_rpm);
+ if (pm_sleep_ops.enter_sleep)
+ ret = pm_sleep_ops.enter_sleep(sleep_delay,
+ msm_pm_idle_rs_limits,
+ true, notify_rpm);
if (!ret) {
collapsed = msm_pm_power_collapse(true);
timer_halted = true;
- msm_rpmrs_exit_sleep(msm_pm_idle_rs_limits, true,
- notify_rpm, collapsed);
+ if (pm_sleep_ops.exit_sleep)
+ pm_sleep_ops.exit_sleep(msm_pm_idle_rs_limits,
+ true, notify_rpm, collapsed);
}
msm_pm_timer_exit_idle(timer_halted);
exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
@@ -920,8 +909,9 @@
}
if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE]) {
- struct msm_rpmrs_limits *rs_limits;
- int ret;
+ void *rs_limits = NULL;
+ int ret = -ENODEV;
+ uint32_t power;
if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s: power collapse\n", __func__);
@@ -936,28 +926,22 @@
msm_pm_sleep_time_override = 0;
}
#endif /* CONFIG_MSM_SLEEP_TIME_OVERRIDE */
-
- if (MSM_PM_DEBUG_SUSPEND_LIMITS & msm_pm_debug_mask)
- msm_rpmrs_show_resources();
-
- rs_limits = msm_rpmrs_lowest_limits(false,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE, -1, -1);
-
- if ((MSM_PM_DEBUG_SUSPEND_LIMITS & msm_pm_debug_mask) &&
- rs_limits)
- pr_info("%s: limit %p: pxo %d, l2_cache %d, "
- "vdd_mem %d, vdd_dig %d\n",
- __func__, rs_limits,
- rs_limits->pxo, rs_limits->l2_cache,
- rs_limits->vdd_mem, rs_limits->vdd_dig);
+ if (pm_sleep_ops.lowest_limits)
+ rs_limits = pm_sleep_ops.lowest_limits(false,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE, -1,
+ -1, &power);
if (rs_limits) {
- ret = msm_rpmrs_enter_sleep(
- msm_pm_max_sleep_time, rs_limits, false, true);
+ if (pm_sleep_ops.enter_sleep)
+ ret = pm_sleep_ops.enter_sleep(
+ msm_pm_max_sleep_time,
+ rs_limits, false, true);
if (!ret) {
int collapsed = msm_pm_power_collapse(false);
- msm_rpmrs_exit_sleep(rs_limits, false, true,
- collapsed);
+ if (pm_sleep_ops.exit_sleep) {
+ pm_sleep_ops.exit_sleep(rs_limits,
+ false, true, collapsed);
+ }
}
} else {
pr_err("%s: cannot find the lowest power limit\n",
@@ -1001,6 +985,12 @@
msm_pm_slp_sts = data;
}
+void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops)
+{
+ if (ops)
+ pm_sleep_ops = *ops;
+}
+
static int __init msm_pm_init(void)
{
pgd_t *pc_pgd;
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index ce0d747..0d5101d 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -76,6 +76,16 @@
uint32_t mask;
};
+struct msm_pm_sleep_ops {
+ void *(*lowest_limits)(bool from_idle,
+ enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
+ uint32_t sleep_us, uint32_t *power);
+ int (*enter_sleep)(uint32_t sclk_count, void *limits,
+ bool from_idle, bool notify_rpm);
+ void (*exit_sleep)(void *limits, bool from_idle,
+ bool notify_rpm, bool collapsed);
+};
+
void msm_pm_set_platform_data(struct msm_pm_platform_data *data, int count);
void msm_pm_set_irq_extns(struct msm_pm_irq_calls *irq_calls);
int msm_pm_idle_prepare(struct cpuidle_device *dev);
@@ -90,12 +100,13 @@
void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
int msm_pm_wait_cpu_shutdown(unsigned int cpu);
bool msm_pm_verify_cpu_pc(unsigned int cpu);
+void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops);
#else
static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
static inline bool msm_pm_verify_cpu_pc(unsigned int cpu) { return true; }
+static inline void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops) {}
#endif
-
#ifdef CONFIG_HOTPLUG_CPU
int msm_platform_secondary_init(unsigned int cpu);
#else
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 7daea5c..5314cee 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -867,15 +867,16 @@
spin_unlock_irqrestore(&msm_rpmrs_lock, flags);
}
-struct msm_rpmrs_limits *msm_rpmrs_lowest_limits(
- bool from_idle, enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us)
+static void *msm_rpmrs_lowest_limits(bool from_idle,
+ enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
+ uint32_t sleep_us, uint32_t *power)
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
bool irqs_detectable = false;
bool gpio_detectable = false;
int i;
+ uint32_t pwr;
if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
irqs_detectable = msm_mpm_irqs_detectable(from_idle);
@@ -884,7 +885,6 @@
for (i = 0; i < msm_rpmrs_level_count; i++) {
struct msm_rpmrs_level *level = &msm_rpmrs_levels[i];
- uint32_t power;
if (!level->available)
continue;
@@ -902,31 +902,38 @@
irqs_detectable, gpio_detectable))
continue;
+ if (MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE == sleep_mode)
+ if (!cpu && msm_rpm_local_request_is_outstanding())
+ break;
+
+
if (sleep_us <= 1) {
- power = level->energy_overhead;
+ pwr = level->energy_overhead;
} else if (sleep_us <= level->time_overhead_us) {
- power = level->energy_overhead / sleep_us;
+ pwr = level->energy_overhead / sleep_us;
} else if ((sleep_us >> 10) > level->time_overhead_us) {
- power = level->steady_state_power;
+ pwr = level->steady_state_power;
} else {
- power = level->steady_state_power;
- power -= (level->time_overhead_us *
+ pwr = level->steady_state_power;
+ pwr -= (level->time_overhead_us *
level->steady_state_power)/sleep_us;
- power += level->energy_overhead / sleep_us;
+ pwr += level->energy_overhead / sleep_us;
}
if (!best_level ||
- best_level->rs_limits.power[cpu] >= power) {
+ best_level->rs_limits.power[cpu] >= pwr) {
level->rs_limits.latency_us[cpu] = level->latency_us;
- level->rs_limits.power[cpu] = power;
+ level->rs_limits.power[cpu] = pwr;
best_level = level;
+ if (power)
+ *power = pwr;
}
}
return best_level ? &best_level->rs_limits : NULL;
}
-int msm_rpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
+static int msm_rpmrs_enter_sleep(uint32_t sclk_count, void *limits,
bool from_idle, bool notify_rpm)
{
int rc = 0;
@@ -944,7 +951,7 @@
return rc;
}
-void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits, bool from_idle,
+static void msm_rpmrs_exit_sleep(void *limits, bool from_idle,
bool notify_rpm, bool collapsed)
{
@@ -1067,6 +1074,12 @@
}
device_initcall(msm_rpmrs_init);
+static struct msm_pm_sleep_ops msm_rpmrs_ops = {
+ .lowest_limits = msm_rpmrs_lowest_limits,
+ .enter_sleep = msm_rpmrs_enter_sleep,
+ .exit_sleep = msm_rpmrs_exit_sleep,
+};
+
static int __init msm_rpmrs_l2_init(void)
{
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064()) {
@@ -1085,6 +1098,9 @@
msm_rpmrs_l2_cache.aggregate = NULL;
msm_rpmrs_l2_cache.restore = NULL;
}
+
+ msm_pm_set_sleep_ops(&msm_rpmrs_ops);
+
return 0;
}
early_initcall(msm_rpmrs_l2_init);
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index a5c61b2..d594405 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -137,16 +137,6 @@
}
void msm_rpmrs_show_resources(void);
-
-struct msm_rpmrs_limits *msm_rpmrs_lowest_limits(
- bool from_idle, enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us);
-
-int msm_rpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm);
-void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits, bool from_idle,
- bool notify_rpm, bool collapsed);
-
int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data);
#endif /* __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H */