2008-02-24 23:24:26 +01:00
/ *
* Low- l e v e l P o w e r M a n a g e m e n t c o d e .
*
* Copyright ( C ) 2 0 0 8 A t m e l C o r p o r a t i o n
*
* 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 < a s m / a s m . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / t h r e a d _ i n f o . h >
2008-08-05 13:57:38 +02:00
# include < m a c h / p m . h >
2008-02-24 23:24:26 +01:00
2008-02-24 13:51:38 +01:00
# include " p m . h "
# include " s d r a m c . h "
/* Same as 0xfff00000 but fits in a 21 bit signed immediate */
# define P M _ B A S E - 0 x10 0 0 0 0
2008-02-24 23:24:26 +01:00
/* Keep this close to the irq handlers */
.section .irq .text , " ax" , @progbits
/ *
* void c p u _ e n t e r _ i d l e ( v o i d )
*
* Put t h e C P U i n t o " i d l e " m o d e , i n w h i c h i t w i l l c o n s u m e
* significantly l e s s p o w e r .
*
* If a n i n t e r r u p t c o m e s a l o n g i n t h e w i n d o w b e t w e e n
* unmask_ i n t e r r u p t s a n d t h e s l e e p i n s t r u c t i o n b e l o w , t h e
* interrupt c o d e w i l l a d j u s t t h e r e t u r n a d d r e s s s o t h a t w e
* never e x e c u t e t h e s l e e p i n s t r u c t i o n . T h i s i s r e q u i r e d
* because t h e A P 7 0 0 0 d o e s n ' t u n m a s k i n t e r r u p t s w h e n e n t e r i n g
* sleep m o d e s ; later CPUs may not need this workaround.
* /
.global cpu_enter_idle
.type cpu_ e n t e r _ i d l e , @function
cpu_enter_idle :
mask_ i n t e r r u p t s
get_ t h r e a d _ i n f o r8
ld. w r9 , r8 [ T I _ f l a g s ]
bld r9 , T I F _ N E E D _ R E S C H E D
brcs . L r e t _ f r o m _ s l e e p
sbr r9 , T I F _ C P U _ G O I N G _ T O _ S L E E P
st. w r8 [ T I _ f l a g s ] , r9
unmask_ i n t e r r u p t s
sleep C P U _ S L E E P _ I D L E
2011-03-09 00:32:36 +00:00
.size cpu_ e n t e r _ i d l e , . - c p u _ e n t e r _ i d l e
2008-02-24 23:24:26 +01:00
/ *
* Common r e t u r n p a t h f o r P M f u n c t i o n s t h a t d o n ' t r u n f r o m
* SRAM.
* /
.global cpu_idle_skip_sleep
.type cpu_ i d l e _ s k i p _ s l e e p , @function
cpu_idle_skip_sleep :
mask_ i n t e r r u p t s
ld. w r9 , r8 [ T I _ f l a g s ]
cbr r9 , T I F _ C P U _ G O I N G _ T O _ S L E E P
st. w r8 [ T I _ f l a g s ] , r9
.Lret_from_sleep :
unmask_ i n t e r r u p t s
retal r12
.size cpu_ i d l e _ s k i p _ s l e e p , . - c p u _ i d l e _ s k i p _ s l e e p
2008-02-24 13:51:38 +01:00
# ifdef C O N F I G _ P M
.section .init .text , " ax" , @progbits
.global pm_exception
.type pm_ e x c e p t i o n , @function
pm_exception :
/ *
* Exceptions a r e m a s k e d w h e n w e s w i t c h t o t h i s h a n d l e r , s o
* we' l l o n l y g e t " u n r e c o v e r a b l e " e x c e p t i o n s ( o f f s e t 0 . )
* /
sub r12 , p c , . - . L p a n i c _ m s g
lddpc p c , . L p a n i c _ a d d r
.align 2
.Lpanic_addr :
.long panic
.Lpanic_msg :
.asciz " Unrecoverable e x c e p t i o n d u r i n g s u s p e n d \ n "
.size pm_ e x c e p t i o n , . - p m _ e x c e p t i o n
.global pm_irq0
.type pm_ i r q0 , @function
pm_irq0 :
/* Disable interrupts and return after the sleep instruction */
mfsr r9 , S Y S R E G _ R S R _ I N T 0
mtsr S Y S R E G _ R A R _ I N T 0 , r8
sbr r9 , S Y S R E G _ G M _ O F F S E T
mtsr S Y S R E G _ R S R _ I N T 0 , r9
rete
/ *
* void c p u _ e n t e r _ s t a n d b y ( u n s i g n e d l o n g s d r a m c _ b a s e )
*
* Enter P M _ S U S P E N D _ S T A N D B Y m o d e . A t t h i s p o i n t , a l l d r i v e r s
* are s u s p e n d e d a n d i n t e r r u p t s a r e d i s a b l e d . I n t e r r u p t s
* marked a s ' w a k e u p ' e v e n t s o u r c e s m a y s t i l l c o m e a l o n g a n d
* get u s o u t o f h e r e .
*
* The S D R A M w i l l b e p u t i n t o s e l f - r e f r e s h m o d e ( w h i c h d o e s
* not r e q u i r e a c l o c k f r o m t h e C P U ) , a n d t h e C P U w i l l b e p u t
* into " f r o z e n " m o d e ( H S B b u s s t o p p e d ) . T h e S D R A M c o n t r o l l e r
* will a u t o m a t i c a l l y b r i n g t h e S D R A M i n t o n o r m a l m o d e o n t h e
* first a c c e s s , a n d t h e p o w e r m a n a g e r w i l l a u t o m a t i c a l l y
* start t h e H S B a n d C P U c l o c k s u p o n a w a k e u p e v e n t .
*
* This c o d e u s e s t h e s a m e " s k i p s l e e p " t e c h n i q u e a s a b o v e .
* It i s v e r y i m p o r t a n t t h a t w e j u m p d i r e c t l y t o
* cpu_ a f t e r _ s l e e p a f t e r t h e s l e e p i n s t r u c t i o n s i n c e t h a t ' s
* where w e ' l l e n d u p i f t h e i n t e r r u p t h a n d l e r d e c i d e s t h a t w e
* need t o s k i p t h e s l e e p i n s t r u c t i o n .
* /
.global pm_standby
.type pm_ s t a n d b y , @function
pm_standby :
/ *
* interrupts a r e a l r e a d y m a s k e d a t t h i s p o i n t , a n d E V B A
* points t o p m _ e x c e p t i o n a b o v e .
* /
ld. w r10 , r12 [ S D R A M C _ L P R ]
sub r8 , p c , . - 1 f / * r e t u r n a d d r e s s f o r i r q h a n d l e r * /
mov r11 , S D R A M C _ L P R _ L P C B _ S E L F _ R F R
bfins r10 , r11 , 0 , 2 / * L P C B < - s e l f R e f r e s h * /
sync 0 / * f l u s h w r i t e b u f f e r * /
2008-08-29 16:27:00 +01:00
st. w r12 [ S D R A M C _ L P R ] , r10 / * p u t S D R A M i n s e l f - r e f r e s h m o d e * /
2008-02-24 13:51:38 +01:00
ld. w r11 , r12 [ S D R A M C _ L P R ]
unmask_ i n t e r r u p t s
sleep C P U _ S L E E P _ F R O Z E N
1 : mask_ i n t e r r u p t s
retal r12
.size pm_ s t a n d b y , . - p m _ s t a n d b y
.global pm_suspend_to_ram
.type pm_ s u s p e n d _ t o _ r a m , @function
pm_suspend_to_ram :
/ *
* interrupts a r e a l r e a d y m a s k e d a t t h i s p o i n t , a n d E V B A
* points t o p m _ e x c e p t i o n a b o v e .
* /
mov r11 , 0
cache r11 [ 2 ] , 8 / * c l e a n a l l d c a c h e l i n e s * /
sync 0 / * f l u s h w r i t e b u f f e r * /
ld. w r10 , r12 [ S D R A M C _ L P R ]
sub r8 , p c , . - 1 f / * r e t u r n a d d r e s s f o r i r q h a n d l e r * /
mov r11 , S D R A M C _ L P R _ L P C B _ S E L F _ R F R
bfins r10 , r11 , 0 , 2 / * L P C B < - s e l f r e f r e s h * /
st. w r12 [ S D R A M C _ L P R ] , r10 / * p u t S D R A M i n s e l f - r e f r e s h m o d e * /
ld. w r11 , r12 [ S D R A M C _ L P R ]
unmask_ i n t e r r u p t s
sleep C P U _ S L E E P _ S T O P
1 : mask_ i n t e r r u p t s
retal r12
.size pm_ s u s p e n d _ t o _ r a m , . - p m _ s u s p e n d _ t o _ r a m
.global pm_sram_end
.type pm_ s r a m _ e n d , @function
pm_sram_end :
.size pm_ s r a m _ e n d , 0
# endif / * C O N F I G _ P M * /