2008-09-21 21:35:18 +01:00
/ *
* arch/ a r m / m a c h - a t 9 1 / p m _ s l o w _ c l o c k . S
*
* Copyright ( C ) 2 0 0 6 S a v i n Z l o b e c
*
* AT9 1 S A M 9 s u p p o r t :
* Copyright ( C ) 2 0 0 7 A n t i S u l l i n < a n t i . s u l l i n @artecdesign.ee
*
* 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 u n d e r t h e t e r m 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 v e r s i o n 2 a s
* published 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 .
*
* /
# include < l i n u x / l i n k a g e . h >
# include < m a c h / h a r d w a r e . h >
# include < m a c h / a t 9 1 _ p m c . h >
2010-06-21 14:59:27 +01:00
# if d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 R M 9 2 0 0 )
2008-09-21 21:35:18 +01:00
# include < m a c h / a t 9 1 r m 9 2 0 0 _ m c . h >
# elif d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 C A P 9 )
# include < m a c h / a t 9 1 c a p9 _ d d r s d r . h >
2010-06-21 14:59:27 +01:00
# elif d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 S A M 9 G 4 5 )
# include < m a c h / a t 9 1 s a m 9 _ d d r s d r . h >
2008-09-21 21:35:18 +01:00
# else
# include < m a c h / a t 9 1 s a m 9 _ s d r a m c . h >
# endif
# ifdef C O N F I G _ A R C H _ A T 9 1 S A M 9 2 6 3
/ *
* FIXME e i t h e r o r b o t h t h e S D R A M c o n t r o l l e r s ( E B 0 , E B 1 ) m i g h t b e i n u s e ;
* handle t h o s e c a s e s b o t h h e r e a n d i n t h e S u s p e n d - T o - R A M s u p p o r t .
* /
# warning A s s u m i n g E B 1 S D R A M c o n t r o l l e r i s * N O T * u s e d
# endif
/ *
* When S L O W D O W N _ M A S T E R _ C L O C K i s d e f i n e d w e w i l l a l s o s l o w d o w n t h e M a s t e r
* clock d u r i n g s u s p e n d b y a d j u s t i n g i t s p r e s c a l a r a n d d i v i s o r .
* NOTE : This h a s n ' t b e e n s h o w n t o b e s t a b l e o n S A M 9 s ; and on the RM9200 there
* are e r r a t a r e g a r d i n g a d j u s t i n g t h e p r e s c a l a r a n d d i v i s o r .
* /
# undef S L O W D O W N _ M A S T E R _ C L O C K
# define M C K R D Y _ T I M E O U T 1 0 0 0
# define M O S C R D Y _ T I M E O U T 1 0 0 0
# define P L L A L O C K _ T I M E O U T 1 0 0 0
# define P L L B L O C K _ T I M E O U T 1 0 0 0
/ *
* Wait u n t i l m a s t e r c l o c k i s r e a d y ( a f t e r s w i t c h i n g m a s t e r c l o c k s o u r c e )
* /
.macro wait_mckrdy
mov r4 , #M C K R D Y _ T I M E O U T
1 : sub r4 , r4 , #1
cmp r4 , #0
beq 2 f
ldr r3 , [ r1 , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
tst r3 , #A T 91 _ P M C _ M C K R D Y
beq 1 b
2 :
.endm
/ *
* Wait u n t i l m a s t e r o s c i l l a t o r h a s s t a b i l i z e d .
* /
.macro wait_moscrdy
mov r4 , #M O S C R D Y _ T I M E O U T
1 : sub r4 , r4 , #1
cmp r4 , #0
beq 2 f
ldr r3 , [ r1 , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
tst r3 , #A T 91 _ P M C _ M O S C S
beq 1 b
2 :
.endm
/ *
* Wait u n t i l P L L A h a s l o c k e d .
* /
.macro wait_pllalock
mov r4 , #P L L A L O C K _ T I M E O U T
1 : sub r4 , r4 , #1
cmp r4 , #0
beq 2 f
ldr r3 , [ r1 , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
tst r3 , #A T 91 _ P M C _ L O C K A
beq 1 b
2 :
.endm
/ *
* Wait u n t i l P L L B h a s l o c k e d .
* /
.macro wait_pllblock
mov r4 , #P L L B L O C K _ T I M E O U T
1 : sub r4 , r4 , #1
cmp r4 , #0
beq 2 f
ldr r3 , [ r1 , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
tst r3 , #A T 91 _ P M C _ L O C K B
beq 1 b
2 :
.endm
.text
ENTRY( a t 9 1 _ s l o w _ c l o c k )
/* Save registers on stack */
stmfd s p ! , { r0 - r12 , l r }
/ *
* Register u s a g e :
* R1 = B a s e a d d r e s s o f A T 9 1 _ P M C
2010-06-21 14:59:27 +01:00
* R2 = B a s e a d d r e s s o f R A M C o n t r o l l e r ( S D R A M , D D R S D R , o r A T 9 1 _ S Y S )
2008-09-21 21:35:18 +01:00
* R3 = t e m p o r a r y r e g i s t e r
* R4 = t e m p o r a r y r e g i s t e r
2010-06-21 14:59:27 +01:00
* R5 = B a s e a d d r e s s o f s e c o n d R A M C o n t r o l l e r o r 0 i f n o t p r e s e n t
2008-09-21 21:35:18 +01:00
* /
ldr r1 , . a t 9 1 _ v a _ b a s e _ p m c
ldr r2 , . a t 9 1 _ v a _ b a s e _ s d r a m c
2010-06-21 14:59:27 +01:00
ldr r5 , . a t 9 1 _ v a _ b a s e _ r a m c1
2008-09-21 21:35:18 +01:00
/* Drain write buffer */
mcr p15 , 0 , r0 , c7 , c10 , 4
# ifdef C O N F I G _ A R C H _ A T 9 1 R M 9 2 0 0
/* Put SDRAM in self-refresh mode */
mov r3 , #1
str r3 , [ r2 , #A T 91 _ S D R A M C _ S R R ]
2010-06-21 14:59:27 +01:00
# elif d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 C A P 9 ) \
| | defined( C O N F I G _ A R C H _ A T 9 1 S A M 9 G 4 5 )
2008-09-21 21:35:18 +01:00
2010-06-21 14:59:27 +01:00
/* prepare for DDRAM self-refresh mode */
ldr r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
str r3 , . s a v e d _ s a m 9 _ l p r
bic r3 , #A T 91 _ D D R S D R C _ L P C B
orr r3 , #A T 91 _ D D R S D R C _ L P C B _ S E L F _ R E F R E S H
/* figure out if we use the second ram controller */
cmp r5 , #0
ldrne r4 , [ r5 , #A T 91 _ D D R S D R C _ L P R ]
strne r4 , . s a v e d _ s a m 9 _ l p r1
bicne r4 , #A T 91 _ D D R S D R C _ L P C B
orrne r4 , #A T 91 _ D D R S D R C _ L P C B _ S E L F _ R E F R E S H
/* Enable DDRAM self-refresh mode */
str r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
strne r4 , [ r5 , #A T 91 _ D D R S D R C _ L P R ]
2008-09-21 21:35:18 +01:00
# else
/* Enable SDRAM self-refresh mode */
2010-06-21 14:59:27 +01:00
ldr r3 , [ r2 , #A T 91 _ S D R A M C _ L P R ]
2008-09-21 21:35:18 +01:00
str r3 , . s a v e d _ s a m 9 _ l p r
2010-06-21 14:59:27 +01:00
bic r3 , #A T 91 _ S D R A M C _ L P C B
orr r3 , #A T 91 _ S D R A M C _ L P C B _ S E L F _ R E F R E S H
str r3 , [ r2 , #A T 91 _ S D R A M C _ L P R ]
2008-09-21 21:35:18 +01:00
# endif
/* Save Master clock setting */
ldr r3 , [ r1 , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
str r3 , . s a v e d _ m c k r
/ *
* Set t h e M a s t e r c l o c k s o u r c e t o s l o w c l o c k
* /
bic r3 , r3 , #A T 91 _ P M C _ C S S
str r3 , [ r1 , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
wait_ m c k r d y
# ifdef S L O W D O W N _ M A S T E R _ C L O C K
/ *
* Set t h e M a s t e r C l o c k P R E S a n d M D I V f i e l d s .
*
* See A T 9 1 R M 9 2 0 0 e r r a t a #27 a n d #28 f o r d e t a i l s .
* /
mov r3 , #0
str r3 , [ r1 , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
wait_ m c k r d y
# endif
/* Save PLLA setting and disable it */
ldr r3 , [ r1 , #( A T 91 _ C K G R _ P L L A R - A T 9 1 _ P M C ) ]
str r3 , . s a v e d _ p l l a r
mov r3 , #A T 91 _ P M C _ P L L C O U N T
orr r3 , r3 , #( 1 < < 2 9 ) / * b i t 2 9 a l w a y s s e t * /
str r3 , [ r1 , #( A T 91 _ C K G R _ P L L A R - A T 9 1 _ P M C ) ]
/* Save PLLB setting and disable it */
ldr r3 , [ r1 , #( A T 91 _ C K G R _ P L L B R - A T 9 1 _ P M C ) ]
str r3 , . s a v e d _ p l l b r
mov r3 , #A T 91 _ P M C _ P L L C O U N T
str r3 , [ r1 , #( A T 91 _ C K G R _ P L L B R - A T 9 1 _ P M C ) ]
/* Turn off the main oscillator */
ldr r3 , [ r1 , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
bic r3 , r3 , #A T 91 _ P M C _ M O S C E N
str r3 , [ r1 , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
/* Wait for interrupt */
mcr p15 , 0 , r0 , c7 , c0 , 4
/* Turn on the main oscillator */
ldr r3 , [ r1 , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
orr r3 , r3 , #A T 91 _ P M C _ M O S C E N
str r3 , [ r1 , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
wait_ m o s c r d y
/* Restore PLLB setting */
ldr r3 , . s a v e d _ p l l b r
str r3 , [ r1 , #( A T 91 _ C K G R _ P L L B R - A T 9 1 _ P M C ) ]
2010-04-08 11:48:16 +01:00
tst r3 , #( A T 91 _ P M C _ M U L & 0 x f f00 0 0 )
bne 1 f
tst r3 , #( A T 91 _ P M C _ M U L & ~ 0 x f f00 0 0 )
beq 2 f
1 :
2008-09-21 21:35:18 +01:00
wait_ p l l b l o c k
2010-04-08 11:48:16 +01:00
2 :
2008-09-21 21:35:18 +01:00
/* Restore PLLA setting */
ldr r3 , . s a v e d _ p l l a r
str r3 , [ r1 , #( A T 91 _ C K G R _ P L L A R - A T 9 1 _ P M C ) ]
2010-04-08 11:48:16 +01:00
tst r3 , #( A T 91 _ P M C _ M U L & 0 x f f00 0 0 )
bne 3 f
tst r3 , #( A T 91 _ P M C _ M U L & ~ 0 x f f00 0 0 )
beq 4 f
3 :
2008-09-21 21:35:18 +01:00
wait_ p l l a l o c k
2010-04-08 11:48:16 +01:00
4 :
2008-09-21 21:35:18 +01:00
# ifdef S L O W D O W N _ M A S T E R _ C L O C K
/ *
* First s e t P R E S i f i t w a s n o t 0 ,
* than s e t C S S a n d M D I V f i e l d s .
*
* See A T 9 1 R M 9 2 0 0 e r r a t a #27 a n d #28 f o r d e t a i l s .
* /
ldr r3 , . s a v e d _ m c k r
tst r3 , #A T 91 _ P M C _ P R E S
beq 2 f
and r3 , r3 , #A T 91 _ P M C _ P R E S
str r3 , [ r1 , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
wait_ m c k r d y
# endif
/ *
* Restore m a s t e r c l o c k s e t t i n g
* /
2 : ldr r3 , . s a v e d _ m c k r
str r3 , [ r1 , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
wait_ m c k r d y
# ifdef C O N F I G _ A R C H _ A T 9 1 R M 9 2 0 0
/* Do nothing - self-refresh is automatically disabled. */
2010-06-21 14:59:27 +01:00
# elif d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 C A P 9 ) \
| | defined( C O N F I G _ A R C H _ A T 9 1 S A M 9 G 4 5 )
/* Restore LPR on AT91 with DDRAM */
2008-09-21 21:35:18 +01:00
ldr r3 , . s a v e d _ s a m 9 _ l p r
2010-06-21 14:59:27 +01:00
str r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
/* if we use the second ram controller */
cmp r5 , #0
ldrne r4 , . s a v e d _ s a m 9 _ l p r1
strne r4 , [ r5 , #A T 91 _ D D R S D R C _ L P R ]
2008-09-21 21:35:18 +01:00
# else
2010-06-21 14:59:27 +01:00
/* Restore LPR on AT91 with SDRAM */
2008-09-21 21:35:18 +01:00
ldr r3 , . s a v e d _ s a m 9 _ l p r
2010-06-21 14:59:27 +01:00
str r3 , [ r2 , #A T 91 _ S D R A M C _ L P R ]
2008-09-21 21:35:18 +01:00
# endif
/* Restore registers, and return */
ldmfd s p ! , { r0 - r12 , p c }
.saved_mckr :
.word 0
.saved_pllar :
.word 0
.saved_pllbr :
.word 0
.saved_sam9_lpr :
.word 0
2010-06-21 14:59:27 +01:00
.saved_sam9_lpr1 :
.word 0
2008-09-21 21:35:18 +01:00
.at91_va_base_pmc :
.word AT91_VA_BASE_SYS + AT9 1 _ P M C
# ifdef C O N F I G _ A R C H _ A T 9 1 R M 9 2 0 0
.at91_va_base_sdramc :
.word AT91_VA_BASE_SYS
2010-06-21 14:59:27 +01:00
# elif d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 C A P 9 ) \
| | defined( C O N F I G _ A R C H _ A T 9 1 S A M 9 G 4 5 )
2008-09-21 21:35:18 +01:00
.at91_va_base_sdramc :
2010-06-21 14:59:27 +01:00
.word AT91_VA_BASE_SYS + AT9 1 _ D D R S D R C 0
2008-09-21 21:35:18 +01:00
# else
.at91_va_base_sdramc :
2010-06-21 14:59:27 +01:00
.word AT91_VA_BASE_SYS + AT9 1 _ S D R A M C 0
# endif
.at91_va_base_ramc1 :
# if d e f i n e d ( C O N F I G _ A R C H _ A T 9 1 S A M 9 G 4 5 )
.word AT91_VA_BASE_SYS + AT9 1 _ D D R S D R C 1
# else
.word 0
2008-09-21 21:35:18 +01:00
# endif
ENTRY( a t 9 1 _ s l o w _ c l o c k _ s z )
.word . - at9 1 _ s l o w _ c l o c k