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 .
*
* 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
2009-02-04 16:49:45 +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:23:50 +08:00
ENTRY( _ _ s t a r t )
/* R0: argument of command line string, passed from uboot, save it */
R7 = R 0 ;
2011-02-03 02:16:44 +00:00
2008-08-06 17:23:50 +08:00
/* 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 ;
2011-02-03 02:16:44 +00:00
/ * Optimization r e g i s t e r t r i c k s : k e e p a b a s e v a l u e i n t h e
* reserved P r e g i s t e r s s o w e u s e t h e l o a d / s t o r e w i t h a n
* offset s y n t a x . R 0 = [ P 5 + < c o n s t a n t > ] ;
* P5 - c o r e M M R b a s e
* R6 - 0
* /
r6 = 0 ;
p5 . l = 0 ;
p5 . h = h i ( C O R E M M R _ B A S E ) ;
/* Zero out registers required by Blackfin ABI */
/* Disable circular buffers */
L0 = r6 ;
L1 = r6 ;
L2 = r6 ;
L3 = r6 ;
/* Disable hardware loops in case we were started by 'go' */
LC0 = r6 ;
LC1 = r6 ;
2008-08-06 17:23:50 +08:00
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
* /
2011-02-03 02:16:44 +00:00
[ p5 + ( D T E S T _ C O M M A N D - C O R E M M R _ B A S E ) ] = r6 ;
[ p5 + ( I T E S T _ C O M M A N D - C O R E M M R _ B A S E ) ] = r6 ;
2008-10-08 18:03:33 +08:00
CSYNC;
2008-08-06 17:23:50 +08:00
trace_ b u f f e r _ i n i t ( p0 ,r0 ) ;
/* Turn off the icache */
2011-02-03 02:16:44 +00:00
r1 = [ p5 + ( I M E M _ C O N T R O L - C O R E M M R _ B A S E ) ] ;
BITCLR ( r1 , E N I C P L B _ P ) ;
[ p5 + ( I M E M _ C O N T R O L - C O R E M M R _ B A S E ) ] = r1 ;
2008-08-06 17:23:50 +08:00
SSYNC;
/* Turn off the dcache */
2011-02-03 02:16:44 +00:00
r1 = [ p5 + ( D M E M _ C O N T R O L - C O R E M M R _ B A S E ) ] ;
BITCLR ( r1 , E N D C P L B _ P ) ;
[ p5 + ( D M E M _ C O N T R O L - C O R E M M R _ B A S E ) ] = r1 ;
2008-08-06 17:23:50 +08:00
SSYNC;
2008-10-08 16:27:12 +08:00
/* in case of double faults, save a few things */
2011-05-29 23:12:51 -04:00
p1 . l = _ i n i t i a l _ p d a ;
p1 . h = _ i n i t i a l _ p d a ;
r4 = R E T X ;
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 ) ;
2011-05-29 23:12:51 -04:00
r0 = [ p0 + P D A _ D F _ R E T X ] ;
r1 = [ p0 + P D A _ D F _ D C P L B ] ;
r2 = [ p0 + P D A _ D F _ I C P L B ] ;
r3 = [ p0 + P D A _ D F _ S E Q S T A T ] ;
[ p1 + P D A _ I N I T _ D F _ R E T X ] = r0 ;
[ p1 + P D A _ I N I T _ D F _ D C P L B ] = r1 ;
[ p1 + P D A _ I N I T _ D F _ I C P L B ] = r2 ;
[ p1 + P D A _ I N I T _ D F _ S E Q S T A T ] = r3 ;
2008-10-08 16:27:12 +08:00
# endif
2011-05-29 23:12:51 -04:00
[ p1 + P D A _ I N I T _ R E T X ] = r4 ;
2008-10-08 16:27:12 +08:00
2008-08-06 17:23:50 +08:00
/* Initialize stack pointer */
2010-01-05 07:25:24 +00:00
sp. l = _ i n i t _ t h r e a d _ u n i o n + T H R E A D _ S I Z E ;
sp. h = _ i n i t _ t h r e a d _ u n i o n + T H R E A D _ S I Z E ;
2008-08-06 17:23:50 +08:00
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 ;
2009-07-07 20:17:09 +00:00
r0 = ( E V T _ I V H W | E V T _ I R P T E N | E V T _ E V X | E V T _ N M I | E V T _ R S T | E V T _ E M U ) ;
sti r0 ;
2008-08-06 17:23:50 +08:00
# endif
2011-02-03 02:16:44 +00:00
r0 = r6 ;
2009-02-04 16:49:45 +08:00
/* Zero out all of the fun bss regions */
# 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 ;
call _ _ i n i t _ c l e a r _ b s s
# 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 ;
call _ _ i n i t _ c l e a r _ b s s
# 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 ;
call _ _ i n i t _ c l e a r _ b s s
# endif
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 ;
call _ _ i n i t _ c l e a r _ b s s
2008-08-06 17:23:50 +08:00
/* 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 ;
2010-01-07 04:11:17 +00:00
# ifdef C O N F I G _ R O M K E R N E L
call _ b f i n _ r e l o c a t e _ x i p _ d a t a ;
# endif
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
2009-04-24 03:55:41 +00:00
/ * Only u s e o n - c h i p s c r a t c h s p a c e f o r s t a c k w h e n a b s o l u t e l y r e q u i r e d
* to a v o i d A n o m a l y 0 5 0 0 0 2 2 7 . . . w e k n o w t h e i n i t _ c l o c k s ( ) f u n c o n l y
* uses L 1 t e x t a n d s t a c k s p a c e a n d n o o t h e r m e m o r y r e g i o n .
* /
# define K E R N E L _ C L O C K _ 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 )
sp. l = l o ( K E R N E L _ C L O C K _ S T A C K ) ;
sp. h = h i ( K E R N E L _ C L O C K _ S T A C K ) ;
2009-01-07 23:14:39 +08:00
call _ i n i t _ c l o c k s ;
2011-03-30 22:57:33 -03:00
sp = u s p ; /* usp hasn't been touched, so restore from there */
2008-08-06 17:23:50 +08:00
# 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 */
p1 . l = _ r e a l _ s t a r t ;
p1 . h = _ r e a l _ s t a r t ;
2011-02-03 02:16:44 +00:00
[ p5 + ( E V T 1 5 - C O R E M M R _ B A S E ) ] = p1 ;
2008-08-06 17:23:50 +08:00
csync;
2009-07-07 20:17:09 +00:00
# ifdef C O N F I G _ E A R L Y _ P R I N T K
r0 = ( E V T _ I V G 1 5 | E V T _ I V H W | E V T _ I R P T E N | E V T _ E V X | E V T _ N M I | E V T _ R S T | E V T _ E M U ) ( z ) ;
# else
2008-11-18 17:48:22 +08:00
r0 = E V T _ I V G 1 5 ( z ) ;
2009-07-07 20:17:09 +00:00
# endif
2008-11-18 17:48:22 +08:00
sti r0 ;
2008-08-06 17:23:50 +08:00
raise 1 5 ;
2009-07-07 20:17:09 +00:00
# ifdef C O N F I G _ E A R L Y _ P R I N T K
p0 . l = _ e a r l y _ t r a p ;
p0 . h = _ e a r l y _ t r a p ;
# else
2008-08-06 17:23:50 +08:00
p0 . l = . L W A I T _ H E R E ;
p0 . h = . L W A I T _ H E R E ;
2009-07-07 20:17:09 +00:00
# endif
2008-08-06 17:23:50 +08:00
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
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;
/* 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 ;
2010-01-05 07:25:24 +00:00
sp + = - 1 2 + 4 ; /* +4 is for reti loading above */
2009-01-07 23:14:39 +08:00
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