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 >
2012-02-13 12:58:53 +08:00
# include < m a c h / a t 9 1 _ r a m c . h >
2008-09-21 21:35:18 +01:00
2012-04-06 11:51:50 +08:00
# ifdef C O N F I G _ S O C _ A T 9 1 S A M 9 2 6 3
2008-09-21 21:35:18 +01:00
/ *
* 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
2012-02-22 17:50:54 +01:00
pmc . r e q r0
sdramc . r e q r1
ramc1 . r e q r2
2012-02-22 17:50:55 +01:00
memctrl . r e q r3
tmp1 . r e q r4
tmp2 . r e q r5
2008-09-21 21:35:18 +01:00
/ *
* 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
2012-02-22 17:50:53 +01:00
mov t m p2 , #M C K R D Y _ T I M E O U T
1 : sub t m p2 , t m p2 , #1
cmp t m p2 , #0
2008-09-21 21:35:18 +01:00
beq 2 f
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ P M C _ S R ]
2012-02-22 17:50:53 +01:00
tst t m p1 , #A T 91 _ P M C _ M C K R D Y
2008-09-21 21:35:18 +01:00
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
2012-02-22 17:50:53 +01:00
mov t m p2 , #M O S C R D Y _ T I M E O U T
1 : sub t m p2 , t m p2 , #1
cmp t m p2 , #0
2008-09-21 21:35:18 +01:00
beq 2 f
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ P M C _ S R ]
2012-02-22 17:50:53 +01:00
tst t m p1 , #A T 91 _ P M C _ M O S C S
2008-09-21 21:35:18 +01:00
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
2012-02-22 17:50:53 +01:00
mov t m p2 , #P L L A L O C K _ T I M E O U T
1 : sub t m p2 , t m p2 , #1
cmp t m p2 , #0
2008-09-21 21:35:18 +01:00
beq 2 f
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ P M C _ S R ]
2012-02-22 17:50:53 +01:00
tst t m p1 , #A T 91 _ P M C _ L O C K A
2008-09-21 21:35:18 +01:00
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
2012-02-22 17:50:53 +01:00
mov t m p2 , #P L L B L O C K _ T I M E O U T
1 : sub t m p2 , t m p2 , #1
cmp t m p2 , #0
2008-09-21 21:35:18 +01:00
beq 2 f
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ P M C _ S R ]
2012-02-22 17:50:53 +01:00
tst t m p1 , #A T 91 _ P M C _ L O C K B
2008-09-21 21:35:18 +01:00
beq 1 b
2 :
.endm
.text
2012-02-22 17:50:55 +01:00
/ * void a t 9 1 _ s l o w _ c l o c k ( v o i d _ _ i o m e m * p m c , v o i d _ _ i o m e m * s d r a m c ,
* void _ _ i o m e m * r a m c1 , i n t m e m c t r l )
* /
2008-09-21 21:35:18 +01:00
ENTRY( a t 9 1 _ s l o w _ c l o c k )
/* Save registers on stack */
2012-02-22 17:50:55 +01:00
stmfd s p ! , { r4 - r12 , l r }
2008-09-21 21:35:18 +01:00
/ *
* Register u s a g e :
2012-02-22 17:50:54 +01:00
* R0 = B a s e a d d r e s s o f A T 9 1 _ P M C
* R1 = 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 )
* R2 = 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
2012-02-22 17:50:55 +01:00
* R3 = M e m o r y c o n t r o l l e r
2008-09-21 21:35:18 +01:00
* R4 = t e m p o r a r y r e g i s t e r
2012-02-22 17:50:55 +01:00
* R5 = t e m p o r a r y r e g i s t e r
2008-09-21 21:35:18 +01:00
* /
/* Drain write buffer */
2012-02-22 17:50:53 +01:00
mov t m p1 , #0
mcr p15 , 0 , t m p1 , c7 , c10 , 4
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:55 +01:00
cmp m e m c t r l , #A T 91 _ M E M C T R L _ M C
bne d d r _ s r _ e n a b l e
/ *
* at9 1 r m 9 2 0 0 M e m o r y c o n t r o l l e r
* /
2008-09-21 21:35:18 +01:00
/* Put SDRAM in self-refresh mode */
2012-02-22 17:50:53 +01:00
mov t m p1 , #1
2011-11-16 02:58:31 +08:00
str t m p1 , [ s d r a m c , #A T 91 R M 9 2 0 0 _ S D R A M C _ S R R ]
2012-02-22 17:50:55 +01:00
b s d r _ s r _ d o n e
/ *
* DDRSDR M e m o r y c o n t r o l l e r
* /
ddr_sr_enable :
cmp m e m c t r l , #A T 91 _ M E M C T R L _ D D R S D R
bne s d r _ s r _ e n a b l e
2008-09-21 21:35:18 +01:00
2010-06-21 14:59:27 +01:00
/* prepare for DDRAM self-refresh mode */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ s d r a m c , #A T 91 _ D D R S D R C _ L P R ]
str t m p1 , . s a v e d _ s a m 9 _ l p r
bic t m p1 , #A T 91 _ D D R S D R C _ L P C B
orr t m p1 , #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
2010-06-21 14:59:27 +01:00
/* figure out if we use the second ram controller */
2012-02-22 17:50:53 +01:00
cmp r a m c1 , #0
ldrne t m p2 , [ r a m c1 , #A T 91 _ D D R S D R C _ L P R ]
strne t m p2 , . s a v e d _ s a m 9 _ l p r1
bicne t m p2 , #A T 91 _ D D R S D R C _ L P C B
orrne t m p2 , #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
2010-06-21 14:59:27 +01:00
/* Enable DDRAM self-refresh mode */
2012-02-22 17:50:53 +01:00
str t m p1 , [ s d r a m c , #A T 91 _ D D R S D R C _ L P R ]
strne t m p2 , [ r a m c1 , #A T 91 _ D D R S D R C _ L P R ]
2012-02-22 17:50:55 +01:00
b s d r _ s r _ d o n e
/ *
* SDRAMC M e m o r y c o n t r o l l e r
* /
sdr_sr_enable :
2008-09-21 21:35:18 +01:00
/* Enable SDRAM self-refresh mode */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ s d r a m c , #A T 91 _ S D R A M C _ L P R ]
str t m p1 , . s a v e d _ s a m 9 _ l p r
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:53 +01:00
bic t m p1 , #A T 91 _ S D R A M C _ L P C B
orr t m p1 , #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 t m p1 , [ s d r a m c , #A T 91 _ S D R A M C _ L P R ]
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:55 +01:00
sdr_sr_done :
2008-09-21 21:35:18 +01:00
/* Save Master clock setting */
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ P M C _ M C K R ]
2012-02-22 17:50:53 +01:00
str t m p1 , . s a v e d _ m c k r
2008-09-21 21:35:18 +01:00
/ *
* 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
* /
2012-02-22 17:50:53 +01:00
bic t m p1 , t m p1 , #A T 91 _ P M C _ C S S
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ P M C _ M C K R ]
2008-09-21 21:35:18 +01:00
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 .
* /
2012-02-22 17:50:53 +01:00
mov t m p1 , #0
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ P M C _ M C K R ]
2008-09-21 21:35:18 +01:00
wait_ m c k r d y
# endif
/* Save PLLA setting and disable it */
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ C K G R _ P L L A R ]
2012-02-22 17:50:53 +01:00
str t m p1 , . s a v e d _ p l l a r
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:53 +01:00
mov t m p1 , #A T 91 _ P M C _ P L L C O U N T
orr t m p1 , t m p1 , #( 1 < < 2 9 ) / * b i t 2 9 a l w a y s s e t * /
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ C K G R _ P L L A R ]
2008-09-21 21:35:18 +01:00
/* Save PLLB setting and disable it */
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ C K G R _ P L L B R ]
2012-02-22 17:50:53 +01:00
str t m p1 , . s a v e d _ p l l b r
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:53 +01:00
mov t m p1 , #A T 91 _ P M C _ P L L C O U N T
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ C K G R _ P L L B R ]
2008-09-21 21:35:18 +01:00
/* Turn off the main oscillator */
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ C K G R _ M O R ]
2012-02-22 17:50:53 +01:00
bic t m p1 , t m p1 , #A T 91 _ P M C _ M O S C E N
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ C K G R _ M O R ]
2008-09-21 21:35:18 +01:00
/* Wait for interrupt */
2012-02-22 17:50:53 +01:00
mcr p15 , 0 , t m p1 , c7 , c0 , 4
2008-09-21 21:35:18 +01:00
/* Turn on the main oscillator */
2011-11-25 09:59:46 +08:00
ldr t m p1 , [ p m c , #A T 91 _ C K G R _ M O R ]
2012-02-22 17:50:53 +01:00
orr t m p1 , t m p1 , #A T 91 _ P M C _ M O S C E N
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ C K G R _ M O R ]
2008-09-21 21:35:18 +01:00
wait_ m o s c r d y
/* Restore PLLB setting */
2012-02-22 17:50:53 +01:00
ldr t m p1 , . s a v e d _ p l l b r
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ C K G R _ P L L B R ]
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:53 +01:00
tst t m p1 , #( A T 91 _ P M C _ M U L & 0 x f f00 0 0 )
2010-04-08 11:48:16 +01:00
bne 1 f
2012-02-22 17:50:53 +01:00
tst t m p1 , #( A T 91 _ P M C _ M U L & ~ 0 x f f00 0 0 )
2010-04-08 11:48:16 +01:00
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 */
2012-02-22 17:50:53 +01:00
ldr t m p1 , . s a v e d _ p l l a r
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ C K G R _ P L L A R ]
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:53 +01:00
tst t m p1 , #( A T 91 _ P M C _ M U L & 0 x f f00 0 0 )
2010-04-08 11:48:16 +01:00
bne 3 f
2012-02-22 17:50:53 +01:00
tst t m p1 , #( A T 91 _ P M C _ M U L & ~ 0 x f f00 0 0 )
2010-04-08 11:48:16 +01:00
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 .
* /
2012-02-22 17:50:53 +01:00
ldr t m p1 , . s a v e d _ m c k r
tst t m p1 , #A T 91 _ P M C _ P R E S
2008-09-21 21:35:18 +01:00
beq 2 f
2012-02-22 17:50:53 +01:00
and t m p1 , t m p1 , #A T 91 _ P M C _ P R E S
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ P M C _ M C K R ]
2008-09-21 21:35:18 +01:00
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
* /
2012-02-22 17:50:53 +01:00
2 : ldr t m p1 , . s a v e d _ m c k r
2011-11-25 09:59:46 +08:00
str t m p1 , [ p m c , #A T 91 _ P M C _ M C K R ]
2008-09-21 21:35:18 +01:00
wait_ m c k r d y
2012-02-22 17:50:55 +01:00
/ *
* at9 1 r m 9 2 0 0 M e m o r y c o n t r o l l e r
* Do n o t h i n g - s e l f - r e f r e s h i s a u t o m a t i c a l l y d i s a b l e d .
* /
cmp m e m c t r l , #A T 91 _ M E M C T R L _ M C
beq r a m _ r e s t o r e d
/ *
* DDRSDR M e m o r y c o n t r o l l e r
* /
cmp m e m c t r l , #A T 91 _ M E M C T R L _ D D R S D R
bne s d r _ e n _ r e s t o r e
2010-06-21 14:59:27 +01:00
/* Restore LPR on AT91 with DDRAM */
2012-02-22 17:50:53 +01:00
ldr t m p1 , . s a v e d _ s a m 9 _ l p r
str t m p1 , [ s d r a m c , #A T 91 _ D D R S D R C _ L P R ]
2010-06-21 14:59:27 +01:00
/* if we use the second ram controller */
2012-02-22 17:50:53 +01:00
cmp r a m c1 , #0
ldrne t m p2 , . s a v e d _ s a m 9 _ l p r1
strne t m p2 , [ r a m c1 , #A T 91 _ D D R S D R C _ L P R ]
2010-06-21 14:59:27 +01:00
2012-02-22 17:50:55 +01:00
b r a m _ r e s t o r e d
/ *
* SDRAMC M e m o r y c o n t r o l l e r
* /
sdr_en_restore :
2010-06-21 14:59:27 +01:00
/* Restore LPR on AT91 with SDRAM */
2012-02-22 17:50:53 +01:00
ldr t m p1 , . s a v e d _ s a m 9 _ l p r
str t m p1 , [ s d r a m c , #A T 91 _ S D R A M C _ L P R ]
2008-09-21 21:35:18 +01:00
2012-02-22 17:50:55 +01:00
ram_restored :
2008-09-21 21:35:18 +01:00
/* Restore registers, and return */
2012-02-22 17:50:55 +01:00
ldmfd s p ! , { r4 - r12 , p c }
2008-09-21 21:35:18 +01:00
.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
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