2005-09-26 10:04:21 +04:00
/ *
* This f i l e c o n t a i n s t h e p o w e r _ s a v e f u n c t i o n f o r 6 x x & 7 x x x C P U s
* rewritten i n a s s e m b l e r
*
* Warning ! T h i s c o d e a s s u m e s t h a t i f y o u r m a c h i n e h a s a 7 5 0 f x
* it w i l l h a v e P L L 1 s e t t o l o w s p e e d m o d e ( u s e d d u r i n g N A P / D O Z E ) .
* if t h i s i s n o t t h e c a s e s o m e a d d i t i o n a l c h a n g e s w i l l h a v e t o
* be d o n e t o c h e c k a r u n t i m e v a r ( a b i t l i k e p o w e r s a v e - n a p )
*
* 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 i t 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
* as p u b l i s h e d 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 ; either version
* 2 of t h e L i c e n s e , o r ( a t y o u r o p t i o n ) a n y l a t e r v e r s i o n .
* /
# include < l i n u x / c o n f i g . h >
# include < l i n u x / t h r e a d s . h >
2005-10-10 16:20:10 +04:00
# include < a s m / r e g . h >
2005-09-26 10:04:21 +04:00
# include < a s m / p a g e . h >
# include < a s m / c p u t a b l e . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / p p c _ a s m . h >
# include < a s m / a s m - o f f s e t s . h >
# undef D E B U G
.text
/ *
* Init i d l e , c a l l e d a t e a r l y C P U s e t u p t i m e f r o m h e a d . S f o r e a c h C P U
* Make s u r e n o r e s t o f N A P m o d e r e m a i n s i n H I D 0 , s a v e d e f a u l t
* values f o r s o m e C P U s p e c i f i c r e g i s t e r s . C a l l e d w i t h r24
* containing C P U n u m b e r a n d r3 r e l o c o f f s e t
* /
_ GLOBAL( i n i t _ i d l e _ 6 x x )
BEGIN_ F T R _ S E C T I O N
mfspr r4 ,S P R N _ H I D 0
rlwinm r4 ,r4 ,0 ,1 0 ,8 / * C l e a r N A P * /
mtspr S P R N _ H I D 0 , r4
b 1 f
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ C A N _ N A P )
blr
1 :
slwi r5 ,r24 ,2
add r5 ,r5 ,r3
BEGIN_ F T R _ S E C T I O N
mfspr r4 ,S P R N _ M S S C R 0
addis r6 ,r5 , n a p _ s a v e _ m s s c r0 @ha
stw r4 ,n a p _ s a v e _ m s s c r0 @l(r6)
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ N A P _ D I S A B L E _ L 2 _ P R )
BEGIN_ F T R _ S E C T I O N
mfspr r4 ,S P R N _ H I D 1
addis r6 ,r5 ,n a p _ s a v e _ h i d1 @ha
stw r4 ,n a p _ s a v e _ h i d1 @l(r6)
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ D U A L _ P L L _ 7 5 0 F X )
blr
/ *
* Here i s t h e p o w e r _ s a v e _ 6 x x f u n c t i o n . T h i s c o u l d e v e n t u a l l y b e
* split i n t o s e v e r a l f u n c t i o n s & c h a n g i n g t h e f u n c t i o n p o i n t e r
* depending o n t h e v a r i o u s f e a t u r e s .
* /
_ GLOBAL( p p c6 x x _ i d l e )
/ * Check i f w e c a n n a p o r d o z e , p u t H I D 0 m a s k i n r3
* /
lis r3 , 0
BEGIN_ F T R _ S E C T I O N
lis r3 ,H I D 0 _ D O Z E @h
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ C A N _ D O Z E )
BEGIN_ F T R _ S E C T I O N
/ * We m u s t d y n a m i c a l l y c h e c k f o r t h e N A P f e a t u r e a s i t
* can b e c l e a r e d b y C P U i n i t a f t e r t h e f i x u p s a r e d o n e
* /
lis r4 ,c u r _ c p u _ s p e c @ha
lwz r4 ,c u r _ c p u _ s p e c @l(r4)
lwz r4 ,C P U _ S P E C _ F E A T U R E S ( r4 )
andi. r0 ,r4 ,C P U _ F T R _ C A N _ N A P
beq 1 f
/* Now check if user or arch enabled NAP mode */
lis r4 ,p o w e r s a v e _ n a p @ha
lwz r4 ,p o w e r s a v e _ n a p @l(r4)
cmpwi 0 ,r4 ,0
beq 1 f
lis r3 ,H I D 0 _ N A P @h
1 :
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ C A N _ N A P )
cmpwi 0 ,r3 ,0
beqlr
/* Clear MSR:EE */
mfmsr r7
rlwinm r0 ,r7 ,0 ,1 7 ,1 5
mtmsr r0
/* Check current_thread_info()->flags */
rlwinm r4 ,r1 ,0 ,0 ,1 8
lwz r4 ,T I _ F L A G S ( r4 )
andi. r0 ,r4 ,_ T I F _ N E E D _ R E S C H E D
beq 1 f
mtmsr r7 / * o u t o f l i n e t h i s ? * /
blr
1 :
/* Some pre-nap cleanups needed on some CPUs */
andis. r0 ,r3 ,H I D 0 _ N A P @h
beq 2 f
BEGIN_ F T R _ S E C T I O N
/ * Disable L 2 p r e f e t c h o n s o m e 7 4 5 x a n d t r y t o e n s u r e
* L2 p r e f e t c h e n g i n e s a r e i d l e . A s e x p l a i n e d b y e r r a t a
* text, w e c a n ' t b e s u r e t h e y a r e , w e j u s t h o p e v e r y h a r d
* that w e l l b e e n o u g h ( s i c ! ) . A t l e a s t I n o t i c e d A p p l e
* doesn' t e v e n b o t h e r d o i n g t h e d c b f ' s h e r e . . .
* /
mfspr r4 ,S P R N _ M S S C R 0
rlwinm r4 ,r4 ,0 ,0 ,2 9
sync
mtspr S P R N _ M S S C R 0 ,r4
sync
isync
lis r4 ,K E R N E L B A S E @h
dcbf 0 ,r4
dcbf 0 ,r4
dcbf 0 ,r4
dcbf 0 ,r4
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ N A P _ D I S A B L E _ L 2 _ P R )
# ifdef D E B U G
lis r6 ,n a p _ e n t e r _ c o u n t @ha
lwz r4 ,n a p _ e n t e r _ c o u n t @l(r6)
addi r4 ,r4 ,1
stw r4 ,n a p _ e n t e r _ c o u n t @l(r6)
# endif
2 :
BEGIN_ F T R _ S E C T I O N
/* Go to low speed mode on some 750FX */
lis r4 ,p o w e r s a v e _ l o w s p e e d @ha
lwz r4 ,p o w e r s a v e _ l o w s p e e d @l(r4)
cmpwi 0 ,r4 ,0
beq 1 f
mfspr r4 ,S P R N _ H I D 1
oris r4 ,r4 ,0 x00 0 1
mtspr S P R N _ H I D 1 ,r4
1 :
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ D U A L _ P L L _ 7 5 0 F X )
/* Go to NAP or DOZE now */
mfspr r4 ,S P R N _ H I D 0
lis r5 ,( H I D 0 _ N A P | H I D 0 _ S L E E P ) @h
BEGIN_ F T R _ S E C T I O N
oris r5 ,r5 ,H I D 0 _ D O Z E @h
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ C A N _ D O Z E )
andc r4 ,r4 ,r5
or r4 ,r4 ,r3
BEGIN_ F T R _ S E C T I O N
oris r4 ,r4 ,H I D 0 _ D P M @h /* that should be done once for all */
END_ F T R _ S E C T I O N _ I F C L R ( C P U _ F T R _ N O _ D P M )
mtspr S P R N _ H I D 0 ,r4
BEGIN_ F T R _ S E C T I O N
DSSALL
sync
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ A L T I V E C )
ori r7 ,r7 ,M S R _ E E / * C o u l d b e o m m i t e d ( a l r e a d y s e t ) * /
oris r7 ,r7 ,M S R _ P O W @h
sync
isync
mtmsr r7
isync
sync
blr
/ *
* Return f r o m N A P / D O Z E m o d e , r e s t o r e s o m e C P U s p e c i f i c r e g i s t e r s ,
* we a r e c a l l e d w i t h D R / I R s t i l l o f f a n d r2 c o n t a i n i n g p h y s i c a l
* address o f c u r r e n t .
* /
_ GLOBAL( p o w e r _ s a v e _ 6 x x _ r e s t o r e )
mfspr r11 ,S P R N _ H I D 0
rlwinm. r11 ,r11 ,0 ,1 0 ,8 / * C l e a r N A P & c o p y N A P b i t ! s t a t e t o c r1 E Q * /
cror 4 * c r1 + e q ,4 * c r0 + e q ,4 * c r0 + e q
BEGIN_ F T R _ S E C T I O N
rlwinm r11 ,r11 ,0 ,9 ,7 / * C l e a r D O Z E * /
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ C A N _ D O Z E )
mtspr S P R N _ H I D 0 , r11
# ifdef D E B U G
beq c r1 ,1 f
lis r11 ,( n a p _ r e t u r n _ c o u n t - K E R N E L B A S E ) @ha
lwz r9 ,n a p _ r e t u r n _ c o u n t @l(r11)
addi r9 ,r9 ,1
stw r9 ,n a p _ r e t u r n _ c o u n t @l(r11)
1 :
# endif
rlwinm r9 ,r1 ,0 ,0 ,1 8
tophys( r9 ,r9 )
lwz r11 ,T I _ C P U ( r9 )
slwi r11 ,r11 ,2
/ * Todo m a k e s u r e a l l t h e s e a r e i n t h e s a m e p a g e
* and l o a d r22 ( @ha part + CPU offset) only once
* /
BEGIN_ F T R _ S E C T I O N
beq c r1 ,1 f
addis r9 ,r11 ,( n a p _ s a v e _ m s s c r0 - K E R N E L B A S E ) @ha
lwz r9 ,n a p _ s a v e _ m s s c r0 @l(r9)
mtspr S P R N _ M S S C R 0 , r9
sync
isync
1 :
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ N A P _ D I S A B L E _ L 2 _ P R )
BEGIN_ F T R _ S E C T I O N
addis r9 ,r11 ,( n a p _ s a v e _ h i d1 - K E R N E L B A S E ) @ha
lwz r9 ,n a p _ s a v e _ h i d1 @l(r9)
mtspr S P R N _ H I D 1 , r9
END_ F T R _ S E C T I O N _ I F S E T ( C P U _ F T R _ D U A L _ P L L _ 7 5 0 F X )
b t r a n s f e r _ t o _ h a n d l e r _ c o n t
.data
_ GLOBAL( n a p _ s a v e _ m s s c r0 )
.space 4 * NR_ C P U S
_ GLOBAL( n a p _ s a v e _ h i d1 )
.space 4 * NR_ C P U S
_ GLOBAL( p o w e r s a v e _ n a p )
.long 0
_ GLOBAL( p o w e r s a v e _ l o w s p e e d )
.long 0
# ifdef D E B U G
_ GLOBAL( n a p _ e n t e r _ c o u n t )
.space 4
_ GLOBAL( n a p _ r e t u r n _ c o u n t )
.space 4
# endif