From 808863866d2c17aeb3e70a7fcd094bd96db4b601 Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Mon, 1 Apr 2013 16:02:35 -0500 Subject: ENGR00257847-1 MX6Q/DL-Fix Ethernet performance issue when WAIT mode is active All of the interrupts from the ENET block are not routed to the GPC block. Hence ENET interrupts are not able to wake up the SOC when the system is in WAIT mode. And the ENET interrupt gets serviced only when another interrupt causes the SOC to exit WAIT mode. This impacts the ENET performance. To fix the issue two options: 1. Route the ENET interrupt to a GPIO. Need to enable the CONFIG_MX6_ENET_IRQ_TO_GPIO in the config. This patch provides support for routing the ENET interrupt to GPIO_1_6. Routing to this GPIO requires no HW board mods. If the GPIO_1_6 is being used for some other peripheral, this patch can be followed to route the ENET interrupt to any other GPIO though a HW mode maybe required. 2. If the GPIO mechanism cannot be used and is not enabled by the above mentioned config, the patch will disable entry to WAIT mode until ENET clock is active. When the ENET clock is disabled, WAIT mode will be automatically enetered. Signed-off-by: Ranjani Vaidyanathan --- arch/arm/mach-mx6/system.c | 51 +++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) (limited to 'arch/arm/mach-mx6/system.c') diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index f6ffa2999ed2..4990a4a0abbb 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -57,6 +57,7 @@ volatile unsigned int num_cpu_idle; volatile unsigned int num_cpu_idle_lock = 0x0; int wait_mode_arm_podf; int cur_arm_podf; +bool enet_is_active; void arch_idle_with_workaround(int cpu); extern void *mx6sl_wfi_iram_base; @@ -350,7 +351,7 @@ void arch_idle_single_core(void) } } -void arch_idle_with_workaround(cpu) +void arch_idle_with_workaround(int cpu) { u32 podf = wait_mode_arm_podf; @@ -369,18 +370,10 @@ void arch_idle_with_workaround(cpu) } -void arch_idle_multi_core(void) +void arch_idle_multi_core(int cpu) { u32 reg; - int cpu = smp_processor_id(); -#ifdef CONFIG_LOCAL_TIMERS - if (!tick_broadcast_oneshot_active() - || !tick_oneshot_mode_active()) - return; - - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); -#endif /* iMX6Q and iMX6DL */ if ((cpu_is_mx6q() && chip_rev >= IMX_CHIP_REVISION_1_2) || (cpu_is_mx6dl() && chip_rev >= IMX_CHIP_REVISION_1_1)) { @@ -398,24 +391,37 @@ void arch_idle_multi_core(void) ca9_do_idle(); } else arch_idle_with_workaround(cpu); -#ifdef CONFIG_LOCAL_TIMERS - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); -#endif - } void arch_idle(void) { + int cpu = smp_processor_id(); + if (enable_wait_mode) { - mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); +#ifdef CONFIG_LOCAL_TIMERS + if (!tick_broadcast_oneshot_active() + || !tick_oneshot_mode_active()) + return; + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); +#endif + if (enet_is_active) + /* Don't allow the chip to enter WAIT mode if enet is active + * and the GPIO workaround for ENET interrupts is not used, + * since all ENET interrupts donot wake up the SOC. + */ + mxc_cpu_lp_set(WAIT_CLOCKED); + else + mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); if (mem_clk_on_in_wait) { u32 reg; /* * MX6SL, MX6Q (TO1.2 or later) and - * MX6DL (TO1.1 or later) have a bit in CCM_CGPR that - * when cleared keeps the clocks to memories ON - * when ARM is in WFI. This mode can be used when - * IPG clock is very low (12MHz) and the ARM:IPG ratio + * MX6DL (TO1.1 or later) have a bit in + * CCM_CGPR that when cleared keeps the + * clocks to memories ON when ARM is in WFI. + * This mode can be used when IPG clock is + * very low (12MHz) and the ARM:IPG ratio * perhaps cannot be maintained. */ reg = __raw_readl(MXC_CCM_CGPR); @@ -427,8 +433,11 @@ void arch_idle(void) /* iMX6SL or iMX6DLS */ arch_idle_single_core(); else - arch_idle_multi_core(); - } else { + arch_idle_multi_core(cpu); +#ifdef CONFIG_LOCAL_TIMERS + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); +#endif + } else { mxc_cpu_lp_set(WAIT_CLOCKED); ca9_do_idle(); } -- cgit v1.2.3