1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
/*
* Idle processing for ARMv7-based Qualcomm SoCs.
*
* Copyright (C) 2007 Google, Inc.
* Copyright (c) 2007-2009, Code Aurora Forum. All rights reserved.
*
* 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.
*
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
ENTRY(msm_arch_idle)
wfi
bx lr
ENTRY(msm_pm_collapse)
#if defined(CONFIG_MSM_FIQ_SUPPORT)
cpsid f
#endif
ldr r0, =saved_state
stmia r0!, {r4-r14}
mrc p15, 0, r1, c1, c0, 0 /* MMU control */
mrc p15, 0, r2, c2, c0, 0 /* TTBR0 */
mrc p15, 0, r3, c3, c0, 0 /* dacr */
mrc p15, 3, r4, c15, c0, 3 /* L2CR1 is the L2 cache control reg 1 */
mrc p15, 0, r5, c10, c2, 0 /* PRRR */
mrc p15, 0, r6, c10, c2, 1 /* NMRR */
mrc p15, 0, r7, c1, c0, 1 /* ACTLR */
mrc p15, 0, r8, c2, c0, 1 /* TTBR1 */
mrc p15, 0, r9, c13, c0, 3 /* TPIDRURO */
mrc p15, 0, ip, c13, c0, 1 /* context ID */
stmia r0!, {r1-r9, ip}
#ifdef CONFIG_MSM_CPU_AVS
mrc p15, 7, r1, c15, c1, 7 /* AVSCSR is the Adaptive Voltage Scaling
* Control and Status Register */
mrc p15, 7, r2, c15, c0, 6 /* AVSDSCR is the Adaptive Voltage
* Scaling Delay Synthesizer Control
* Register */
mrc p15, 7, r3, c15, c1, 0 /* TSCSR is the Temperature Status and
* Control Register
*/
stmia r0!, {r1-r3}
#endif
#ifdef CONFIG_MSM_JTAG_V7
bl msm_save_jtag_debug
#endif
bl v7_flush_dcache_all
mrc p15, 0, r1, c1, c0, 0 /* read current CR */
bic r0, r1, #(1 << 2) /* clear dcache bit */
bic r0, r0, #(1 << 12) /* clear icache bit */
mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */
dsb
wfi
mcr p15, 0, r1, c1, c0, 0 /* restore d/i cache */
isb
#if defined(CONFIG_MSM_FIQ_SUPPORT)
cpsie f
#endif
ldr r0, =saved_state /* restore registers */
ldmfd r0, {r4-r14}
mov r0, #0 /* return power collapse failed */
bx lr
ENTRY(msm_pm_collapse_exit)
#if 0 /* serial debug */
mov r0, #0x80000016
mcr p15, 0, r0, c15, c2, 4
mov r0, #0xA9000000
add r0, r0, #0x00A00000 /* UART1 */
/*add r0, r0, #0x00C00000*/ /* UART3 */
mov r1, #'A'
str r1, [r0, #0x00C]
#endif
ldr r1, =saved_state_end
ldr r2, =msm_pm_collapse_exit
adr r3, msm_pm_collapse_exit
add r1, r1, r3
sub r1, r1, r2
#ifdef CONFIG_MSM_CPU_AVS
ldmdb r1!, {r2-r4}
mcr p15, 7, r4, c15, c1, 0 /* TSCSR */
mcr p15, 7, r3, c15, c0, 6 /* AVSDSCR */
mcr p15, 7, r2, c15, c1, 7 /* AVSCSR */
#endif
ldmdb r1!, {r2-r11}
mcr p15, 0, r4, c3, c0, 0 /* dacr */
mcr p15, 0, r3, c2, c0, 0 /* TTBR0 */
mcr p15, 3, r5, c15, c0, 3 /* L2CR1 */
mcr p15, 0, r6, c10, c2, 0 /* PRRR */
mcr p15, 0, r7, c10, c2, 1 /* NMRR */
mcr p15, 0, r8, c1, c0, 1 /* ACTLR */
mcr p15, 0, r9, c2, c0, 1 /* TTBR1 */
mcr p15, 0, r10, c13, c0, 3 /* TPIDRURO */
mcr p15, 0, r11, c13, c0, 1 /* context ID */
isb
ldmdb r1!, {r4-r14}
/* Add 1:1 map in the PMD to allow smooth switch when turning on MMU */
and r3, r3, #~0x7F /* mask off lower 7 bits of TTB */
adr r0, msm_pm_mapped_pa /* get address of the mapped instr */
lsr r1, r0, #20 /* get the addr range of addr in MB */
lsl r1, r1, #2 /* multiply by 4 to get to the pg index */
add r3, r3, r1 /* pgd + pgd_index(addr) */
ldr r1, [r3] /* save current entry to r1 */
lsr r0, #20 /* align current addr to 1MB boundary */
lsl r0, #20
/* Create new entry for this 1MB page */
orr r0, r0, #0x4 /* PMD_SECT_BUFFERED */
orr r0, r0, #0x400 /* PMD_SECT_AP_WRITE */
orr r0, r0, #0x2 /* PMD_TYPE_SECT|PMD_DOMAIN(DOMAIN_KERNEL) */
str r0, [r3] /* put new entry into the MMU table */
mcr p15, 0, r3, c7, c10, 1 /* flush_pmd */
dsb
isb
mcr p15, 0, r2, c1, c0, 0 /* MMU control */
isb
msm_pm_mapped_pa:
/* Switch to virtual */
adr r2, msm_pm_pa_to_va
ldr r0, =msm_pm_pa_to_va
mov pc, r0
msm_pm_pa_to_va:
sub r0, r0, r2
/* Restore r1 in MMU table */
add r3, r3, r0
str r1, [r3]
mcr p15, 0, r3, c7, c10, 1 /* flush_pmd */
dsb
isb
mcr p15, 0, r3, c8, c7, 0 /* UTLBIALL */
mcr p15, 0, r3, c7, c5, 6 /* BPIALL */
dsb
isb
stmfd sp!, {lr}
bl v7_flush_kern_cache_all
#ifdef CONFIG_MSM_JTAG_V7
bl msm_restore_jtag_debug
#endif
ldmfd sp!, {lr}
mov r0, #1
bx lr
nop
nop
nop
nop
nop
1: b 1b
.data
saved_state:
.space 4 * 11 /* r4-14 */
.space 4 * 10 /* cp15 */
#ifdef CONFIG_MSM_CPU_AVS
.space 4 * 3 /* AVS control registers */
#endif
saved_state_end:
|