2011-02-06 15:48:39 +00:00
# include < l i n u x / l i n k a g e . h >
2011-02-11 11:32:19 +00:00
# include < l i n u x / t h r e a d s . h >
2011-02-06 15:48:39 +00:00
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / g l u e - c a c h e . h >
# include < a s m / g l u e - p r o c . h >
.text
/ *
2011-09-01 11:52:33 +01:00
* Save C P U s t a t e f o r a s u s p e n d . T h i s s a v e s t h e C P U g e n e r a l p u r p o s e
* registers, a n d a l l o c a t e s s p a c e o n t h e k e r n e l s t a c k t o s a v e t h e C P U
* specific r e g i s t e r s a n d s o m e o t h e r d a t a f o r r e s u m e .
* r0 = s u s p e n d f u n c t i o n a r g 0
* r1 = s u s p e n d f u n c t i o n
2011-02-06 15:48:39 +00:00
* /
2011-06-22 17:41:48 +01:00
ENTRY( _ _ c p u _ s u s p e n d )
2011-06-13 15:58:34 +01:00
stmfd s p ! , { r4 - r11 , l r }
2011-02-06 15:48:39 +00:00
# ifdef M U L T I _ C P U
ldr r10 , =processor
2011-09-01 11:52:33 +01:00
ldr r4 , [ r10 , #C P U _ S L E E P _ S I Z E ] @ s i z e o f C P U s l e e p s t a t e
2011-02-11 11:32:19 +00:00
# else
2011-09-01 11:52:33 +01:00
ldr r4 , =cpu_suspend_size
2011-06-13 13:53:06 +01:00
# endif
2011-09-01 11:52:33 +01:00
mov r5 , s p @ current virtual SP
add r4 , r4 , #12 @ Space for pgd, virt sp, phys resume fn
sub s p , s p , r4 @ allocate CPU state on stack
stmfd s p ! , { r0 , r1 } @ save suspend func arg and pointer
add r0 , s p , #8 @ save pointer to save block
mov r1 , r4 @ size of save block
mov r2 , r5 @ virtual SP
ldr r3 , =sleep_save_sp
2011-02-11 11:32:19 +00:00
# ifdef C O N F I G _ S M P
ALT_ S M P ( m r c p15 , 0 , l r , c0 , c0 , 5 )
ALT_ U P ( m o v l r , #0 )
and l r , l r , #15
2011-09-01 11:52:33 +01:00
add r3 , r3 , l r , l s l #2
2011-02-06 15:48:39 +00:00
# endif
2011-09-01 11:52:33 +01:00
bl _ _ c p u _ s u s p e n d _ s a v e
2011-07-02 09:54:01 +01:00
adr l r , B S Y M ( c p u _ s u s p e n d _ a b o r t )
2011-06-13 15:28:40 +01:00
ldmfd s p ! , { r0 , p c } @ call suspend fn
2011-06-22 17:41:48 +01:00
ENDPROC( _ _ c p u _ s u s p e n d )
2011-02-06 15:48:39 +00:00
.ltorg
2011-07-02 09:54:01 +01:00
cpu_suspend_abort :
2011-08-27 22:39:09 +01:00
ldmia s p ! , { r1 - r3 } @ pop phys pgd, virt SP, phys resume fn
2011-08-27 11:17:36 +01:00
teq r0 , #0
moveq r0 , #1 @ force non-zero value
2011-07-02 09:54:01 +01:00
mov s p , r2
ldmfd s p ! , { r4 - r11 , p c }
ENDPROC( c p u _ s u s p e n d _ a b o r t )
2011-02-06 15:48:39 +00:00
/ *
* r0 = c o n t r o l r e g i s t e r v a l u e
* /
2011-08-31 23:26:18 +01:00
.align 5
2011-11-15 11:11:19 +00:00
.pushsection .idmap .text , " ax"
2011-02-06 15:48:39 +00:00
ENTRY( c p u _ r e s u m e _ m m u )
ldr r3 , =cpu_resume_after_mmu
2011-11-22 17:30:28 +00:00
instr_ s y n c
2011-08-26 20:28:52 +01:00
mcr p15 , 0 , r0 , c1 , c0 , 0 @ turn on MMU, I-cache, etc
mrc p15 , 0 , r0 , c0 , c0 , 0 @ read id reg
2011-11-22 17:30:28 +00:00
instr_ s y n c
2011-08-26 20:28:52 +01:00
mov r0 , r0
mov r0 , r0
2011-02-06 15:48:39 +00:00
mov p c , r3 @ jump to virtual address
2011-08-31 23:26:18 +01:00
ENDPROC( c p u _ r e s u m e _ m m u )
2011-11-15 11:11:19 +00:00
.popsection
2011-02-06 15:48:39 +00:00
cpu_resume_after_mmu :
2011-06-21 16:32:58 +01:00
bl c p u _ i n i t @ restore the und/abt/irq banked regs
2011-07-02 09:54:01 +01:00
mov r0 , #0 @ return zero on success
2011-06-13 15:04:14 +01:00
ldmfd s p ! , { r4 - r11 , p c }
2011-02-06 15:48:39 +00:00
ENDPROC( c p u _ r e s u m e _ a f t e r _ m m u )
/ *
* Note : Yes, p a r t o f t h e f o l l o w i n g c o d e i s l o c a t e d i n t o t h e . d a t a s e c t i o n .
* This i s t o a l l o w s l e e p _ s a v e _ s p t o b e a c c e s s e d w i t h a r e l a t i v e l o a d
* while w e c a n ' t r e l y o n a n y M M U t r a n s l a t i o n . W e c o u l d h a v e p u t
* sleep_ s a v e _ s p i n t h e . t e x t s e c t i o n a s w e l l , b u t s o m e s e t u p s m i g h t
* insist o n i t t o b e t r u l y r e a d - o n l y .
* /
.data
.align
ENTRY( c p u _ r e s u m e )
2011-02-11 11:32:19 +00:00
# ifdef C O N F I G _ S M P
adr r0 , s l e e p _ s a v e _ s p
ALT_ S M P ( m r c p15 , 0 , r1 , c0 , c0 , 5 )
ALT_ U P ( m o v r1 , #0 )
and r1 , r1 , #15
ldr r0 , [ r0 , r1 , l s l #2 ] @ stack phys addr
# else
2011-02-06 15:48:39 +00:00
ldr r0 , s l e e p _ s a v e _ s p @ stack phys addr
2011-02-11 11:32:19 +00:00
# endif
2011-03-22 19:09:14 +01:00
setmode P S R _ I _ B I T | P S R _ F _ B I T | S V C _ M O D E , r1 @ set SVC, irqs off
2011-08-27 22:39:09 +01:00
@ load phys pgd, stack, resume fn
ARM( l d m i a r0 ! , { r1 , s p , p c } )
THUMB( l d m i a r0 ! , { r1 , r2 , r3 } )
THUMB( m o v s p , r2 )
THUMB( b x r3 )
2011-02-06 15:48:39 +00:00
ENDPROC( c p u _ r e s u m e )
sleep_save_sp :
2011-02-11 11:32:19 +00:00
.rept CONFIG_NR_CPUS
.long 0 @ preserve stack phys ptr here
.endr