2005-04-16 15:20:36 -07:00
/ *
* linux/ a r c h / a r m / m m / p r o c - a r m 6 ,7 . S
*
* Copyright ( C ) 1 9 9 7 - 2 0 0 0 R u s s e l l K i n g
2006-06-28 14:10:01 +01:00
* hacked f o r n o n - p a g e d - M M b y H y o k S . C h o i , 2 0 0 3 .
2005-04-16 15:20:36 -07:00
*
* 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 .
*
* These a r e t h e l o w l e v e l a s s e m b l e r f o r p e r f o r m i n g c a c h e a n d T L B
* functions o n t h e A R M 6 1 0 & A R M 7 1 0 .
* /
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / i n i t . h >
# include < a s m / a s s e m b l e r . h >
2005-09-09 21:08:59 +02:00
# include < a s m / a s m - o f f s e t s . h >
2008-09-07 19:15:31 +01:00
# include < a s m / h w c a p . h >
2006-03-16 14:44:36 +00:00
# include < a s m / p g t a b l e - h w d e f . h >
2005-04-16 15:20:36 -07:00
# include < a s m / p g t a b l e . h >
# include < a s m / p t r a c e . h >
2008-09-06 17:19:08 +01:00
# include " p r o c - m a c r o s . S "
2005-04-16 15:20:36 -07:00
ENTRY( c p u _ a r m 6 _ d c a c h e _ c l e a n _ a r e a )
ENTRY( c p u _ a r m 7 _ d c a c h e _ c l e a n _ a r e a )
mov p c , l r
/ *
* Function : arm6 _ 7 _ d a t a _ a b o r t ( )
*
* Params : r2 = a d d r e s s o f a b o r t e d i n s t r u c t i o n
* : sp = p o i n t e r t o r e g i s t e r s
*
* Purpose : o b t a i n i n f o r m a t i o n a b o u t c u r r e n t a b o r t e d i n s t r u c t i o n
*
* Returns : r0 = a d d r e s s o f a b o r t
* : r1 = F S R
* /
ENTRY( c p u _ a r m 7 _ d a t a _ a b o r t )
mrc p15 , 0 , r1 , c5 , c0 , 0 @ get FSR
mrc p15 , 0 , r0 , c6 , c0 , 0 @ get FAR
2010-02-03 15:48:03 +00:00
ldr r8 , [ r2 ] @ read arm instruction
2005-09-04 10:13:48 +01:00
tst r8 , #1 < < 2 0 @ L = 0 -> write?
orreq r1 , r1 , #1 < < 1 1 @ yes.
2005-04-16 15:20:36 -07:00
and r7 , r8 , #15 < < 2 4
add p c , p c , r7 , l s r #22 @ Now branch to the relevant processing routine
nop
/* 0 */ b . d a t a _ u n k n o w n
/* 1 */ mov p c , l r @ swp
/* 2 */ b . d a t a _ u n k n o w n
/* 3 */ b . d a t a _ u n k n o w n
/* 4 */ b . d a t a _ a r m _ l a t e l d r p o s t c o n s t @ ldr rd, [rn], #m
/* 5 */ b . d a t a _ a r m _ l a t e l d r p r e c o n s t @ ldr rd, [rn, #m]
/* 6 */ b . d a t a _ a r m _ l a t e l d r p o s t r e g @ ldr rd, [rn], rm
/* 7 */ b . d a t a _ a r m _ l a t e l d r p r e r e g @ ldr rd, [rn, rm]
/* 8 */ b . d a t a _ a r m _ l d m s t m @ ldm*a rn, <rlist>
/* 9 */ b . d a t a _ a r m _ l d m s t m @ ldm*b rn, <rlist>
/* a */ b . d a t a _ u n k n o w n
/* b */ b . d a t a _ u n k n o w n
/* c */ mov p c , l r @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
/* d */ mov p c , l r @ ldc rd, [rn, #m]
/* e */ b . d a t a _ u n k n o w n
/* f */
.data_unknown : @ Part of jumptable
mov r0 , r2
mov r1 , r8
mov r2 , s p
bl b a d d a t a a b o r t
b r e t _ f r o m _ e x c e p t i o n
ENTRY( c p u _ a r m 6 _ d a t a _ a b o r t )
mrc p15 , 0 , r1 , c5 , c0 , 0 @ get FSR
mrc p15 , 0 , r0 , c6 , c0 , 0 @ get FAR
ldr r8 , [ r2 ] @ read arm instruction
2005-09-04 10:13:48 +01:00
tst r8 , #1 < < 2 0 @ L = 0 -> write?
orreq r1 , r1 , #1 < < 1 1 @ yes.
2005-04-16 15:20:36 -07:00
and r7 , r8 , #14 < < 2 4
teq r7 , #8 < < 2 4 @ was it ldm/stm
movne p c , l r
.data_arm_ldmstm :
tst r8 , #1 < < 2 1 @ check writeback bit
moveq p c , l r @ no writeback -> no fixup
mov r7 , #0x11
orr r7 , r7 , #0x1100
and r6 , r8 , r7
and r2 , r8 , r7 , l s l #1
add r6 , r6 , r2 , l s r #1
and r2 , r8 , r7 , l s l #2
add r6 , r6 , r2 , l s r #2
and r2 , r8 , r7 , l s l #3
add r6 , r6 , r2 , l s r #3
add r6 , r6 , r6 , l s r #8
add r6 , r6 , r6 , l s r #4
and r6 , r6 , #15 @ r6 = no. of registers to transfer.
and r5 , r8 , #15 < < 1 6 @ Extract 'n' from instruction
ldr r7 , [ s p , r5 , l s r #14 ] @ Get register 'Rn'
tst r8 , #1 < < 2 3 @ Check U bit
subne r7 , r7 , r6 , l s l #2 @ Undo increment
addeq r7 , r7 , r6 , l s l #2 @ Undo decrement
str r7 , [ s p , r5 , l s r #14 ] @ Put register 'Rn'
mov p c , l r
.data_arm_apply_r6_and_rn :
and r5 , r8 , #15 < < 1 6 @ Extract 'n' from instruction
ldr r7 , [ s p , r5 , l s r #14 ] @ Get register 'Rn'
tst r8 , #1 < < 2 3 @ Check U bit
subne r7 , r7 , r6 @ Undo incrmenet
addeq r7 , r7 , r6 @ Undo decrement
str r7 , [ s p , r5 , l s r #14 ] @ Put register 'Rn'
mov p c , l r
.data_arm_lateldrpreconst :
tst r8 , #1 < < 2 1 @ check writeback bit
moveq p c , l r @ no writeback -> no fixup
.data_arm_lateldrpostconst :
movs r2 , r8 , l s l #20 @ Get offset
moveq p c , l r @ zero -> no fixup
and r5 , r8 , #15 < < 1 6 @ Extract 'n' from instruction
ldr r7 , [ s p , r5 , l s r #14 ] @ Get register 'Rn'
tst r8 , #1 < < 2 3 @ Check U bit
subne r7 , r7 , r2 , l s r #20 @ Undo increment
addeq r7 , r7 , r2 , l s r #20 @ Undo decrement
str r7 , [ s p , r5 , l s r #14 ] @ Put register 'Rn'
mov p c , l r
.data_arm_lateldrprereg :
tst r8 , #1 < < 2 1 @ check writeback bit
moveq p c , l r @ no writeback -> no fixup
.data_arm_lateldrpostreg :
and r7 , r8 , #15 @ Extract 'm' from instruction
ldr r6 , [ s p , r7 , l s l #2 ] @ Get register 'Rm'
mov r5 , r8 , l s r #7 @ get shift count
ands r5 , r5 , #31
and r7 , r8 , #0x70 @ get shift type
orreq r7 , r7 , #8 @ shift count = 0
add p c , p c , r7
nop
mov r6 , r6 , l s l r5 @ 0: LSL #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n @ 1: LSL #0
nop
b . d a t a _ u n k n o w n @ 2: MUL?
nop
b . d a t a _ u n k n o w n @ 3: MUL?
nop
mov r6 , r6 , l s r r5 @ 4: LSR #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
mov r6 , r6 , l s r #32 @ 5: LSR #32
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ u n k n o w n @ 6: MUL?
nop
b . d a t a _ u n k n o w n @ 7: MUL?
nop
mov r6 , r6 , a s r r5 @ 8: ASR #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
mov r6 , r6 , a s r #32 @ 9: ASR #32
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ u n k n o w n @ A: MUL?
nop
b . d a t a _ u n k n o w n @ B: MUL?
nop
mov r6 , r6 , r o r r5 @ C: ROR #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
mov r6 , r6 , r r x @ D: RRX
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ u n k n o w n @ E: MUL?
nop
b . d a t a _ u n k n o w n @ F: MUL?
/ *
* Function : arm6 _ 7 _ p r o c _ i n i t ( v o i d )
* : arm6 _ 7 _ p r o c _ f i n ( v o i d )
*
* Notes : T h i s p r o c e s s o r d o e s n o t r e q u i r e t h e s e
* /
ENTRY( c p u _ a r m 6 _ p r o c _ i n i t )
ENTRY( c p u _ a r m 7 _ p r o c _ i n i t )
mov p c , l r
ENTRY( c p u _ a r m 6 _ p r o c _ f i n )
ENTRY( c p u _ a r m 7 _ p r o c _ f i n )
mov r0 , #0x31 @ ....S..DP...M
mcr p15 , 0 , r0 , c1 , c0 , 0 @ disable caches
mov p c , l r
ENTRY( c p u _ a r m 6 _ d o _ i d l e )
ENTRY( c p u _ a r m 7 _ d o _ i d l e )
mov p c , l r
/ *
* Function : arm6 _ 7 _ s w i t c h _ m m ( u n s i g n e d l o n g p g d _ p h y s )
* Params : p g d _ p h y s P h y s i c a l a d d r e s s o f p a g e t a b l e
* Purpose : P e r f o r m a t a s k s w i t c h , s a v i n g t h e o l d p r o c e s s e s s t a t e , a n d r e s t o r i n g
* the n e w .
* /
ENTRY( c p u _ a r m 6 _ s w i t c h _ m m )
ENTRY( c p u _ a r m 7 _ s w i t c h _ m m )
2006-06-28 14:10:01 +01:00
# ifdef C O N F I G _ M M U
2005-04-16 15:20:36 -07:00
mov r1 , #0
mcr p15 , 0 , r1 , c7 , c0 , 0 @ flush cache
mcr p15 , 0 , r0 , c2 , c0 , 0 @ update page table ptr
mcr p15 , 0 , r1 , c5 , c0 , 0 @ flush TLBs
2006-06-28 14:10:01 +01:00
# endif
2005-04-16 15:20:36 -07:00
mov p c , l r
/ *
2006-12-13 14:34:43 +00:00
* Function : arm6 _ 7 _ s e t _ p t e _ e x t ( p t e _ t * p t e p , p t e _ t p t e , u n s i g n e d i n t e x t )
2005-04-16 15:20:36 -07:00
* Params : r0 = A d d r e s s t o s e t
* : r1 = v a l u e t o s e t
* Purpose : S e t a P T E a n d f l u s h i t o u t o f a n y W B c a c h e
* /
2008-09-06 17:19:08 +01:00
.align 5
2006-12-13 14:34:43 +00:00
ENTRY( c p u _ a r m 6 _ s e t _ p t e _ e x t )
ENTRY( c p u _ a r m 7 _ s e t _ p t e _ e x t )
2006-06-28 14:10:01 +01:00
# ifdef C O N F I G _ M M U
2008-09-06 17:19:08 +01:00
armv3 _ s e t _ p t e _ e x t w c _ d i s a b l e =0
2006-06-28 14:10:01 +01:00
# endif / * C O N F I G _ M M U * /
2008-09-06 17:19:08 +01:00
mov p c , l r
2005-04-16 15:20:36 -07:00
/ *
* Function : _ arm6 _ 7 _ r e s e t
* Params : r0 = a d d r e s s t o j u m p t o
* Notes : T h i s s e t s u p e v e r y t h i n g f o r a r e s e t
* /
ENTRY( c p u _ a r m 6 _ r e s e t )
ENTRY( c p u _ a r m 7 _ r e s e t )
mov r1 , #0
mcr p15 , 0 , r1 , c7 , c0 , 0 @ flush cache
2006-06-28 14:10:01 +01:00
# ifdef C O N F I G _ M M U
2005-04-16 15:20:36 -07:00
mcr p15 , 0 , r1 , c5 , c0 , 0 @ flush TLB
2006-06-28 14:10:01 +01:00
# endif
2005-04-16 15:20:36 -07:00
mov r1 , #0x30
mcr p15 , 0 , r1 , c1 , c0 , 0 @ turn off MMU etc
mov p c , r0
2010-10-01 15:37:05 +01:00
_ _ CPUINIT
2005-04-16 15:20:36 -07:00
.type _ _ arm6 _ s e t u p , #f u n c t i o n
__arm6_setup : mov r0 , #0
mcr p15 , 0 , r0 , c7 , c0 @ flush caches on v3
2006-06-28 14:10:01 +01:00
# ifdef C O N F I G _ M M U
2005-04-16 15:20:36 -07:00
mcr p15 , 0 , r0 , c5 , c0 @ flush TLBs on v3
mov r0 , #0x3d @ . ..RS BLDP WCAM
orr r0 , r0 , #0x100 @ . ..01 0011 1101
2006-06-28 14:10:01 +01:00
# else
mov r0 , #0x3c @ . ..RS BLDP WCA.
# endif
2005-04-16 15:20:36 -07:00
mov p c , l r
.size _ _ arm6 _ s e t u p , . - _ _ a r m 6 _ s e t u p
.type _ _ arm7 _ s e t u p , #f u n c t i o n
__arm7_setup : mov r0 , #0
mcr p15 , 0 , r0 , c7 , c0 @ flush caches on v3
2006-06-28 14:10:01 +01:00
# ifdef C O N F I G _ M M U
2005-04-16 15:20:36 -07:00
mcr p15 , 0 , r0 , c5 , c0 @ flush TLBs on v3
mcr p15 , 0 , r0 , c3 , c0 @ load domain access register
mov r0 , #0x7d @ . ..RS BLDP WCAM
orr r0 , r0 , #0x100 @ . ..01 0111 1101
2006-06-28 14:10:01 +01:00
# else
mov r0 , #0x7c @ . ..RS BLDP WCA.
# endif
2005-04-16 15:20:36 -07:00
mov p c , l r
.size _ _ arm7 _ s e t u p , . - _ _ a r m 7 _ s e t u p
_ _ INITDATA
/ *
* Purpose : F u n c t i o n p o i n t e r s u s e d t o a c c e s s a b o v e f u n c t i o n s - a l l c a l l s
* come t h r o u g h t h e s e
* /
.type arm6 _ p r o c e s s o r _ f u n c t i o n s , #o b j e c t
ENTRY( a r m 6 _ p r o c e s s o r _ f u n c t i o n s )
.word cpu_arm6_data_abort
2009-09-25 13:39:47 +01:00
.word legacy_pabort
2005-04-16 15:20:36 -07:00
.word cpu_arm6_proc_init
.word cpu_arm6_proc_fin
.word cpu_arm6_reset
.word cpu_arm6_do_idle
.word cpu_arm6_dcache_clean_area
.word cpu_arm6_switch_mm
2006-12-13 14:34:43 +00:00
.word cpu_arm6_set_pte_ext
2011-02-06 15:48:39 +00:00
.word 0
.word 0
.word 0
2005-04-16 15:20:36 -07:00
.size arm6 _ p r o c e s s o r _ f u n c t i o n s , . - a r m 6 _ p r o c e s s o r _ f u n c t i o n s
/ *
* Purpose : F u n c t i o n p o i n t e r s u s e d t o a c c e s s a b o v e f u n c t i o n s - a l l c a l l s
* come t h r o u g h t h e s e
* /
.type arm7 _ p r o c e s s o r _ f u n c t i o n s , #o b j e c t
ENTRY( a r m 7 _ p r o c e s s o r _ f u n c t i o n s )
.word cpu_arm7_data_abort
2009-09-25 13:39:47 +01:00
.word legacy_pabort
2005-04-16 15:20:36 -07:00
.word cpu_arm7_proc_init
.word cpu_arm7_proc_fin
.word cpu_arm7_reset
.word cpu_arm7_do_idle
.word cpu_arm7_dcache_clean_area
.word cpu_arm7_switch_mm
2006-12-13 14:34:43 +00:00
.word cpu_arm7_set_pte_ext
2011-02-06 15:48:39 +00:00
.word 0
.word 0
.word 0
2005-04-16 15:20:36 -07:00
.size arm7 _ p r o c e s s o r _ f u n c t i o n s , . - a r m 7 _ p r o c e s s o r _ f u n c t i o n s
.section " .rodata "
.type cpu_ a r c h _ n a m e , #o b j e c t
cpu_arch_name : .asciz " armv3 "
.size cpu_ a r c h _ n a m e , . - c p u _ a r c h _ n a m e
.type cpu_ e l f _ n a m e , #o b j e c t
cpu_elf_name : .asciz " v3 "
.size cpu_ e l f _ n a m e , . - c p u _ e l f _ n a m e
.type cpu_ a r m 6 _ n a m e , #o b j e c t
cpu_arm6_name : .asciz " ARM6 "
.size cpu_ a r m 6 _ n a m e , . - c p u _ a r m 6 _ n a m e
.type cpu_ a r m 6 1 0 _ n a m e , #o b j e c t
cpu_arm610_name :
.asciz " ARM6 1 0 "
.size cpu_ a r m 6 1 0 _ n a m e , . - c p u _ a r m 6 1 0 _ n a m e
.type cpu_ a r m 7 _ n a m e , #o b j e c t
cpu_arm7_name : .asciz " ARM7 "
.size cpu_ a r m 7 _ n a m e , . - c p u _ a r m 7 _ n a m e
.type cpu_ a r m 7 1 0 _ n a m e , #o b j e c t
cpu_arm710_name :
.asciz " ARM7 1 0 "
.size cpu_ a r m 7 1 0 _ n a m e , . - c p u _ a r m 7 1 0 _ n a m e
.align
2005-09-20 16:35:03 +01:00
.section " .proc .info .init " , # alloc, #e x e c i n s t r
2005-04-16 15:20:36 -07:00
.type _ _ arm6 _ p r o c _ i n f o , #o b j e c t
__arm6_proc_info :
.long 0x41560600
.long 0xfffffff0
.long 0x00000c1e
2006-06-29 18:24:21 +01:00
.long PMD_TYPE_SECT | \
PMD_ B I T 4 | \
PMD_ S E C T _ A P _ W R I T E | \
PMD_ S E C T _ A P _ R E A D
2005-04-16 15:20:36 -07:00
b _ _ a r m 6 _ s e t u p
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_ 2 6 B I T
.long cpu_arm6_name
.long arm6_processor_functions
.long v3_tlb_fns
.long v3_user_fns
.long v3_cache_fns
.size _ _ arm6 _ p r o c _ i n f o , . - _ _ a r m 6 _ p r o c _ i n f o
.type _ _ arm6 1 0 _ p r o c _ i n f o , #o b j e c t
__arm610_proc_info :
.long 0x41560610
.long 0xfffffff0
.long 0x00000c1e
2006-06-29 18:24:21 +01:00
.long PMD_TYPE_SECT | \
PMD_ B I T 4 | \
PMD_ S E C T _ A P _ W R I T E | \
PMD_ S E C T _ A P _ R E A D
2005-04-16 15:20:36 -07:00
b _ _ a r m 6 _ s e t u p
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_ 2 6 B I T
.long cpu_arm610_name
.long arm6_processor_functions
.long v3_tlb_fns
.long v3_user_fns
.long v3_cache_fns
.size _ _ arm6 1 0 _ p r o c _ i n f o , . - _ _ a r m 6 1 0 _ p r o c _ i n f o
.type _ _ arm7 _ p r o c _ i n f o , #o b j e c t
__arm7_proc_info :
.long 0x41007000
.long 0xffffff00
.long 0x00000c1e
2006-06-29 18:24:21 +01:00
.long PMD_TYPE_SECT | \
PMD_ B I T 4 | \
PMD_ S E C T _ A P _ W R I T E | \
PMD_ S E C T _ A P _ R E A D
2005-04-16 15:20:36 -07:00
b _ _ a r m 7 _ s e t u p
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_ 2 6 B I T
.long cpu_arm7_name
.long arm7_processor_functions
.long v3_tlb_fns
.long v3_user_fns
.long v3_cache_fns
.size _ _ arm7 _ p r o c _ i n f o , . - _ _ a r m 7 _ p r o c _ i n f o
.type _ _ arm7 1 0 _ p r o c _ i n f o , #o b j e c t
__arm710_proc_info :
.long 0x41007100
.long 0xfff8ff00
.long PMD_TYPE_SECT | \
PMD_ S E C T _ B U F F E R A B L E | \
PMD_ S E C T _ C A C H E A B L E | \
PMD_ B I T 4 | \
PMD_ S E C T _ A P _ W R I T E | \
PMD_ S E C T _ A P _ R E A D
2006-06-29 18:24:21 +01:00
.long PMD_TYPE_SECT | \
PMD_ B I T 4 | \
PMD_ S E C T _ A P _ W R I T E | \
PMD_ S E C T _ A P _ R E A D
2005-04-16 15:20:36 -07:00
b _ _ a r m 7 _ s e t u p
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_ 2 6 B I T
.long cpu_arm710_name
.long arm7_processor_functions
.long v3_tlb_fns
.long v3_user_fns
.long v3_cache_fns
.size _ _ arm7 1 0 _ p r o c _ i n f o , . - _ _ a r m 7 1 0 _ p r o c _ i n f o