summaryrefslogtreecommitdiff
path: root/drivers/cpuidle/lpm-levels.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle/lpm-levels.c')
-rw-r--r--drivers/cpuidle/lpm-levels.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 64c4bf8f58a8..4224b594f1b8 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -43,6 +43,7 @@
#include <soc/qcom/event_timer.h>
#include <soc/qcom/lpm-stats.h>
#include <soc/qcom/jtag.h>
+#include <soc/qcom/minidump.h>
#include <asm/cputype.h>
#include <asm/arch_timer.h>
#include <asm/cacheflush.h>
@@ -72,6 +73,8 @@ enum debug_event {
CLUSTER_ENTER,
CLUSTER_EXIT,
PRE_PC_CB,
+ CPU_HP_STARTING,
+ CPU_HP_DYING,
};
struct lpm_debug {
@@ -341,10 +344,16 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb,
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_DYING:
+ update_debug_pc_event(CPU_HP_DYING, cpu,
+ cluster->num_children_in_sync.bits[0],
+ cluster->child_cpus.bits[0], false);
cluster_prepare(cluster, get_cpu_mask((unsigned int) cpu),
NR_LPM_LEVELS, false, 0);
break;
case CPU_STARTING:
+ update_debug_pc_event(CPU_HP_STARTING, cpu,
+ cluster->num_children_in_sync.bits[0],
+ cluster->child_cpus.bits[0], false);
cluster_unprepare(cluster, get_cpu_mask((unsigned int) cpu),
NR_LPM_LEVELS, false, 0);
break;
@@ -682,7 +691,7 @@ static int cpu_power_select(struct cpuidle_device *dev,
if (!cpu)
return -EINVAL;
- if (sleep_disabled)
+ if (sleep_disabled && !cpu_isolated(dev->cpu))
return 0;
idx_restrict = cpu->nlevels + 1;
@@ -1123,6 +1132,8 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx,
struct cpumask nextcpu, *cpumask;
uint64_t us;
uint32_t pred_us;
+ uint64_t sec;
+ uint64_t nsec;
us = get_cluster_sleep_time(cluster, &nextcpu,
from_idle, &pred_us);
@@ -1134,11 +1145,20 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx,
goto failed_set_mode;
}
- us = (us + 1) * 1000;
clear_predict_history();
clear_cl_predict_history();
- do_div(us, NSEC_PER_SEC/SCLK_HZ);
+ us = us + 1;
+ sec = us;
+ do_div(sec, USEC_PER_SEC);
+ nsec = us - sec * USEC_PER_SEC;
+
+ sec = sec * SCLK_HZ;
+ if (nsec > 0) {
+ nsec = nsec * NSEC_PER_USEC;
+ do_div(nsec, NSEC_PER_SEC/SCLK_HZ);
+ }
+ us = sec + nsec;
msm_mpm_enter_sleep(us, from_idle, cpumask);
}
@@ -1835,6 +1855,7 @@ static int lpm_probe(struct platform_device *pdev)
int ret;
int size;
struct kobject *module_kobj = NULL;
+ struct md_region md_entry;
get_online_cpus();
lpm_root_node = lpm_of_parse_cluster(pdev);
@@ -1895,6 +1916,14 @@ static int lpm_probe(struct platform_device *pdev)
goto failed;
}
+ /* Add lpm_debug to Minidump*/
+ strlcpy(md_entry.name, "KLPMDEBUG", sizeof(md_entry.name));
+ md_entry.virt_addr = (uintptr_t)lpm_debug;
+ md_entry.phys_addr = lpm_debug_phys;
+ md_entry.size = size;
+ if (msm_minidump_add_region(&md_entry))
+ pr_info("Failed to add lpm_debug in Minidump\n");
+
return 0;
failed:
free_cluster_node(lpm_root_node);