Browse Source

Blackfin: set up simple NMI handlers for anomaly 05000219

Older on-chip Blackfin bootroms do not create a dummy NMI handler, so set
up one ourselves when anomaly 05000219 applies.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Mike Frysinger 15 years ago
parent
commit
ce53fc6601
4 changed files with 34 additions and 1 deletions
  1. 3 1
      arch/blackfin/cpu/cpu.c
  2. 1 0
      arch/blackfin/cpu/cpu.h
  3. 25 0
      arch/blackfin/cpu/initcode.c
  4. 5 0
      arch/blackfin/cpu/interrupt.S

+ 3 - 1
arch/blackfin/cpu/cpu.c

@@ -91,7 +91,9 @@ int irq_init(void)
 #else
 	bfin_write_SIC_IMASK(0);
 #endif
-	bfin_write_EVT2(evt_default);	/* NMI */
+	/* Set up a dummy NMI handler if needed.  */
+	if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS || ANOMALY_05000219)
+		bfin_write_EVT2(evt_nmi);	/* NMI */
 	bfin_write_EVT5(evt_default);	/* hardware error */
 	bfin_write_EVT6(evt_default);	/* core timer */
 	bfin_write_EVT7(evt_default);

+ 1 - 0
arch/blackfin/cpu/cpu.h

@@ -34,6 +34,7 @@ void bfin_panic(struct pt_regs *reg);
 void dump(struct pt_regs *regs);
 
 asmlinkage void trap(void);
+asmlinkage void evt_nmi(void);
 asmlinkage void evt_default(void);
 
 #endif

+ 25 - 0
arch/blackfin/cpu/initcode.c

@@ -101,6 +101,28 @@ static inline void serial_putc(char c)
 		continue;
 }
 
+__attribute__((always_inline)) static inline void
+program_nmi_handler(void)
+{
+	u32 tmp1, tmp2;
+
+	/* Older bootroms don't create a dummy NMI handler,
+	 * so make one ourselves ASAP in case it fires.
+	 */
+	if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS && !ANOMALY_05000219)
+		return;
+
+	asm volatile (
+		"%0 = RETS;" /* Save current RETS */
+		"CALL 1f;"   /* Figure out current PC */
+		"RTN;"       /* The simple NMI handler */
+		"1:"
+		"%1 = RETS;" /* Load addr of NMI handler */
+		"RETS = %0;" /* Restore RETS */
+		"[%2] = %1;" /* Write NMI handler */
+		: "=r"(tmp1), "=r"(tmp2) : "ab"(EVT2)
+	);
+}
 
 /* Max SCLK can be 133MHz ... dividing that by (2*4) gives
  * us a freq of 16MHz for SPI which should generally be
@@ -640,6 +662,9 @@ void initcode(ADI_BOOT_DATA *bs)
 {
 	ADI_BOOT_DATA bootstruct_scratch;
 
+	/* Setup NMI handler before anything else */
+	program_nmi_handler();
+
 	serial_init();
 
 	serial_putc('A');

+ 5 - 0
arch/blackfin/cpu/interrupt.S

@@ -150,3 +150,8 @@ ENTRY(_evt_default)
 	RESTORE_ALL_SYS
 	rti;
 ENDPROC(_evt_default)
+
+/* NMI handler */
+ENTRY(_evt_nmi)
+	rtn;
+ENDPROC(_evt_nmi)