ARM: tegra: cpuidle: Fix compile issues with CONFIG_SMP=n

Change-Id: Id02744bcdfc079a6091be2e8a736bcd3a6cc0ba6
Signed-off-by: Colin Cross <ccross@android.com>
This commit is contained in:
Colin Cross
2010-10-23 14:56:27 -07:00
parent b1a196f10a
commit 1d583e43c3

View 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,36 +185,9 @@ static inline bool tegra_cpu_in_reset(int cpu)
return !!(readl(CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET) & (1 << cpu));
}
static void tegra_idle_enter_lp2_cpu0(struct cpuidle_device *dev,
struct cpuidle_state *state)
static int tegra_tear_down_cpu1(void)
{
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))
return;
idle_stats.both_idle_count++;
if (need_resched())
return;
/* CPU1 woke CPU0 because both are idle */
request = ktime_to_us(tick_nohz_get_sleep_length());
if (request < tegra_lp2_exit_latency) {
/* 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);
@@ -226,39 +201,24 @@ restart:
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))
goto restart;
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);
/* Enter LP2 */
request = ktime_to_us(tick_nohz_get_sleep_length());
smp_rmb();
request = min_t(s64, request, tegra_cpu1_idle_time);
return 0;
}
enter = ktime_get();
if (request > tegra_lp2_exit_latency + state->target_residency) {
s64 sleep_time = request - tegra_lp2_exit_latency;
static void tegra_wake_cpu1(void)
{
unsigned long boot_vector;
unsigned long old_boot_vector;
unsigned long timeout;
u32 reg;
bin = time_to_bin((u32)request / 1000);
idle_stats.lp2_count++;
idle_stats.lp2_count_bin[bin]++;
if (tegra_suspend_lp2(sleep_time) == 0)
sleep_completed = true;
}
/* Bring CPU1 out of LP2 */
/* TODO: polls for CPU1 to boot, wfi would be better */
/* takes ~80 us */
/* 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);
@@ -284,6 +244,80 @@ restart:
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;
ktime_t enter;
ktime_t exit;
bool sleep_completed = false;
int bin;
restart:
if (!tegra_wait_for_both_idle(dev))
return;
idle_stats.both_idle_count++;
if (need_resched())
return;
/* CPU1 woke CPU0 because both are idle */
request = ktime_to_us(tick_nohz_get_sleep_length());
if (request < state->target_residency) {
/* Not enough time left to enter LP2 */
tegra_flow_wfi(dev);
return;
}
idle_stats.tear_down_count++;
if (tegra_tear_down_cpu1())
goto restart;
/* 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 > state->target_residency) {
s64 sleep_time = request - tegra_lp2_exit_latency;
bin = time_to_bin((u32)request / 1000);
idle_stats.lp2_count++;
idle_stats.lp2_count_bin[bin]++;
if (tegra_suspend_lp2(sleep_time) == 0)
sleep_completed = true;
}
/* Bring CPU1 out of LP2 */
/* TODO: polls for CPU1 to boot, wfi would be better */
/* takes ~80 us */
/* set the reset vector to point to the secondary_startup routine */
smp_wmb();
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);