2012-08-16 17:31:50 +08:00
/*
2013-02-13 19:15:48 +02:00
* Copyright ( c ) 2010 - 2013 , NVIDIA Corporation . All rights reserved .
2012-08-16 17:31:50 +08:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifndef __MACH_TEGRA_SLEEP_H
# define __MACH_TEGRA_SLEEP_H
2012-10-04 14:24:09 -06:00
# include "iomap.h"
2015-01-15 13:58:57 +03:00
# include "irammap.h"
2012-08-16 17:31:50 +08:00
2012-08-16 17:31:51 +08:00
# define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
+ IO_CPU_VIRT )
2012-08-16 17:31:50 +08:00
# define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
+ IO_PPSB_VIRT )
2012-08-16 17:31:52 +08:00
# define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
+ IO_PPSB_VIRT )
2013-05-20 18:39:29 +08:00
# define TEGRA_APB_MISC_VIRT (TEGRA_APB_MISC_BASE - IO_APB_PHYS \
+ IO_APB_VIRT )
2013-01-15 22:10:38 +00:00
# define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
2015-01-15 13:58:57 +03:00
# define TEGRA_IRAM_RESET_BASE_VIRT (IO_IRAM_VIRT + \
TEGRA_IRAM_RESET_HANDLER_OFFSET )
2013-01-15 22:10:38 +00:00
/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */
# define PMC_SCRATCH37 0x130
# define PMC_SCRATCH38 0x134
# define PMC_SCRATCH39 0x138
# define PMC_SCRATCH41 0x140
# ifdef CONFIG_ARCH_TEGRA_2x_SOC
# define CPU_RESETTABLE 2
# define CPU_RESETTABLE_SOON 1
# define CPU_NOT_RESETTABLE 0
# endif
2012-08-16 17:31:50 +08:00
2013-07-03 17:50:38 +08:00
/* flag of tegra_disable_clean_inv_dcache to do LoUIS or all */
# define TEGRA_FLUSH_CACHE_LOUIS 0
# define TEGRA_FLUSH_CACHE_ALL 1
2012-08-16 17:31:50 +08:00
# ifdef __ASSEMBLY__
ARM: tegra: add LP1 suspend support for Tegra30
The LP1 suspend mode will power off the CPU, clock gated the PLLs and put
SDRAM to self-refresh mode. Any interrupt can wake up device from LP1. The
sequence when LP1 suspending:
* tunning off L1 data cache and the MMU
* storing some EMC registers, DPD (deep power down) status, clk source of
mselect and SCLK burst policy
* putting SDRAM into self-refresh
* switching CPU to CLK_M (12MHz OSC)
* tunning off PLLM, PLLP, PLLA, PLLC and PLLX
* switching SCLK to CLK_S (32KHz OSC)
* shutting off the CPU rail
The sequence of LP1 resuming:
* re-enabling PLLM, PLLP, PLLA, PLLC and PLLX
* restoring the clk source of mselect and SCLK burst policy
* setting up CCLK burst policy to PLLX
* restoring DPD status and some EMC registers
* resuming SDRAM to normal mode
* jumping to the "tegra_resume" from PMC_SCRATCH41
Due to the SDRAM will be put into self-refresh mode, the low level
procedures of LP1 suspending and resuming should be copied to
TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K) when suspending. Before
restoring the CPU context when resuming, the SDRAM needs to be switched
back to normal mode. And the PLLs need to be re-enabled, SCLK burst policy
be restored, CCLK burst policy be set in PLLX. Then jumping to
"tegra_resume" that was expected to be stored in PMC_SCRATCH41 to restore
CPU context and back to kernel.
Based on the work by: Scott Williams <scwilliams@nvidia.com>
Signed-off-by: Joseph Lo <josephl@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-08-12 17:40:04 +08:00
/* waits until the microsecond counter (base) is > rn */
. macro wait_until , rn , base , tmp
add \ rn , \ rn , # 1
1001 : ldr \ tmp , [ \ base ]
cmp \ tmp , \ rn
bmi 1001 b
. endm
2012-08-16 17:31:50 +08:00
/* returns the offset of the flow controller halt register for a cpu */
. macro cpu_to_halt_reg rd , rcpu
cmp \ rcpu , # 0
subne \ rd , \ rcpu , # 1
movne \ rd , \ rd , lsl # 3
addne \ rd , \ rd , # 0x14
moveq \ rd , # 0
. endm
/* returns the offset of the flow controller csr register for a cpu */
. macro cpu_to_csr_reg rd , rcpu
cmp \ rcpu , # 0
subne \ rd , \ rcpu , # 1
movne \ rd , \ rd , lsl # 3
addne \ rd , \ rd , # 0x18
moveq \ rd , # 8
. endm
/* returns the ID of the current processor */
. macro cpu_id , rd
mrc p15 , 0 , \ rd , c0 , c0 , 5
and \ rd , \ rd , # 0xF
. endm
/* loads a 32-bit value into a register without a data access */
. macro mov32 , reg , val
movw \ reg , # : lower16 : \ val
movt \ reg , # : upper16 : \ val
. endm
2012-08-16 17:31:51 +08:00
2013-05-20 18:39:25 +08:00
/* Marco to check CPU part num */
. macro check_cpu_part_num part_num , tmp1 , tmp2
mrc p15 , 0 , \ tmp1 , c0 , c0 , 0
ubfx \ tmp1 , \ tmp1 , # 4 , # 12
mov32 \ tmp2 , \ part_num
cmp \ tmp1 , \ tmp2
. endm
2012-08-16 17:31:51 +08:00
/* Macro to exit SMP coherency. */
. macro exit_smp , tmp1 , tmp2
mrc p15 , 0 , \ tmp1 , c1 , c0 , 1 @ ACTLR
bic \ tmp1 , \ tmp1 , # ( 1 < < 6 ) | ( 1 < < 0 ) @ clear ACTLR . SMP | ACTLR . FW
mcr p15 , 0 , \ tmp1 , c1 , c0 , 1 @ ACTLR
isb
2013-05-20 18:39:25 +08:00
# ifdef CONFIG_HAVE_ARM_SCU
check_cpu_part_num 0xc09 , \ tmp1 , \ tmp2
mrceq p15 , 0 , \ tmp1 , c0 , c0 , 5
andeq \ tmp1 , \ tmp1 , # 0xF
moveq \ tmp1 , \ tmp1 , lsl # 2
moveq \ tmp2 , # 0xf
moveq \ tmp2 , \ tmp2 , lsl \ tmp1
ldreq \ tmp1 , = ( TEGRA_ARM_PERIF_VIRT + 0xC )
streq \ tmp2 , [ \ tmp1 ] @ invalidate SCU tags for CPU
2012-08-16 17:31:51 +08:00
dsb
2013-05-20 18:39:25 +08:00
# endif
2012-08-16 17:31:51 +08:00
. endm
2012-11-13 10:04:48 +08:00
2013-05-20 18:39:24 +08:00
/* Macro to check Tegra revision */
# define APB_MISC_GP_HIDREV 0x804
. macro tegra_get_soc_id base , tmp1
mov32 \ tmp1 , \ base
ldr \ tmp1 , [ \ tmp1 , # APB_MISC_GP_HIDREV ]
and \ tmp1 , \ tmp1 , # 0xff00
mov \ tmp1 , \ tmp1 , lsr # 8
. endm
2012-08-16 17:31:51 +08:00
# else
2013-01-15 22:10:38 +00:00
void tegra_pen_lock ( void ) ;
void tegra_pen_unlock ( void ) ;
2012-10-31 17:41:16 +08:00
void tegra_resume ( void ) ;
2012-10-31 17:41:21 +08:00
int tegra_sleep_cpu_finish ( unsigned long ) ;
2013-07-03 17:50:38 +08:00
void tegra_disable_clean_inv_dcache ( u32 flag ) ;
2012-08-16 17:31:51 +08:00
# ifdef CONFIG_HOTPLUG_CPU
2013-02-13 19:15:48 +02:00
void tegra20_hotplug_shutdown ( void ) ;
void tegra30_hotplug_shutdown ( void ) ;
2012-08-16 17:31:51 +08:00
# endif
2013-01-16 17:33:55 +00:00
void tegra20_cpu_shutdown ( int cpu ) ;
int tegra20_cpu_is_resettable_soon ( void ) ;
2013-01-15 22:10:38 +00:00
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 ) ;
2013-01-16 17:33:55 +00:00
void tegra20_tear_down_cpu ( void ) ;
2012-10-31 17:41:17 +08:00
int tegra30_sleep_cpu_secondary_finish ( unsigned long ) ;
2012-10-31 17:41:21 +08:00
void tegra30_tear_down_cpu ( void ) ;
2012-10-31 17:41:17 +08:00
2012-08-16 17:31:50 +08:00
# endif
# endif