Commit 9cba3ccc authored by Catalin Marinas's avatar Catalin Marinas Committed by Russell King

[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: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 10993374
...@@ -740,6 +740,15 @@ if !MMU ...@@ -740,6 +740,15 @@ if !MMU
source "arch/arm/Kconfig-nommu" source "arch/arm/Kconfig-nommu"
endif 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 endmenu
source "arch/arm/common/Kconfig" source "arch/arm/common/Kconfig"
......
...@@ -20,6 +20,31 @@ ...@@ -20,6 +20,31 @@
#define D_CACHE_LINE_SIZE 32 #define D_CACHE_LINE_SIZE 32
#define BTB_FLUSH_SIZE 8 #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() * v6_flush_cache_all()
* *
...@@ -31,7 +56,11 @@ ENTRY(v6_flush_kern_cache_all) ...@@ -31,7 +56,11 @@ ENTRY(v6_flush_kern_cache_all)
mov r0, #0 mov r0, #0
#ifdef HARVARD_CACHE #ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate 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 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
#else
b v6_icache_inval_all
#endif
#else #else
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
#endif #endif
...@@ -103,7 +132,11 @@ ENTRY(v6_coherent_user_range) ...@@ -103,7 +132,11 @@ ENTRY(v6_coherent_user_range)
mov r0, #0 mov r0, #0
#ifdef HARVARD_CACHE #ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 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 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
#else
b v6_icache_inval_all
#endif
#else #else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
#endif #endif
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#include "mm.h" #include "mm.h"
#ifdef CONFIG_ARM_ERRATA_411920
extern void v6_icache_inval_all(void);
#endif
#ifdef CONFIG_CPU_CACHE_VIPT #ifdef CONFIG_CPU_CACHE_VIPT
#define ALIAS_FLUSH_START 0xffff4000 #define ALIAS_FLUSH_START 0xffff4000
...@@ -32,10 +36,15 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) ...@@ -32,10 +36,15 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
asm( "mcrr p15, 0, %1, %0, c14\n" asm( "mcrr p15, 0, %1, %0, c14\n"
" mcr p15, 0, %2, c7, c10, 4\n" " mcr p15, 0, %2, c7, c10, 4\n"
#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %2, c7, c5, 0\n" " mcr p15, 0, %2, c7, c5, 0\n"
#endif
: :
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero) : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
: "cc"); : "cc");
#ifdef CONFIG_ARM_ERRATA_411920
v6_icache_inval_all();
#endif
} }
void flush_cache_mm(struct mm_struct *mm) void flush_cache_mm(struct mm_struct *mm)
...@@ -48,11 +57,16 @@ 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()) { if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n" 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, c5, 0\n"
" mcr p15, 0, %0, c7, c10, 4" #endif
: :
: "r" (0) : "r" (0)
: "cc"); : "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 ...@@ -67,11 +81,16 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned
if (cache_is_vipt_aliasing()) { if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n" 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, c5, 0\n"
" mcr p15, 0, %0, c7, c10, 4" #endif
: :
: "r" (0) : "r" (0)
: "cc"); : "cc");
#ifdef CONFIG_ARM_ERRATA_411920
v6_icache_inval_all();
#endif
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment