Commit d90bdb72 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Thierry Reding
Browse files

ARM: tegra: Remove pen-locking from cpuidle-tegra20



Pen-locking is meant to block CPU0 if CPU1 wakes up during of entering
into LP2 because of some interrupt firing up, preventing unnecessary LP2
enter that will be resumed immediately. Apparently this case doesn't
happen often in practice, I checked how often it takes place and found
that after ~20 hours of browsing web, managing email, watching videos and
idling (15+ hours) there is only a dozen of early LP2 entering abortions
and they all happened while device was idling. Thus let's remove the
pen-locking and make LP2 entering uninterruptible, simplifying code quite
a lot. This will also become very handy for the upcoming unified cpuidle
driver, allowing to have a common LP2 code-path across of different
hardware generations.

Acked-by: default avatarPeter De Schrijver <pdeschrijver@nvidia.com>
Tested-by: default avatarPeter Geis <pgwipeout@gmail.com>
Tested-by: default avatarJasper Korten <jja2000@gmail.com>
Tested-by: default avatarDavid Heidelberg <david@ixit.cz>
Tested-by: default avatarNicolas Chauvet <kwizart@gmail.com>
Acked-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 859a6f6e
Loading
Loading
Loading
Loading
+2 −43
Original line number Diff line number Diff line
@@ -65,28 +65,8 @@ static struct cpuidle_driver tegra_idle_driver = {

#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_SMP
static int tegra20_reset_sleeping_cpu_1(void)
{
	int ret = 0;

	tegra_pen_lock();

	if (readb(tegra20_cpu1_resettable_status) == CPU_RESETTABLE)
		tegra20_cpu_shutdown(1);
	else
		ret = -EINVAL;

	tegra_pen_unlock();

	return ret;
}

static void tegra20_wake_cpu1_from_reset(void)
{
	tegra_pen_lock();

	tegra20_cpu_clear_resettable();

	/* enable cpu clock on cpu */
	tegra_enable_cpu_clock(1);

@@ -95,39 +75,20 @@ static void tegra20_wake_cpu1_from_reset(void)

	/* unhalt the cpu */
	flowctrl_write_cpu_halt(1, 0);

	tegra_pen_unlock();
}

static int tegra20_reset_cpu_1(void)
{
	if (!cpu_online(1) || !tegra20_reset_sleeping_cpu_1())
		return 0;

	tegra20_wake_cpu1_from_reset();
	return -EBUSY;
}
#else
static inline void tegra20_wake_cpu1_from_reset(void)
{
}

static inline int tegra20_reset_cpu_1(void)
{
	return 0;
}
#endif

static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
					   struct cpuidle_driver *drv,
					   int index)
{
	while (tegra20_cpu_is_resettable_soon())
	while (!tegra_cpu_rail_off_ready())
		cpu_relax();

	if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
		return false;

	tegra_idle_lp2_last();

	if (cpu_online(1))
@@ -141,9 +102,7 @@ static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
					 struct cpuidle_driver *drv,
					 int index)
{
	cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);

	tegra20_cpu_clear_resettable();
	cpu_suspend(dev->cpu, tegra_pm_park_secondary_cpu);

	return true;
}
+0 −7
Original line number Diff line number Diff line
@@ -137,18 +137,11 @@ bool tegra_set_cpu_in_lp2(void)

	if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
		last_cpu = true;
	else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1)
		tegra20_cpu_set_resettable_soon();

	spin_unlock(&tegra_lp2_lock);
	return last_cpu;
}

int tegra_cpu_do_idle(void)
{
	return cpu_do_idle();
}

static int tegra_sleep_cpu(unsigned long v2p)
{
	/*
+0 −1
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ void tegra30_sleep_core_init(void);

void tegra_clear_cpu_in_lp2(void);
bool tegra_set_cpu_in_lp2(void);
int tegra_cpu_do_idle(void);
void tegra_idle_lp2_last(void);
extern void (*tegra_tear_down_cpu)(void);

+0 −11
Original line number Diff line number Diff line
@@ -183,17 +183,6 @@ after_errata:
	bleq	__die				@ CPU not present (to OS)
#endif

#ifdef CONFIG_ARCH_TEGRA_2x_SOC
	/* Are we on Tegra20? */
	cmp	r6, #TEGRA20
	bne	1f
	/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
	mov	r0, #CPU_NOT_RESETTABLE
	cmp	r10, #0
	strbne	r0, [r12, #RESET_DATA(RESETTABLE_STATUS)]
1:
#endif

	/* Waking up from LP1? */
	ldr	r8, [r12, #RESET_DATA(MASK_LP1)]
	tst	r8, r11				@ if in_lp1
+2 −7
Original line number Diff line number Diff line
@@ -16,9 +16,8 @@
#define TEGRA_RESET_STARTUP_SECONDARY	3
#define TEGRA_RESET_STARTUP_LP2		4
#define TEGRA_RESET_STARTUP_LP1		5
#define TEGRA_RESET_RESETTABLE_STATUS	6
#define TEGRA_RESET_TF_PRESENT		7
#define TEGRA_RESET_DATA_SIZE		8
#define TEGRA_RESET_TF_PRESENT		6
#define TEGRA_RESET_DATA_SIZE		7

#define RESET_DATA(x)	((TEGRA_RESET_##x)*4)

@@ -42,10 +41,6 @@ void __tegra_cpu_reset_handler_end(void);
	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \
	 (u32)__tegra_cpu_reset_handler_start)))
#define tegra20_cpu1_resettable_status \
	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_RESETTABLE_STATUS] - \
	 (u32)__tegra_cpu_reset_handler_start)))
#endif

#define tegra_cpu_reset_handler_offset \
Loading