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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
|
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: David Paris <david.paris-nonst@stericsson.com>
*
* ux500 core context/save for low power modes
*/
#include <linux/linkage.h>
#include <linux/init.h>
#include <mach/hardware.h>
#include <asm/hardware/cache-l2x0.h>
/* Define for DeepSleep specific case */
#define _BACKUPRAM1_BASE IO_ADDRESS(U8500_BACKUPRAM1_BASE)
#define BACKUPRAMCPU0 (_BACKUPRAM1_BASE + 0xF80)
#define BACKUPRAMCPU1 (_BACKUPRAM1_BASE + 0xFA0)
#define UX500L2CCBASE IO_ADDRESS(UX500_L2CC_BASE)
ENTRY(ux500_cpu_context_deepsleep)
.code 32
.extern prcmu_apply_ap_state_transition
push {r0-r4, lr}
mov r2, r0
cmp r0, #0
bne load_cpu1_ctxt
ldr r0, =BACKUPRAMCPU0
b common_ctxt
load_cpu1_ctxt:
ldr r0, =BACKUPRAMCPU1
common_ctxt:
/* Save SystemControl Register */
mrc p15, 0, r1, c1, c0, 0
str r1,[r0,#0x00]
/* Save TTBR0 */
mrc p15, 0, r1, c2, c0, 0
str r1,[r0,#0x04]
/* Save TTBR1 */
mrc p15, 0, r1, c2, c0, 1
str r1,[r0,#0x08]
/* save TTBRC */
mrc p15, 0, r1, c2, c0, 2
str r1,[r0,#0x0C]
/* Save DACR */
mrc p15, 0, r1, c3, c0, 0
str r1,[r0,#0x10]
cmp r2, #0
bne store_ret_addr_for_cpu1
ldr r1, =_return_from_deepsleep_cpu0
str r1,[r0,#0x14]
b common_continue
store_ret_addr_for_cpu1:
ldr r1, =_return_from_deepsleep_cpu1
str r1,[r0,#0x14]
common_continue:
/* save CPSR */
mrs r1, cpsr
str r1,[r0,#0x18]
/* save Current stack (Must not be used after) */
str sp,[r0,#0x1C]
/* Save ARM Context */
mov r0, r2
bl save_processor_context
cmp r2, #0
bne _cpu1_wait_deepsleep
stmfd sp!, {r0, r1, r2}
bl ux500_flush_all
ldmfd sp!, {r0, r1, r2}
mov r0, #0x4 /* APEXECUTE_TO_APDEEPSLEEP */
mov r1, #0x0 /* DDR_PWR_STATE_UNCHANGED */
mov r2, #0x0 /* INTR_NOT_AS_WAKEUP */
bl prcmu_apply_ap_state_transition
b _return_from_deepsleep_cpu0
_cpu1_wait_deepsleep:
dsb
wfi
b _return_from_deepsleep_cpu1
_return_from_deepsleep_cpu0:
mov r0, #0
b _exit_deeps
_return_from_deepsleep_cpu1:
mov r0, #1
_exit_deeps:
bl restore_processor_context
pop {r0-r4, pc}
ENDPROC(ux500_cpu_context_deepsleep)
ENTRY(save_processor_context)
.extern arm_cntxt_cpu0
.extern arm_cntxt_cpu1
.code 32
push {r0-r3, lr}
/* load the backup pointer accordingly */
cmp r0, #0
bne save_cpu1_ctxt
ldr r1, =arm_cntxt_cpu0
b save_ctxt
save_cpu1_ctxt:
ldr r1, =arm_cntxt_cpu1
save_ctxt:
ldr r1, [r1]
mrs r2, cpsr
str r2, [r1], #+4
/* clear up all mode bits which change with the mode. */
bic r2, r2, #0xf
/*
* enter all modes and save banked registers
* suffix to CPSR : c-control, f-flags, s-status, x-xtension
*/
/*
* Enter FIQ mode, Interrupts disabled
* Save: r8-r14 and spsr
* Assume: r2 depicts the processor in Supervisor mode
*/
orr r3, r2, #0x1
msr cpsr_cxsf, r3
mrs r3, spsr
stmia r1!, {r3,r8-r14}
/*
* Enter IRQ mode, Interrupts disabled
* Save: r13,r14 and spsr
*/
orr r3, r2, #0x2
msr cpsr_cxsf, r3 /* Enter IRQ mode with IRQ/FIQ disable */
mrs r3, spsr
stmia r1!, {r3,r13,r14}
/*
* Enter Abort mode, irq/fiq disabled
* Save: r13,r14 and sps
*/
orr r3, r2, #0x7
msr cpsr_cxsf, r3
mrs r3, spsr
stmia r1!, {r3, r4-r14}
/*
* Enter Undef mode, irq/fiq disable
* Save: r13,r14 and spsr
*/
orr r3, r2, #0xB
msr cpsr_cxsf, r3
mrs r3, spsr
stmia r1!, {r3,r13,r14}
/* go back to the SVC mode now */
orr r3, r2, #0x3
msr cpsr_cxsf, r3
/* in SVC mode, save all CP15 configs */
/* Non-secure Vector Base Address Register */
mrc p15, 0, r2, c12, c0, 0
str r2, [r1], #4
/* Primary Region Remap reg */
mrc p15, 0, r2, c10, c2, 0
str r2, [r1], #4
mrc p15, 0, r2, c10, c2, 1
str r2, [r1], #4
/* Context ID reg */
mrc p15, 0, r2, c13, c0, 1
str r2, [r1], #4
/* Thread ID registers */
mrc p15, 0, r2, c13, c0, 2
str r2, [r1], #4
mrc p15, 0, r2, c13, c0, 3
str r2, [r1], #4
mrc p15, 0, r2, c13, c0, 4
str r2, [r1], #4
/* Cache Size Selection Register */
mrc p15, 2, r2, c0, c0, 0
str r2, [r1], #4
/* PMNC */
mrc p15, 0, r2, c9, c12, 0
str r2, [r1], #4
/* PMCNTENSET register */
mrc p15, 0, r2, c9, c12, 1
str r2, [r1], #4
/* PMSELR register */
mrc p15, 0, r2, c9, c12, 5
str r2, [r1], #4
/* PMCCNTR register */
mrc p15, 0, r2, c9, c13, 0
str r2, [r1], #4
/* PMXEVTYPER register */
mrc p15, 0, r2, c9, c13, 1
str r2, [r1], #4
/* PMUSERENR register */
mrc p15, 0, r2, c9, c14, 0
str r2, [r1], #4
/* PMINTENSET register */
mrc p15, 0, r2, c9, c14, 1
str r2, [r1], #4
/* PMINTENCLR register */
mrc p15, 0, r2, c9, c14, 2
str r2, [r1], #4
/* CPACR register */
mrc p15, 0, r2, c1, c0, 2
str r2, [r1], #4
cmp r0, #0
bne backup_ptr_cpu1
ldr r0, =arm_cntxt_cpu0
b update_backup_ptr
backup_ptr_cpu1:
ldr r0, =arm_cntxt_cpu1
update_backup_ptr:
str r1, [r0]
pop {r0-r3,pc}
ENDPROC(save_processor_context)
ENTRY (restore_processor_context)
.code 32
.extern arm_cntxt_cpu0
.extern arm_cntxt_cpu1
push {r0-r3, lr}
cmp r0, #0
bne restore_cpu1_cntxt
ldr r1, =arm_cntxt_cpu0
b restore_cntxt
restore_cpu1_cntxt:
ldr r1, =arm_cntxt_cpu1
restore_cntxt:
ldr r1, [r1]
/* restore the CP15 configs */
sub r1, r1, #4
/* CPACR register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c1, c0, 2
/* PMINTENCLR register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c14, 2
/* PMINTENSET register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c14, 1
/* PMUSERENR register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c14, 0
/* PMXEVTYPER register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c13, 1
/* PMCCNTR register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c13, 0
/* PMSELR register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c12, 5
/* PMCNTENSET register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c12, 1
/* PMNC register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c9, c12, 0
/* Cache Size Selection register */
ldr r2, [r1], #-4
mcr p15, 2, r2, c0, c0, 0
/* Thread IDs registers */
ldr r2, [r1], #-4
mcr p15, 0, r2, c13, c0, 4
ldr r2, [r1], #-4
mcr p15, 0, r2, c13, c0, 3
ldr r2, [r1], #-4
mcr p15, 0, r2, c13, c0, 2
/* Context ID register */
ldr r2, [r1], #-4
mcr p15, 0, r2, c13, c0, 1
/* memory region map registers */
ldr r2, [r1], #-4
mcr p15, 0, r2, c10, c2, 1
ldr r2, [r1], #-4
mcr p15, 0, r2, c10, c2, 0
/* Non-secure Vector Base Address register */
ldr r2, [r1]
mcr p15, 0, r2, c12, c0, 0
/* backup the value of cpsr */
mrs r2, cpsr
orr r2, r2, #0xC0
bic r2, r2, #0xf
/*
* Enter Undef mode, irq/fiq disabled
* restore: r13,r14 and spsr
*/
orr r3, r2, #0xB
msr cpsr_cxsf, r3
ldmdb r1!, {r3,r13,r14}
msr spsr_cxsf, r3
/*
* Enter Abort mode, irq/fiq disabled
* restore: r13,r14 and spsr
*/
orr r3, r2, #0x7
msr cpsr_cxsf, r3
ldmdb r1!, {r3, r4-r14}
msr spsr_cxsf, r3
/*
* Enter IRQ mode, irq disabled
* restore: r13,r14 and spsr
*/
orr r3, r2, #0x2
msr cpsr_cxsf, r3
ldmdb r1!, {r3,r13,r14}
msr spsr_cxsf, r3
/*
* Enter FIQ mode, irq disabled
* restore: r13,r14 and spsr
*/
orr r3, r2, #0x1
msr cpsr_cxsf, r3
ldmdb r1!, {r3,r8-r14}
msr spsr_cxsf, r3
/*
* Enter SVC mode, irq disabled
* restore: cpsr
*/
orr r3, r2, #0x3
msr cpsr_cxsf, r3
ldr r2, [r1, #-4]!
msr cpsr, r2
msr cpsr_cxsf, r3
cmp r0, #0
bne backup_ptr_restore_cpu1
ldr r0, =arm_cntxt_cpu0
b update_backup_restore_ptr
backup_ptr_restore_cpu1:
ldr r0, =arm_cntxt_cpu1
update_backup_restore_ptr:
sub r1, r1, #4
str r1, [r0]
pop {r0-r3, pc}
ENDPROC(restore_processor_context)
ENTRY(ux500_flush_all)
.code 32
/*
* Flush the entire cache system.
* The data cache flush is now achieved using atomic clean/invalidates
* working outwards from L1 cache. This is done using Set/Way based
* cache maintainance instructions.
* The instruction cache can still be invalidated back to the point of
* unification in a single instruction.
*
*/
stmfd sp!, {r4-r5, r7, r9-r11, lr}
mrc p15, 1, r0, c0, c0, 1 @ read clidr
ands r3, r0, #0x7000000 @ extract loc from clidr
mov r3, r3, lsr #23 @ left align loc bit field
beq finished @ if loc is 0, no need to clean
mov r10, #0 @ start clean at cache level 0
loop1:
add r2, r10, r10, lsr #1 @ work 3x current cache level
mov r1, r0, lsr r2 @ extract cache type from clidr
and r1, r1, #7 @ mask bits for current cache
cmp r1, #2 @ see cache at this level
blt skip @ skip if no cache, or i-cache
mcr p15, 2, r10, c0, c0, 0 @ select current cache level
isb @ isb to sych new cssr&csidr
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
and r2, r1, #7 @ extract length of cache lines
add r2, r2, #4 @ add 4 (line length offset)
ldr r4, =0x3ff
ands r4, r4, r1, lsr #3 @ find maximum on the way size
clz r5, r4 @ bit position of way size inc
ldr r7, =0x7fff
ands r7, r7, r1, lsr #13 @ max number of the index size
loop2:
mov r9, r4 @ create copy of max way size
loop3:
orr r11, r10, r9, lsl r5 @ way and cache number into r11
orr r11, r11, r7, lsl r2 @ way and cache number into r11
mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
subs r9, r9, #1 @ decrement the way
bge loop3
subs r7, r7, #1 @ decrement the index
bge loop2
skip:
add r10, r10, #2 @ increment cache number
cmp r3, r10
bgt loop1
finished:
mov r10, #0 @ swith back to cache level 0
mcr p15, 2, r10, c0, c0, 0 @ current cache level in cssr
dsb
isb
/* L2 cache cleaning */
ldr r0, =UX500L2CCBASE
ldr r2, [r0, #L2X0_AUX_CTRL]
ldr r2, =0xff
str r2, [r0, #L2X0_CLEAN_WAY]
2:
ldr r3, [r0, #L2X0_CLEAN_WAY]
cmp r3, #0
bne 2b
ldr r2, =0xff
str r2, [r0, #L2X0_INV_WAY]
1:
ldr r3, [r0, #L2X0_INV_WAY]
cmp r3, #0
bne 1b
mcr p15, 0, r0, c7, c5, 6 @ flush BTAC/BTB
isb
ldmfd sp!, {r4-r5,r7,r9-r11, pc}
ENDPROC(ux500_flush_all)
|