summary refs log tree commit diff
path: root/arch/blackfin/include
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2009-08-26 15:54:10 +0000
committerMike Frysinger <vapier@gentoo.org>2009-09-16 22:10:34 -0400
commitdedfd5d7f21b08d50ba8c0220778e119952e2f77 (patch)
tree2d6bf1d13dfe16679c126beed7f35a2f840d22bd /arch/blackfin/include
parent05d17dfaab6671def3fcdcd95c39fd49924dbb3b (diff)
downloadlinux-dedfd5d7f21b08d50ba8c0220778e119952e2f77.tar.gz
Blackfin: workaround anomaly 05000283
Make sure our interrupt entry code with exact hardware errors handles
anomaly 05000283 (infinite stall in system MMR kill) so we don't stall
while under load.

Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/include')
-rw-r--r--arch/blackfin/include/asm/entry.h30
1 files changed, 26 insertions, 4 deletions
diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h
index ec58efc130e6..55b808fced71 100644
--- a/arch/blackfin/include/asm/entry.h
+++ b/arch/blackfin/include/asm/entry.h
@@ -36,6 +36,21 @@
 # define LOAD_IPIPE_IPEND
 #endif
 
+/*
+ * Workaround for anomalies 05000283 and 05000315
+ */
+#if ANOMALY_05000283 || ANOMALY_05000315
+# define ANOMALY_283_315_WORKAROUND(preg, dreg)		\
+	cc = dreg == dreg;				\
+	preg.h = HI(CHIPID);				\
+	preg.l = LO(CHIPID);				\
+	if cc jump 1f;					\
+	dreg.l = W[preg];				\
+1:
+#else
+# define ANOMALY_283_315_WORKAROUND(preg, dreg)
+#endif /* ANOMALY_05000283 || ANOMALY_05000315 */
+
 #ifndef CONFIG_EXACT_HWERR
 /* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
  * otherwise it is a waste of cycles.
@@ -88,17 +103,22 @@
  * As you can see by the code - we actually need to do two SSYNCS - one to
  * make sure the read/writes complete, and another to make sure the hardware
  * error is recognized by the core.
+ *
+ * The extra nop before the SSYNC is to make sure we work around 05000244,
+ * since the 283/315 workaround includes a branch to the end
  */
 #define INTERRUPT_ENTRY(N)						\
-    SSYNC;								\
-    SSYNC;								\
     [--sp] = SYSCFG;							\
     [--sp] = P0;	/*orig_p0*/					\
     [--sp] = R0;	/*orig_r0*/					\
     [--sp] = (R7:0,P5:0);						\
     R1 = ASTAT;								\
+    ANOMALY_283_315_WORKAROUND(p0, r0)					\
     P0.L = LO(ILAT);							\
     P0.H = HI(ILAT);							\
+    NOP;								\
+    SSYNC;								\
+    SSYNC;								\
     R0 = [P0];								\
     CC = BITTST(R0, EVT_IVHW_P);					\
     IF CC JUMP 1f;							\
@@ -118,15 +138,17 @@
     RTI;
 
 #define TIMER_INTERRUPT_ENTRY(N)					\
-    SSYNC;								\
-    SSYNC;								\
     [--sp] = SYSCFG;							\
     [--sp] = P0;	/*orig_p0*/					\
     [--sp] = R0;	/*orig_r0*/					\
     [--sp] = (R7:0,P5:0);						\
     R1 = ASTAT;								\
+    ANOMALY_283_315_WORKAROUND(p0, r0)					\
     P0.L = LO(ILAT);							\
     P0.H = HI(ILAT);							\
+    NOP;								\
+    SSYNC;								\
+    SSYNC;								\
     R0 = [P0];								\
     CC = BITTST(R0, EVT_IVHW_P);					\
     IF CC JUMP 1f;							\