Commit e8c04e50 authored by Thierry Reding's avatar Thierry Reding

Merge branch 'for-5.7/arm/core' into for-5.7/cpuidle

parents bb6d3fb3 650a941c
......@@ -8,13 +8,13 @@ obj-y += reset.o
obj-y += reset-handler.o
obj-y += sleep.o
obj-y += tegra.o
obj-y += sleep-tegra20.o
obj-y += sleep-tegra30.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-tegra20.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o
endif
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
......@@ -22,12 +22,10 @@ endif
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
endif
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += cpuidle-tegra114.o
......
......@@ -12,13 +12,14 @@
#include <linux/firmware/trusted_foundations.h>
#include <soc/tegra/pm.h>
#include <asm/cpuidle.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include <asm/psci.h>
#include "cpuidle.h"
#include "pm.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
......@@ -34,17 +35,17 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
{
local_fiq_disable();
tegra_set_cpu_in_lp2();
tegra_pm_set_cpu_in_lp2();
cpu_pm_enter();
call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2);
/* Do suspend by ourselves if the firmware does not implement it */
if (call_firmware_op(do_idle, 0) == -ENOSYS)
cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
cpu_suspend(0, tegra30_pm_secondary_cpu_suspend);
cpu_pm_exit();
tegra_clear_cpu_in_lp2();
tegra_pm_clear_cpu_in_lp2();
local_fiq_enable();
......
......@@ -14,10 +14,13 @@
#include <linux/tick.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <soc/tegra/flowctrl.h>
#include <soc/tegra/irq.h>
#include <soc/tegra/pm.h>
#include <asm/cpuidle.h>
#include <asm/smp_plat.h>
......@@ -25,13 +28,11 @@
#include "cpuidle.h"
#include "iomap.h"
#include "irq.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
static bool abort_flag;
static atomic_t abort_flag;
static atomic_t abort_barrier;
static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
......@@ -65,28 +66,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,45 +76,74 @@ 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)
{
}
#endif
static inline int tegra20_reset_cpu_1(void)
static void tegra20_report_cpus_state(void)
{
return 0;
unsigned long cpu, lcpu, csr;
for_each_cpu(lcpu, cpu_possible_mask) {
cpu = cpu_logical_map(lcpu);
csr = flowctrl_read_cpu_csr(cpu);
pr_err("cpu%lu: online=%d flowctrl_csr=0x%08lx\n",
cpu, cpu_online(lcpu), csr);
}
}
static int tegra20_wait_for_secondary_cpu_parking(void)
{
unsigned int retries = 3;
while (retries--) {
unsigned int delay_us = 10;
unsigned int timeout_us = 500 * 1000 / delay_us;
/*
* The primary CPU0 core shall wait for the secondaries
* shutdown in order to power-off CPU's cluster safely.
* The timeout value depends on the current CPU frequency,
* it takes about 40-150us in average and over 1000us in
* a worst case scenario.
*/
do {
if (tegra_cpu_rail_off_ready())
return 0;
udelay(delay_us);
} while (timeout_us--);
pr_err("secondary CPU taking too long to park\n");
tegra20_report_cpus_state();
}
pr_err("timed out waiting secondaries to park\n");
return -ETIMEDOUT;
}
#endif
static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
while (tegra20_cpu_is_resettable_soon())
cpu_relax();
bool ret;
if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
if (tegra20_wait_for_secondary_cpu_parking())
return false;
tegra_idle_lp2_last();
ret = !tegra_pm_enter_lp2();
if (cpu_online(1))
tegra20_wake_cpu1_from_reset();
return true;
return ret;
}
#ifdef CONFIG_SMP
......@@ -141,9 +151,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;
}
......@@ -163,19 +171,20 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
bool entered_lp2 = false;
if (tegra_pending_sgi())
WRITE_ONCE(abort_flag, true);
atomic_set(&abort_flag, 1);
cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
if (abort_flag) {
if (atomic_read(&abort_flag)) {
cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
abort_flag = false; /* clean flag for next coming */
/* clean flag for next coming */
atomic_set(&abort_flag, 0);
return -EINTR;
}
local_fiq_disable();
tegra_set_cpu_in_lp2();
tegra_pm_set_cpu_in_lp2();
cpu_pm_enter();
if (dev->cpu == 0)
......@@ -184,12 +193,10 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index);
cpu_pm_exit();
tegra_clear_cpu_in_lp2();
tegra_pm_clear_cpu_in_lp2();
local_fiq_enable();
smp_rmb();
return entered_lp2 ? index : 0;
}
#endif
......
......@@ -17,12 +17,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <soc/tegra/pm.h>
#include <asm/cpuidle.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include "cpuidle.h"
#include "pm.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
......@@ -68,9 +69,7 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
return false;
}
tegra_idle_lp2_last();
return true;
return !tegra_pm_enter_lp2();
}
#ifdef CONFIG_SMP
......@@ -80,7 +79,7 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
{
smp_wmb();
cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
cpu_suspend(0, tegra30_pm_secondary_cpu_suspend);
return true;
}
......@@ -98,30 +97,22 @@ static int tegra30_idle_lp2(struct cpuidle_device *dev,
int index)
{
bool entered_lp2 = false;
bool last_cpu;
local_fiq_disable();
last_cpu = tegra_set_cpu_in_lp2();
tegra_pm_set_cpu_in_lp2();
cpu_pm_enter();
if (dev->cpu == 0) {
if (last_cpu)
entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv,
index);
else
cpu_do_idle();
} else {
if (dev->cpu == 0)
entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv, index);
else
entered_lp2 = tegra30_cpu_core_power_down(dev, drv, index);
}
cpu_pm_exit();
tegra_clear_cpu_in_lp2();
tegra_pm_clear_cpu_in_lp2();
local_fiq_enable();
smp_rmb();
return (entered_lp2) ? index : 0;
}
#endif
......
......@@ -18,9 +18,10 @@
#include <linux/of.h>
#include <linux/syscore_ops.h>
#include <soc/tegra/irq.h>
#include "board.h"
#include "iomap.h"
#include "irq.h"
#define SGI_MASK 0xFFFF
......
......@@ -110,7 +110,7 @@ static void suspend_cpu_complex(void)
flowctrl_cpu_suspend_enter(cpu);
}
void tegra_clear_cpu_in_lp2(void)
void tegra_pm_clear_cpu_in_lp2(void)
{
int phy_cpu_id = cpu_logical_map(smp_processor_id());
u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
......@@ -123,11 +123,9 @@ void tegra_clear_cpu_in_lp2(void)
spin_unlock(&tegra_lp2_lock);
}
bool tegra_set_cpu_in_lp2(void)
void tegra_pm_set_cpu_in_lp2(void)
{
int phy_cpu_id = cpu_logical_map(smp_processor_id());
bool last_cpu = false;
cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
spin_lock(&tegra_lp2_lock);
......@@ -135,22 +133,15 @@ bool tegra_set_cpu_in_lp2(void)
BUG_ON((*cpu_in_lp2 & BIT(phy_cpu_id)));
*cpu_in_lp2 |= BIT(phy_cpu_id);
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)
{
if (tegra_cpu_car_ops->rail_off_ready &&
WARN_ON(!tegra_cpu_rail_off_ready()))
return -EBUSY;
/*
* L2 cache disabling using kernel API only allowed when all
* secondary CPU's are offline. Cache have to be disabled with
......@@ -159,9 +150,10 @@ static int tegra_sleep_cpu(unsigned long v2p)
* if any of secondary CPU's is online and this is the LP2-idle
* code-path only for Tegra20/30.
*/
if (trusted_foundations_registered())
outer_disable();
#ifdef CONFIG_OUTER_CACHE
if (trusted_foundations_registered() && outer_cache.disable)
outer_cache.disable();
#endif
/*
* Note that besides of setting up CPU reset vector this firmware
* call may also do the following, depending on the FW version:
......@@ -202,14 +194,16 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
tegra_pmc_enter_suspend_mode(mode);
}
void tegra_idle_lp2_last(void)
int tegra_pm_enter_lp2(void)
{
int err;
tegra_pm_set(TEGRA_SUSPEND_LP2);
cpu_cluster_pm_enter();
suspend_cpu_complex();
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
err = cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
/*
* Resume L2 cache if it wasn't re-enabled early during resume,
......@@ -221,6 +215,8 @@ void tegra_idle_lp2_last(void)
restore_cpu_complex();
cpu_cluster_pm_exit();
return err;
}
enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
......@@ -365,7 +361,7 @@ static int tegra_suspend_enter(suspend_state_t state)
tegra_suspend_enter_lp1();
break;
case TEGRA_SUSPEND_LP2:
tegra_set_cpu_in_lp2();
tegra_pm_set_cpu_in_lp2();
break;
default:
break;
......@@ -386,7 +382,7 @@ static int tegra_suspend_enter(suspend_state_t state)
tegra_suspend_exit_lp1();
break;
case TEGRA_SUSPEND_LP2:
tegra_clear_cpu_in_lp2();
tegra_pm_clear_cpu_in_lp2();
break;
default:
break;
......@@ -436,4 +432,18 @@ void __init tegra_init_suspend(void)
suspend_set_ops(&tegra_suspend_ops);
}
int tegra_pm_park_secondary_cpu(unsigned long cpu)
{
if (cpu > 0) {
tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
if (tegra_get_chip_id() == TEGRA20)
tegra20_hotplug_shutdown();
else
tegra30_hotplug_shutdown();
}
return -EINVAL;
}
#endif
......@@ -23,10 +23,6 @@ void tegra20_sleep_core_init(void);
void tegra30_lp1_iram_hook(void);
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);
#ifdef CONFIG_PM_SLEEP
......
......@@ -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
......
......@@ -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 \
......
......@@ -43,9 +43,6 @@
#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
#define __tegra20_cpu1_resettable_status_offset \
(__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
.macro pll_enable, rd, r_car_base, pll_base
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 30)
......@@ -90,10 +87,6 @@ ENDPROC(tegra20_hotplug_shutdown)
ENTRY(tegra20_cpu_shutdown)
cmp r0, #0
reteq lr @ must not be called for CPU 0
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
ldr r2, =__tegra20_cpu1_resettable_status_offset
mov r12, #CPU_RESETTABLE
strb r12, [r1, r2]
cpu_to_halt_reg r1, r0
ldr r3, =TEGRA_FLOW_CTRL_VIRT
......@@ -116,107 +109,6 @@ ENDPROC(tegra20_cpu_shutdown)
#endif
#ifdef CONFIG_PM_SLEEP
/*
* tegra_pen_lock
*
* spinlock implementation with no atomic test-and-set and no coherence
* using Peterson's algorithm on strongly-ordered registers
* used to synchronize a cpu waking up from wfi with entering lp2 on idle
*
* The reference link of Peterson's algorithm:
* http://en.wikipedia.org/wiki/Peterson's_algorithm
*
* SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
* on cpu 0:
* r2 = flag[0] (in SCRATCH38)
* r3 = flag[1] (in SCRATCH39)
* on cpu1:
* r2 = flag[1] (in SCRATCH39)
* r3 = flag[0] (in SCRATCH38)
*
* must be called with MMU on
* corrupts r0-r3, r12
*/
ENTRY(tegra_pen_lock)
mov32 r3, TEGRA_PMC_VIRT
cpu_id r0
add r1, r3, #PMC_SCRATCH37
cmp r0, #0
addeq r2, r3, #PMC_SCRATCH38
addeq r3, r3, #PMC_SCRATCH39
addne r2, r3, #PMC_SCRATCH39
addne r3, r3, #PMC_SCRATCH38
mov r12, #1
str r12, [r2] @ flag[cpu] = 1
dsb
str r12, [r1] @ !turn = cpu
1: dsb
ldr r12, [r3]
cmp r12, #1 @ flag[!cpu] == 1?
ldreq r12, [r1]
cmpeq r12, r0 @ !turn == cpu?
beq 1b @ while !turn == cpu && flag[!cpu] == 1
ret lr @ locked
ENDPROC(tegra_pen_lock)
ENTRY(tegra_pen_unlock)
dsb
mov32 r3, TEGRA_PMC_VIRT
cpu_id r0
cmp r0, #0
addeq r2, r3, #PMC_SCRATCH38
addne r2, r3, #PMC_SCRATCH39
mov r12, #0
str r12, [r2]
ret lr
ENDPROC(tegra_pen_unlock)
/*
* tegra20_cpu_clear_resettable(void)
*
* Called to clear the "resettable soon" flag in IRAM variable when
* it is expected that the secondary CPU will be idle soon.
*/
ENTRY(tegra20_cpu_clear_resettable)
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
ldr r2, =__tegra20_cpu1_resettable_status_offset
mov r12, #CPU_NOT_RESETTABLE
strb r12, [r1, r2]
ret lr
ENDPROC(tegra20_cpu_clear_resettable)
/*
* tegra20_cpu_set_resettable_soon(void)
*
* Called to set the "resettable soon" flag in IRAM variable when
* it is expected that the secondary CPU will be idle soon.
*/
ENTRY(tegra20_cpu_set_resettable_soon)
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
ldr r2, =__tegra20_cpu1_resettable_status_offset
mov r12, #CPU_RESETTABLE_SOON
strb r12, [r1, r2]
ret lr
ENDPROC(tegra20_cpu_set_resettable_soon)
/*
* tegra20_cpu_is_resettable_soon(void)
*
* Returns true if the "resettable soon" flag in IRAM variable has been
* set because it is expected that the secondary CPU will be idle soon.
*/
ENTRY(tegra20_cpu_is_resettable_soon)
mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
ldr r2, =__tegra20_cpu1_resettable_status_offset
ldrb r12, [r1, r2]
cmp r12, #CPU_RESETTABLE_SOON
moveq r0, #1
movne r0, #0
ret lr
ENDPROC(tegra20_cpu_is_resettable_soon)
/*
* tegra20_sleep_core_finish(unsigned long v2p)
*
......@@ -242,68 +134,6 @@ ENTRY(tegra20_sleep_core_finish)
ret r3
ENDPROC(tegra20_sleep_core_finish)
/*
* tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
*
* Enters WFI on secondary CPU by exiting coherency.
*/
ENTRY(tegra20_sleep_cpu_secondary_finish)
stmfd sp!, {r4-r11, lr}
mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency
/* Flush and disable the L1 data cache */
mov r0, #TEGRA_FLUSH_CACHE_LOUIS
bl tegra_disable_clean_inv_dcache
mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
ldr r4, =__tegra20_cpu1_resettable_status_offset
mov r3, #CPU_RESETTABLE
strb r3, [r0, r4]
bl tegra_cpu_do_idle
/*
* cpu may be reset while in wfi, which will return through
* tegra_resume to cpu_resume
* or interrupt may wake wfi, which will return here
* cpu state is unchanged - MMU is on, cache is on, coherency
* is off, and the data cache is off
*
* r11 contains the original actlr
*/
bl tegra_pen_lock
mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
ldr r4, =__tegra20_cpu1_resettable_status_offset
mov r3, #CPU_NOT_RESETTABLE
strb r3, [r0, r4]
bl tegra_pen_unlock
/* Re-enable the data cache */
mrc p15, 0, r10, c1, c0, 0
orr r10, r10, #CR_C
mcr p15, 0, r10, c1, c0, 0
isb
mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
/* Invalidate the TLBs & BTAC */
mov r1, #0
mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
dsb
isb
/* the cpu was running with coherency disabled,
* caches may be out of date */
bl v7_flush_kern_cache_louis
ldmfd sp!, {r4 - r11, pc}
ENDPROC(tegra20_sleep_cpu_secondary_finish)
/*
* tegra20_tear_down_cpu
*
......
......@@ -265,11 +265,11 @@ ENTRY(tegra30_sleep_core_finish)
ENDPROC(tegra30_sleep_core_finish)
/*
* tegra30_sleep_cpu_secondary_finish(unsigned long v2p)
* tegra30_pm_secondary_cpu_suspend(unsigned long unused_arg)
*
* Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
*/
ENTRY(tegra30_sleep_cpu_secondary_finish)
ENTRY(tegra30_pm_secondary_cpu_suspend)
mov r7, lr
/* Flush and disable the L1 data cache */
......@@ -281,7 +281,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish)
bl tegra30_cpu_shutdown
mov r0, #1 @ never return here
ret r7
ENDPROC(tegra30_sleep_cpu_secondary_finish)
ENDPROC(tegra30_pm_secondary_cpu_suspend)
/*
* tegra30_tear_down_cpu
......
......@@ -114,29 +114,14 @@
.endm
#else
void tegra_pen_lock(void);
void tegra_pen_unlock(void);
void tegra_resume(void);
int tegra_sleep_cpu_finish(unsigned long);
void tegra_disable_clean_inv_dcache(u32 flag);
#ifdef CONFIG_HOTPLUG_CPU
void tegra20_hotplug_shutdown(void);
void tegra30_hotplug_shutdown(void);
#endif
void tegra20_cpu_shutdown(int cpu);
int tegra20_cpu_is_resettable_soon(void);
void tegra20_cpu_clear_resettable(void);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
void tegra20_cpu_set_resettable_soon(void);
#else
static inline void tegra20_cpu_set_resettable_soon(void) {}
#endif
int tegra20_sleep_cpu_secondary_finish(unsigned long);
void tegra20_tear_down_cpu(void);
int tegra30_sleep_cpu_secondary_finish(unsigned long);
void tegra30_tear_down_cpu(void);
#endif
......
......@@ -42,7 +42,6 @@
#include "common.h"
#include "cpuidle.h"
#include "iomap.h"
#include "irq.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
......
......@@ -3,9 +3,11 @@
* Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
*/
#ifndef __TEGRA_IRQ_H
#define __TEGRA_IRQ_H
#ifndef __SOC_TEGRA_IRQ_H
#define __SOC_TEGRA_IRQ_H
#if defined(CONFIG_ARM)
bool tegra_pending_sgi(void);
#endif
#endif /* __SOC_TEGRA_IRQ_H */
......@@ -6,6 +6,8 @@
#ifndef __SOC_TEGRA_PM_H__
#define __SOC_TEGRA_PM_H__
#include <linux/errno.h>
enum tegra_suspend_mode {
TEGRA_SUSPEND_NONE = 0,
TEGRA_SUSPEND_LP2, /* CPU voltage off */
......@@ -20,6 +22,12 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
/* low-level resume entry point */
void tegra_resume(void);
int tegra30_pm_secondary_cpu_suspend(unsigned long arg);
void tegra_pm_clear_cpu_in_lp2(void);
void tegra_pm_set_cpu_in_lp2(void);
int tegra_pm_enter_lp2(void);
int tegra_pm_park_secondary_cpu(unsigned long cpu);
#else
static inline enum tegra_suspend_mode
tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
......@@ -30,6 +38,29 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
static inline void tegra_resume(void)
{
}
static inline int tegra30_pm_secondary_cpu_suspend(unsigned long arg)
{
return -ENOTSUPP;
}
static inline void tegra_pm_clear_cpu_in_lp2(void)
{
}
static inline void tegra_pm_set_cpu_in_lp2(void)
{
}
static inline int tegra_pm_enter_lp2(void)
{
return -ENOTSUPP;
}
static inline int tegra_pm_park_secondary_cpu(unsigned long cpu)
{
return -ENOTSUPP;
}
#endif /* CONFIG_PM_SLEEP */
#endif /* __SOC_TEGRA_PM_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment