diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index cdce8cc5b7b3..26ebb0e8c431 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -521,6 +521,52 @@ config BFIN_IDLE_LED_NUM help Select the LED (marked on the board) for you to blink. +choice + prompt "Blackfin Exception Scratch Register" + default BFIN_SCRATCH_REG_RETN + help + Select the resource to reserve for the Exception handler: + - RETN: Non-Maskable Interrupt (NMI) + - RETE: Exception Return (JTAG/ICE) + - CYCLES: Performance counter + + If you are unsure, please select "RETN". + +config BFIN_SCRATCH_REG_RETN + bool "RETN" + help + Use the RETN register in the Blackfin exception handler + as a stack scratch register. This means you cannot + safely use NMI on the Blackfin while running Linux, but + you can debug the system with a JTAG ICE and use the + CYCLES performance registers. + + If you are unsure, please select "RETN". + +config BFIN_SCRATCH_REG_RETE + bool "RETE" + help + Use the RETE register in the Blackfin exception handler + as a stack scratch register. This means you cannot + safely use a JTAG ICE while debugging a Blackfin board, + but you can safely use the CYCLES performance registers + and the NMI. + + If you are unsure, please select "RETN". + +config BFIN_SCRATCH_REG_CYCLES + bool "CYCLES" + help + Use the CYCLES register in the Blackfin exception handler + as a stack scratch register. This means you cannot + safely use the CYCLES performance registers on a Blackfin + board at anytime, but you can debug the system with a JTAG + ICE and use the NMI. + + If you are unsure, please select "RETN". + +endchoice + # # Sorry - but you need to put the hex address here - # diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 462ae41144c7..73647c158774 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -98,9 +98,8 @@ int show_interrupts(struct seq_file *p, void *v) */ #ifdef CONFIG_DO_IRQ_L1 -asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)__attribute__((l1_text)); +__attribute__((l1_text)) #endif - asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs; diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S index 1d5b9dbbbaa7..3be6feefa8a9 100644 --- a/arch/blackfin/mach-bf533/head.S +++ b/arch/blackfin/mach-bf533/head.S @@ -53,10 +53,12 @@ __INIT ENTRY(__start) /* R0: argument of command line string, passed from uboot, save it */ R7 = R0; - /* Set the SYSCFG register: - * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) - */ - R0 = 0x36; + /* Enable Cycle Counter and Nesting Of Interrupts */ +#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES + R0 = SYSCFG_SNEN; +#else + R0 = SYSCFG_SNEN | SYSCFG_CCEN; +#endif SYSCFG = R0; R0 = 0; diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S index 6dbcb77c8d36..0836bfdcc6c5 100644 --- a/arch/blackfin/mach-bf537/head.S +++ b/arch/blackfin/mach-bf537/head.S @@ -51,10 +51,12 @@ __INIT ENTRY(__start) /* R0: argument of command line string, passed from uboot, save it */ R7 = R0; - /* Set the SYSCFG register: - * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) - */ - R0 = 0x36; + /* Enable Cycle Counter and Nesting Of Interrupts */ +#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES + R0 = SYSCFG_SNEN; +#else + R0 = SYSCFG_SNEN | SYSCFG_CCEN; +#endif SYSCFG = R0; R0 = 0; diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S index 4c7d49f41187..937fbef26a51 100644 --- a/arch/blackfin/mach-bf548/head.S +++ b/arch/blackfin/mach-bf548/head.S @@ -50,9 +50,13 @@ ENTRY(__start) ENTRY(__stext) /* R0: argument of command line string, passed from uboot, save it */ R7 = R0; - /* Set the SYSCFG register */ - R0 = 0x36; - SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/ + /* Enable Cycle Counter and Nesting Of Interrupts */ +#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES + R0 = SYSCFG_SNEN; +#else + R0 = SYSCFG_SNEN | SYSCFG_CCEN; +#endif + SYSCFG = R0; R0 = 0; /* Clear Out All the data and pointer Registers*/ diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S index 8c9f73b8e579..139f4cff801b 100644 --- a/arch/blackfin/mach-bf561/head.S +++ b/arch/blackfin/mach-bf561/head.S @@ -51,10 +51,12 @@ __INIT ENTRY(__start) /* R0: argument of command line string, passed from uboot, save it */ R7 = R0; - /* Set the SYSCFG register: - * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) - */ - R0 = 0x36; + /* Enable Cycle Counter and Nesting Of Interrupts */ +#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES + R0 = SYSCFG_SNEN; +#else + R0 = SYSCFG_SNEN | SYSCFG_CCEN; +#endif SYSCFG = R0; R0 = 0; diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index ab278a72f282..2188f81c6456 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -58,6 +58,14 @@ #include +#if defined(CONFIG_BFIN_SCRATCH_REG_RETN) +# define EX_SCRATCH_REG RETN +#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE) +# define EX_SCRATCH_REG RETE +#else +# define EX_SCRATCH_REG CYCLES +#endif + #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 .section .l1.text #else @@ -93,7 +101,7 @@ ENTRY(_ex_icplb) call __cplb_hdr; DEBUG_START_HWTRACE(p5, r7) RESTORE_ALL_SYS - SP = RETN; + SP = EX_SCRATCH_REG; rtx; ENDPROC(_ex_icplb) @@ -102,7 +110,7 @@ ENTRY(_ex_syscall) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; raise 15; /* invoked by TRAP #0, for sys call */ - sp = retn; + sp = EX_SCRATCH_REG; rtx ENDPROC(_ex_syscall) @@ -145,7 +153,7 @@ _return_from_exception: #endif (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; - sp = retn; + sp = EX_SCRATCH_REG; rtx; ENDPROC(_ex_soft_bp) @@ -204,7 +212,7 @@ ENTRY(_ex_trap_c) DEBUG_START_HWTRACE(p5, r7) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; - SP = RETN; + SP = EX_SCRATCH_REG; raise 5; rtx; ENDPROC(_ex_trap_c) @@ -279,7 +287,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ * covered by a CPLB. Switch to an exception stack; use RETN as a * scratch register (for want of a better option). */ - retn = sp; + EX_SCRATCH_REG = sp; sp.l = _exception_stack_top; sp.h = _exception_stack_top; /* Try to deal with syscalls quickly. */ diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 1d5ba5e3d91c..c6b32fe0f6e9 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -177,27 +177,15 @@ ENTRY(_evt_ivhw) jump .Lcommon_restore_context; #endif -/* interrupt routine for evt2 - 2. This is NMI. */ -ENTRY(_evt_evt2) - SAVE_CONTEXT -#ifdef CONFIG_FRAME_POINTER - fp = 0; -#endif -#if ANOMALY_05000283 - cc = r7 == r7; - p5.h = 0xffc0; - p5.l = 0x0014; - if cc jump 1f; - r7.l = W[p5]; -1: -#endif - r0 = IRQ_NMI; - r1 = sp; - SP += -12; - call _asm_do_IRQ; - SP += 12; - RESTORE_CONTEXT +/* Interrupt routine for evt2 (NMI). + * We don't actually use this, so just return. + * For inner circle type details, please see: + * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi + */ +ENTRY(_evt_nmi) +.weak _evt_nmi rtn; +ENDPROC(_evt_nmi) /* interrupt routine for core timer - 6 */ ENTRY(_evt_timer) diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c index 684d306ab6bb..2db3546fc874 100644 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ b/arch/blackfin/mach-common/ints-priority-dc.c @@ -362,7 +362,11 @@ void __init init_exception_vectors(void) { SSYNC(); - bfin_write_EVT2(evt_evt2); + /* cannot program in software: + * evt0 - emulation (jtag) + * evt1 - reset + */ + bfin_write_EVT2(evt_nmi); bfin_write_EVT3(trap); bfin_write_EVT5(evt_ivhw); bfin_write_EVT6(evt_timer); diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index a2016af65eb0..d3b7672b2b94 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c @@ -721,7 +721,11 @@ void __init init_exception_vectors(void) { SSYNC(); - bfin_write_EVT2(evt_evt2); + /* cannot program in software: + * evt0 - emulation (jtag) + * evt1 - reset + */ + bfin_write_EVT2(evt_nmi); bfin_write_EVT3(trap); bfin_write_EVT5(evt_ivhw); bfin_write_EVT6(evt_timer); diff --git a/include/asm-blackfin/irq_handler.h b/include/asm-blackfin/irq_handler.h index 6a768315bbf7..f13cd73b0966 100644 --- a/include/asm-blackfin/irq_handler.h +++ b/include/asm-blackfin/irq_handler.h @@ -1,12 +1,15 @@ #ifndef _IRQ_HANDLER_H #define _IRQ_HANDLER_H +#include +#include + /* BASE LEVEL interrupt handler routines */ asmlinkage void evt_exception(void); asmlinkage void trap(void); asmlinkage void evt_ivhw(void); asmlinkage void evt_timer(void); -asmlinkage void evt_evt2(void); +asmlinkage void evt_nmi(void); asmlinkage void evt_evt7(void); asmlinkage void evt_evt8(void); asmlinkage void evt_evt9(void);