[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:
Catalin Marinas
2009-04-30 17:06:03 +01:00
committed by Russell King
parent 10993374f8
commit 9cba3ccc8f
3 changed files with 63 additions and 2 deletions

View File

@@ -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

View File

@@ -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
}
}