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 >
2013-10-11 09:37:45 +02:00
# include < l i n u x / c l k / a t 9 1 _ p m c . h >
2015-03-09 11:49:46 +08:00
# include " p m . h "
2017-01-31 18:12:57 +01:00
# include " g e n e r a t e d / a t 9 1 _ p m _ d a t a - o f f s e t s . h "
2008-09-21 21:35:18 +01:00
2015-03-09 11:48:26 +08:00
# define S R A M C _ S E L F _ F R E S H _ A C T I V E 0 x01
# define S R A M C _ S E L F _ F R E S H _ E X I T 0 x00
2012-02-22 17:50:54 +01:00
pmc . r e q r0
2012-02-22 17:50:55 +01:00
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
2015-02-05 14:00:37 +08:00
1 : 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
.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
2015-02-05 14:00:37 +08:00
1 : 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
.endm
/ *
* Wait u n t i l P L L A h a s l o c k e d .
* /
.macro wait_pllalock
2015-02-05 14:00:37 +08:00
1 : 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
.endm
2015-03-09 11:53:46 +08:00
/ *
* Put t h e p r o c e s s o r t o e n t e r t h e i d l e s t a t e
* /
.macro at91_cpu_idle
# if d e f i n e d ( C O N F I G _ C P U _ V 7 )
mov t m p1 , #A T 91 _ P M C _ P C K
str t m p1 , [ p m c , #A T 91 _ P M C _ S C D R ]
dsb
wfi @ Wait For Interrupt
# else
mcr p15 , 0 , t m p1 , c7 , c0 , 4
# endif
.endm
2008-09-21 21:35:18 +01:00
.text
2015-03-11 10:08:12 +08:00
.arm
2015-03-09 11:51:09 +08:00
/ *
2017-01-31 18:12:57 +01:00
* void a t 9 1 _ s u s p e n d _ s r a m _ f n ( s t r u c t a t 9 1 _ p m _ d a t a * )
2015-03-09 11:51:09 +08:00
* @input param:
2017-01-31 18:12:57 +01:00
* @r0: base address of struct at91_pm_data
2012-02-22 17:50:55 +01:00
* /
2015-10-16 12:39:05 +02:00
/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
.align 3
2015-03-09 11:51:09 +08:00
ENTRY( a t 9 1 _ p m _ s u s p e n d _ i n _ s r a m )
2008-09-21 21:35:18 +01:00
/* 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
/* 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
2017-01-31 18:12:57 +01:00
ldr t m p1 , [ r0 , #P M _ D A T A _ P M C ]
str t m p1 , . p m c _ b a s e
ldr t m p1 , [ r0 , #P M _ D A T A _ R A M C 0 ]
str t m p1 , . s r a m c _ b a s e
ldr t m p1 , [ r0 , #P M _ D A T A _ R A M C 1 ]
str t m p1 , . s r a m c1 _ b a s e
ldr t m p1 , [ r0 , #P M _ D A T A _ M E M C T R L ]
str t m p1 , . m e m t y p e
ldr t m p1 , [ r0 , #P M _ D A T A _ M O D E ]
str t m p1 , . p m _ m o d e
2012-02-22 17:50:55 +01:00
2015-03-09 11:48:26 +08:00
/* Active the self-refresh mode */
mov r0 , #S R A M C _ S E L F _ F R E S H _ A C T I V E
bl a t 9 1 _ s r a m c _ s e l f _ r e f r e s h
2012-02-22 17:50:55 +01:00
2015-03-09 11:49:46 +08:00
ldr r0 , . p m _ m o d e
tst r0 , #A T 91 _ P M _ S L O W _ C L O C K
beq s k i p _ d i s a b l e _ m a i n _ c l o c k
2015-03-09 11:48:26 +08:00
ldr p m c , . p m c _ b a s e
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
/* 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
/* 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
2015-02-12 10:52:13 +08:00
orr t m p1 , t m p1 , #A T 91 _ P M C _ K E Y
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
2015-03-09 11:49:46 +08:00
skip_disable_main_clock :
ldr p m c , . p m c _ b a s e
2008-09-21 21:35:18 +01:00
/* Wait for interrupt */
2015-03-09 11:53:46 +08:00
at9 1 _ c p u _ i d l e
2008-09-21 21:35:18 +01:00
2015-03-09 11:49:46 +08:00
ldr r0 , . p m _ m o d e
tst r0 , #A T 91 _ P M _ S L O W _ C L O C K
beq s k i p _ e n a b l e _ m a i n _ c l o c k
ldr p m c , . p m c _ b a s e
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
2015-02-12 10:52:13 +08:00
orr t m p1 , t m p1 , #A T 91 _ P M C _ K E Y
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 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
/ *
* Restore m a s t e r c l o c k s e t t i n g
* /
2015-03-09 11:48:26 +08:00
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
2015-03-09 11:49:46 +08:00
skip_enable_main_clock :
2015-03-09 11:48:26 +08:00
/* Exit the self-refresh mode */
mov r0 , #S R A M C _ S E L F _ F R E S H _ E X I T
bl a t 9 1 _ s r a m c _ s e l f _ r e f r e s h
/* Restore registers, and return */
ldmfd s p ! , { r4 - r12 , p c }
2015-03-09 11:51:09 +08:00
ENDPROC( a t 9 1 _ p m _ s u s p e n d _ i n _ s r a m )
2015-03-09 11:48:26 +08:00
/ *
* void a t 9 1 _ s r a m c _ s e l f _ r e f r e s h ( u n s i g n e d i n t i s _ a c t i v e )
*
* @input param:
* @r0: 1 - active self-refresh mode
* 0 - exit s e l f - r e f r e s h m o d e
* register u s a g e :
* @r1: memory type
* @r2: base address of the sram controller
* /
ENTRY( a t 9 1 _ s r a m c _ s e l f _ r e f r e s h )
ldr r1 , . m e m t y p e
ldr r2 , . s r a m c _ b a s e
cmp r1 , #A T 91 _ M E M C T R L _ M C
bne d d r c _ s f
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
* /
2015-03-09 11:48:26 +08:00
/ *
* For e x i t i n g t h e s e l f - r e f r e s h m o d e , d o n o t h i n g ,
* automatically e x i t t h e s e l f - r e f r e s h m o d e .
* /
tst r0 , #S R A M C _ S E L F _ F R E S H _ A C T I V E
beq e x i t _ s r a m c _ s f
/* Active SDRAM self-refresh mode */
mov r3 , #1
2015-03-16 15:14:50 +01:00
str r3 , [ r2 , #A T 91 _ M C _ S D R A M C _ S R R ]
2015-03-09 11:48:26 +08:00
b e x i t _ s r a m c _ s f
ddrc_sf :
cmp r1 , #A T 91 _ M E M C T R L _ D D R S D R
bne s d r a m c _ s f
2012-02-22 17:50:55 +01:00
/ *
2015-03-09 11:48:26 +08:00
* DDR M e m o r y c o n t r o l l e r
2012-02-22 17:50:55 +01:00
* /
2015-03-09 11:48:26 +08:00
tst r0 , #S R A M C _ S E L F _ F R E S H _ A C T I V E
beq d d r c _ e x i t _ s f
/* LPDDR1 --> force DDR2 mode during self-refresh */
ldr r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
str r3 , . s a v e d _ s a m 9 _ m d r
bic r3 , r3 , #~ A T 91 _ D D R S D R C _ M D
cmp r3 , #A T 91 _ D D R S D R C _ M D _ L O W _ P O W E R _ D D R
ldreq r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
biceq r3 , r3 , #A T 91 _ D D R S D R C _ M D
orreq r3 , r3 , #A T 91 _ D D R S D R C _ M D _ D D R 2
streq r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
/* Active DDRC 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 , r3 , #A T 91 _ D D R S D R C _ L P C B
orr r3 , 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
str r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
/* If using the 2nd ddr controller */
ldr r2 , . s r a m c1 _ b a s e
cmp r2 , #0
beq n o _ 2 n d _ d d r c
ldr r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
str r3 , . s a v e d _ s a m 9 _ m d r1
bic r3 , r3 , #~ A T 91 _ D D R S D R C _ M D
cmp r3 , #A T 91 _ D D R S D R C _ M D _ L O W _ P O W E R _ D D R
ldreq r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
biceq r3 , r3 , #A T 91 _ D D R S D R C _ M D
orreq r3 , r3 , #A T 91 _ D D R S D R C _ M D _ D D R 2
streq r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
/* Active DDRC 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 r1
bic r3 , r3 , #A T 91 _ D D R S D R C _ L P C B
orr r3 , 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
str r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
no_2nd_ddrc :
b e x i t _ s r a m c _ s f
ddrc_exit_sf :
2015-02-05 14:02:09 +08:00
/* Restore MDR in case of LPDDR1 */
2015-03-09 11:48:26 +08:00
ldr r3 , . s a v e d _ s a m 9 _ m d r
str r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
2010-06-21 14:59:27 +01:00
/* Restore LPR on AT91 with DDRAM */
2015-03-09 11:48:26 +08:00
ldr r3 , . s a v e d _ s a m 9 _ l p r
str r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
2010-06-21 14:59:27 +01:00
2015-03-09 11:48:26 +08:00
/* If using the 2nd ddr controller */
ldr r2 , . s r a m c1 _ b a s e
cmp r2 , #0
ldrne r3 , . s a v e d _ s a m 9 _ m d r1
strne r3 , [ r2 , #A T 91 _ D D R S D R C _ M D R ]
ldrne r3 , . s a v e d _ s a m 9 _ l p r1
strne r3 , [ r2 , #A T 91 _ D D R S D R C _ L P R ]
2010-06-21 14:59:27 +01:00
2015-03-09 11:48:26 +08:00
b e x i t _ s r a m c _ s f
2012-02-22 17:50:55 +01:00
/ *
* SDRAMC M e m o r y c o n t r o l l e r
* /
2015-03-09 11:48:26 +08:00
sdramc_sf :
tst r0 , #S R A M C _ S E L F _ F R E S H _ A C T I V E
beq s d r a m c _ e x i t _ s f
/* Active SDRAMC self-refresh mode */
ldr r3 , [ r2 , #A T 91 _ S D R A M C _ L P R ]
str r3 , . s a v e d _ s a m 9 _ l p r
bic r3 , r3 , #A T 91 _ S D R A M C _ L P C B
orr r3 , 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 ]
sdramc_exit_sf :
ldr r3 , . s a v e d _ s a m 9 _ l p r
str r3 , [ r2 , #A T 91 _ S D R A M C _ L P R ]
exit_sramc_sf :
mov p c , l r
ENDPROC( a t 9 1 _ s r a m c _ s e l f _ r e f r e s h )
.pmc_base :
.word 0
.sramc_base :
.word 0
.sramc1_base :
.word 0
.memtype :
.word 0
2015-03-09 11:49:46 +08:00
.pm_mode :
.word 0
2008-09-21 21:35:18 +01:00
.saved_mckr :
.word 0
.saved_pllar :
.word 0
.saved_sam9_lpr :
.word 0
2010-06-21 14:59:27 +01:00
.saved_sam9_lpr1 :
.word 0
2015-02-05 14:02:09 +08:00
.saved_sam9_mdr :
.word 0
.saved_sam9_mdr1 :
.word 0
2015-03-09 11:51:09 +08:00
ENTRY( a t 9 1 _ p m _ s u s p e n d _ i n _ s r a m _ s z )
.word . - at9 1 _ p m _ s u s p e n d _ i n _ s r a m