]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00210850 mx6: boot failure with local timer and wait mode enabled
authorXinyu Chen <xinyu.chen@freescale.com>
Fri, 25 May 2012 03:39:15 +0000 (11:39 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:43 +0000 (08:34 +0200)
Previous patch only check the condition that GPT broadcast
event is ready or not before doing clock event switch.
It's not enough, as the clock switch from local timer to GPT
broadcast must be happen after GPT broadcast clock event setup
and current cpu's clock device switch to local timer clock event.
Otherwise, we will have chance that cpu exit the wait mode and
switch back clock event without local timer event setup correctly.

Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
arch/arm/mach-mx6/system.c

index 1886649f9abb05d8d638cc72d4676d6b7709876d..943b757997d6dbdb1fd21c5bcb0c325660e22300 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/pmic_external.h>
 #include <linux/clockchips.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
 #include <asm/io.h>
 #include <mach/hardware.h>
 #include <mach/clock.h>
@@ -217,12 +219,6 @@ extern int tick_broadcast_oneshot_active(void);
        if (enable_wait_mode) {
                u32 reg;
                int cpu = smp_processor_id();
-#ifdef CONFIG_LOCAL_TIMERS
-               if (!tick_broadcast_oneshot_active())
-                       return;
-
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
-#endif
                *((char *)(&num_cpu_idle_lock) + (char)cpu) = 0x0;
                mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
                if (arm_mem_clked_in_wait || mem_clk_on_in_wait) {
@@ -249,6 +245,13 @@ extern int tick_broadcast_oneshot_active(void);
 
                        __raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR);
                } else {
+#ifdef CONFIG_LOCAL_TIMERS
+                       if (!tick_broadcast_oneshot_active()
+                               || !tick_oneshot_mode_active())
+                               return;
+
+                       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+#endif
                        if (low_bus_freq_mode || audio_bus_freq_mode)
                                mx6_wait((void *)&num_cpu_idle_lock,
                                                        (void *)&num_cpu_idle,
@@ -257,10 +260,10 @@ extern int tick_broadcast_oneshot_active(void);
                                mx6_wait((void *)&num_cpu_idle_lock,
                                        (void *)&num_cpu_idle,
                                        wait_mode_arm_podf, cur_arm_podf - 1);
-               }
 #ifdef CONFIG_LOCAL_TIMERS
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+                       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 #endif
+               }
        } else {
                mxc_cpu_lp_set(WAIT_CLOCKED);
                cpu_do_idle();