summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2012-08-09 20:49:36 +0800
committerAnson Huang <b20788@freescale.com>2012-08-11 03:37:27 +0800
commit2bb33d7d7cae1602602ca93c084772017bb89e62 (patch)
treeb27040697475a6883d0cc91df353c0d9fc56c997
parentf588fca89c529c559ef280a96b4c9143aec904bc (diff)
ENGR00219870 [MX6]Add interrupt check to idle to minish SMP impact
CPUs may be waked up by SMP broadcast, and for this scenario, CPUs can enter idle again directly to avoid run a long way to re-enter idle, adding this interrupt check can minish SMP impact on peripheral devices' performance. Signed-off-by: Anson Huang <b20788@freescale.com>
-rw-r--r--arch/arm/mach-mx6/system.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
index ebc1ca1ee3cc..016dbec6cfc0 100644
--- a/arch/arm/mach-mx6/system.c
+++ b/arch/arm/mach-mx6/system.c
@@ -30,6 +30,7 @@
#include <mach/clock.h>
#include <asm/proc-fns.h>
#include <asm/system.h>
+#include <asm/hardware/gic.h>
#include "crm_regs.h"
#include "regs-anadig.h"
@@ -219,6 +220,13 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
extern int tick_broadcast_oneshot_active(void);
+void ca9_do_idle(void)
+{
+ do {
+ cpu_do_idle();
+ } while (__raw_readl(gic_cpu_base_addr + GIC_CPU_HIGHPRI) == 1023);
+}
+
void arch_idle_single_core(void)
{
u32 reg;
@@ -232,7 +240,7 @@ void arch_idle_single_core(void)
reg |= MXC_CCM_CGPR_WAIT_MODE_FIX;
__raw_writel(reg, MXC_CCM_CGPR);
- cpu_do_idle();
+ ca9_do_idle();
} else {
/*
* Implement the 12:5 ARM:IPG_CLK ratio
@@ -250,7 +258,7 @@ void arch_idle_single_core(void)
__raw_writel(wait_mode_arm_podf, MXC_CCM_CACRR);
while (__raw_readl(MXC_CCM_CDHIPR))
;
- cpu_do_idle();
+ ca9_do_idle();
__raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR);
}
@@ -258,7 +266,6 @@ void arch_idle_single_core(void)
void arch_idle_with_workaround(cpu)
{
- u32 reg;
u32 podf = wait_mode_arm_podf;
*((char *)(&num_cpu_idle_lock) + (char)cpu) = 0x0;
@@ -302,7 +309,7 @@ void arch_idle_multi_core(void)
reg |= MXC_CCM_CGPR_WAIT_MODE_FIX;
__raw_writel(reg, MXC_CCM_CGPR);
- cpu_do_idle();
+ ca9_do_idle();
} else
arch_idle_with_workaround(cpu);
#ifdef CONFIG_LOCAL_TIMERS
@@ -329,7 +336,7 @@ void arch_idle(void)
reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK;
__raw_writel(reg, MXC_CCM_CGPR);
- cpu_do_idle();
+ ca9_do_idle();
} else if (num_possible_cpus() == 1)
/* iMX6SL or iMX6DLS */
arch_idle_single_core();
@@ -337,7 +344,7 @@ void arch_idle(void)
arch_idle_multi_core();
} else {
mxc_cpu_lp_set(WAIT_CLOCKED);
- cpu_do_idle();
+ ca9_do_idle();
}
}