ARM: tegra: cpuidle: Fix compile issues with CONFIG_SMP=n
authorColin Cross <ccross@android.com>
Sat, 23 Oct 2010 21:56:27 +0000 (14:56 -0700)
committerColin Cross <ccross@android.com>
Tue, 26 Oct 2010 01:46:19 +0000 (18:46 -0700)
Change-Id: Id02744bcdfc079a6091be2e8a736bcd3a6cc0ba6
Signed-off-by: Colin Cross <ccross@android.com>
arch/arm/mach-tegra/cpuidle.c

index e8b9dcb5649e8d980aec3703b791a038ea68036e..fc1d2ab2cdda3a9548d7208b5ab43da71fd0fa3a 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/tick.h>
 
 #include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
 
 #include <mach/iomap.h>
@@ -63,7 +64,7 @@ static bool lp2_in_idle __read_mostly = true;
 static bool lp2_disabled_by_suspend;
 module_param(lp2_in_idle, bool, 0644);
 
-static s64 tegra_cpu1_idle_time;
+static s64 tegra_cpu1_idle_time = LLONG_MAX;;
 static int tegra_lp2_exit_latency;
 static int tegra_lp2_power_off_time;
 
@@ -146,6 +147,7 @@ static inline void tegra_flow_wfi(struct cpuidle_device *dev)
        reg = __raw_readl(flow_ctrl);
 }
 
+#ifdef CONFIG_SMP
 static inline bool tegra_wait_for_both_idle(struct cpuidle_device *dev)
 {
        int wake_int;
@@ -183,18 +185,90 @@ static inline bool tegra_cpu_in_reset(int cpu)
        return !!(readl(CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET) & (1 << cpu));
 }
 
+static int tegra_tear_down_cpu1(void)
+{
+       u32 reg;
+
+       /* Signal to CPU1 to tear down */
+       tegra_legacy_force_irq_set(TEGRA_CPUIDLE_TEAR_DOWN);
+
+       /* At this point, CPU0 can no longer abort LP2, but CP1 can */
+       /* TODO: any way not to poll here? Use the LP2 timer to wfi? */
+       /* takes ~80 us */
+       while (!tegra_cpu_in_reset(1) &&
+               tegra_legacy_force_irq_status(TEGRA_CPUIDLE_BOTH_IDLE))
+               cpu_relax();
+
+       tegra_legacy_force_irq_clr(TEGRA_CPUIDLE_TEAR_DOWN);
+
+       /* If CPU1 aborted LP2, restart the process */
+       if (!tegra_legacy_force_irq_status(TEGRA_CPUIDLE_BOTH_IDLE))
+               return -EAGAIN;
+
+       /* CPU1 is ready for LP2, clock gate it */
+       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+       writel(reg | (1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+
+       return 0;
+}
+
+static void tegra_wake_cpu1(void)
+{
+       unsigned long boot_vector;
+       unsigned long old_boot_vector;
+       unsigned long timeout;
+       u32 reg;
+
+       boot_vector = virt_to_phys(tegra_hotplug_startup);
+       old_boot_vector = readl(EVP_CPU_RESET_VECTOR);
+       writel(boot_vector, EVP_CPU_RESET_VECTOR);
+
+       /* enable cpu clock on cpu */
+       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+       writel(reg & ~(1 << (8 + 1)), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+
+       reg = 0x1111 << 1;
+       writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+
+       /* unhalt the cpu */
+       writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14);
+
+       timeout = jiffies + msecs_to_jiffies(1000);
+       while (time_before(jiffies, timeout)) {
+               if (readl(EVP_CPU_RESET_VECTOR) != boot_vector)
+                       break;
+               udelay(10);
+       }
+
+       /* put the old boot vector back */
+       writel(old_boot_vector, EVP_CPU_RESET_VECTOR);
+
+       /* CPU1 is now started */
+}
+#else
+static inline bool tegra_wait_for_both_idle(struct cpuidle_device *dev)
+{
+       return true;
+}
+
+static inline int tegra_tear_down_cpu1(void)
+{
+       return 0;
+}
+
+static inline void tegra_wake_cpu1(void)
+{
+}
+#endif
+
 static void tegra_idle_enter_lp2_cpu0(struct cpuidle_device *dev,
        struct cpuidle_state *state)
 {
        s64 request;
-       u32 reg;
        ktime_t enter;
        ktime_t exit;
        bool sleep_completed = false;
        int bin;
-       unsigned long boot_vector;
-       unsigned long old_boot_vector;
-       unsigned long timeout;
 
 restart:
        if (!tegra_wait_for_both_idle(dev))
@@ -208,41 +282,24 @@ restart:
        /* CPU1 woke CPU0 because both are idle */
 
        request = ktime_to_us(tick_nohz_get_sleep_length());
-       if (request < tegra_lp2_exit_latency) {
+       if (request < state->target_residency) {
                /* Not enough time left to enter LP2 */
                tegra_flow_wfi(dev);
                return;
        }
 
-       /* Signal to CPU1 to tear down */
-       tegra_legacy_force_irq_set(TEGRA_CPUIDLE_TEAR_DOWN);
-
-       /* At this point, CPU0 can no longer abort LP2, but CP1 can */
-       /* TODO: any way not to poll here? Use the LP2 timer to wfi? */
-       /* takes ~80 us */
-       while (!tegra_cpu_in_reset(1) &&
-               tegra_legacy_force_irq_status(TEGRA_CPUIDLE_BOTH_IDLE))
-               cpu_relax();
-
-       tegra_legacy_force_irq_clr(TEGRA_CPUIDLE_TEAR_DOWN);
-
        idle_stats.tear_down_count++;
 
-       /* If CPU1 aborted LP2, restart the process */
-       if (!tegra_legacy_force_irq_status(TEGRA_CPUIDLE_BOTH_IDLE))
+       if (tegra_tear_down_cpu1())
                goto restart;
 
-       /* CPU1 is ready for LP2, clock gate it */
-       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-       writel(reg | (1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-
        /* Enter LP2 */
        request = ktime_to_us(tick_nohz_get_sleep_length());
        smp_rmb();
        request = min_t(s64, request, tegra_cpu1_idle_time);
 
        enter = ktime_get();
-       if (request > tegra_lp2_exit_latency + state->target_residency) {
+       if (request > state->target_residency) {
                s64 sleep_time = request - tegra_lp2_exit_latency;
 
                bin = time_to_bin((u32)request / 1000);
@@ -259,31 +316,8 @@ restart:
 
        /* set the reset vector to point to the secondary_startup routine */
        smp_wmb();
-       boot_vector = virt_to_phys(tegra_hotplug_startup);
-       old_boot_vector = readl(EVP_CPU_RESET_VECTOR);
-       writel(boot_vector, EVP_CPU_RESET_VECTOR);
 
-       /* enable cpu clock on cpu */
-       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-       writel(reg & ~(1 << (8 + 1)), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-
-       reg = 0x1111 << 1;
-       writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
-
-       /* unhalt the cpu */
-       writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14);
-
-       timeout = jiffies + msecs_to_jiffies(1000);
-       while (time_before(jiffies, timeout)) {
-               if (readl(EVP_CPU_RESET_VECTOR) != boot_vector)
-                       break;
-               udelay(10);
-       }
-
-       /* put the old boot vector back */
-       writel(old_boot_vector, EVP_CPU_RESET_VECTOR);
-
-       /* CPU1 is now started */
+       tegra_wake_cpu1();
 
        /*
         * TODO: is it worth going back to wfi if no interrupt is pending
@@ -312,6 +346,7 @@ restart:
        }
 }
 
+#ifdef CONFIG_SMP
 static void tegra_idle_enter_lp2_cpu1(struct cpuidle_device *dev,
        struct cpuidle_state *state)
 {
@@ -380,6 +415,7 @@ static void tegra_idle_enter_lp2_cpu1(struct cpuidle_device *dev,
 out:
        tegra_legacy_force_irq_clr(TEGRA_CPUIDLE_BOTH_IDLE);
 }
+#endif
 
 static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
        struct cpuidle_state *state)
@@ -416,10 +452,14 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev,
 
        idle_stats.cpu_ready_count[dev->cpu]++;
 
+#ifdef CONFIG_SMP
        if (dev->cpu == 0)
                tegra_idle_enter_lp2_cpu0(dev, state);
        else
                tegra_idle_enter_lp2_cpu1(dev, state);
+#else
+       tegra_idle_enter_lp2_cpu0(dev, state);
+#endif
 
        exit = ktime_sub(ktime_get(), enter);
        us = ktime_to_us(exit);