| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											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)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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	1001b | 
					
						
							|  |  |  | .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-11-13 10:04:48 +08:00
										 |  |  | /* Macro to resume & re-enable L2 cache */ | 
					
						
							|  |  |  | #ifndef L2X0_CTRL_EN
 | 
					
						
							|  |  |  | #define L2X0_CTRL_EN	1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_CACHE_L2X0
 | 
					
						
							|  |  |  | .macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs | 
					
						
							| 
									
										
										
										
											2013-04-16 11:09:09 -06:00
										 |  |  | 	W(adr)	\tmp1, \phys_l2x0_saved_regs | 
					
						
							| 
									
										
										
										
											2012-11-13 10:04:48 +08:00
										 |  |  | 	ldr	\tmp1, [\tmp1] | 
					
						
							|  |  |  | 	ldr	\tmp2, [\tmp1, #L2X0_R_PHY_BASE] | 
					
						
							|  |  |  | 	ldr	\tmp3, [\tmp2, #L2X0_CTRL] | 
					
						
							|  |  |  | 	tst	\tmp3, #L2X0_CTRL_EN | 
					
						
							|  |  |  | 	bne	exit_l2_resume | 
					
						
							|  |  |  | 	ldr	\tmp3, [\tmp1, #L2X0_R_TAG_LATENCY] | 
					
						
							|  |  |  | 	str	\tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL] | 
					
						
							|  |  |  | 	ldr	\tmp3, [\tmp1, #L2X0_R_DATA_LATENCY] | 
					
						
							|  |  |  | 	str	\tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL] | 
					
						
							|  |  |  | 	ldr	\tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL] | 
					
						
							|  |  |  | 	str	\tmp3, [\tmp2, #L2X0_PREFETCH_CTRL] | 
					
						
							|  |  |  | 	ldr	\tmp3, [\tmp1, #L2X0_R_PWR_CTRL] | 
					
						
							|  |  |  | 	str	\tmp3, [\tmp2, #L2X0_POWER_CTRL] | 
					
						
							|  |  |  | 	ldr	\tmp3, [\tmp1, #L2X0_R_AUX_CTRL] | 
					
						
							|  |  |  | 	str	\tmp3, [\tmp2, #L2X0_AUX_CTRL] | 
					
						
							|  |  |  | 	mov	\tmp3, #L2X0_CTRL_EN | 
					
						
							|  |  |  | 	str	\tmp3, [\tmp2, #L2X0_CTRL] | 
					
						
							|  |  |  | exit_l2_resume: | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | #else /* CONFIG_CACHE_L2X0 */
 | 
					
						
							|  |  |  | .macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | #endif /* CONFIG_CACHE_L2X0 */
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							|  |  |  | void tegra_hotplug_init(void); | 
					
						
							| 
									
										
										
										
											2012-08-16 17:31:51 +08:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-02-13 19:15:48 +02:00
										 |  |  | static inline void tegra_hotplug_init(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
 |