i.MX31 and i.MX35 : fix errate TLSbo65953 and ENGcm09472
authorEric Bénard <eric@eukrea.com>
Tue, 5 Oct 2010 09:20:21 +0000 (11:20 +0200)
committerSascha Hauer <s.hauer@pengutronix.de>
Tue, 19 Oct 2010 16:44:58 +0000 (18:44 +0200)
Without this exiting WFI can result in cache corruption.
Code taken from Freescale's 2.6.27 BSP and tested on i.MX35

Signed-off-by: Eric Bénard <eric@eukrea.com>
arch/arm/plat-mxc/include/mach/system.h

index 4acd114..95be51b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *  Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,8 +28,34 @@ static inline void arch_idle(void)
                mxc91231_prepare_idle();
        }
 #endif
-
-       cpu_do_idle();
+       /* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
+       if (cpu_is_mx31() || cpu_is_mx35()) {
+               unsigned long reg = 0;
+               __asm__ __volatile__(
+                       /* disable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "bic %0, %0, #0x00001000\n"
+                       "bic %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       /* invalidate I cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c5, 0\n"
+                       /* clear and invalidate D cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c14, 0\n"
+                       /* WFI */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c0, 4\n"
+                       "nop\n" "nop\n" "nop\n" "nop\n"
+                       "nop\n" "nop\n" "nop\n"
+                       /* enable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "orr %0, %0, #0x00001000\n"
+                       "orr %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       : "=r" (reg));
+       } else
+               cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);