mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-14 08:57:58 +00:00
3a649407a4
Today, we have cases where we wish to build all of U-Boot in Thumb2 mode for various reasons. We also have cases where we only build SPL in Thumb2 mode due to size constraints and wish to build the rest of the system in ARM mode. So in this migration we introduce a new symbol as well, SPL_SYS_THUMB_BUILD to control if we build everything or just SPL (or in theory, just U-Boot) in Thumb2 mode. Signed-off-by: Tom Rini <trini@konsulko.com> Acked-by: Siarhei Siamashka <siarhei.siamashka@gmail.com>
154 lines
5 KiB
ArmAsm
154 lines
5 KiB
ArmAsm
/*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <linux/linkage.h>
|
|
#include <linux/sizes.h>
|
|
#include <asm/system.h>
|
|
|
|
#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
|
|
#define ARM(x...)
|
|
#define THUMB(x...) x
|
|
#else
|
|
#define ARM(x...) x
|
|
#define THUMB(x...)
|
|
#endif
|
|
|
|
/*
|
|
* v7_flush_dcache_all()
|
|
*
|
|
* Flush the whole D-cache.
|
|
*
|
|
* Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
|
|
*
|
|
* Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
|
|
*/
|
|
ENTRY(__v7_flush_dcache_all)
|
|
dmb @ ensure ordering with previous memory accesses
|
|
mrc p15, 1, r0, c0, c0, 1 @ read clidr
|
|
mov r3, r0, lsr #23 @ move LoC into position
|
|
ands r3, r3, #7 << 1 @ extract LoC*2 from clidr
|
|
beq finished @ if loc is 0, then no need to clean
|
|
start_flush_levels:
|
|
mov r10, #0 @ start clean at cache level 0
|
|
flush_levels:
|
|
add r2, r10, r10, lsr #1 @ work out 3x current cache level
|
|
mov r1, r0, lsr r2 @ extract cache type bits from clidr
|
|
and r1, r1, #7 @ mask of the bits for current cache only
|
|
cmp r1, #2 @ see what cache we have at this level
|
|
blt skip @ skip if no cache, or just i-cache
|
|
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
|
isb @ isb to sych the new cssr&csidr
|
|
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
|
|
and r2, r1, #7 @ extract the length of the cache lines
|
|
add r2, r2, #4 @ add 4 (line length offset)
|
|
movw r4, #0x3ff
|
|
ands r4, r4, r1, lsr #3 @ find maximum number on the way size
|
|
clz r5, r4 @ find bit position of way size increment
|
|
movw r7, #0x7fff
|
|
ands r7, r7, r1, lsr #13 @ extract max number of the index size
|
|
loop1:
|
|
mov r9, r7 @ create working copy of max index
|
|
loop2:
|
|
ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11
|
|
THUMB( lsl r6, r4, r5 )
|
|
THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11
|
|
ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11
|
|
THUMB( lsl r6, r9, r2 )
|
|
THUMB( orr r11, r11, r6 ) @ factor index number into r11
|
|
mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
|
|
subs r9, r9, #1 @ decrement the index
|
|
bge loop2
|
|
subs r4, r4, #1 @ decrement the way
|
|
bge loop1
|
|
skip:
|
|
add r10, r10, #2 @ increment cache number
|
|
cmp r3, r10
|
|
bgt flush_levels
|
|
finished:
|
|
mov r10, #0 @ swith back to cache level 0
|
|
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
|
dsb st
|
|
isb
|
|
bx lr
|
|
ENDPROC(__v7_flush_dcache_all)
|
|
|
|
ENTRY(v7_flush_dcache_all)
|
|
ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} )
|
|
THUMB( stmfd sp!, {r4-r7, r9-r11, lr} )
|
|
bl __v7_flush_dcache_all
|
|
ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} )
|
|
THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} )
|
|
bx lr
|
|
ENDPROC(v7_flush_dcache_all)
|
|
|
|
/*
|
|
* v7_invalidate_dcache_all()
|
|
*
|
|
* Invalidate the whole D-cache.
|
|
*
|
|
* Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
|
|
*
|
|
* Note: copied from __v7_flush_dcache_all above with
|
|
* mcr p15, 0, r11, c7, c14, 2
|
|
* Replaced with:
|
|
* mcr p15, 0, r11, c7, c6, 2
|
|
*/
|
|
ENTRY(__v7_invalidate_dcache_all)
|
|
dmb @ ensure ordering with previous memory accesses
|
|
mrc p15, 1, r0, c0, c0, 1 @ read clidr
|
|
mov r3, r0, lsr #23 @ move LoC into position
|
|
ands r3, r3, #7 << 1 @ extract LoC*2 from clidr
|
|
beq inval_finished @ if loc is 0, then no need to clean
|
|
mov r10, #0 @ start clean at cache level 0
|
|
inval_levels:
|
|
add r2, r10, r10, lsr #1 @ work out 3x current cache level
|
|
mov r1, r0, lsr r2 @ extract cache type bits from clidr
|
|
and r1, r1, #7 @ mask of the bits for current cache only
|
|
cmp r1, #2 @ see what cache we have at this level
|
|
blt inval_skip @ skip if no cache, or just i-cache
|
|
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
|
isb @ isb to sych the new cssr&csidr
|
|
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
|
|
and r2, r1, #7 @ extract the length of the cache lines
|
|
add r2, r2, #4 @ add 4 (line length offset)
|
|
movw r4, #0x3ff
|
|
ands r4, r4, r1, lsr #3 @ find maximum number on the way size
|
|
clz r5, r4 @ find bit position of way size increment
|
|
movw r7, #0x7fff
|
|
ands r7, r7, r1, lsr #13 @ extract max number of the index size
|
|
inval_loop1:
|
|
mov r9, r7 @ create working copy of max index
|
|
inval_loop2:
|
|
ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11
|
|
THUMB( lsl r6, r4, r5 )
|
|
THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11
|
|
ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11
|
|
THUMB( lsl r6, r9, r2 )
|
|
THUMB( orr r11, r11, r6 ) @ factor index number into r11
|
|
mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way
|
|
subs r9, r9, #1 @ decrement the index
|
|
bge inval_loop2
|
|
subs r4, r4, #1 @ decrement the way
|
|
bge inval_loop1
|
|
inval_skip:
|
|
add r10, r10, #2 @ increment cache number
|
|
cmp r3, r10
|
|
bgt inval_levels
|
|
inval_finished:
|
|
mov r10, #0 @ swith back to cache level 0
|
|
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
|
dsb st
|
|
isb
|
|
bx lr
|
|
ENDPROC(__v7_invalidate_dcache_all)
|
|
|
|
ENTRY(v7_invalidate_dcache_all)
|
|
ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} )
|
|
THUMB( stmfd sp!, {r4-r7, r9-r11, lr} )
|
|
bl __v7_invalidate_dcache_all
|
|
ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} )
|
|
THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} )
|
|
bx lr
|
|
ENDPROC(v7_invalidate_dcache_all)
|