28d641be43
Previous version was based on code from kernel 2.6.22 with Broadcom two trivial modifications. This updates the copy to the version from current kernel and refreshes the patch. This was tested for regressions on Netgear R6250 (BCM4708A0), D-Link DIR-885L (BCM4709C0) and Tenda AC9 (BCM47189B0). Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
82 lines
2.7 KiB
ArmAsm
82 lines
2.7 KiB
ArmAsm
/*
|
|
* This is a part of mm/cache-v7.S with extracted entry flushing D-cache. We
|
|
* need it for Broadcom devices with broken bootloader leaving cache enabled.
|
|
*
|
|
* Copyright (C) 2001 Deep Blue Solutions Ltd.
|
|
* Copyright (C) 2005 ARM Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <linux/init.h>
|
|
|
|
__INIT
|
|
|
|
/*
|
|
* v7_flush_dcache_all()
|
|
*
|
|
* Flush the whole D-cache.
|
|
*
|
|
* Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
|
|
*
|
|
* - mm - mm_struct describing address space
|
|
*/
|
|
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
|
|
#ifdef CONFIG_PREEMPT
|
|
save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic
|
|
#endif
|
|
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
|
|
#ifdef CONFIG_PREEMPT
|
|
restore_irqs_notrace r9
|
|
#endif
|
|
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
|
|
ret lr
|
|
ENDPROC(v7_flush_dcache_all)
|