Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/frv/kernel/sleep.S
10817 views
1
/* sleep.S: power saving mode entry
2
*
3
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4
* Written by David Woodhouse ([email protected])
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
10
*
11
*/
12
13
#include <linux/sys.h>
14
#include <linux/linkage.h>
15
#include <asm/setup.h>
16
#include <asm/segment.h>
17
#include <asm/page.h>
18
#include <asm/ptrace.h>
19
#include <asm/errno.h>
20
#include <asm/cache.h>
21
#include <asm/spr-regs.h>
22
23
#define __addr_MASK 0xfeff9820 /* interrupt controller mask */
24
25
#define __addr_FR55X_DRCN 0xfeff0218 /* Address of DRCN register */
26
#define FR55X_DSTS_OFFSET -4 /* Offset from DRCN to DSTS */
27
#define FR55X_SDRAMC_DSTS_SSI 0x00000002 /* indicates that the SDRAM is in self-refresh mode */
28
29
#define __addr_FR4XX_DRCN 0xfe000430 /* Address of DRCN register */
30
#define FR4XX_DSTS_OFFSET -8 /* Offset from DRCN to DSTS */
31
#define FR4XX_SDRAMC_DSTS_SSI 0x00000001 /* indicates that the SDRAM is in self-refresh mode */
32
33
#define SDRAMC_DRCN_SR 0x00000001 /* transition SDRAM into self-refresh mode */
34
35
.section .bss
36
.balign 8
37
.globl __sleep_save_area
38
__sleep_save_area:
39
.space 16
40
41
42
.text
43
.balign 4
44
45
.macro li v r
46
sethi.p %hi(\v),\r
47
setlo %lo(\v),\r
48
.endm
49
50
#ifdef CONFIG_PM
51
###############################################################################
52
#
53
# CPU suspension routine
54
# - void frv_cpu_suspend(unsigned long pdm_mode)
55
#
56
###############################################################################
57
.globl frv_cpu_suspend
58
.type frv_cpu_suspend,@function
59
frv_cpu_suspend:
60
61
#----------------------------------------------------
62
# save hsr0, psr, isr, and lr for resume code
63
#----------------------------------------------------
64
li __sleep_save_area,gr11
65
66
movsg hsr0,gr4
67
movsg psr,gr5
68
movsg isr,gr6
69
movsg lr,gr7
70
stdi gr4,@(gr11,#0)
71
stdi gr6,@(gr11,#8)
72
73
# store the return address from sleep in GR14, and its complement in GR13 as a check
74
li __ramboot_resume,gr14
75
#ifdef CONFIG_MMU
76
# Resume via RAMBOOT# will turn MMU off, so bootloader needs a physical address.
77
sethi.p %hi(__page_offset),gr13
78
setlo %lo(__page_offset),gr13
79
sub gr14,gr13,gr14
80
#endif
81
not gr14,gr13
82
83
#----------------------------------------------------
84
# preload and lock into icache that code which may have to run
85
# when dram is in self-refresh state.
86
#----------------------------------------------------
87
movsg hsr0, gr3
88
li HSR0_ICE,gr4
89
or gr3,gr4,gr3
90
movgs gr3,hsr0
91
or gr3,gr8,gr7 // add the sleep bits for later
92
93
li #__icache_lock_start,gr3
94
li #__icache_lock_end,gr4
95
1: icpl gr3,gr0,#1
96
addi gr3,#L1_CACHE_BYTES,gr3
97
cmp gr4,gr3,icc0
98
bhi icc0,#0,1b
99
100
# disable exceptions
101
movsg psr,gr8
102
andi.p gr8,#~PSR_PIL,gr8
103
andi gr8,~PSR_ET,gr8
104
movgs gr8,psr
105
ori gr8,#PSR_ET,gr8
106
107
srli gr8,#28,gr4
108
subicc gr4,#3,gr0,icc0
109
beq icc0,#0,1f
110
# FR4xx
111
li __addr_FR4XX_DRCN,gr4
112
li FR4XX_SDRAMC_DSTS_SSI,gr5
113
li FR4XX_DSTS_OFFSET,gr6
114
bra __icache_lock_start
115
1:
116
# FR5xx
117
li __addr_FR55X_DRCN,gr4
118
li FR55X_SDRAMC_DSTS_SSI,gr5
119
li FR55X_DSTS_OFFSET,gr6
120
bra __icache_lock_start
121
122
.size frv_cpu_suspend, .-frv_cpu_suspend
123
124
#
125
# the final part of the sleep sequence...
126
# - we want it to be be cacheline aligned so we can lock it into the icache easily
127
# On entry: gr7 holds desired hsr0 sleep value
128
# gr8 holds desired psr sleep value
129
#
130
.balign L1_CACHE_BYTES
131
.type __icache_lock_start,@function
132
__icache_lock_start:
133
134
#----------------------------------------------------
135
# put SDRAM in self-refresh mode
136
#----------------------------------------------------
137
138
# Flush all data in the cache using the DCEF instruction.
139
dcef @(gr0,gr0),#1
140
141
# Stop DMAC transfer
142
143
# Execute dummy load from SDRAM
144
ldi @(gr11,#0),gr11
145
146
# put the SDRAM into self-refresh mode
147
ld @(gr4,gr0),gr11
148
ori gr11,#SDRAMC_DRCN_SR,gr11
149
st gr11,@(gr4,gr0)
150
membar
151
152
# wait for SDRAM to reach self-refresh mode
153
1: ld @(gr4,gr6),gr11
154
andcc gr11,gr5,gr11,icc0
155
beq icc0,#0,1b
156
157
# Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
158
# Set the clock mode (CLKC register) as required.
159
# - At this time, also set the CLKC register P0 bit.
160
161
# Set the HSR0 register PDM field.
162
movgs gr7,hsr0
163
164
# Execute NOP 32 times.
165
.rept 32
166
nop
167
.endr
168
169
#if 0 // Fujitsu recommend to skip this and will update docs.
170
# Release the interrupt mask setting of the MASK register of the
171
# interrupt controller if necessary.
172
sti gr10,@(gr9,#0)
173
membar
174
#endif
175
176
# Set the PSR register ET bit to 1 to enable interrupts.
177
movgs gr8,psr
178
179
###################################################
180
# this is only reached if waking up via interrupt
181
###################################################
182
183
# Execute NOP 32 times.
184
.rept 32
185
nop
186
.endr
187
188
#----------------------------------------------------
189
# wake SDRAM from self-refresh mode
190
#----------------------------------------------------
191
ld @(gr4,gr0),gr11
192
andi gr11,#~SDRAMC_DRCN_SR,gr11
193
st gr11,@(gr4,gr0)
194
membar
195
2:
196
ld @(gr4,gr6),gr11 // Wait for it to come back...
197
andcc gr11,gr5,gr0,icc0
198
bne icc0,0,2b
199
200
# wait for the SDRAM to stabilise
201
li 0x0100000,gr3
202
3: subicc gr3,#1,gr3,icc0
203
bne icc0,#0,3b
204
205
# now that DRAM is back, this is the end of the code which gets
206
# locked in icache.
207
__icache_lock_end:
208
.size __icache_lock_start, .-__icache_lock_start
209
210
# Fall-through to the RAMBOOT# wakeup path
211
212
###############################################################################
213
#
214
# resume from suspend re-entry point reached via RAMBOOT# and bootloader
215
#
216
###############################################################################
217
__ramboot_resume:
218
219
#----------------------------------------------------
220
# restore hsr0, psr, isr, and leave saved lr in gr7
221
#----------------------------------------------------
222
li __sleep_save_area,gr11
223
#ifdef CONFIG_MMU
224
movsg hsr0,gr4
225
sethi.p %hi(HSR0_EXMMU),gr3
226
setlo %lo(HSR0_EXMMU),gr3
227
andcc gr3,gr4,gr0,icc0
228
bne icc0,#0,2f
229
230
# need to use physical address
231
sethi.p %hi(__page_offset),gr3
232
setlo %lo(__page_offset),gr3
233
sub gr11,gr3,gr11
234
235
# flush all tlb entries
236
setlos #64,gr4
237
setlos.p #PAGE_SIZE,gr5
238
setlos #0,gr6
239
1:
240
tlbpr gr6,gr0,#6,#0
241
subicc.p gr4,#1,gr4,icc0
242
add gr6,gr5,gr6
243
bne icc0,#2,1b
244
245
# need a temporary mapping for the current physical address we are
246
# using between time MMU is enabled and jump to virtual address is
247
# made.
248
sethi.p %hi(0x00000000),gr4
249
setlo %lo(0x00000000),gr4 ; physical address
250
setlos #xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5
251
or gr4,gr5,gr5
252
253
movsg cxnr,gr13
254
or gr4,gr13,gr4
255
256
movgs gr4,iamlr1 ; mapped from real address 0
257
movgs gr5,iampr1 ; cached kernel memory at 0x00000000
258
2:
259
#endif
260
261
lddi @(gr11,#0),gr4 ; hsr0, psr
262
lddi @(gr11,#8),gr6 ; isr, lr
263
movgs gr4,hsr0
264
bar
265
266
#ifdef CONFIG_MMU
267
sethi.p %hi(1f),gr11
268
setlo %lo(1f),gr11
269
jmpl @(gr11,gr0)
270
1:
271
movgs gr0,iampr1 ; get rid of temporary mapping
272
#endif
273
movgs gr5,psr
274
movgs gr6,isr
275
276
#----------------------------------------------------
277
# unlock the icache which was locked before going to sleep
278
#----------------------------------------------------
279
li __icache_lock_start,gr3
280
li __icache_lock_end,gr4
281
1: icul gr3
282
addi gr3,#L1_CACHE_BYTES,gr3
283
cmp gr4,gr3,icc0
284
bhi icc0,#0,1b
285
286
#----------------------------------------------------
287
# back to business as usual
288
#----------------------------------------------------
289
jmpl @(gr7,gr0) ;
290
291
#endif /* CONFIG_PM */
292
293
###############################################################################
294
#
295
# CPU core sleep mode routine
296
#
297
###############################################################################
298
.globl frv_cpu_core_sleep
299
.type frv_cpu_core_sleep,@function
300
frv_cpu_core_sleep:
301
302
# Preload into icache.
303
li #__core_sleep_icache_lock_start,gr3
304
li #__core_sleep_icache_lock_end,gr4
305
306
1: icpl gr3,gr0,#1
307
addi gr3,#L1_CACHE_BYTES,gr3
308
cmp gr4,gr3,icc0
309
bhi icc0,#0,1b
310
311
bra __core_sleep_icache_lock_start
312
313
.balign L1_CACHE_BYTES
314
__core_sleep_icache_lock_start:
315
316
# (1) Set the PSR register ET bit to 0 to disable interrupts.
317
movsg psr,gr8
318
andi.p gr8,#~(PSR_PIL),gr8
319
andi gr8,#~(PSR_ET),gr4
320
movgs gr4,psr
321
322
#if 0 // Fujitsu recommend to skip this and will update docs.
323
# (2) Set '1' to all bits in the MASK register of the interrupt
324
# controller and mask interrupts.
325
sethi.p %hi(__addr_MASK),gr9
326
setlo %lo(__addr_MASK),gr9
327
sethi.p %hi(0xffff0000),gr4
328
setlo %lo(0xffff0000),gr4
329
ldi @(gr9,#0),gr10
330
sti gr4,@(gr9,#0)
331
#endif
332
# (3) Flush all data in the cache using the DCEF instruction.
333
dcef @(gr0,gr0),#1
334
335
# (4) Execute the memory barrier instruction
336
membar
337
338
# (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
339
# (6) Set the clock mode (CLKC register) as required.
340
# - At this time, also set the CLKC register P0 bit.
341
# (7) Set the HSR0 register PDM field to 001 .
342
movsg hsr0,gr4
343
ori gr4,HSR0_PDM_CORE_SLEEP,gr4
344
movgs gr4,hsr0
345
346
# (8) Execute NOP 32 times.
347
.rept 32
348
nop
349
.endr
350
351
#if 0 // Fujitsu recommend to skip this and will update docs.
352
# (9) Release the interrupt mask setting of the MASK register of the
353
# interrupt controller if necessary.
354
sti gr10,@(gr9,#0)
355
membar
356
#endif
357
358
# (10) Set the PSR register ET bit to 1 to enable interrupts.
359
movgs gr8,psr
360
361
__core_sleep_icache_lock_end:
362
363
# Unlock from icache
364
li __core_sleep_icache_lock_start,gr3
365
li __core_sleep_icache_lock_end,gr4
366
1: icul gr3
367
addi gr3,#L1_CACHE_BYTES,gr3
368
cmp gr4,gr3,icc0
369
bhi icc0,#0,1b
370
371
bralr
372
373
.size frv_cpu_core_sleep, .-frv_cpu_core_sleep
374
375