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
# 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
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:53 +01:00
tmp1 . r e q r3
tmp2 . r e q r4
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
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
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
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
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
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
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
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ P M C _ S R - A T 9 1 _ P M C ) ]
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:54 +01:00
/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc, void __iomem *ramc1) */
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:54 +01:00
stmfd s p ! , { r3 - 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
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
* /
/* 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
# 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 */
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-01-26 14:07:09 +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 )
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 ]
2008-09-21 21:35:18 +01:00
# else
/* 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
# endif
/* Save Master clock setting */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
2008-09-21 21:35:18 +01:00
wait_ m c k r d y
# endif
/* Save PLLA setting and disable it */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ C K G R _ P L L A R - A T 9 1 _ P M C ) ]
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 * /
str t m p1 , [ p m c , #( A T 91 _ C K G R _ P L L A R - A T 9 1 _ P M C ) ]
2008-09-21 21:35:18 +01:00
/* Save PLLB setting and disable it */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ C K G R _ P L L B R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ C K G R _ P L L B R - A T 9 1 _ P M C ) ]
2008-09-21 21:35:18 +01:00
/* Turn off the main oscillator */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
bic t m p1 , t m p1 , #A T 91 _ P M C _ M O S C E N
str t m p1 , [ p m c , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
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 */
2012-02-22 17:50:53 +01:00
ldr t m p1 , [ p m c , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
orr t m p1 , t m p1 , #A T 91 _ P M C _ M O S C E N
str t m p1 , [ p m c , #( A T 91 _ C K G R _ M O R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ C K G R _ P L L B R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ C K G R _ P L L A R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
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
str t m p1 , [ p m c , #( A T 91 _ P M C _ M C K R - A T 9 1 _ P M C ) ]
2008-09-21 21:35:18 +01:00
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. */
2012-01-26 14:07:09 +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 )
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
2008-09-21 21:35:18 +01:00
# else
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
# endif
/* Restore registers, and return */
2012-02-22 17:50:54 +01:00
ldmfd s p ! , { r3 - 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