aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-blackfin/delay.h
diff options
context:
space:
mode:
authorMike Frysinger <michael.frysinger@analog.com>2007-11-21 03:08:58 -0500
committerBryan Wu <bryan.wu@analog.com>2007-11-21 03:08:58 -0500
commit9e83b98a79d25136282a1757f879c40ee929a28b (patch)
tree1ec7588320b7e95f05eab8b2f9a06c07f48034bc /include/asm-blackfin/delay.h
parentb5f87aa41db4d5cd64ca77f10b33fdfba61a47d7 (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/delay.h')
-rw-r--r--include/asm-blackfin/delay.h66
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
4static 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" 14static 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