2005-04-16 15:20:36 -07:00
/ * linux/ a r c h / a r m / m a c h - s3 c24 1 0 / s l e e p . S
*
* Copyright ( c ) 2 0 0 4 S i m t e c E l e c t r o n i c s
* Ben D o o k s < b e n @simtec.co.uk>
*
* S3 C 2 4 1 0 P o w e r M a n a g e r ( S u s p e n d - T o - R A M ) s u p p o r t
*
* Based o n P X A / S A 1 1 0 0 s l e e p c o d e b y :
* Nicolas P i t r e , ( c ) 2 0 0 2 M o n t a V i s t a S o f t w a r e I n c
* Cliff B r a k e , ( c ) 2 0 0 1
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e a s p u b l i s h e d b y
* the F r e e S o f t w a r e F o u n d a t i o n ; either version 2 of the License, or
* ( at y o u r o p t i o n ) a n y l a t e r v e r s i o n .
*
* This p r o g r a m i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
* but W I T H O U T A N Y W A R R A N T Y ; without even the implied warranty of
* MERCHANTABILITY o r F I T N E S S F O R A P A R T I C U L A R P U R P O S E . S e e t h e
* GNU G e n e r a l P u b l i c L i c e n s e f o r m o r e d e t a i l s .
*
* You s h o u l d h a v e r e c e i v e d a c o p y o f t h e G N U G e n e r a l P u b l i c L i c e n s e
* along w i t h t h i s p r o g r a m ; if not, write to the Free Software
* Foundation, I n c . , 5 9 T e m p l e P l a c e , S u i t e 3 3 0 , B o s t o n , M A 0 2 1 1 1 - 1 3 0 7 U S A
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / h a r d w a r e . h >
# include < a s m / a r c h / m a p . h >
# include < a s m / a r c h / r e g s - g p i o . h >
# include < a s m / a r c h / r e g s - c l o c k . h >
# include < a s m / a r c h / r e g s - m e m . h >
# include < a s m / a r c h / r e g s - s e r i a l . h >
/ * CONFIG_ D E B U G _ R E S U M E i s d a n g e r o u s i f y o u r b o o t l o a d e r d o e s n o t
* reset t h e U A R T c o n f i g u r a t i o n , o n l y e n a b l e i f y o u r e a l l y n e e d t h i s !
* /
/ / # define C O N F I G _ D E B U G _ R E S U M E
.text
2006-09-16 00:04:23 +01:00
/ * s3 c24 1 0 _ c p u _ s a v e
2005-04-16 15:20:36 -07:00
*
2006-09-16 00:04:23 +01:00
* save e n o u g h o f t h e C P U s t a t e t o a l l o w u s t o r e - s t a r t
* pm. c c o d e . a s w e s t o r e i t e m s l i k e t h e s p / l r , w e w i l l
* end u p r e t u r n i n g f r o m t h i s f u n c t i o n w h e n t h e c p u r e s u m e s
* so t h e r e t u r n v a l u e i s s e t t o m a r k t h i s .
*
* This a r a n g e m e n t m e a n s w e a v o i d h a v i n g t o f l u s h t h e c a c h e
* from t h i s c o d e .
2005-04-16 15:20:36 -07:00
*
* entry :
2006-09-16 00:04:23 +01:00
* r0 = p o i n t e r t o s a v e b l o c k
*
* exit :
* r0 = 0 = > w e s t o r e d e v e r y t h i n g
* 1 = > resumed f r o m s l e e p
2005-04-16 15:20:36 -07:00
* /
2006-09-16 00:04:23 +01:00
ENTRY( s3 c24 1 0 _ c p u _ s a v e )
2005-04-16 15:20:36 -07:00
stmfd s p ! , { r4 - r12 , l r }
@@ store co-processor registers
mrc p15 , 0 , r4 , c15 , c1 , 0 @ CP access register
mrc p15 , 0 , r5 , c13 , c0 , 0 @ PID
mrc p15 , 0 , r6 , c3 , c0 , 0 @ Domain ID
mrc p15 , 0 , r7 , c2 , c0 , 0 @ translation table base address
[ARM] 3529/1: s3c24xx: fix restoring control register with undefined instruction
Patch from Dimitry Andric
In arch/arm/mach-s3c2410/sleep.S, the coprocessor registers are saved at
suspend time, and restored at resume time. However, an undefined
instruction is used when attempting to restore a non-existent "auxiliary
control register". This leads to a crash on S3C2412, which has an ARM926
core instead of an ARM920.
At suspend time, the following fragment runs:
mrc p15, 0, r7, c2, c0, 0 @ translation table base address
mrc p15, 0, r8, c2, c0, 0 @ auxiliary control register
mrc p15, 0, r9, c1, c0, 0 @ control register
and at resume time, the following fragment runs:
mcr p15, 0, r7, c2, c0, 0 @ translation table base
mcr p15, 0, r8, c1, c1, 0 @ auxilliary control
...
mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
There are several problems with these fragments:
1. The ARM920 and ARM926 cores don't have any "auxiliary control
register", at least not according to the ARM920 and ARM926 TRM's.
2. The 2nd line of suspend erroneously saves the c2 register again.
3. This saved c2 value is restored using an undefined instruction. For
some reason this does not crash on ARM920, but does crash on ARM926.
The following patch fixes all these problems.
Signed-off-by: Dimitry Andric <dimitry@andric.com>
Yes, this looks sensible
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2006-05-17 16:31:11 +01:00
mrc p15 , 0 , r8 , c1 , c0 , 0 @ control register
2005-04-16 15:20:36 -07:00
stmia r0 , { r4 - r13 }
2006-09-16 00:04:23 +01:00
mov r0 , #0
ldmfd s p , { r4 - r12 , p c }
2005-04-16 15:20:36 -07:00
@@ return to the caller, after having the MMU
@@ turned on, this restores the last bits from the
@@ stack
resume_with_mmu :
2006-09-16 00:04:23 +01:00
mov r0 , #1
2005-04-16 15:20:36 -07:00
ldmfd s p ! , { r4 - r12 , p c }
.ltorg
@@ the next bits sit in the .data segment, even though they
@@ happen to be code... the s3c2410_sleep_save_phys needs to be
@@ accessed by the resume code before it can restore the MMU.
@@ This means that the variable has to be close enough for the
@@ code to read it... since the .text segment needs to be RO,
@@ the data segment can be the only place to put this code.
.data
.global s3c2410_sleep_save_phys
s3c2410_sleep_save_phys :
.word 0
/ * s3 c24 1 0 _ c p u _ r e s u m e
*
* resume c o d e e n t r y f o r b o o t l o a d e r t o c a l l
*
* we m u s t p u t t h i s c o d e h e r e i n t h e d a t a s e g m e n t a s w e h a v e n o
* other w a y o f r e s t o r i n g t h e s t a c k p o i n t e r a f t e r s l e e p , a n d w e
* must n o t w r i t e t o t h e c o d e s e g m e n t ( c o d e i s r e a d - o n l y )
* /
ENTRY( s3 c24 1 0 _ c p u _ r e s u m e )
2006-06-25 12:01:48 +01:00
mov r0 , #P S R _ I _ B I T | P S R _ F _ B I T | S V C _ M O D E
2005-04-16 15:20:36 -07:00
msr c p s r _ c , r0
@@ load UART to allow us to print the two characters for
@@ resume debug
2006-01-26 15:20:50 +00:00
mov r2 , #S 3 C 2 4 X X _ P A _ U A R T & 0 x f f00 0 0 0 0
orr r2 , r2 , #S 3 C 2 4 X X _ P A _ U A R T & 0 x f f00 0
2005-04-16 15:20:36 -07:00
# if 0
/* SMDK2440 LED set */
2006-01-26 15:20:50 +00:00
mov r14 , #S 3 C 2 4 X X _ P A _ G P I O
2005-04-16 15:20:36 -07:00
ldr r12 , [ r14 , #0x54 ]
bic r12 , r12 , #3 < < 4
orr r12 , r12 , #1 < < 7
str r12 , [ r14 , #0x54 ]
# endif
# ifdef C O N F I G _ D E B U G _ R E S U M E
mov r3 , #' L '
strb r3 , [ r2 , #S 3 C 2 4 1 0 _ U T X H ]
1001 :
ldrb r14 , [ r3 , #S 3 C 2 4 1 0 _ U T R S T A T ]
tst r14 , #S 3 C 2 4 1 0 _ U T R S T A T _ T X E
beq 1 0 0 1 b
# endif / * C O N F I G _ D E B U G _ R E S U M E * /
mov r1 , #0
mcr p15 , 0 , r1 , c8 , c7 , 0 @@ invalidate I & D TLBs
mcr p15 , 0 , r1 , c7 , c7 , 0 @@ invalidate I & D caches
ldr r0 , s3 c24 1 0 _ s l e e p _ s a v e _ p h y s @ address of restore block
ldmia r0 , { r4 - r13 }
mcr p15 , 0 , r4 , c15 , c1 , 0 @ CP access register
mcr p15 , 0 , r5 , c13 , c0 , 0 @ PID
mcr p15 , 0 , r6 , c3 , c0 , 0 @ Domain ID
mcr p15 , 0 , r7 , c2 , c0 , 0 @ translation table base
# ifdef C O N F I G _ D E B U G _ R E S U M E
mov r3 , #' R '
strb r3 , [ r2 , #S 3 C 2 4 1 0 _ U T X H ]
# endif
ldr r2 , =resume_with_mmu
[ARM] 3529/1: s3c24xx: fix restoring control register with undefined instruction
Patch from Dimitry Andric
In arch/arm/mach-s3c2410/sleep.S, the coprocessor registers are saved at
suspend time, and restored at resume time. However, an undefined
instruction is used when attempting to restore a non-existent "auxiliary
control register". This leads to a crash on S3C2412, which has an ARM926
core instead of an ARM920.
At suspend time, the following fragment runs:
mrc p15, 0, r7, c2, c0, 0 @ translation table base address
mrc p15, 0, r8, c2, c0, 0 @ auxiliary control register
mrc p15, 0, r9, c1, c0, 0 @ control register
and at resume time, the following fragment runs:
mcr p15, 0, r7, c2, c0, 0 @ translation table base
mcr p15, 0, r8, c1, c1, 0 @ auxilliary control
...
mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
There are several problems with these fragments:
1. The ARM920 and ARM926 cores don't have any "auxiliary control
register", at least not according to the ARM920 and ARM926 TRM's.
2. The 2nd line of suspend erroneously saves the c2 register again.
3. This saved c2 value is restored using an undefined instruction. For
some reason this does not crash on ARM920, but does crash on ARM926.
The following patch fixes all these problems.
Signed-off-by: Dimitry Andric <dimitry@andric.com>
Yes, this looks sensible
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2006-05-17 16:31:11 +01:00
mcr p15 , 0 , r8 , c1 , c0 , 0 @ turn on MMU, etc
2005-04-16 15:20:36 -07:00
nop @ second-to-last before mmu
mov p c , r2 @ go back to virtual address
.ltorg