diff options
author | Mike Frysinger <michael.frysinger@analog.com> | 2007-11-21 03:08:58 -0500 |
---|---|---|
committer | Bryan Wu <bryan.wu@analog.com> | 2007-11-21 03:08:58 -0500 |
commit | 9e83b98a79d25136282a1757f879c40ee929a28b (patch) | |
tree | 1ec7588320b7e95f05eab8b2f9a06c07f48034bc /include/asm-blackfin | |
parent | b5f87aa41db4d5cd64ca77f10b33fdfba61a47d7 (diff) |
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 <michael.frysinger@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'include/asm-blackfin')
-rw-r--r-- | 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 52e7a10d7ff8..473a8113277f 100644 --- a/include/asm-blackfin/delay.h +++ b/include/asm-blackfin/delay.h | |||
@@ -1,29 +1,47 @@ | |||
1 | #ifndef _BLACKFIN_DELAY_H | ||
2 | #define _BLACKFIN_DELAY_H | ||
3 | |||
4 | static inline void __delay(unsigned long loops) | ||
5 | { | ||
6 | |||
7 | /* FIXME: Currently the assembler doesn't recognize Loop Register Clobbers, | ||
8 | uncomment this as soon those are implemented */ | ||
9 | /* | 1 | /* |
10 | __asm__ __volatile__ ( "\t LSETUP (1f,1f) LC0= %0\n\t" | 2 | * delay.h - delay functions |
11 | "1:\t NOP;\n\t" | 3 | * |
12 | : :"a" (loops) | 4 | * Copyright (c) 2004-2007 Analog Devices Inc. |
13 | : "LT0","LB0","LC0"); | 5 | * |
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef __ASM_DELAY_H__ | ||
10 | #define __ASM_DELAY_H__ | ||
14 | 11 | ||
15 | */ | 12 | #include <asm/mach/anomaly.h> |
16 | 13 | ||
17 | __asm__ __volatile__("[--SP] = LC0;\n\t" | 14 | static inline void __delay(unsigned long loops) |
18 | "[--SP] = LT0;\n\t" | 15 | { |
19 | "[--SP] = LB0;\n\t" | 16 | if (ANOMALY_05000312) { |
20 | "LSETUP (1f,1f) LC0 = %0;\n\t" | 17 | /* Interrupted loads to loop registers -> bad */ |
21 | "1:\t NOP;\n\t" | 18 | unsigned long tmp; |
22 | "LB0 = [SP++];\n\t" | 19 | __asm__ __volatile__( |
23 | "LT0 = [SP++];\n\t" | 20 | "[--SP] = LC0;" |
24 | "LC0 = [SP++];\n" | 21 | "[--SP] = LT0;" |
25 | : | 22 | "[--SP] = LB0;" |
26 | :"a" (loops)); | 23 | "LSETUP (1f,1f) LC0 = %1;" |
24 | "1: NOP;" | ||
25 | /* We take advantage of the fact that LC0 is 0 at | ||
26 | * the end of the loop. Otherwise we'd need some | ||
27 | * NOPs after the CLI here. | ||
28 | */ | ||
29 | "CLI %0;" | ||
30 | "LB0 = [SP++];" | ||
31 | "LT0 = [SP++];" | ||
32 | "LC0 = [SP++];" | ||
33 | "STI %0;" | ||
34 | : "=d" (tmp) | ||
35 | : "a" (loops) | ||
36 | ); | ||
37 | } else | ||
38 | __asm__ __volatile__ ( | ||
39 | "LSETUP(1f, 1f) LC0 = %0;" | ||
40 | "1: NOP;" | ||
41 | : | ||
42 | : "a" (loops) | ||
43 | : "LT0", "LB0", "LC0" | ||
44 | ); | ||
27 | } | 45 | } |
28 | 46 | ||
29 | #include <linux/param.h> /* needed for HZ */ | 47 | #include <linux/param.h> /* needed for HZ */ |
@@ -41,4 +59,4 @@ static inline void udelay(unsigned long usecs) | |||
41 | __delay(usecs * loops_per_jiffy / (1000000 / HZ)); | 59 | __delay(usecs * loops_per_jiffy / (1000000 / HZ)); |
42 | } | 60 | } |
43 | 61 | ||
44 | #endif /* defined(_BLACKFIN_DELAY_H) */ | 62 | #endif |