2010-02-22 04:46:23 +03:00
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / i n i t . h >
2012-02-10 03:47:45 +04:00
# include < a s m / c a c h e . h >
2012-11-13 06:04:48 +04:00
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / h a r d w a r e / c a c h e - l 2 x0 . h >
2012-02-10 03:47:45 +04:00
# include " f l o w c t r l . h "
2012-10-05 00:24:09 +04:00
# include " i o m a p . h "
2012-02-10 03:47:45 +04:00
# include " r e s e t . h "
2012-08-16 13:31:50 +04:00
# include " s l e e p . h "
2012-02-10 03:47:45 +04:00
# define A P B _ M I S C _ G P _ H I D R E V 0 x80 4
# define P M C _ S C R A T C H 4 1 0 x14 0
# define R E S E T _ D A T A ( x ) ( ( T E G R A _ R E S E T _ ## x ) * 4 )
2010-02-22 04:46:23 +03:00
.section " .text .head " , " ax"
/ *
* Tegra s p e c i f i c e n t r y p o i n t f o r s e c o n d a r y C P U s .
* The s e c o n d a r y k e r n e l i n i t c a l l s v7 _ f l u s h _ d c a c h e _ a l l b e f o r e i t e n a b l e s
* the L 1 ; however, the L1 comes out of reset in an undefined state, so
* the c l e a n + i n v a l i d a t e p e r f o r m e d b y v7 _ f l u s h _ d c a c h e _ a l l c a u s e s a b u n c h
* of c a c h e l i n e s w i t h u n i n i t i a l i z e d d a t a a n d u n i n i t i a l i z e d t a g s t o g e t
* written o u t t o m e m o r y , w h i c h d o e s r e a l l y u n p l e a s a n t t h i n g s t o t h e m a i n
* processor. W e f i x t h i s b y p e r f o r m i n g a n i n v a l i d a t e , r a t h e r t h a n a
* clean + i n v a l i d a t e , b e f o r e j u m p i n g i n t o t h e k e r n e l .
* /
ENTRY( v7 _ i n v a l i d a t e _ l 1 )
mov r0 , #0
mcr p15 , 2 , r0 , c0 , c0 , 0
mrc p15 , 1 , r0 , c0 , c0 , 0
ldr r1 , =0x7fff
and r2 , r1 , r0 , l s r #13
ldr r1 , =0x3ff
and r3 , r1 , r0 , l s r #3 @ NumWays - 1
add r2 , r2 , #1 @ NumSets
and r0 , r0 , #0x7
add r0 , r0 , #4 @ SetShift
clz r1 , r3 @ WayShift
add r4 , r3 , #1 @ NumWays
1 : sub r2 , r2 , #1 @ NumSets--
mov r3 , r4 @ Temp = NumWays
2 : subs r3 , r3 , #1 @ Temp--
mov r5 , r3 , l s l r1
mov r6 , r2 , l s l r0
orr r5 , r5 , r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
mcr p15 , 0 , r5 , c7 , c6 , 2
bgt 2 b
cmp r2 , #0
bgt 1 b
dsb
isb
mov p c , l r
ENDPROC( v7 _ i n v a l i d a t e _ l 1 )
2012-02-10 03:47:45 +04:00
2010-02-22 04:46:23 +03:00
ENTRY( t e g r a _ s e c o n d a r y _ s t a r t u p )
bl v7 _ i n v a l i d a t e _ l 1
2012-02-10 03:47:45 +04:00
/* Enable coresight */
mov3 2 r0 , 0 x C 5 A C C E 5 5
mcr p14 , 0 , r0 , c7 , c12 , 6
2010-02-22 04:46:23 +03:00
b s e c o n d a r y _ s t a r t u p
ENDPROC( t e g r a _ s e c o n d a r y _ s t a r t u p )
2012-02-10 03:47:45 +04:00
2012-10-31 13:41:16 +04:00
# ifdef C O N F I G _ P M _ S L E E P
/ *
* tegra_ r e s u m e
*
* CPU b o o t v e c t o r w h e n r e s t a r t i n g t h e a C P U f o l l o w i n g
* an L P 2 t r a n s i t i o n . A l s o b r a n c h e d t o b y L P 0 a n d L P 1 r e s u m e a f t e r
* re- e n a b l i n g s d r a m .
* /
ENTRY( t e g r a _ r e s u m e )
bl v7 _ i n v a l i d a t e _ l 1
/* Enable coresight */
mov3 2 r0 , 0 x C 5 A C C E 5 5
mcr p14 , 0 , r0 , c7 , c12 , 6
cpu_ i d r0
cmp r0 , #0 @ CPU0?
bne c p u _ r e s u m e @ no
# ifdef C O N F I G _ A R C H _ T E G R A _ 3 x _ S O C
/* Are we on Tegra20? */
mov3 2 r6 , T E G R A _ A P B _ M I S C _ B A S E
ldr r0 , [ r6 , #A P B _ M I S C _ G P _ H I D R E V ]
and r0 , r0 , #0xff00
cmp r0 , #( 0x20 < < 8 )
beq 1 f @ Yes
/* Clear the flow controller flags for this CPU. */
mov3 2 r2 , T E G R A _ F L O W _ C T R L _ B A S E + F L O W _ C T R L _ C P U 0 _ C S R @ CPU0 CSR
ldr r1 , [ r2 ]
/* Clear event & intr flag */
orr r1 , r1 , \
# 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
movw r0 , #0x0FFD @ enable, cluster_switch, immed, & bitmaps
bic r1 , r1 , r0
str r1 , [ r2 ]
1 :
# endif
# ifdef C O N F I G _ H A V E _ A R M _ S C U
/* enable SCU */
mov3 2 r0 , T E G R A _ A R M _ P E R I F _ B A S E
ldr r1 , [ r0 ]
orr r1 , r1 , #1
str r1 , [ r0 ]
# endif
2012-11-13 06:04:48 +04:00
/* L2 cache resume & re-enable */
l2 _ c a c h e _ r e s u m e r0 , r1 , r2 , l 2 x0 _ s a v e d _ r e g s _ a d d r
2012-10-31 13:41:16 +04:00
b c p u _ r e s u m e
ENDPROC( t e g r a _ r e s u m e )
# endif
2012-11-13 06:04:48 +04:00
# ifdef C O N F I G _ C A C H E _ L 2 X 0
.globl l2x0_saved_regs_addr
l2x0_saved_regs_addr :
.long 0
# endif
2012-02-10 03:47:45 +04:00
.align L1_CACHE_SHIFT
ENTRY( _ _ t e g r a _ c p u _ r e s e t _ h a n d l e r _ s t a r t )
/ *
* __tegra_cpu_reset_handler :
*
* Common h a n d l e r f o r a l l C P U r e s e t e v e n t s .
*
* Register u s a g e w i t h i n t h e r e s e t h a n d l e r :
*
* R7 = C P U p r e s e n t ( t o t h e O S ) m a s k
* R8 = C P U i n L P 1 s t a t e m a s k
* R9 = C P U i n L P 2 s t a t e m a s k
* R1 0 = C P U n u m b e r
* R1 1 = C P U m a s k
* R1 2 = p o i n t e r t o r e s e t h a n d l e r d a t a
*
* NOTE : This c o d e i s c o p i e d t o I R A M . A l l c o d e a n d d a t a a c c e s s e s
* must b e p o s i t i o n - i n d e p e n d e n t .
* /
.align L1_CACHE_SHIFT
ENTRY( _ _ t e g r a _ c p u _ r e s e t _ h a n d l e r )
cpsid a i f , 0 x13 @ SVC mode, interrupts disabled
mrc p15 , 0 , r10 , c0 , c0 , 5 @ MPIDR
and r10 , r10 , #0x3 @ R10 = CPU number
mov r11 , #1
mov r11 , r11 , l s l r10 @ R11 = CPU mask
adr r12 , _ _ t e g r a _ c p u _ r e s e t _ h a n d l e r _ d a t a
# ifdef C O N F I G _ S M P
/* Does the OS know about this CPU? */
ldr r7 , [ r12 , #R E S E T _ D A T A ( M A S K _ P R E S E N T ) ]
tst r7 , r11 @ if !present
bleq _ _ d i e @ CPU not present (to OS)
# endif
# ifdef C O N F I G _ A R C H _ T E G R A _ 2 x _ S O C
/* Are we on Tegra20? */
mov3 2 r6 , T E G R A _ A P B _ M I S C _ B A S E
ldr r0 , [ r6 , #A P B _ M I S C _ G P _ H I D R E V ]
and r0 , r0 , #0xff00
cmp r0 , #( 0x20 < < 8 )
bne 1 f
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
mov3 2 r6 , T E G R A _ P M C _ B A S E
mov r0 , #0
cmp r10 , #0
strne r0 , [ r6 , #P M C _ S C R A T C H 41 ]
1 :
# endif
2012-10-31 13:41:16 +04:00
/* Waking up from LP2? */
ldr r9 , [ r12 , #R E S E T _ D A T A ( M A S K _ L P 2 ) ]
tst r9 , r11 @ if in_lp2
beq _ _ i s _ n o t _ l p2
ldr l r , [ r12 , #R E S E T _ D A T A ( S T A R T U P _ L P 2 ) ]
cmp l r , #0
bleq _ _ d i e @ no LP2 startup handler
bx l r
__is_not_lp2 :
2012-02-10 03:47:45 +04:00
# ifdef C O N F I G _ S M P
/ *
* Can o n l y b e s e c o n d a r y b o o t ( i n i t i a l o r h o t p l u g ) b u t C P U 0
* cannot b e h e r e .
* /
cmp r10 , #0
bleq _ _ d i e @ CPU0 cannot be here
ldr l r , [ r12 , #R E S E T _ D A T A ( S T A R T U P _ S E C O N D A R Y ) ]
cmp l r , #0
bleq _ _ d i e @ no secondary startup handler
bx l r
# endif
/ *
* We d o n ' t k n o w w h y t h e C P U r e s e t . J u s t k i l l i t .
* The L R r e g i s t e r w i l l c o n t a i n t h e a d d r e s s w e d i e d a t + 4 .
* /
__die :
sub l r , l r , #4
mov3 2 r7 , T E G R A _ P M C _ B A S E
str l r , [ r7 , #P M C _ S C R A T C H 41 ]
mov3 2 r7 , T E G R A _ C L K _ R E S E T _ B A S E
/* Are we on Tegra20? */
mov3 2 r6 , T E G R A _ A P B _ M I S C _ B A S E
ldr r0 , [ r6 , #A P B _ M I S C _ G P _ H I D R E V ]
and r0 , r0 , #0xff00
cmp r0 , #( 0x20 < < 8 )
bne 1 f
# ifdef C O N F I G _ A R C H _ T E G R A _ 2 x _ S O C
mov3 2 r0 , 0 x11 1 1
mov r1 , r0 , l s l r10
str r1 , [ r7 , #0x340 ] @ CLK_RST_CPU_CMPLX_SET
# endif
1 :
2012-02-10 03:47:50 +04:00
# ifdef C O N F I G _ A R C H _ T E G R A _ 3 x _ S O C
mov3 2 r6 , T E G R A _ F L O W _ C T R L _ B A S E
cmp r10 , #0
moveq r1 , #F L O W _ C T R L _ H A L T _ C P U 0 _ E V E N T S
moveq r2 , #F L O W _ C T R L _ C P U 0 _ C S R
movne r1 , r10 , l s l #3
addne r2 , r1 , #( F L O W _ C T R L _ C P U 1 _ C S R - 8 )
addne r1 , r1 , #( F L O W _ C T R L _ H A L T _ C P U 1 _ E V E N T S - 8 )
/ * Clear C P U " 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 I " s t a t e . * /
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 ]
/* Unconditionally halt this CPU */
mov r0 , #F L O W _ C T R L _ W A I T E V E N T
str r0 , [ r6 , + r1 ]
ldr r0 , [ r6 , + r1 ] @ memory barrier
dsb
isb
wfi @ CPU should be power gated here
/* If the CPU didn't power gate above just kill it's clock. */
mov r0 , r11 , l s l #8
str r0 , [ r7 , #348 ] @ CLK_CPU_CMPLX_SET
# endif
2012-02-10 03:47:45 +04:00
/* If the CPU still isn't dead, just spin here. */
b .
ENDPROC( _ _ t e g r a _ c p u _ r e s e t _ h a n d l e r )
.align L1_CACHE_SHIFT
.type _ _ tegra_ c p u _ r e s e t _ h a n d l e r _ d a t a , % o b j e c t
.globl __tegra_cpu_reset_handler_data
__tegra_cpu_reset_handler_data :
.rept TEGRA_RESET_DATA_SIZE
.long 0
.endr
.align L1_CACHE_SHIFT
ENTRY( _ _ t e g r a _ c p u _ r e s e t _ h a n d l e r _ e n d )