2010-10-27 17:28:45 +01:00
/ * MN1 0 3 0 0 C P U c a c h e i n v a l i d a t i o n r o u t i n e s , u s i n g a u t o m a t i c p u r g e r e g i s t e r s
*
* Copyright ( C ) 2 0 0 7 R e d H a t , I n c . A l l R i g h t s R e s e r v e d .
* Written b y D a v i d H o w e l l s ( d h o w e l l s @redhat.com)
*
* 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 c 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 c 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 / s y s . h >
# include < l i n u x / l i n k a g e . h >
# include < a s m / s m p . h >
# include < a s m / p a g e . h >
# include < a s m / c a c h e . h >
# include < a s m / i r q f l a g s . h >
# include < a s m / c a c h e f l u s h . h >
MN10300: The icache invalidate functions should disable the icache first
The icache invalidate functions should disable the icache on AM33 and wait for
it to quiesce before attempting to invalidate it, and should then wait for it
to quiesce again before reenabling it, but on AM34 they should invalidate
directly. The same goes for the dcache invalidation, but this isn't used much.
Whilst we're at it, this can be wrapped in assembler macros to remove duplicate
code.
The AM33 manual states that:
An operation that invalidates the cache, switches the writing mode, or
changes the way mode must be performed after disabling the cache,
checking the busy bit, and confirming that the cache is not in
operation.
for the dcache [sec 2.8.3.2.1]. This is not stated so for the icache [sec
2.8.3.1.1] but the example code there suggests that it is.
Whilst the AM34 manual states that the cache must be disabled for both the
icache [sec 1.8.3.2.1] and the dcache [sec 1.8.3.2.1], the Panasonic hardware
engineers say the manual is wrong and that disabling the caches for
invalidation is wrong.
Furthermore, they say that disabling the caches on the AM34 whilst running an
SMP kernel can lead to incoherency between the various CPU caches and should
thus be avoided.
Signed-off-by: David Howells <dhowells@redhat.com>
2011-03-18 16:54:29 +00:00
# include " c a c h e . i n c "
2010-10-27 17:28:45 +01:00
# define m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e _ i n t r _ i n t e r v a l \
+ ( ( 1 < < MN1 0 3 0 0 _ D C A C H E _ I N V _ R A N G E _ I N T R _ L O G 2 _ I N T E R V A L ) - 1 )
# if m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e _ i n t r _ i n t e r v a l > 0 x f f
# error M N 1 0 3 0 0 _ D C A C H E _ I N V _ R A N G E _ I N T R _ L O G 2 _ I N T E R V A L m u s t b e 8 o r l e s s
# endif
.am33_2
# ifndef C O N F I G _ S M P
.globl mn10300_icache_inv
.globl mn10300_icache_inv_page
.globl mn10300_icache_inv_range
.globl mn10300_icache_inv_range2
.globl mn10300_dcache_inv
.globl mn10300_dcache_inv_page
.globl mn10300_dcache_inv_range
.globl mn10300_dcache_inv_range2
mn1 0 3 0 0 _ i c a c h e _ i n v = m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v
mn1 0 3 0 0 _ i c a c h e _ i n v _ p a g e = m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ p a g e
mn1 0 3 0 0 _ i c a c h e _ i n v _ r a n g e = m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e
mn1 0 3 0 0 _ i c a c h e _ i n v _ r a n g e 2 = m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e 2
mn1 0 3 0 0 _ d c a c h e _ i n v = m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v
mn1 0 3 0 0 _ d c a c h e _ i n v _ p a g e = m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ p a g e
mn1 0 3 0 0 _ d c a c h e _ i n v _ r a n g e = m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e
mn1 0 3 0 0 _ d c a c h e _ i n v _ r a n g e 2 = m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e 2
# endif / * ! C O N F I G _ S M P * /
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# void m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v ( v o i d )
# Invalidate t h e e n t i r e i c a c h e
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
ALIGN
.globl mn10300_local_icache_inv
.type mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v ,@function
mn10300_local_icache_inv :
mov C H C T R ,a0
movhu ( a0 ) ,d0
btst C H C T R _ I C E N ,d0
beq m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ e n d
MN10300: The icache invalidate functions should disable the icache first
The icache invalidate functions should disable the icache on AM33 and wait for
it to quiesce before attempting to invalidate it, and should then wait for it
to quiesce again before reenabling it, but on AM34 they should invalidate
directly. The same goes for the dcache invalidation, but this isn't used much.
Whilst we're at it, this can be wrapped in assembler macros to remove duplicate
code.
The AM33 manual states that:
An operation that invalidates the cache, switches the writing mode, or
changes the way mode must be performed after disabling the cache,
checking the busy bit, and confirming that the cache is not in
operation.
for the dcache [sec 2.8.3.2.1]. This is not stated so for the icache [sec
2.8.3.1.1] but the example code there suggests that it is.
Whilst the AM34 manual states that the cache must be disabled for both the
icache [sec 1.8.3.2.1] and the dcache [sec 1.8.3.2.1], the Panasonic hardware
engineers say the manual is wrong and that disabling the caches for
invalidation is wrong.
Furthermore, they say that disabling the caches on the AM34 whilst running an
SMP kernel can lead to incoherency between the various CPU caches and should
thus be avoided.
Signed-off-by: David Howells <dhowells@redhat.com>
2011-03-18 16:54:29 +00:00
invalidate_ i c a c h e 1
2010-10-27 17:28:45 +01:00
mn10300_local_icache_inv_end :
ret [ ] ,0
.size mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v ,. - m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# void m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v ( v o i d )
# Invalidate t h e e n t i r e d c a c h e
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
ALIGN
.globl mn10300_local_dcache_inv
.type mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v ,@function
mn10300_local_dcache_inv :
mov C H C T R ,a0
movhu ( a0 ) ,d0
btst C H C T R _ D C E N ,d0
beq m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ e n d
MN10300: The icache invalidate functions should disable the icache first
The icache invalidate functions should disable the icache on AM33 and wait for
it to quiesce before attempting to invalidate it, and should then wait for it
to quiesce again before reenabling it, but on AM34 they should invalidate
directly. The same goes for the dcache invalidation, but this isn't used much.
Whilst we're at it, this can be wrapped in assembler macros to remove duplicate
code.
The AM33 manual states that:
An operation that invalidates the cache, switches the writing mode, or
changes the way mode must be performed after disabling the cache,
checking the busy bit, and confirming that the cache is not in
operation.
for the dcache [sec 2.8.3.2.1]. This is not stated so for the icache [sec
2.8.3.1.1] but the example code there suggests that it is.
Whilst the AM34 manual states that the cache must be disabled for both the
icache [sec 1.8.3.2.1] and the dcache [sec 1.8.3.2.1], the Panasonic hardware
engineers say the manual is wrong and that disabling the caches for
invalidation is wrong.
Furthermore, they say that disabling the caches on the AM34 whilst running an
SMP kernel can lead to incoherency between the various CPU caches and should
thus be avoided.
Signed-off-by: David Howells <dhowells@redhat.com>
2011-03-18 16:54:29 +00:00
invalidate_ d c a c h e 1
2010-10-27 17:28:45 +01:00
mn10300_local_dcache_inv_end :
ret [ ] ,0
.size mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v ,. - m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# void m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g e n d )
# void m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e 2 ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g s i z e )
# void m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ p a g e ( u n s i g n e d l o n g s t a r t )
# Invalidate a r a n g e o f a d d r e s s e s o n a p a g e i n t h e d c a c h e
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
ALIGN
.globl mn10300_local_dcache_inv_page
.globl mn10300_local_dcache_inv_range
.globl mn10300_local_dcache_inv_range2
.type mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ p a g e ,@function
.type mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e ,@function
.type mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e 2 ,@function
mn10300_local_dcache_inv_page :
and ~ ( P A G E _ S I Z E - 1 ) ,d0
mov P A G E _ S I Z E ,d1
mn10300_local_dcache_inv_range2 :
add d0 ,d1
mn10300_local_dcache_inv_range :
# If w e a r e i n w r i t e b a c k m o d e w e c h e c k t h e s t a r t a n d e n d a l i g n m e n t s ,
# and i f t h e y ' r e n o t c a c h e l i n e - a l i g n e d , w e m u s t f l u s h a n y b i t s o u t s i d e
# the r a n g e t h a t s h a r e c a c h e l i n e s w i t h s t u f f i n s i d e t h e r a n g e
# ifdef C O N F I G _ M N 1 0 3 0 0 _ C A C H E _ W B A C K
2011-03-18 16:54:30 +00:00
btst ~ L 1 _ C A C H E _ T A G _ M A S K ,d0
2010-10-27 17:28:45 +01:00
bne 1 f
2011-03-18 16:54:30 +00:00
btst ~ L 1 _ C A C H E _ T A G _ M A S K ,d1
2010-10-27 17:28:45 +01:00
beq 2 f
1 :
bra m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ f l u s h _ i n v _ r a n g e
2 :
# endif / * C O N F I G _ M N 1 0 3 0 0 _ C A C H E _ W B A C K * /
movm [ d2 ,d3 ,a2 ] ,( s p )
mov C H C T R ,a0
movhu ( a0 ) ,d2
btst C H C T R _ D C E N ,d2
beq m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e _ e n d
# round t h e a d d r e s s e s o u t t o b e f u l l c a c h e l i n e s , u n l e s s w e ' r e i n
# writeback m o d e , i n w h i c h c a s e w e w o u l d b e i n f l u s h a n d i n v a l i d a t e b y
# now
# ifndef C O N F I G _ M N 1 0 3 0 0 _ C A C H E _ W B A C K
2011-03-18 16:54:30 +00:00
and L 1 _ C A C H E _ T A G _ M A S K ,d0 # r o u n d s t a r t a d d r d o w n
2010-10-27 17:28:45 +01:00
mov L 1 _ C A C H E _ B Y T E S - 1 ,d2
add d2 ,d1
2011-03-18 16:54:30 +00:00
and L 1 _ C A C H E _ T A G _ M A S K ,d1 # r o u n d e n d a d d r u p
2010-10-27 17:28:45 +01:00
# endif / * ! C O N F I G _ M N 1 0 3 0 0 _ C A C H E _ W B A C K * /
sub d0 ,d1 ,d2 # c a l c u l a t e t h e t o t a l s i z e
mov d0 ,a2 # A 2 = s t a r t a d d r e s s
mov d1 ,a1 # A 1 = e n d a d d r e s s
LOCAL_ C L I _ S A V E ( d3 )
mov D C P G C R ,a0 # m a k e s u r e t h e p u r g e r i s n ' t b u s y
setlb
mov ( a0 ) ,d0
btst D C P G C R _ D C P G B S Y ,d0
lne
# skip i n i t i a l a d d r e s s a l i g n m e n t c a l c u l a t i o n i f a d d r e s s i s z e r o
mov d2 ,d1
cmp 0 ,a2
beq 1 f
dcivloop :
/ * calculate a l i g n s i z e
*
* alignsize = L 1 _ C A C H E _ B Y T E S ;
* while ( ! s t a r t & a l i g n s i z e ) {
* alignsize < < =1 ;
* }
* d1 = a l i g n s i z e ;
* /
mov L 1 _ C A C H E _ B Y T E S ,d1
lsr 1 ,d1
setlb
add d1 ,d1
mov d1 ,d0
and a2 ,d0
leq
1 :
/ * calculate i n v s i z e
*
* if ( t o t a l s i z e > a l i g n s i z e ) {
* invsize = a l i g n s i z e ;
* } else {
* invsize = t o t a l s i z e ;
* tmp = 0 x80 0 0 0 0 0 0 ;
* while ( ! i n v s i z e & t m p ) {
* tmp > > = 1 ;
* }
* invsize = t m p ;
* }
* d1 = i n v s i z e
* /
cmp d2 ,d1
bns 2 f
mov d2 ,d1
mov 0 x80 0 0 0 0 0 0 ,d0 # s t a r t f r o m 31 b i t =1
setlb
lsr 1 ,d0
mov d0 ,e 0
and d1 ,e 0
leq
mov d0 ,d1
2 :
/ * set m a s k
*
* mask = ~ ( i n v s i z e - 1 ) ;
* DCPGMR = m a s k ;
* /
mov d1 ,d0
add - 1 ,d0
not d0
mov d0 ,( D C P G M R )
# invalidate a r e a
mov a2 ,d0
or D C P G C R _ D C I ,d0
mov d0 ,( a0 ) # D C P G C R = ( m a s k & s t a r t ) | D C P G C R _ D C I
setlb # w a i t f o r t h e p u r g e t o c o m p l e t e
mov ( a0 ) ,d0
btst D C P G C R _ D C P G B S Y ,d0
lne
sub d1 ,d2 # d e c r e a s e s i z e r e m a i n i n g
add d1 ,a2 # i n c r e a s e n e x t s t a r t a d d r e s s
/ * check i n v a l i d a t i n g o f e n d a d d r e s s
*
* a2 = a2 + i n v s i z e
* if ( a2 < e n d ) {
* goto d c i v l o o p ;
* } * /
cmp a1 ,a2
bns d c i v l o o p
LOCAL_ I R Q _ R E S T O R E ( d3 )
mn10300_local_dcache_inv_range_end :
ret [ d2 ,d3 ,a2 ] ,1 2
.size mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ p a g e ,. - m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ p a g e
.size mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e ,. - m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e
.size mn1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e 2 ,. - m n 1 0 3 0 0 _ l o c a l _ d c a c h e _ i n v _ r a n g e 2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# void m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ p a g e ( u n s i g n e d l o n g s t a r t )
# void m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e 2 ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g s i z e )
# void m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e ( u n s i g n e d l o n g s t a r t , u n s i g n e d l o n g e n d )
# Invalidate a r a n g e o f a d d r e s s e s o n a p a g e i n t h e i c a c h e
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
ALIGN
.globl mn10300_local_icache_inv_page
.globl mn10300_local_icache_inv_range
.globl mn10300_local_icache_inv_range2
.type mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ p a g e ,@function
.type mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e ,@function
.type mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e 2 ,@function
mn10300_local_icache_inv_page :
and ~ ( P A G E _ S I Z E - 1 ) ,d0
mov P A G E _ S I Z E ,d1
mn10300_local_icache_inv_range2 :
add d0 ,d1
mn10300_local_icache_inv_range :
movm [ d2 ,d3 ,a2 ] ,( s p )
mov C H C T R ,a0
movhu ( a0 ) ,d2
btst C H C T R _ I C E N ,d2
beq m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e _ r e g _ e n d
/ * calculate a l i g n s i z e
*
* alignsize = L 1 _ C A C H E _ B Y T E S ;
* for ( i = ( e n d - s t a r t - 1 ) / L 1 _ C A C H E _ B Y T E S ; i > 0; i >>= 1) {
* alignsize < < = 1 ;
* }
* d2 = a l i g n s i z e ;
* /
mov L 1 _ C A C H E _ B Y T E S ,d2
sub d0 ,d1 ,d3
add - 1 ,d3
lsr L 1 _ C A C H E _ S H I F T ,d3
beq 2 f
1 :
add d2 ,d2
lsr 1 ,d3
bne 1 b
2 :
/* a1 = end */
mov d1 ,a1
LOCAL_ C L I _ S A V E ( d3 )
mov I C I V C R ,a0
/* wait for busy bit of area invalidation */
setlb
mov ( a0 ) ,d1
btst I C I V C R _ I C I V B S Y ,d1
lne
/ * set m a s k
*
* mask = ~ ( a l i g n s i z e - 1 ) ;
* ICIVMR = m a s k ;
* /
mov d2 ,d1
add - 1 ,d1
not d1
mov d1 ,( I C I V M R )
/* a2 = mask & start */
and d1 ,d0 ,a2
icivloop :
/ * area i n v a l i d a t e
*
* ICIVCR = ( m a s k & s t a r t ) | I C I V C R _ I C I
* /
mov a2 ,d0
or I C I V C R _ I C I ,d0
mov d0 ,( a0 )
/* wait for busy bit of area invalidation */
setlb
mov ( a0 ) ,d1
btst I C I V C R _ I C I V B S Y ,d1
lne
/ * check i n v a l i d a t i n g o f e n d a d d r e s s
*
* a2 = a2 + a l i g n s i z e
* if ( a2 < e n d ) {
* goto i c i v l o o p ;
* } * /
add d2 ,a2
cmp a1 ,a2
bns i c i v l o o p
LOCAL_ I R Q _ R E S T O R E ( d3 )
mn10300_local_icache_inv_range_reg_end :
ret [ d2 ,d3 ,a2 ] ,1 2
.size mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ p a g e ,. - m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ p a g e
.size mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e ,. - m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e
.size mn1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e 2 ,. - m n 1 0 3 0 0 _ l o c a l _ i c a c h e _ i n v _ r a n g e 2