linux/arch/arm/mach-tegra/reset.h
Dmitry Osipenko 4d48edb3c3 ARM: tegra20: Store CPU "resettable" status in IRAM
Commit 7232398abc ("ARM: tegra: Convert PMC to a driver") changed tegra_resume()
location storing from late to early and, as a result, broke suspend on Tegra20.
PMC scratch register 41 is used by tegra LP1 resume code for retrieving stored
physical memory address of common resume function and in the same time used by
tegra20_cpu_shutdown() (shared by Tegra20 cpuidle driver and platform SMP code),
which is storing CPU1 "resettable" status. It implies strict order of scratch
register usage, otherwise resume function address is lost on Tegra20 after
disabling non-boot CPU's on suspend. Fix it by storing "resettable" status in
IRAM instead of PMC scratch register.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Fixes: 7232398abc (ARM: tegra: Convert PMC to a driver)
Cc: <stable@vger.kernel.org> # v3.17+
Signed-off-by: Thierry Reding <treding@nvidia.com>
2015-05-04 12:58:19 +02:00

68 lines
2.1 KiB
C

/*
* arch/arm/mach-tegra/reset.h
*
* CPU reset dispatcher.
*
* Copyright (c) 2011, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __MACH_TEGRA_RESET_H
#define __MACH_TEGRA_RESET_H
#define TEGRA_RESET_MASK_PRESENT 0
#define TEGRA_RESET_MASK_LP1 1
#define TEGRA_RESET_MASK_LP2 2
#define TEGRA_RESET_STARTUP_SECONDARY 3
#define TEGRA_RESET_STARTUP_LP2 4
#define TEGRA_RESET_STARTUP_LP1 5
#define TEGRA_RESET_DATA_SIZE 6
#ifndef __ASSEMBLY__
#include "irammap.h"
extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE];
void __tegra_cpu_reset_handler_start(void);
void __tegra_cpu_reset_handler(void);
void __tegra20_cpu1_resettable_status_offset(void);
void __tegra_cpu_reset_handler_end(void);
void tegra_secondary_startup(void);
#ifdef CONFIG_PM_SLEEP
#define tegra_cpu_lp1_mask \
(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP1] - \
(u32)__tegra_cpu_reset_handler_start)))
#define tegra_cpu_lp2_mask \
(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)__tegra20_cpu1_resettable_status_offset))
#endif
#define tegra_cpu_reset_handler_offset \
((u32)__tegra_cpu_reset_handler - \
(u32)__tegra_cpu_reset_handler_start)
#define tegra_cpu_reset_handler_size \
(__tegra_cpu_reset_handler_end - \
__tegra_cpu_reset_handler_start)
void __init tegra_cpu_reset_handler_init(void);
#endif
#endif