1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * arch/arm/mach-tegra/sleep.S
4 *
5 * Copyright (c) 2010-2011, NVIDIA Corporation.
6 * Copyright (c) 2011, Google, Inc.
7 *
8 * Author: Colin Cross <ccross@android.com>
9 *         Gary King <gking@nvidia.com>
10 */
11
12#include <linux/linkage.h>
13
14#include <asm/assembler.h>
15#include <asm/cache.h>
16#include <asm/cp15.h>
17#include <asm/hardware/cache-l2x0.h>
18
19#include "iomap.h"
20#include "sleep.h"
21
22#define CLK_RESET_CCLK_BURST	0x20
23#define CLK_RESET_CCLK_DIVIDER  0x24
24
25.arch armv7-a
26
27#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
28/*
29 * tegra_disable_clean_inv_dcache
30 *
31 * disable, clean & invalidate the D-cache
32 *
33 * Corrupted registers: r1-r3, r6, r8, r9-r11
34 */
35ENTRY(tegra_disable_clean_inv_dcache)
36	stmfd	sp!, {r0, r4-r5, r7, r9-r11, lr}
37	dmb					@ ensure ordering
38
39	/* Disable the D-cache */
40	mrc	p15, 0, r2, c1, c0, 0
41	tst	r2, #CR_C			@ see tegra_sleep_cpu()
42	bic	r2, r2, #CR_C
43	mcrne	p15, 0, r2, c1, c0, 0
44	isb
45
46	/* Flush the D-cache */
47	cmp	r0, #TEGRA_FLUSH_CACHE_ALL
48	blne	v7_flush_dcache_louis
49	bleq	v7_flush_dcache_all
50
51	/* Trun off coherency */
52	exit_smp r4, r5
53
54	ldmfd	sp!, {r0, r4-r5, r7, r9-r11, pc}
55ENDPROC(tegra_disable_clean_inv_dcache)
56#endif
57
58#ifdef CONFIG_PM_SLEEP
59/*
60 * tegra_init_l2_for_a15
61 *
62 * set up the correct L2 cache data RAM latency
63 */
64ENTRY(tegra_init_l2_for_a15)
65	mrc	p15, 0, r0, c0, c0, 5
66	ubfx	r0, r0, #8, #4
67	tst	r0, #1				@ only need for cluster 0
68	bne	_exit_init_l2_a15
69
70	mrc	p15, 0x1, r0, c9, c0, 2
71	and	r0, r0, #7
72	cmp	r0, #2
73	bicne	r0, r0, #7
74	orrne	r0, r0, #2
75	mcrne	p15, 0x1, r0, c9, c0, 2
76_exit_init_l2_a15:
77
78	ret	lr
79ENDPROC(tegra_init_l2_for_a15)
80
81/*
82 * tegra_sleep_cpu_finish(unsigned long v2p)
83 *
84 * enters suspend in LP2 by turning off the mmu and jumping to
85 * tegra?_tear_down_cpu
86 */
87ENTRY(tegra_sleep_cpu_finish)
88	mov	r4, r0
89	/* Flush and disable the L1 data cache */
90	mov	r0, #TEGRA_FLUSH_CACHE_ALL
91	bl	tegra_disable_clean_inv_dcache
92
93	mov	r0, r4
94	mov32	r6, tegra_tear_down_cpu
95	ldr	r1, [r6]
96	add	r1, r1, r0
97
98	mov32	r3, tegra_shut_off_mmu
99	add	r3, r3, r0
100	mov	r0, r1
101
102	ret	r3
103ENDPROC(tegra_sleep_cpu_finish)
104
105/*
106 * tegra_shut_off_mmu
107 *
108 * r0 = physical address to jump to with mmu off
109 *
110 * called with VA=PA mapping
111 * turns off MMU, icache, dcache and branch prediction
112 */
113	.align	L1_CACHE_SHIFT
114	.pushsection	.idmap.text, "ax"
115ENTRY(tegra_shut_off_mmu)
116	mrc	p15, 0, r3, c1, c0, 0
117	movw	r2, #CR_I | CR_Z | CR_C | CR_M
118	bic	r3, r3, r2
119	dsb
120	mcr	p15, 0, r3, c1, c0, 0
121	isb
122#ifdef CONFIG_CACHE_L2X0
123	/* Disable L2 cache */
124	check_cpu_part_num 0xc09, r9, r10
125	retne	r0
126
127	mov32	r2, TEGRA_ARM_PERIF_BASE + 0x3000
128	ldr	r3, [r2, #L2X0_CTRL]
129	tst	r3, #L2X0_CTRL_EN		@ see tegra_sleep_cpu()
130	mov	r3, #0
131	strne	r3, [r2, #L2X0_CTRL]
132#endif
133	ret	r0
134ENDPROC(tegra_shut_off_mmu)
135	.popsection
136
137/*
138 * tegra_switch_cpu_to_pllp
139 *
140 * In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
141 */
142ENTRY(tegra_switch_cpu_to_pllp)
143	/* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
144	mov32	r5, TEGRA_CLK_RESET_BASE
145	mov	r0, #(2 << 28)			@ burst policy = run mode
146	orr	r0, r0, #(4 << 4)		@ use PLLP in run mode burst
147	str	r0, [r5, #CLK_RESET_CCLK_BURST]
148	mov	r0, #0
149	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
150	ret	lr
151ENDPROC(tegra_switch_cpu_to_pllp)
152#endif
153