Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9e83b98a79d25136282a1757f879c40ee929a28b
Commit:     9e83b98a79d25136282a1757f879c40ee929a28b
Parent:     b5f87aa41db4d5cd64ca77f10b33fdfba61a47d7
Author:     Mike Frysinger <[EMAIL PROTECTED]>
AuthorDate: Wed Nov 21 16:08:58 2007 +0800
Committer:  Bryan Wu <[EMAIL PROTECTED]>
CommitDate: Wed Nov 21 16:08:58 2007 +0800

    Blackfin arch: add support for working around anomaly 05000312
    
    Anomaly 05000312 - Errors When SSYNC, CSYNC, or Loads to LT, LB and LC 
Registers Are Interrupted:
    
    DESCRIPTION:
    When instruction cache is enabled, erroneous behavior may occur when any of 
the following instructions are interrupted:
    
    . CSYNC
    • SSYNC
    • LCx =
    • LTx = (only when LCx is non-zero)
    • LBx = (only when LCx is non-zero)
    
    When this problem occurs, a variety of incorrect things could happen, 
including an illegal instruction exception. Additional errors could
    show up as an exception, a hardware error, or an instruction that is valid 
but different than the one that was expected.
    
    WORKAROUND:
    Place a cli before all SSYNC, CSYNC, "LCx =", "LTx =", and "LBx =" 
instructions to disable interrupts, and place an sti after each of these
    instructions to re-enable interrupts. When these instructions are executed 
in code that is already non-interruptible, the problem will not
    occur.
    
    Signed-off-by: Mike Frysinger <[EMAIL PROTECTED]>
    Signed-off-by: Bryan Wu <[EMAIL PROTECTED]>
---
 include/asm-blackfin/delay.h |   66 ++++++++++++++++++++++++++---------------
 1 files changed, 42 insertions(+), 24 deletions(-)

diff --git a/include/asm-blackfin/delay.h b/include/asm-blackfin/delay.h
index 52e7a10..473a811 100644
--- a/include/asm-blackfin/delay.h
+++ b/include/asm-blackfin/delay.h
@@ -1,29 +1,47 @@
-#ifndef _BLACKFIN_DELAY_H
-#define _BLACKFIN_DELAY_H
-
-static inline void __delay(unsigned long loops)
-{
-
-/* FIXME: Currently the assembler doesn't recognize Loop Register Clobbers,
-   uncomment this as soon those are implemented */
 /*
-      __asm__ __volatile__ (  "\t LSETUP (1f,1f) LC0= %0\n\t"
-                              "1:\t NOP;\n\t"
-                              : :"a" (loops)
-                              : "LT0","LB0","LC0");
+ * delay.h - delay functions
+ *
+ * Copyright (c) 2004-2007 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_DELAY_H__
+#define __ASM_DELAY_H__
 
-*/
+#include <asm/mach/anomaly.h>
 
-       __asm__ __volatile__("[--SP] = LC0;\n\t"
-                            "[--SP] = LT0;\n\t"
-                            "[--SP] = LB0;\n\t"
-                            "LSETUP (1f,1f) LC0 = %0;\n\t"
-                            "1:\t NOP;\n\t"
-                            "LB0 = [SP++];\n\t"
-                               "LT0 = [SP++];\n\t"
-                               "LC0 = [SP++];\n"
-                               :
-                               :"a" (loops));
+static inline void __delay(unsigned long loops)
+{
+       if (ANOMALY_05000312) {
+               /* Interrupted loads to loop registers -> bad */
+               unsigned long tmp;
+               __asm__ __volatile__(
+                       "[--SP] = LC0;"
+                       "[--SP] = LT0;"
+                       "[--SP] = LB0;"
+                       "LSETUP (1f,1f) LC0 = %1;"
+                       "1: NOP;"
+                       /* We take advantage of the fact that LC0 is 0 at
+                        * the end of the loop.  Otherwise we'd need some
+                        * NOPs after the CLI here.
+                        */
+                       "CLI %0;"
+                       "LB0 = [SP++];"
+                       "LT0 = [SP++];"
+                       "LC0 = [SP++];"
+                       "STI %0;"
+                       : "=d" (tmp)
+                       : "a" (loops)
+               );
+       } else
+               __asm__ __volatile__ (
+                       "LSETUP(1f, 1f) LC0 = %0;"
+                       "1: NOP;"
+                       :
+                       : "a" (loops)
+                       : "LT0", "LB0", "LC0"
+               );
 }
 
 #include <linux/param.h>       /* needed for HZ */
@@ -41,4 +59,4 @@ static inline void udelay(unsigned long usecs)
        __delay(usecs * loops_per_jiffy / (1000000 / HZ));
 }
 
-#endif                         /* defined(_BLACKFIN_DELAY_H) */
+#endif
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to