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"
 
 #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()
  *
        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
        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
 
 
 #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
 
        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)
 
        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
        }
 }
 
 
        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
        }
 }