2012-08-16 13:31:52 +04:00
/ *
* Copyright ( c ) 2 0 1 0 - 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 .
* Copyright ( c ) 2 0 1 1 , G o o g l e , I n c .
*
* Author : Colin C r o s s < c c r o s s @android.com>
* Gary K i n g < g k i n g @nvidia.com>
*
* 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 >
2013-01-16 02:10:38 +04:00
# include < a s m / p r o c - f n s . h >
# include < a s m / c p15 . h >
2012-08-16 13:31:52 +04:00
# include " s l e e p . h "
# include " f l o w c t r l . h "
# 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 )
/ *
* tegra2 0 _ h o t p l u g _ s h u t d o w n ( v o i d )
*
* puts t h e c u r r e n t c p u i n r e s e t
* should n e v e r r e t u r n
* /
ENTRY( t e g r a20 _ h o t p l u g _ s h u t d o w n )
/* Put this CPU down */
cpu_ i d r0
bl t e g r a20 _ 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 a20 _ h o t p l u g _ s h u t d o w n )
/ *
* tegra2 0 _ c p u _ s h u t d o w n ( i n t c p u )
*
* r0 i s c p u t o r e s e t
*
* puts t h e s p e c i f i e d 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 u t s t h e C P U i n r e s e t
* can b e c a l l e d o n t h e c u r r e n t c p u o r a n o t h e r c p u
* if c a l l e d o n t h e c u r r e n t c p u , d o e s n o t r e t u r n
* MUST N O T B E C A L L E D F O R C P U 0 .
*
* corrupts r0 - r3 , r12
* /
ENTRY( t e g r a20 _ c p u _ s h u t d o w n )
cmp r0 , #0
moveq p c , l r @ must not be called for CPU 0
2013-01-16 21:33:55 +04:00
mov3 2 r1 , T E G R A _ P M C _ V I R T + P M C _ S C R A T C H 4 1
mov r12 , #C P U _ R E S E T T A B L E
str r12 , [ r1 ]
2012-08-16 13:31:52 +04:00
cpu_ t o _ h a l t _ r e g r1 , r0
ldr r3 , =TEGRA_FLOW_CTRL_VIRT
mov r2 , #F L O W _ C T R L _ W A I T E V E N T | F L O W _ C T R L _ J T A G _ R E S U M E
str r2 , [ r3 , r1 ] @ put flow controller in wait event mode
ldr r2 , [ r3 , r1 ]
isb
dsb
movw r1 , 0 x10 1 1
mov r1 , r1 , l s l r0
ldr r3 , =TEGRA_CLK_RESET_VIRT
str r1 , [ r3 , #0x340 ] @ put slave CPU in reset
isb
dsb
cpu_ i d r3
cmp r3 , r0
beq .
mov p c , l r
ENDPROC( t e g r a20 _ c p u _ s h u t d o w n )
# endif
2013-01-16 02:10:38 +04:00
# ifdef C O N F I G _ P M _ S L E E P
/ *
* tegra_ p e n _ l o c k
*
* spinlock i m p l e m e n t a t i o n w i t h n o a t o m i c t e s t - a n d - s e t a n d n o c o h e r e n c e
* using P e t e r s o n ' s a l g o r i t h m o n s t r o n g l y - o r d e r e d r e g i s t e r s
* used t o s y n c h r o n i z e a c p u w a k i n g u p f r o m w f i w i t h e n t e r i n g l p2 o n i d l e
*
* The r e f e r e n c e l i n k o f P e t e r s o n ' s a l g o r i t h m :
* http : / / en. w i k i p e d i a . o r g / w i k i / P e t e r s o n ' s _ a l g o r i t h m
*
* SCRATCH3 7 = r1 = ! t u r n ( i n v e r t e d f r o m P e t e r s o n ' s a l g o r i t h m )
* on c p u 0 :
* r2 = f l a g [ 0 ] ( i n S C R A T C H 3 8 )
* r3 = f l a g [ 1 ] ( i n S C R A T C H 3 9 )
* on c p u 1 :
* r2 = f l a g [ 1 ] ( i n S C R A T C H 3 9 )
* r3 = f l a g [ 0 ] ( i n S C R A T C H 3 8 )
*
* must b e c a l l e d w i t h M M U o n
* corrupts r0 - r3 , r12
* /
ENTRY( t e g r a _ p e n _ l o c k )
mov3 2 r3 , T E G R A _ P M C _ V I R T
cpu_ i d r0
add r1 , r3 , #P M C _ S C R A T C H 37
cmp r0 , #0
addeq r2 , r3 , #P M C _ S C R A T C H 38
addeq r3 , r3 , #P M C _ S C R A T C H 39
addne r2 , r3 , #P M C _ S C R A T C H 39
addne r3 , r3 , #P M C _ S C R A T C H 38
mov r12 , #1
str r12 , [ r2 ] @ flag[cpu] = 1
dsb
str r12 , [ r1 ] @ !turn = cpu
1 : dsb
ldr r12 , [ r3 ]
cmp r12 , #1 @ flag[!cpu] == 1?
ldreq r12 , [ r1 ]
cmpeq r12 , r0 @ !turn == cpu?
beq 1 b @ while !turn == cpu && flag[!cpu] == 1
mov p c , l r @ locked
ENDPROC( t e g r a _ p e n _ l o c k )
ENTRY( t e g r a _ p e n _ u n l o c k )
dsb
mov3 2 r3 , T E G R A _ P M C _ V I R T
cpu_ i d r0
cmp r0 , #0
addeq r2 , r3 , #P M C _ S C R A T C H 38
addne r2 , r3 , #P M C _ S C R A T C H 39
mov r12 , #0
str r12 , [ r2 ]
mov p c , l r
ENDPROC( t e g r a _ p e n _ u n l o c k )
/ *
* tegra2 0 _ c p u _ c l e a r _ r e s e t t a b l e ( v o i d )
*
* Called t o c l e a r t h e " r e s e t t a b l e s o o n " f l a g i n P M C _ S C R A T C H 4 1 w h e n
* it i s e x p e c t e d t h a t t h e s e c o n d a r y C P U w i l l b e i d l e s o o n .
* /
ENTRY( t e g r a20 _ c p u _ c l e a r _ r e s e t t a b l e )
mov3 2 r1 , T E G R A _ P M C _ V I R T + P M C _ S C R A T C H 4 1
mov r12 , #C P U _ N O T _ R E S E T T A B L E
str r12 , [ r1 ]
mov p c , l r
ENDPROC( t e g r a20 _ c p u _ c l e a r _ r e s e t t a b l e )
/ *
* tegra2 0 _ c p u _ s e t _ r e s e t t a b l e _ s o o n ( v o i d )
*
* Called t o s e t t h e " r e s e t t a b l e s o o n " f l a g i n P M C _ S C R A T C H 4 1 w h e n
* it i s e x p e c t e d t h a t t h e s e c o n d a r y C P U w i l l b e i d l e s o o n .
* /
ENTRY( t e g r a20 _ c p u _ s e t _ r e s e t t a b l e _ s o o n )
mov3 2 r1 , T E G R A _ P M C _ V I R T + P M C _ S C R A T C H 4 1
mov r12 , #C P U _ R E S E T T A B L E _ S O O N
str r12 , [ r1 ]
mov p c , l r
ENDPROC( t e g r a20 _ c p u _ s e t _ r e s e t t a b l e _ s o o n )
2013-01-16 21:33:55 +04:00
/ *
* tegra2 0 _ c p u _ i s _ r e s e t t a b l e _ s o o n ( v o i d )
*
* Returns t r u e i f t h e " r e s e t t a b l e s o o n " f l a g i n P M C _ S C R A T C H 4 1 h a s b e e n
* set b e c a u s e i t i s e x p e c t e d t h a t t h e s e c o n d a r y C P U w i l l b e i d l e s o o n .
* /
ENTRY( t e g r a20 _ c p u _ i s _ r e s e t t a b l e _ s o o n )
mov3 2 r1 , T E G R A _ P M C _ V I R T + P M C _ S C R A T C H 4 1
ldr r12 , [ r1 ]
cmp r12 , #C P U _ R E S E T T A B L E _ S O O N
moveq r0 , #1
movne r0 , #0
mov p c , l r
ENDPROC( t e g r a20 _ c p u _ i s _ r e s e t t a b l e _ s o o n )
2013-01-16 02:10:38 +04:00
/ *
* tegra2 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 W F I 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 .
* /
ENTRY( t e g r a20 _ s l e e p _ c p u _ s e c o n d a r y _ f i n i s h )
stmfd s p ! , { r4 - r11 , l r }
mrc p15 , 0 , r11 , c1 , c0 , 1 @ save actlr before exiting coherency
/* Flush and disable the L1 data cache */
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
mov3 2 r0 , T E G R A _ P M C _ V I R T + P M C _ S C R A T C H 4 1
mov r3 , #C P U _ R E S E T T A B L E
str r3 , [ r0 ]
2013-04-23 17:36:26 +04:00
bl t e g r a _ c p u _ d o _ i d l e
2013-01-16 02:10:38 +04:00
/ *
* cpu m a y b e r e s e t w h i l e i n w f i , w h i c h w i l l r e t u r n t h r o u g h
* tegra_ r e s u m e t o c p u _ r e s u m e
* or i n t e r r u p t m a y w a k e w f i , w h i c h w i l l r e t u r n h e r e
* cpu s t a t e i s u n c h a n g e d - M M U i s o n , c a c h e i s o n , c o h e r e n c y
* is o f f , a n d t h e d a t a c a c h e i s o f f
*
* r1 1 c o n t a i n s t h e o r i g i n a l a c t l r
* /
bl t e g r a _ p e n _ l o c k
mov3 2 r3 , T E G R A _ P M C _ V I R T
add r0 , r3 , #P M C _ S C R A T C H 41
mov r3 , #C P U _ N O T _ R E S E T T A B L E
str r3 , [ r0 ]
bl t e g r a _ p e n _ u n l o c k
/* Re-enable the data cache */
mrc p15 , 0 , r10 , c1 , c0 , 0
orr r10 , r10 , #C R _ C
mcr p15 , 0 , r10 , c1 , c0 , 0
isb
mcr p15 , 0 , r11 , c1 , c0 , 1 @ reenable coherency
/* Invalidate the TLBs & BTAC */
mov r1 , #0
mcr p15 , 0 , r1 , c8 , c3 , 0 @ invalidate shared TLBs
mcr p15 , 0 , r1 , c7 , c1 , 6 @ invalidate shared BTAC
dsb
isb
/ * the c p u w a s r u n n i n g w i t h c o h e r e n c y d i s a b l e d ,
* caches m a y b e o u t o f d a t e * /
bl v7 _ f l u s h _ k e r n _ c a c h e _ l o u i s
ldmfd s p ! , { r4 - r11 , p c }
ENDPROC( t e g r a20 _ s l e e p _ c p u _ s e c o n d a r y _ f i n i s h )
2013-01-16 21:33:55 +04:00
/ *
* tegra2 0 _ t e a r _ d o w n _ c p u
*
* Switches t h e C P U c l u s t e r t o P L L - P a n d e n t e r s s l e e p .
* /
ENTRY( t e g r a20 _ t e a r _ d o w n _ c p u )
bl t e g r a _ s w i t c h _ c p u _ t o _ p l l p
b t e g r a20 _ e n t e r _ s l e e p
ENDPROC( t e g r a20 _ t e a r _ d o w n _ c p u )
/ *
* tegra2 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
* /
tegra20_enter_sleep :
mov3 2 r6 , T E G R A _ F L O W _ C T R L _ B A S E
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
orr 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
cpu_ i d r1
cpu_ t o _ h a l t _ r e g r1 , r1
str r0 , [ r6 , r1 ]
dsb
ldr r0 , [ r6 , r1 ] / * m e m o r y b a r r i e r * /
halted :
dsb
wfe / * 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 * /
isb
b h a l t e d
2013-01-16 02:10:38 +04:00
# endif