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