summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/cpuidle-imx7d.c
diff options
context:
space:
mode:
authorLeonard Crestez <leonard.crestez@nxp.com>2017-07-05 20:34:01 +0300
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commit0c09360a7d91e688ce80826924995effa1bf5ce8 (patch)
tree41db11e7c185a9aca2158bb9e832280da8e72d20 /arch/arm/mach-imx/cpuidle-imx7d.c
parentbca40f2f16d507177d73fa8c2f8f4dca48d3a69a (diff)
MLK15034: ARM: cpuidle imx7d: Use a single counter for lpi flow
The current code for deciding which CPU runs the complete lpi flow is too complicated. Since all enter/exit code now runs under the same lock we can just use a single non-atomic counter of cpus inside lpi. Another variable is used to make num_online_cpus() available to ASM code but idle code can treat it as a constant. Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Diffstat (limited to 'arch/arm/mach-imx/cpuidle-imx7d.c')
-rw-r--r--arch/arm/mach-imx/cpuidle-imx7d.c35
1 files changed, 11 insertions, 24 deletions
diff --git a/arch/arm/mach-imx/cpuidle-imx7d.c b/arch/arm/mach-imx/cpuidle-imx7d.c
index 740cbb2278ba..d54954aba734 100644
--- a/arch/arm/mach-imx/cpuidle-imx7d.c
+++ b/arch/arm/mach-imx/cpuidle-imx7d.c
@@ -62,10 +62,9 @@ struct imx7_cpuidle_pm_info {
phys_addr_t pbase; /* The physical address of pm_info. */
phys_addr_t resume_addr; /* The physical resume address for asm code */
u32 pm_info_size;
- int last_cpu;
u32 ttbr;
- u32 cpu1_wfi;
- u32 lpi_enter;
+ u32 num_online_cpus;
+ u32 num_lpi_cpus;
atomic_t val;
atomic_t flag0;
atomic_t flag1;
@@ -78,7 +77,6 @@ struct imx7_cpuidle_pm_info {
struct imx7_pm_base gic_dist_base;
} __aligned(8);
-static atomic_t master_lpi = ATOMIC_INIT(0);
static atomic_t master_wait = ATOMIC_INIT(0);
static void (*imx7d_wfi_in_iram_fn)(void __iomem *iram_vbase);
@@ -151,9 +149,10 @@ static int imx7d_enter_low_power_idle(struct cpuidle_device *dev,
imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
} else {
imx_pen_lock(dev->cpu);
+ ++cpuidle_pm_info->num_lpi_cpus;
cpu_pm_enter();
- if (atomic_inc_return(&master_lpi) == num_online_cpus() &&
- cpuidle_pm_info->last_cpu == -1) {
+ if (cpuidle_pm_info->num_lpi_cpus ==
+ cpuidle_pm_info->num_online_cpus) {
/*
* GPC will not wake on SGIs so check for them
* manually here. At this point we know the other cpu
@@ -167,26 +166,22 @@ static int imx7d_enter_low_power_idle(struct cpuidle_device *dev,
imx_gpcv2_set_lpm_mode(WAIT_UNCLOCKED);
imx_gpcv2_set_cpu_power_gate_in_idle(true);
cpu_cluster_pm_enter();
-
- cpuidle_pm_info->last_cpu = dev->cpu;
-
} else {
imx_set_cpu_jump(dev->cpu, ca7_cpu_resume);
}
cpu_suspend(0, imx7d_idle_finish);
- if (atomic_dec_return(&master_lpi) == (num_online_cpus() - 1)) {
+ if (cpuidle_pm_info->num_lpi_cpus ==
+ cpuidle_pm_info->num_online_cpus) {
cpu_cluster_pm_exit();
imx_gpcv2_set_cpu_power_gate_in_idle(false);
imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
}
- if (cpuidle_pm_info->last_cpu == dev->cpu)
- cpuidle_pm_info->last_cpu = -1;
-
skip_lpi_flow:
cpu_pm_exit();
+ --cpuidle_pm_info->num_lpi_cpus;
imx_pen_unlock(dev->cpu);
}
@@ -227,11 +222,9 @@ static int cpu_hotplug_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
switch (action) {
- case CPU_UP_PREPARE:
- cpuidle_pm_info->cpu1_wfi = 0;
- break;
case CPU_DEAD:
- cpuidle_pm_info->cpu1_wfi = 1;
+ case CPU_ONLINE:
+ cpuidle_pm_info->num_online_cpus = num_online_cpus();
break;
}
return NOTIFY_OK;
@@ -316,13 +309,7 @@ int __init imx7d_cpuidle_init(void)
cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys;
cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info);
cpuidle_pm_info->resume_addr = virt_to_phys(ca7_cpu_resume);
- if (num_online_cpus() == 1)
- cpuidle_pm_info->cpu1_wfi = 1;
- else
- cpuidle_pm_info->cpu1_wfi = 0;
- cpuidle_pm_info->lpi_enter = 0;
- /* initialize the last cpu id to invalid here */
- cpuidle_pm_info->last_cpu = -1;
+ cpuidle_pm_info->num_online_cpus = num_online_cpus();
cpuidle_pm_info->ddrc_base.pbase = MX7D_DDRC_BASE_ADDR;
cpuidle_pm_info->ddrc_base.vbase =