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
|
/* linux/0arch/arm/plat-s3c64xx/sleep.S
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C64XX CPU sleep code
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/map.h>
#undef S3C64XX_VA_GPIO
#define S3C64XX_VA_GPIO (0x0)
#include <plat/regs-gpio.h>
#include <plat/gpio-bank-n.h>
#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
.text
/* s3c_cpu_save
*
* Save enough processor state to allow the restart of the pm.c
* code after resume.
*
* entry:
* r0 = pointer to the save block
* exit:
* r0 = exit code: 1 => stored data
* 0 => resumed from sleep
*/
ENTRY(s3c_cpu_save)
stmfd sp!, { r4 - r12, lr }
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
mrc p15, 0, r9, c1, c0, 0 @ Control register
mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
stmia r0, { r4 - r13 } @ Save CP registers and SP
mov r0, #0
ldmfd sp, { r4 - r12, pc } @ return, not disturbing SP
@@ return to the caller, after the MMU is turned on.
@@ restore the last bits of the stack and return.
resume_with_mmu:
mov r0, #1
ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
.data
/* the next bit is code, but it requires easy access to the
* s3c_sleep_save_phys data before the MMU is switched on, so
* we store the code that needs this variable in the .data where
* the value can be written to (the .text segment is RO).
*/
.global s3c_sleep_save_phys
s3c_sleep_save_phys:
.word 0
/* Sleep magic, the word before the resume entry point so that the
* bootloader can check for a resumeable image. */
.word 0x2bedf00d
/* s3c_cpu_reusme
*
* This is the entry point, stored by whatever method the bootloader
* requires to get the kernel runnign again. This code expects to be
* entered with no caches live and the MMU disabled. It will then
* restore the MMU and other basic CP registers saved and restart
* the kernel C code to finish the resume code.
*/
ENTRY(s3c_cpu_resume)
msr cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
ldr r2, =LL_UART /* for debug */
#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
/* Initialise the GPIO state if we are debugging via the SMDK LEDs,
* as the uboot version supplied resets these to inputs during the
* resume checks.
*/
ldr r3, =S3C64XX_PA_GPIO
ldr r0, [ r3, #S3C64XX_GPNCON ]
bic r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
orr r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
str r0, [ r3, #S3C64XX_GPNCON ]
ldr r0, [ r3, #S3C64XX_GPNDAT ]
bic r0, r0, #0xf << 12 @ GPN12..15
orr r0, r0, #1 << 15 @ GPN15
str r0, [ r3, #S3C64XX_GPNDAT ]
#endif
/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
* are thoroughly cleaned just in case the bootloader didn't do it
* for us. */
mov r0, #0
mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
@@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
@@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches
ldr r0, s3c_sleep_save_phys
ldmia r0, { r4 - r13 }
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
mov r0, #0 @ restore copro access controls
mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
mcr p15, 0, r0, c7, c5, 4
ldr r2, =resume_with_mmu
mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
nop
mov pc, r2 /* jump back */
.end
|