2008-08-06 17:15:27 +08:00
/ *
* Common B l a c k f i n s t a r t u p c o d e
*
* Copyright 2 0 0 4 - 2 0 0 8 A n a l o g D e v i c e s I n c .
*
* Enter b u g s a t h t t p : / / b l a c k f i n . u c l i n u x . o r g /
*
* Licensed u n d e r t h e G P L - 2 o r l a t e r .
* /
# 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 >
# include < a s m / b l a c k f i n . h >
2008-08-06 17:18:31 +08:00
# include < a s m / t h r e a d _ i n f o . h >
2008-08-06 17:15:27 +08:00
# include < a s m / t r a c e . h >
2009-01-07 23:14:39 +08:00
# include < a s m / a s m - o f f s e t s . h >
2008-08-06 17:15:27 +08:00
2008-08-06 17:23:50 +08:00
_ _ INIT
# define I N I T I A L _ S T A C K ( L 1 _ S C R A T C H _ S T A R T + L 1 _ S C R A T C H _ L E N G T H - 1 2 )
ENTRY( _ _ s t a r t )
/* R0: argument of command line string, passed from uboot, save it */
R7 = R 0 ;
/* Enable Cycle Counter and Nesting Of Interrupts */
# ifdef C O N F I G _ B F I N _ S C R A T C H _ R E G _ C Y C L E S
R0 = S Y S C F G _ S N E N ;
# else
R0 = S Y S C F G _ S N E N | S Y S C F G _ C C E N ;
# endif
SYSCFG = R 0 ;
R0 = 0 ;
/* Clear Out All the data and pointer Registers */
R1 = R 0 ;
R2 = R 0 ;
R3 = R 0 ;
R4 = R 0 ;
R5 = R 0 ;
R6 = R 0 ;
P0 = R 0 ;
P1 = R 0 ;
P2 = R 0 ;
P3 = R 0 ;
P4 = R 0 ;
P5 = R 0 ;
LC0 = r0 ;
LC1 = r0 ;
L0 = r0 ;
L1 = r0 ;
L2 = r0 ;
L3 = r0 ;
/* Clear Out All the DAG Registers */
B0 = r0 ;
B1 = r0 ;
B2 = r0 ;
B3 = r0 ;
I0 = r0 ;
I1 = r0 ;
I2 = r0 ;
I3 = r0 ;
M0 = r0 ;
M1 = r0 ;
M2 = r0 ;
M3 = r0 ;
2008-10-08 18:03:33 +08:00
/ *
* Clear I T E S T _ C O M M A N D a n d D T E S T _ C O M M A N D r e g i s t e r s ,
* Leaving t h e s e a s n o n - z e r o c a n c o n f u s e t h e e m u l a t o r
* /
p0 . L = L O ( D T E S T _ C O M M A N D ) ;
p0 . H = H I ( D T E S T _ C O M M A N D ) ;
[ p0 ] = R 0 ;
[ p0 + ( I T E S T _ C O M M A N D - D T E S T _ C O M M A N D ) ] = R 0 ;
CSYNC;
2008-08-06 17:23:50 +08:00
trace_ b u f f e r _ i n i t ( p0 ,r0 ) ;
P0 = R 1 ;
R0 = R 1 ;
/* Turn off the icache */
p0 . l = L O ( I M E M _ C O N T R O L ) ;
p0 . h = H I ( I M E M _ C O N T R O L ) ;
R1 = [ p0 ] ;
R0 = ~ E N I C P L B ;
R0 = R 0 & R 1 ;
[ p0 ] = R 0 ;
SSYNC;
/* Turn off the dcache */
p0 . l = L O ( D M E M _ C O N T R O L ) ;
p0 . h = H I ( D M E M _ C O N T R O L ) ;
R1 = [ p0 ] ;
R0 = ~ E N D C P L B ;
R0 = R 0 & R 1 ;
[ p0 ] = R 0 ;
SSYNC;
2008-10-08 16:27:12 +08:00
/* in case of double faults, save a few things */
p0 . l = _ i n i t _ r e t x ;
p0 . h = _ i n i t _ r e t x ;
2008-08-14 14:44:33 +08:00
R0 = R E T X ;
[ P0 ] = R 0 ;
2008-10-08 16:27:12 +08:00
# ifdef C O N F I G _ D E B U G _ D O U B L E F A U L T
/ * Only s a v e t h e s e i f w e a r e s t o r i n g t h e m ,
* This h a p p e n s h e r e , s i n c e L 1 g e t s c l o b b e r e d
* below
* /
2009-01-07 23:14:39 +08:00
GET_ P D A ( p0 , r0 ) ;
r7 = [ p0 + P D A _ R E T X ] ;
2008-10-08 16:27:12 +08:00
p1 . l = _ i n i t _ s a v e d _ r e t x ;
p1 . h = _ i n i t _ s a v e d _ r e t x ;
2009-01-07 23:14:39 +08:00
[ p1 ] = r7 ;
2008-10-08 16:27:12 +08:00
2009-01-07 23:14:39 +08:00
r7 = [ p0 + P D A _ D C P L B ] ;
2008-10-08 16:27:12 +08:00
p1 . l = _ i n i t _ s a v e d _ d c p l b _ f a u l t _ a d d r ;
p1 . h = _ i n i t _ s a v e d _ d c p l b _ f a u l t _ a d d r ;
2009-01-07 23:14:39 +08:00
[ p1 ] = r7 ;
2008-10-08 16:27:12 +08:00
2009-01-07 23:14:39 +08:00
r7 = [ p0 + P D A _ I C P L B ] ;
2008-10-08 16:27:12 +08:00
p1 . l = _ i n i t _ s a v e d _ i c p l b _ f a u l t _ a d d r ;
p1 . h = _ i n i t _ s a v e d _ i c p l b _ f a u l t _ a d d r ;
2009-01-07 23:14:39 +08:00
[ p1 ] = r7 ;
2008-10-08 16:27:12 +08:00
2009-01-07 23:14:39 +08:00
r7 = [ p0 + P D A _ S E Q S T A T ] ;
2008-10-08 16:27:12 +08:00
p1 . l = _ i n i t _ s a v e d _ s e q s t a t ;
p1 . h = _ i n i t _ s a v e d _ s e q s t a t ;
2009-01-07 23:14:39 +08:00
[ p1 ] = r7 ;
2008-10-08 16:27:12 +08:00
# endif
2008-08-06 17:23:50 +08:00
/* Initialize stack pointer */
sp. l = l o ( I N I T I A L _ S T A C K ) ;
sp. h = h i ( I N I T I A L _ S T A C K ) ;
fp = s p ;
usp = s p ;
# ifdef C O N F I G _ E A R L Y _ P R I N T K
call _ i n i t _ e a r l y _ e x c e p t i o n _ v e c t o r s ;
# endif
/* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
2008-10-08 17:32:57 +08:00
call _ b f i n _ r e l o c a t e _ l 1 _ m e m ;
2008-08-06 17:23:50 +08:00
# ifdef C O N F I G _ B F I N _ K E R N E L _ C L O C K
call _ s t a r t _ d m a _ c o d e ;
# endif
/ * This s e c t i o n k e e p s t h e p r o c e s s o r i n s u p e r v i s o r m o d e
* during k e r n e l b o o t . S w i t c h e s t o u s e r m o d e a t e n d o f b o o t .
* See p a g e 3 - 9 o f H a r d w a r e R e f e r e n c e m a n u a l f o r d o c u m e n t a t i o n .
* /
/* EVT15 = _real_start */
p0 . l = l o ( E V T 1 5 ) ;
p0 . h = h i ( E V T 1 5 ) ;
p1 . l = _ r e a l _ s t a r t ;
p1 . h = _ r e a l _ s t a r t ;
[ p0 ] = p1 ;
csync;
2008-11-18 17:48:22 +08:00
r0 = E V T _ I V G 1 5 ( z ) ;
sti r0 ;
2008-08-06 17:23:50 +08:00
raise 1 5 ;
p0 . l = . L W A I T _ H E R E ;
p0 . h = . L W A I T _ H E R E ;
reti = p0 ;
# if A N O M A L Y _ 0 5 0 0 0 2 8 1
nop; nop; nop;
# endif
rti;
.LWAIT_HERE :
jump . L W A I T _ H E R E ;
ENDPROC( _ _ s t a r t )
2008-08-06 17:15:27 +08:00
/* A little BF561 glue ... */
# ifndef W D O G _ C T L
# define W D O G _ C T L W D O G A _ C T L
# endif
2008-10-27 18:17:41 +08:00
ENTRY( _ _ i n i t _ c l e a r _ b s s )
r2 = r2 - r1 ;
cc = r2 = = 0 ;
if c c j u m p . L _ b s s _ d o n e ;
r2 > > = 2 ;
p1 = r1 ;
p2 = r2 ;
lsetup ( 1 f , 1 f ) l c0 = p2 ;
1 : [ p1 + + ] = r0 ;
.L_bss_done :
rts;
ENDPROC( _ _ i n i t _ c l e a r _ b s s )
2008-08-06 17:15:27 +08:00
ENTRY( _ r e a l _ s t a r t )
/* Enable nested interrupts */
[ - - sp] = r e t i ;
/* watchdog off for now */
p0 . l = l o ( W D O G _ C T L ) ;
p0 . h = h i ( W D O G _ C T L ) ;
r0 = 0 x A D 6 ( z ) ;
w[ p0 ] = r0 ;
ssync;
2008-10-27 18:17:41 +08:00
r0 = 0 ( x ) ;
/* Zero out all of the fun bss regions */
2008-10-16 22:50:46 +08:00
# if L 1 _ D A T A _ A _ L E N G T H > 0
r1 . l = _ _ s b s s _ l 1 ;
r1 . h = _ _ s b s s _ l 1 ;
r2 . l = _ _ e b s s _ l 1 ;
r2 . h = _ _ e b s s _ l 1 ;
2008-10-27 18:17:41 +08:00
call _ _ i n i t _ c l e a r _ b s s
2008-10-16 22:50:46 +08:00
# endif
# if L 1 _ D A T A _ B _ L E N G T H > 0
r1 . l = _ _ s b s s _ b _ l 1 ;
r1 . h = _ _ s b s s _ b _ l 1 ;
r2 . l = _ _ e b s s _ b _ l 1 ;
r2 . h = _ _ e b s s _ b _ l 1 ;
2008-10-27 18:17:41 +08:00
call _ _ i n i t _ c l e a r _ b s s
2008-10-16 22:50:46 +08:00
# endif
# if L 2 _ L E N G T H > 0
r1 . l = _ _ s b s s _ l 2 ;
r1 . h = _ _ s b s s _ l 2 ;
r2 . l = _ _ e b s s _ l 2 ;
r2 . h = _ _ e b s s _ l 2 ;
2008-10-27 18:17:41 +08:00
call _ _ i n i t _ c l e a r _ b s s
2008-10-16 22:50:46 +08:00
# endif
2008-08-06 17:15:27 +08:00
r1 . l = _ _ _ b s s _ s t a r t ;
r1 . h = _ _ _ b s s _ s t a r t ;
r2 . l = _ _ _ b s s _ s t o p ;
r2 . h = _ _ _ b s s _ s t o p ;
2008-10-27 18:17:41 +08:00
call _ _ i n i t _ c l e a r _ b s s
2008-08-06 17:15:27 +08:00
/* Pass the u-boot arguments to the global value command line */
R0 = R 7 ;
call _ c m d l i n e _ i n i t ;
/* Load the current thread pointer and stack */
sp. l = _ i n i t _ t h r e a d _ u n i o n ;
sp. h = _ i n i t _ t h r e a d _ u n i o n ;
p1 = T H R E A D _ S I Z E ( z ) ;
sp = s p + p1 ;
usp = s p ;
fp = s p ;
2009-01-07 23:14:39 +08:00
sp + = - 1 2 ;
call _ i n i t _ p d a
sp + = 1 2 ;
2008-08-06 17:15:27 +08:00
jump. l _ s t a r t _ k e r n e l ;
ENDPROC( _ r e a l _ s t a r t )
_ _ FINIT