2012-08-16 17:31:51 +08:00
/ *
* Copyright ( c ) 2 0 1 2 , N V I D I A C o r p o r a t i o n . A l l r i g h t s r e s e r v e d .
*
* 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
* under t h e t e r m s a n d c o n d i t i o n 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 ,
* version 2 , a s p u b l i s h e d b y t h e F r e e S o f t w a r e F o u n d a t 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 i t w i l l b e u s e f u l , b u t W I T H O U T
* ANY W A R R A N T Y ; without even the implied warranty of MERCHANTABILITY or
* FITNESS 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 G N U G e n e r a l P u b l i c L i c e n s e f o r
* more 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 . I f n o t , s e e < h t t p : / / w w w . g n u . o r g / l i c e n s e s / > .
* /
# 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 >
2012-10-31 17:41:17 +08:00
# include < a s m / a s m - o f f s e t s . h >
2012-08-16 17:31:51 +08:00
2013-05-20 18:39:29 +08:00
# include " f u s e . h "
2012-08-16 17:31:51 +08:00
# include " s l e e p . h "
# include " f l o w c t r l . h "
# define T E G R A 3 0 _ P O W E R _ H O T P L U G _ S H U T D O W N ( 1 < < 2 7 ) / * H o t p l u g s h u t d o w n * /
# if d e f i n e d ( C O N F I G _ H O T P L U G _ C P U ) | | d e f i n e d ( C O N F I G _ P M _ S L E E P )
/ *
* tegra3 0 _ h o t p l u g _ s h u t d o w n ( v o i d )
*
* Powergates t h e c u r r e n t C P U .
* Should n e v e r r e t u r n .
* /
ENTRY( t e g r a30 _ h o t p l u g _ s h u t d o w n )
/* Powergate this CPU */
mov r0 , #T E G R A 30 _ P O W E R _ H O T P L U G _ S H U T D O W N
bl t e g r a30 _ c p u _ s h u t d o w n
mov p c , l r @ should never get here
ENDPROC( t e g r a30 _ h o t p l u g _ s h u t d o w n )
/ *
* tegra3 0 _ c p u _ s h u t d o w n ( u n s i g n e d l o n g f l a g s )
*
* Puts t h e c u r r e n t C P U i n w a i t - f o r - e v e n t m o d e o n t h e f l o w c o n t r o l l e r
* and p o w e r g a t e s i t - - f l a g s ( i n R 0 ) i n d i c a t e t h e r e q u e s t t y p e .
*
2013-05-20 18:39:29 +08:00
* r1 0 = S o C I D
* corrupts r0 - r4 , r10 - r12
2012-08-16 17:31:51 +08:00
* /
ENTRY( t e g r a30 _ c p u _ s h u t d o w n )
cpu_ i d r3
2013-05-20 18:39:29 +08:00
tegra_ g e t _ s o c _ i d T E G R A _ A P B _ M I S C _ V I R T , r10
cmp r10 , #T E G R A 30
bne _ n o _ c p u 0 _ c h k @ It's not Tegra30
2012-08-16 17:31:51 +08:00
cmp r3 , #0
moveq p c , l r @ Must never be called for CPU 0
2013-05-20 18:39:29 +08:00
_no_cpu0_chk :
2012-08-16 17:31:51 +08:00
ldr r12 , =TEGRA_FLOW_CTRL_VIRT
cpu_ t o _ c s r _ r e g r1 , r3
add r1 , r1 , r12 @ virtual CSR address for this CPU
cpu_ t o _ h a l t _ r e g r2 , r3
add r2 , r2 , r12 @ virtual HALT_EVENTS address for this CPU
/ *
* Clear t h i s C P U ' s " e v e n t " a n d " i n t e r r u p t " f l a g s a n d p o w e r g a t e
* it w h e n h a l t i n g b u t n o t b e f o r e i t i s i n t h e " W F E " s t a t e .
* /
movw r12 , \
FLOW_ C T R L _ C S R _ I N T R _ F L A G | F L O W _ C T R L _ C S R _ E V E N T _ F L A G | \
FLOW_ C T R L _ C S R _ E N A B L E
2013-05-20 18:39:29 +08:00
cmp r10 , #T E G R A 30
moveq r4 , #( 1 < < 4 ) @ wfe bitmap
movne r4 , #( 1 < < 8 ) @ wfi bitmap
2013-04-15 16:50:53 -06:00
ARM( o r r r12 , r12 , r4 , l s l r3 )
THUMB( l s l r4 , r4 , r3 )
THUMB( o r r r12 , r12 , r4 )
2012-08-16 17:31:51 +08:00
str r12 , [ r1 ]
/* Halt this CPU. */
mov r3 , #0x400
delay_1 :
subs r3 , r3 , #1 @ delay as a part of wfe war.
bge d e l a y _ 1 ;
cpsid a @ disable imprecise aborts.
ldr r3 , [ r1 ] @ read CSR
str r3 , [ r1 ] @ clear CSR
2013-05-20 18:39:29 +08:00
2012-08-16 17:31:51 +08:00
tst r0 , #T E G R A 30 _ P O W E R _ H O T P L U G _ S H U T D O W N
2013-05-20 18:39:29 +08:00
beq f l o w _ c t r l _ s e t t i n g _ f o r _ l p2
/* flow controller set up for hotplug */
mov r3 , #F L O W _ C T R L _ W A I T E V E N T @ F o r h o t p l u g
b f l o w _ c t r l _ d o n e
flow_ctrl_setting_for_lp2 :
/* flow controller set up for LP2 */
cmp r10 , #T E G R A 30
2012-10-31 17:41:17 +08:00
moveq r3 , #F L O W _ C T R L _ W A I T _ F O R _ I N T E R R U P T @ F o r L P 2
2013-05-20 18:39:29 +08:00
movne r3 , #F L O W _ C T R L _ W A I T E V E N T
2013-07-19 17:25:25 +08:00
orrne r3 , r3 , #F L O W _ C T R L _ H A L T _ G I C _ I R Q
orrne r3 , r3 , #F L O W _ C T R L _ H A L T _ G I C _ F I Q
2013-05-20 18:39:29 +08:00
flow_ctrl_done :
cmp r10 , #T E G R A 30
2012-08-16 17:31:51 +08:00
str r3 , [ r2 ]
ldr r0 , [ r2 ]
b w f e _ w a r
__cpu_reset_again :
dsb
.align 5
2013-05-20 18:39:29 +08:00
wfeeq @ CPU should be power gated here
wfine
2012-08-16 17:31:51 +08:00
wfe_war :
b _ _ c p u _ r e s e t _ a g a i n
/ *
* 3 8 nop' s , w h i c h f i l l s r e s e t o f w f e c a c h e l i n e a n d
* 4 more c a c h e l i n e s w i t h n o p
* /
.rept 38
nop
.endr
b . @ should never get here
ENDPROC( t e g r a30 _ c p u _ s h u t d o w n )
# endif
2012-10-31 17:41:17 +08:00
# ifdef C O N F I G _ P M _ S L E E P
/ *
* tegra3 0 _ s l e e p _ c p u _ s e c o n d a r y _ f i n i s h ( u n s i g n e d l o n g v2 p )
*
* Enters L P 2 o n s e c o n d a r y C P U b y e x i t i n g c o h e r e n c y a n d p o w e r g a t i n g t h e C P U .
* /
ENTRY( t e g r a30 _ s l e e p _ c p u _ s e c o n d a r y _ f i n i s h )
mov r7 , l r
/* Flush and disable the L1 data cache */
2013-07-03 17:50:38 +08:00
mov r0 , #T E G R A _ F L U S H _ C A C H E _ L O U I S
2012-10-31 17:41:17 +08:00
bl t e g r a _ d i s a b l e _ c l e a n _ i n v _ d c a c h e
/* Powergate this CPU. */
mov r0 , #0 @ power mode flags (!hotplug)
bl t e g r a30 _ c p u _ s h u t d o w n
mov r0 , #1 @ never return here
mov p c , r7
ENDPROC( t e g r a30 _ s l e e p _ c p u _ s e c o n d a r y _ f i n i s h )
2012-10-31 17:41:21 +08:00
/ *
* tegra3 0 _ t e a r _ d o w n _ c p u
*
* Switches t h e C P U t o e n t e r s l e e p .
* /
ENTRY( t e g r a30 _ t e a r _ d o w n _ c p u )
mov3 2 r6 , T E G R A _ F L O W _ C T R L _ B A S E
b t e g r a30 _ e n t e r _ s l e e p
ENDPROC( t e g r a30 _ t e a r _ d o w n _ c p u )
/ *
* tegra3 0 _ e n t e r _ s l e e p
*
* uses f l o w c o n t r o l l e r t o e n t e r s l e e p s t a t e
* executes f r o m I R A M w i t h S D R A M i n s e l f r e f r e s h w h e n t a r g e t s t a t e i s L P 0 o r L P 1
* executes f r o m S D R A M w i t h t a r g e t s t a t e i s L P 2
* r6 = T E G R A _ F L O W _ C T R L _ B A S E
* /
tegra30_enter_sleep :
cpu_ i d r1
cpu_ t o _ c s r _ r e g r2 , r1
ldr r0 , [ r6 , r2 ]
orr r0 , r0 , #F L O W _ C T R L _ C S R _ I N T R _ F L A G | F L O W _ C T R L _ C S R _ E V E N T _ F L A G
orr r0 , r0 , #F L O W _ C T R L _ C S R _ E N A B L E
str r0 , [ r6 , r2 ]
2013-07-03 17:50:40 +08:00
tegra_ g e t _ s o c _ i d T E G R A _ A P B _ M I S C _ B A S E , r10
cmp r10 , #T E G R A 30
2012-10-31 17:41:21 +08:00
mov r0 , #F L O W _ C T R L _ W A I T _ F O R _ I N T E R R U P T
2013-07-03 17:50:40 +08:00
orreq r0 , r0 , #F L O W _ C T R L _ H A L T _ C P U _ I R Q | F L O W _ C T R L _ H A L T _ C P U _ F I Q
orrne r0 , r0 , #F L O W _ C T R L _ H A L T _ L I C _ I R Q | F L O W _ C T R L _ H A L T _ L I C _ F I Q
2012-10-31 17:41:21 +08:00
cpu_ t o _ h a l t _ r e g r2 , r1
str r0 , [ r6 , r2 ]
dsb
ldr r0 , [ r6 , r2 ] / * m e m o r y b a r r i e r * /
halted :
isb
dsb
wfi / * C P U s h o u l d b e p o w e r g a t e d h e r e * /
/* !!!FIXME!!! Implement halt failure handler */
b h a l t e d
2012-10-31 17:41:17 +08:00
# endif