[ARM] 5488/1: ARM errata: Invalidation of the Instruction Cache operation can fail
This patch implements the recommended workaround for erratum 411920 (ARM1136, ARM1156, ARM1176). Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
10993374f8
commit
9cba3ccc8f
3 changed files with 63 additions and 2 deletions
|
@ -740,6 +740,15 @@ if !MMU
|
|||
source "arch/arm/Kconfig-nommu"
|
||||
endif
|
||||
|
||||
config ARM_ERRATA_411920
|
||||
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
|
||||
depends on CPU_V6 && !SMP
|
||||
help
|
||||
Invalidation of the Instruction Cache operation can
|
||||
fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
|
||||
It does not affect the MPCore. This option enables the ARM Ltd.
|
||||
recommended workaround.
|
||||
|
||||
endmenu
|
||||
|
||||
source "arch/arm/common/Kconfig"
|
||||
|
|
|
@ -20,6 +20,31 @@
|
|||
#define D_CACHE_LINE_SIZE 32
|
||||
#define BTB_FLUSH_SIZE 8
|
||||
|
||||
#ifdef CONFIG_ARM_ERRATA_411920
|
||||
/*
|
||||
* Invalidate the entire I cache (this code is a workaround for the ARM1136
|
||||
* erratum 411920 - Invalidate Instruction Cache operation can fail. This
|
||||
* erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
|
||||
*
|
||||
* Registers:
|
||||
* r0 - set to 0
|
||||
* r1 - corrupted
|
||||
*/
|
||||
ENTRY(v6_icache_inval_all)
|
||||
mov r0, #0
|
||||
mrs r1, cpsr
|
||||
cpsid ifa @ disable interrupts
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
|
||||
msr cpsr_cx, r1 @ restore interrupts
|
||||
.rept 11 @ ARM Ltd recommends at least
|
||||
nop @ 11 NOPs
|
||||
.endr
|
||||
mov pc, lr
|
||||
#endif
|
||||
|
||||
/*
|
||||
* v6_flush_cache_all()
|
||||
*
|
||||
|
@ -31,7 +56,11 @@ ENTRY(v6_flush_kern_cache_all)
|
|||
mov r0, #0
|
||||
#ifdef HARVARD_CACHE
|
||||
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate
|
||||
#ifndef CONFIG_ARM_ERRATA_411920
|
||||
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
||||
#else
|
||||
b v6_icache_inval_all
|
||||
#endif
|
||||
#else
|
||||
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
|
||||
#endif
|
||||
|
@ -103,7 +132,11 @@ ENTRY(v6_coherent_user_range)
|
|||
mov r0, #0
|
||||
#ifdef HARVARD_CACHE
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||
#ifndef CONFIG_ARM_ERRATA_411920
|
||||
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
||||
#else
|
||||
b v6_icache_inval_all
|
||||
#endif
|
||||
#else
|
||||
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
#include "mm.h"
|
||||
|
||||
#ifdef CONFIG_ARM_ERRATA_411920
|
||||
extern void v6_icache_inval_all(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_CACHE_VIPT
|
||||
|
||||
#define ALIAS_FLUSH_START 0xffff4000
|
||||
|
@ -32,10 +36,15 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
|
|||
|
||||
asm( "mcrr p15, 0, %1, %0, c14\n"
|
||||
" mcr p15, 0, %2, c7, c10, 4\n"
|
||||
#ifndef CONFIG_ARM_ERRATA_411920
|
||||
" mcr p15, 0, %2, c7, c5, 0\n"
|
||||
#endif
|
||||
:
|
||||
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
|
||||
: "cc");
|
||||
#ifdef CONFIG_ARM_ERRATA_411920
|
||||
v6_icache_inval_all();
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush_cache_mm(struct mm_struct *mm)
|
||||
|
@ -48,11 +57,16 @@ void flush_cache_mm(struct mm_struct *mm)
|
|||
|
||||
if (cache_is_vipt_aliasing()) {
|
||||
asm( "mcr p15, 0, %0, c7, c14, 0\n"
|
||||
" mcr p15, 0, %0, c7, c10, 4\n"
|
||||
#ifndef CONFIG_ARM_ERRATA_411920
|
||||
" mcr p15, 0, %0, c7, c5, 0\n"
|
||||
" mcr p15, 0, %0, c7, c10, 4"
|
||||
#endif
|
||||
:
|
||||
: "r" (0)
|
||||
: "cc");
|
||||
#ifdef CONFIG_ARM_ERRATA_411920
|
||||
v6_icache_inval_all();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,11 +81,16 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned
|
|||
|
||||
if (cache_is_vipt_aliasing()) {
|
||||
asm( "mcr p15, 0, %0, c7, c14, 0\n"
|
||||
" mcr p15, 0, %0, c7, c10, 4\n"
|
||||
#ifndef CONFIG_ARM_ERRATA_411920
|
||||
" mcr p15, 0, %0, c7, c5, 0\n"
|
||||
" mcr p15, 0, %0, c7, c10, 4"
|
||||
#endif
|
||||
:
|
||||
: "r" (0)
|
||||
: "cc");
|
||||
#ifdef CONFIG_ARM_ERRATA_411920
|
||||
v6_icache_inval_all();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue