diff options
Diffstat (limited to 'arch/frv/kernel')
31 files changed, 648 insertions, 1309 deletions
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile index 5a827b349b5e..32db3499c461 100644 --- a/arch/frv/kernel/Makefile +++ b/arch/frv/kernel/Makefile @@ -10,15 +10,14 @@ extra-y:= head.o init_task.o vmlinux.lds obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \ process.o traps.o ptrace.o signal.o dma.o \ sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \ - debug-stub.o irq.o irq-routing.o sleep.o uaccess.o + debug-stub.o irq.o sleep.o uaccess.o obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o -obj-$(CONFIG_MB93093_PDK) += irq-mb93093.o -obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o obj-$(CONFIG_PM) += pm.o cmode.o obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o +obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o obj-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_FUTEX) += futex.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c index 9e263112a6e2..fbb19fc1af40 100644 --- a/arch/frv/kernel/asm-offsets.c +++ b/arch/frv/kernel/asm-offsets.c @@ -1 +1,115 @@ -/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */ +/* + * Generate definitions needed by assembly language modules. + * This code generates raw asm output which is post-processed + * to extract and format the required data. + */ + +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/personality.h> +#include <asm/registers.h> +#include <asm/ucontext.h> +#include <asm/processor.h> +#include <asm/thread_info.h> +#include <asm/gdb-stub.h> + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + +#define DEF_PTREG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \ + : : "i" (offsetof(struct pt_regs, reg))) + +#define DEF_IREG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \ + : : "i" (offsetof(struct user_context, reg))) + +#define DEF_FREG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \ + : : "i" (offsetof(struct user_context, reg))) + +#define DEF_0REG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \ + : : "i" (offsetof(struct frv_frame0, reg))) + +#define BLANK() asm volatile("\n->" : : ) + +#define OFFSET(sym, str, mem) \ + DEFINE(sym, offsetof(struct str, mem)); + +void foo(void) +{ + /* offsets into the thread_info structure */ + OFFSET(TI_TASK, thread_info, task); + OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain); + OFFSET(TI_FLAGS, thread_info, flags); + OFFSET(TI_STATUS, thread_info, status); + OFFSET(TI_CPU, thread_info, cpu); + OFFSET(TI_PREEMPT_COUNT, thread_info, preempt_count); + OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit); + OFFSET(TI_RESTART_BLOCK, thread_info, restart_block); + BLANK(); + + /* offsets into register file storage */ + DEF_PTREG(REG_PSR, psr); + DEF_PTREG(REG_ISR, isr); + DEF_PTREG(REG_CCR, ccr); + DEF_PTREG(REG_CCCR, cccr); + DEF_PTREG(REG_LR, lr); + DEF_PTREG(REG_LCR, lcr); + DEF_PTREG(REG_PC, pc); + DEF_PTREG(REG__STATUS, __status); + DEF_PTREG(REG_SYSCALLNO, syscallno); + DEF_PTREG(REG_ORIG_GR8, orig_gr8); + DEF_PTREG(REG_GNER0, gner0); + DEF_PTREG(REG_GNER1, gner1); + DEF_PTREG(REG_IACC0, iacc0); + DEF_PTREG(REG_TBR, tbr); + DEF_PTREG(REG_GR0, tbr); + DEFINE(REG__END, sizeof(struct pt_regs)); + BLANK(); + + DEF_0REG(REG_DCR, debug.dcr); + DEF_0REG(REG_IBAR0, debug.ibar[0]); + DEF_0REG(REG_DBAR0, debug.dbar[0]); + DEF_0REG(REG_DBDR00, debug.dbdr[0][0]); + DEF_0REG(REG_DBMR00, debug.dbmr[0][0]); + BLANK(); + + DEF_IREG(__INT_GR0, i.gr[0]); + DEF_FREG(__USER_FPMEDIA, f); + DEF_FREG(__FPMEDIA_FR0, f.fr[0]); + DEF_FREG(__FPMEDIA_FNER0, f.fner[0]); + DEF_FREG(__FPMEDIA_MSR0, f.msr[0]); + DEF_FREG(__FPMEDIA_ACC0, f.acc[0]); + DEF_FREG(__FPMEDIA_ACCG0, f.accg[0]); + DEF_FREG(__FPMEDIA_FSR0, f.fsr[0]); + BLANK(); + + DEFINE(NR_PT_REGS, sizeof(struct pt_regs) / 4); + DEFINE(NR_USER_INT_REGS, sizeof(struct user_int_regs) / 4); + DEFINE(NR_USER_FPMEDIA_REGS, sizeof(struct user_fpmedia_regs) / 4); + DEFINE(NR_USER_CONTEXT, sizeof(struct user_context) / 4); + DEFINE(FRV_FRAME0_SIZE, sizeof(struct frv_frame0)); + BLANK(); + + /* offsets into thread_struct */ + OFFSET(__THREAD_FRAME, thread_struct, frame); + OFFSET(__THREAD_CURR, thread_struct, curr); + OFFSET(__THREAD_SP, thread_struct, sp); + OFFSET(__THREAD_FP, thread_struct, fp); + OFFSET(__THREAD_LR, thread_struct, lr); + OFFSET(__THREAD_PC, thread_struct, pc); + OFFSET(__THREAD_GR16, thread_struct, gr[0]); + OFFSET(__THREAD_SCHED_LR, thread_struct, sched_lr); + OFFSET(__THREAD_FRAME0, thread_struct, frame0); + OFFSET(__THREAD_USER, thread_struct, user); + BLANK(); + + /* offsets into frv_debug_status */ + OFFSET(DEBUG_BPSR, frv_debug_status, bpsr); + OFFSET(DEBUG_DCR, frv_debug_status, dcr); + OFFSET(DEBUG_BRR, frv_debug_status, brr); + OFFSET(DEBUG_NMAR, frv_debug_status, nmar); + BLANK(); +} diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S index 687c48d62dde..dac4a5f68c2e 100644 --- a/arch/frv/kernel/break.S +++ b/arch/frv/kernel/break.S @@ -9,12 +9,11 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/setup.h> #include <asm/segment.h> #include <asm/ptrace.h> +#include <asm/thread_info.h> #include <asm/spr-regs.h> #include <asm/errno.h> @@ -24,13 +23,11 @@ # .section .bss.stack .globl __break_user_context - .balign 8192 + .balign THREAD_SIZE __break_stack: - .space (8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7 -__break_stack_tos: - .space REG__DEBUG_XTRA -__break_user_context: - .space USER_CONTEXT_SIZE + .space THREAD_SIZE - FRV_FRAME0_SIZE +__break_frame_0: + .space FRV_FRAME0_SIZE # # miscellaneous variables @@ -75,8 +72,8 @@ __entry_break: #endif LEDS 0x1001,gr31 - sethi.p %hi(__break_user_context),gr31 - setlo %lo(__break_user_context),gr31 + sethi.p %hi(__break_frame_0),gr31 + setlo %lo(__break_frame_0),gr31 stdi gr2,@(gr31,#REG_GR(2)) movsg ccr,gr3 @@ -586,8 +583,8 @@ __break_continue: # set up the kernel stack pointer sti sp,@(gr31,#REG_SP) - sethi.p %hi(__break_stack_tos),sp - setlo %lo(__break_stack_tos),sp + sethi.p %hi(__break_frame_0),sp + setlo %lo(__break_frame_0),sp # finish building the exception frame stdi gr4 ,@(gr31,#REG_GR(4)) @@ -652,9 +649,12 @@ __break_continue: movsg nmar,gr5 movsg dcr,gr6 - stdi gr4 ,@(gr31,#REG_BRR) - sti gr19,@(gr31,#REG_BPSR) - sti.p gr6 ,@(gr31,#REG_DCR) + sethi.p %hi(__debug_status),gr7 + setlo %lo(__debug_status),gr7 + + stdi gr4 ,@(gr7,#DEBUG_BRR) + sti gr19,@(gr7,#DEBUG_BPSR) + sti.p gr6 ,@(gr7,#DEBUG_DCR) # trap exceptions during break handling and disable h/w breakpoints/watchpoints sethi %hi(DCR_EBE),gr5 @@ -699,7 +699,10 @@ __break_continue: lddi @(gr31,#REG_PSR) ,gr22 ldi @(gr31,#REG_PC) ,gr21 ldi @(gr31,#REG_TBR) ,gr20 - ldi.p @(gr31,#REG_DCR) ,gr6 + + sethi.p %hi(__debug_status),gr6 + setlo %lo(__debug_status),gr6 + ldi.p @(gr6,#DEBUG_DCR) ,gr6 andi gr22,#PSR_S,gr19 /* rebuild BPSR */ andi.p gr22,#PSR_ET,gr5 diff --git a/arch/frv/kernel/cmode.S b/arch/frv/kernel/cmode.S index 6591e6a37ae9..81ba28ad2207 100644 --- a/arch/frv/kernel/cmode.S +++ b/arch/frv/kernel/cmode.S @@ -11,7 +11,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/setup.h> #include <asm/segment.h> diff --git a/arch/frv/kernel/debug-stub.c b/arch/frv/kernel/debug-stub.c index 4761cc4b4a90..2f6c60c921e0 100644 --- a/arch/frv/kernel/debug-stub.c +++ b/arch/frv/kernel/debug-stub.c @@ -39,10 +39,9 @@ do { \ gdbstub_do_rx(); \ } while(!FLOWCTL_QUERY(LINE)) -static void __init debug_stub_init(void); +struct frv_debug_status __debug_status; -extern asmlinkage void __break_hijack_kernel_event(void); -extern asmlinkage void __break_hijack_kernel_event_breaks_here(void); +static void __init debug_stub_init(void); /*****************************************************************************/ /* @@ -67,7 +66,7 @@ asmlinkage void debug_stub(void) __set_HSR(0, hsr0 & ~HSR0_ETMD); /* disable single stepping */ - __debug_regs->dcr &= ~DCR_SE; + __debug_status.dcr &= ~DCR_SE; /* kernel mode can propose an exception be handled in debug mode by jumping to a special * location */ @@ -76,8 +75,8 @@ asmlinkage void debug_stub(void) * the top kernel context */ *__debug_frame = *__frame; __frame = __debug_frame->next_frame; - __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; - __debug_regs->brr |= BRR_EB; + __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12; + __debug_status.brr |= BRR_EB; } if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) { @@ -124,7 +123,7 @@ static void __init debug_stub_init(void) __debug_frame->pc = (unsigned long) start_kernel; /* enable the debug events we want to trap */ - __debug_regs->dcr = DCR_EBE; + __debug_status.dcr = DCR_EBE; #ifdef CONFIG_GDBSTUB gdbstub_init(); diff --git a/arch/frv/kernel/entry-table.S b/arch/frv/kernel/entry-table.S index 81568acea9cd..d3b9253d862a 100644 --- a/arch/frv/kernel/entry-table.S +++ b/arch/frv/kernel/entry-table.S @@ -11,7 +11,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/spr-regs.h> diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 81d94e41a189..940ac306e9a0 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -27,8 +27,6 @@ * */ -#include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/thread_info.h> #include <asm/setup.h> diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index dee637fffda5..f772704b3d28 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -7,7 +7,6 @@ #include <linux/elfcore.h> #include <linux/in6.h> #include <linux/interrupt.h> -#include <linux/config.h> #include <asm/setup.h> #include <asm/pgalloc.h> diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c index 508601fad079..9550f37fb62c 100644 --- a/arch/frv/kernel/gdb-stub.c +++ b/arch/frv/kernel/gdb-stub.c @@ -124,6 +124,7 @@ #include <linux/slab.h> #include <linux/nmi.h> +#include <asm/asm-offsets.h> #include <asm/pgtable.h> #include <asm/system.h> #include <asm/gdb-stub.h> @@ -136,7 +137,6 @@ extern void debug_to_serial(const char *p, int n); extern void gdbstub_console_write(struct console *co, const char *p, unsigned n); extern volatile uint32_t __break_error_detect[3]; /* ESFR1, ESR15, EAR15 */ -extern struct user_context __break_user_context; struct __debug_amr { unsigned long L, P; @@ -926,6 +926,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE0)) { //gdbstub_printk("set h/w break 0: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE0; + __debug_regs->ibar[0] = addr; asm volatile("movgs %0,ibar0" : : "r"(addr)); return 0; } @@ -933,6 +934,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE1)) { //gdbstub_printk("set h/w break 1: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE1; + __debug_regs->ibar[1] = addr; asm volatile("movgs %0,ibar1" : : "r"(addr)); return 0; } @@ -940,6 +942,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE2)) { //gdbstub_printk("set h/w break 2: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE2; + __debug_regs->ibar[2] = addr; asm volatile("movgs %0,ibar2" : : "r"(addr)); return 0; } @@ -947,6 +950,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE3)) { //gdbstub_printk("set h/w break 3: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE3; + __debug_regs->ibar[3] = addr; asm volatile("movgs %0,ibar3" : : "r"(addr)); return 0; } @@ -971,7 +975,14 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & (DCR_DRBE0|DCR_DWBE0))) { //gdbstub_printk("set h/w watchpoint 0 type %ld: %08lx\n", type, addr); tmp = type==2 ? DCR_DWBE0 : type==3 ? DCR_DRBE0 : DCR_DRBE0|DCR_DWBE0; + __debug_regs->dcr |= tmp; + __debug_regs->dbar[0] = addr; + __debug_regs->dbmr[0][0] = dbmr.mask0; + __debug_regs->dbmr[0][1] = dbmr.mask1; + __debug_regs->dbdr[0][0] = 0; + __debug_regs->dbdr[0][1] = 0; + asm volatile(" movgs %0,dbar0 \n" " movgs %1,dbmr00 \n" " movgs %2,dbmr01 \n" @@ -984,7 +995,14 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & (DCR_DRBE1|DCR_DWBE1))) { //gdbstub_printk("set h/w watchpoint 1 type %ld: %08lx\n", type, addr); tmp = type==2 ? DCR_DWBE1 : type==3 ? DCR_DRBE1 : DCR_DRBE1|DCR_DWBE1; + __debug_regs->dcr |= tmp; + __debug_regs->dbar[1] = addr; + __debug_regs->dbmr[1][0] = dbmr.mask0; + __debug_regs->dbmr[1][1] = dbmr.mask1; + __debug_regs->dbdr[1][0] = 0; + __debug_regs->dbdr[1][1] = 0; + asm volatile(" movgs %0,dbar1 \n" " movgs %1,dbmr10 \n" " movgs %2,dbmr11 \n" @@ -1047,6 +1065,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE0 && __get_ibar(0) == addr) { //gdbstub_printk("clear h/w break 0: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE0; + __debug_regs->ibar[0] = 0; asm volatile("movgs gr0,ibar0"); return 0; } @@ -1054,6 +1073,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE1 && __get_ibar(1) == addr) { //gdbstub_printk("clear h/w break 1: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE1; + __debug_regs->ibar[1] = 0; asm volatile("movgs gr0,ibar1"); return 0; } @@ -1061,6 +1081,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE2 && __get_ibar(2) == addr) { //gdbstub_printk("clear h/w break 2: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE2; + __debug_regs->ibar[2] = 0; asm volatile("movgs gr0,ibar2"); return 0; } @@ -1068,6 +1089,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE3 && __get_ibar(3) == addr) { //gdbstub_printk("clear h/w break 3: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE3; + __debug_regs->ibar[3] = 0; asm volatile("movgs gr0,ibar3"); return 0; } @@ -1104,6 +1126,12 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo //gdbstub_printk("clear h/w watchpoint 0 type %ld: %08lx\n", type, addr); __debug_regs->dcr &= ~(DCR_DRBE0|DCR_DWBE0); + __debug_regs->dbar[0] = 0; + __debug_regs->dbmr[0][0] = 0; + __debug_regs->dbmr[0][1] = 0; + __debug_regs->dbdr[0][0] = 0; + __debug_regs->dbdr[0][1] = 0; + asm volatile(" movgs gr0,dbar0 \n" " movgs gr0,dbmr00 \n" " movgs gr0,dbmr01 \n" @@ -1123,6 +1151,12 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo //gdbstub_printk("clear h/w watchpoint 1 type %ld: %08lx\n", type, addr); __debug_regs->dcr &= ~(DCR_DRBE1|DCR_DWBE1); + __debug_regs->dbar[1] = 0; + __debug_regs->dbmr[1][0] = 0; + __debug_regs->dbmr[1][1] = 0; + __debug_regs->dbdr[1][0] = 0; + __debug_regs->dbdr[1][1] = 0; + asm volatile(" movgs gr0,dbar1 \n" " movgs gr0,dbmr10 \n" " movgs gr0,dbmr11 \n" @@ -1163,7 +1197,7 @@ static void gdbstub_check_breakpoint(void) */ static void __attribute__((unused)) gdbstub_show_regs(void) { - uint32_t *reg; + unsigned long *reg; int loop; gdbstub_printk("\n"); @@ -1172,11 +1206,11 @@ static void __attribute__((unused)) gdbstub_show_regs(void) __debug_frame, __debug_frame->psr & PSR_S ? "kernel" : "user"); - reg = (uint32_t *) __debug_frame; - for (loop = 0; loop < REG__END; loop++) { - printk("%s %08x", regnames[loop + 0], reg[loop + 0]); + reg = (unsigned long *) __debug_frame; + for (loop = 0; loop < NR_PT_REGS; loop++) { + printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); - if (loop == REG__END - 1 || loop % 5 == 4) + if (loop == NR_PT_REGS - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); @@ -1191,13 +1225,8 @@ static void __attribute__((unused)) gdbstub_show_regs(void) */ static void __attribute__((unused)) gdbstub_dump_debugregs(void) { - unsigned long x; - - x = __debug_regs->dcr; - gdbstub_printk("DCR %08lx ", x); - - x = __debug_regs->brr; - gdbstub_printk("BRR %08lx\n", x); + gdbstub_printk("DCR %08lx ", __debug_status.dcr); + gdbstub_printk("BRR %08lx\n", __debug_status.brr); gdbstub_printk("IBAR0 %08lx ", __get_ibar(0)); gdbstub_printk("IBAR1 %08lx ", __get_ibar(1)); @@ -1360,7 +1389,7 @@ void gdbstub(int sigval) #endif } - save_user_regs(&__break_user_context); + save_user_regs(&__debug_frame0->uc); #if 0 gdbstub_printk("--> gdbstub() %08x %p %08x %08x\n", @@ -1389,8 +1418,8 @@ void gdbstub(int sigval) __debug_frame->psr &= ~PSR_S; if (__debug_frame->psr & PSR_PS) __debug_frame->psr |= PSR_S; - __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; - __debug_regs->brr |= BRR_EB; + __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12; + __debug_status.brr |= BRR_EB; sigval = SIGINT; } @@ -1404,15 +1433,15 @@ void gdbstub(int sigval) __debug_frame->psr &= ~PSR_S; if (__debug_frame->psr & PSR_PS) __debug_frame->psr |= PSR_S; - __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; - __debug_regs->brr |= BRR_EB; + __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12; + __debug_status.brr |= BRR_EB; sigval = SIGXCPU; } LEDS(0x5002); /* after a BREAK insn, the PC lands on the far side of it */ - if (__debug_regs->brr & BRR_SB) + if (__debug_status.brr & BRR_SB) gdbstub_check_breakpoint(); LEDS(0x5003); @@ -1431,7 +1460,7 @@ void gdbstub(int sigval) } if (!sigval) - sigval = gdbstub_compute_signal(__debug_regs->brr); + sigval = gdbstub_compute_signal(__debug_status.brr); LEDS(0x5004); @@ -1441,7 +1470,7 @@ void gdbstub(int sigval) if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) { static const char title[] = "Break "; static const char crlf[] = "\r\n"; - unsigned long brr = __debug_regs->brr; + unsigned long brr = __debug_status.brr; char hx; ptr = output_buffer; @@ -1565,28 +1594,24 @@ void gdbstub(int sigval) ptr = mem2hex(&zero, ptr, 4, 0); for (loop = 1; loop <= 27; loop++) - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[loop], ptr, 4, 0); temp = (unsigned long) __frame; ptr = mem2hex(&temp, ptr, 4, 0); - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(29), ptr, 4, 0); - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(30), ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[29], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[30], ptr, 4, 0); #ifdef CONFIG_MMU - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(31), ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[31], ptr, 4, 0); #else temp = (unsigned long) __debug_frame; ptr = mem2hex(&temp, ptr, 4, 0); #endif for (loop = 32; loop <= 63; loop++) - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[loop], ptr, 4, 0); /* deal with FR0-FR63 */ for (loop = 0; loop <= 63; loop++) - ptr = mem2hex((unsigned long *)&__break_user_context + - __FPMEDIA_FR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fr[loop], ptr, 4, 0); /* deal with special registers */ ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0); @@ -1597,7 +1622,7 @@ void gdbstub(int sigval) ptr = mem2hex(&zero, ptr, 4, 0); ptr = mem2hex(&zero, ptr, 4, 0); ptr = mem2hex(&__debug_frame->tbr, ptr, 4, 0); - ptr = mem2hex(&__debug_regs->brr , ptr, 4, 0); + ptr = mem2hex(&__debug_status.brr , ptr, 4, 0); asm volatile("movsg dbar0,%0" : "=r"(dbar)); ptr = mem2hex(&dbar, ptr, 4, 0); @@ -1622,21 +1647,21 @@ void gdbstub(int sigval) ptr = mem2hex(&__debug_frame->iacc0, ptr, 8, 0); - ptr = mem2hex(&__break_user_context.f.fsr[0], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fsr[0], ptr, 4, 0); for (loop = 0; loop <= 7; loop++) - ptr = mem2hex(&__break_user_context.f.acc[loop], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.acc[loop], ptr, 4, 0); - ptr = mem2hex(&__break_user_context.f.accg, ptr, 8, 0); + ptr = mem2hex(&__debug_user_context->f.accg, ptr, 8, 0); for (loop = 0; loop <= 1; loop++) - ptr = mem2hex(&__break_user_context.f.msr[loop], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.msr[loop], ptr, 4, 0); ptr = mem2hex(&__debug_frame->gner0, ptr, 4, 0); ptr = mem2hex(&__debug_frame->gner1, ptr, 4, 0); - ptr = mem2hex(&__break_user_context.f.fner[0], ptr, 4, 0); - ptr = mem2hex(&__break_user_context.f.fner[1], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fner[0], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fner[1], ptr, 4, 0); break; @@ -1648,8 +1673,7 @@ void gdbstub(int sigval) ptr = hex2mem(ptr, &temp, 4); for (loop = 1; loop <= 27; loop++) - ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop), - 4); + ptr = hex2mem(ptr, &__debug_user_context->i.gr[loop], 4); ptr = hex2mem(ptr, &temp, 4); __frame = (struct pt_regs *) temp; @@ -1662,14 +1686,11 @@ void gdbstub(int sigval) #endif for (loop = 32; loop <= 63; loop++) - ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop), - 4); + ptr = hex2mem(ptr, &__debug_user_context->i.gr[loop], 4); /* deal with FR0-FR63 */ for (loop = 0; loop <= 63; loop++) - ptr = mem2hex((unsigned long *)&__break_user_context + - __FPMEDIA_FR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fr[loop], ptr, 4, 0); /* deal with special registers */ ptr = hex2mem(ptr, &__debug_frame->pc, 4); @@ -1694,21 +1715,21 @@ void gdbstub(int sigval) ptr = hex2mem(ptr, &__debug_frame->iacc0, 8); - ptr = hex2mem(ptr, &__break_user_context.f.fsr[0], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.fsr[0], 4); for (loop = 0; loop <= 7; loop++) - ptr = hex2mem(ptr, &__break_user_context.f.acc[loop], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.acc[loop], 4); - ptr = hex2mem(ptr, &__break_user_context.f.accg, 8); + ptr = hex2mem(ptr, &__debug_user_context->f.accg, 8); for (loop = 0; loop <= 1; loop++) - ptr = hex2mem(ptr, &__break_user_context.f.msr[loop], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.msr[loop], 4); ptr = hex2mem(ptr, &__debug_frame->gner0, 4); ptr = hex2mem(ptr, &__debug_frame->gner1, 4); - ptr = hex2mem(ptr, &__break_user_context.f.fner[0], 4); - ptr = hex2mem(ptr, &__break_user_context.f.fner[1], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.fner[0], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.fner[1], 4); gdbstub_strcpy(output_buffer,"OK"); break; @@ -1769,52 +1790,52 @@ void gdbstub(int sigval) case GDB_REG_GR(0): break; case GDB_REG_GR(1) ... GDB_REG_GR(63): - __break_user_context.i.gr[addr - GDB_REG_GR(0)] = temp; + __debug_user_context->i.gr[addr - GDB_REG_GR(0)] = temp; break; case GDB_REG_FR(0) ... GDB_REG_FR(63): - __break_user_context.f.fr[addr - GDB_REG_FR(0)] = temp; + __debug_user_context->f.fr[addr - GDB_REG_FR(0)] = temp; break; case GDB_REG_PC: - __break_user_context.i.pc = temp; + __debug_user_context->i.pc = temp; break; case GDB_REG_PSR: - __break_user_context.i.psr = temp; + __debug_user_context->i.psr = temp; break; case GDB_REG_CCR: - __break_user_context.i.ccr = temp; + __debug_user_context->i.ccr = temp; break; case GDB_REG_CCCR: - __break_user_context.i.cccr = temp; + __debug_user_context->i.cccr = temp; break; case GDB_REG_BRR: - __debug_regs->brr = temp; + __debug_status.brr = temp; break; case GDB_REG_LR: - __break_user_context.i.lr = temp; + __debug_user_context->i.lr = temp; break; case GDB_REG_LCR: - __break_user_context.i.lcr = temp; + __debug_user_context->i.lcr = temp; break; case GDB_REG_FSR0: - __break_user_context.f.fsr[0] = temp; + __debug_user_context->f.fsr[0] = temp; break; case GDB_REG_ACC(0) ... GDB_REG_ACC(7): - __break_user_context.f.acc[addr - GDB_REG_ACC(0)] = temp; + __debug_user_context->f.acc[addr - GDB_REG_ACC(0)] = temp; break; case GDB_REG_ACCG(0): - *(uint32_t *) &__break_user_context.f.accg[0] = temp; + *(uint32_t *) &__debug_user_context->f.accg[0] = temp; break; case GDB_REG_ACCG(4): - *(uint32_t *) &__break_user_context.f.accg[4] = temp; + *(uint32_t *) &__debug_user_context->f.accg[4] = temp; break; case GDB_REG_MSR(0) ... GDB_REG_MSR(1): - __break_user_context.f.msr[addr - GDB_REG_MSR(0)] = temp; + __debug_user_context->f.msr[addr - GDB_REG_MSR(0)] = temp; break; case GDB_REG_GNER(0) ... GDB_REG_GNER(1): - __break_user_context.i.gner[addr - GDB_REG_GNER(0)] = temp; + __debug_user_context->i.gner[addr - GDB_REG_GNER(0)] = temp; break; case GDB_REG_FNER(0) ... GDB_REG_FNER(1): - __break_user_context.f.fner[addr - GDB_REG_FNER(0)] = temp; + __debug_user_context->f.fner[addr - GDB_REG_FNER(0)] = temp; break; default: temp2 = 0; @@ -1850,6 +1871,7 @@ void gdbstub(int sigval) /* step to next instruction */ case 's': __debug_regs->dcr |= DCR_SE; + __debug_status.dcr |= DCR_SE; goto done; /* set baud rate (bBB) */ @@ -1934,7 +1956,7 @@ void gdbstub(int sigval) } done: - restore_user_regs(&__break_user_context); + restore_user_regs(&__debug_frame0->uc); //gdbstub_dump_debugregs(); //gdbstub_printk("<-- gdbstub() %08x\n", __debug_frame->pc); @@ -1966,7 +1988,6 @@ void __init gdbstub_init(void) #endif gdbstub_printk("%s", gdbstub_banner); - gdbstub_printk("DCR: %x\n", __debug_regs->dcr); gdbstub_io_init(); diff --git a/arch/frv/kernel/head-mmu-fr451.S b/arch/frv/kernel/head-mmu-fr451.S index a143c2f66ee5..c8f210d84ff5 100644 --- a/arch/frv/kernel/head-mmu-fr451.S +++ b/arch/frv/kernel/head-mmu-fr451.S @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> diff --git a/arch/frv/kernel/head-uc-fr401.S b/arch/frv/kernel/head-uc-fr401.S index 4ccf8414ae44..ee282be20fff 100644 --- a/arch/frv/kernel/head-uc-fr401.S +++ b/arch/frv/kernel/head-uc-fr401.S @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> diff --git a/arch/frv/kernel/head-uc-fr451.S b/arch/frv/kernel/head-uc-fr451.S index 31cb54a6f080..b10d9c8295d2 100644 --- a/arch/frv/kernel/head-uc-fr451.S +++ b/arch/frv/kernel/head-uc-fr451.S @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> diff --git a/arch/frv/kernel/head-uc-fr555.S b/arch/frv/kernel/head-uc-fr555.S index d088db2699bf..39937c19b460 100644 --- a/arch/frv/kernel/head-uc-fr555.S +++ b/arch/frv/kernel/head-uc-fr555.S @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> diff --git a/arch/frv/kernel/head.S b/arch/frv/kernel/head.S index 29a5265489b7..fecf751c5cae 100644 --- a/arch/frv/kernel/head.S +++ b/arch/frv/kernel/head.S @@ -9,9 +9,9 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <linux/linkage.h> +#include <asm/thread_info.h> #include <asm/ptrace.h> #include <asm/page.h> #include <asm/spr-regs.h> diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c index 9778e0ff7c1c..369bc0a7443d 100644 --- a/arch/frv/kernel/irq-mb93091.c +++ b/arch/frv/kernel/irq-mb93091.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -25,7 +24,6 @@ #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) @@ -34,83 +32,131 @@ #define __get_IFR() ({ __reg16(0xffc0000c); }) #define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0) -static void frv_fpga_doirq(struct irq_source *source); -static void frv_fpga_control(struct irq_group *group, int irq, int on); -/*****************************************************************************/ /* - * FPGA IRQ multiplexor + * on-motherboard FPGA PIC operations */ -static struct irq_source frv_fpga[4] = { -#define __FPGA(X, M) \ - [X] = { \ - .muxname = "fpga."#X, \ - .irqmask = M, \ - .doirq = frv_fpga_doirq, \ - } +static void frv_fpga_mask(unsigned int irq) +{ + uint16_t imr = __get_IMR(); - __FPGA(0, 0x0028), - __FPGA(1, 0x0050), - __FPGA(2, 0x1c00), - __FPGA(3, 0x6386), -}; + imr |= 1 << (irq - IRQ_BASE_FPGA); -static struct irq_group frv_fpga_irqs = { - .first_irq = IRQ_BASE_FPGA, - .control = frv_fpga_control, - .sources = { - [ 1] = &frv_fpga[3], - [ 2] = &frv_fpga[3], - [ 3] = &frv_fpga[0], - [ 4] = &frv_fpga[1], - [ 5] = &frv_fpga[0], - [ 6] = &frv_fpga[1], - [ 7] = &frv_fpga[3], - [ 8] = &frv_fpga[3], - [ 9] = &frv_fpga[3], - [10] = &frv_fpga[2], - [11] = &frv_fpga[2], - [12] = &frv_fpga[2], - [13] = &frv_fpga[3], - [14] = &frv_fpga[3], - }, -}; + __set_IMR(imr); +} +static void frv_fpga_ack(unsigned int irq) +{ + __clr_IFR(1 << (irq - IRQ_BASE_FPGA)); +} -static void frv_fpga_control(struct irq_group *group, int index, int on) +static void frv_fpga_mask_ack(unsigned int irq) { uint16_t imr = __get_IMR(); - if (on) - imr &= ~(1 << index); - else - imr |= 1 << index; + imr |= 1 << (irq - IRQ_BASE_FPGA); + __set_IMR(imr); + + __clr_IFR(1 << (irq - IRQ_BASE_FPGA)); +} + +static void frv_fpga_unmask(unsigned int irq) +{ + uint16_t imr = __get_IMR(); + + imr &= ~(1 << (irq - IRQ_BASE_FPGA)); __set_IMR(imr); } -static void frv_fpga_doirq(struct irq_source *source) +static struct irq_chip frv_fpga_pic = { + .name = "mb93091", + .ack = frv_fpga_ack, + .mask = frv_fpga_mask, + .mask_ack = frv_fpga_mask_ack, + .unmask = frv_fpga_unmask, +}; + +/* + * FPGA PIC interrupt handler + */ +static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs) { - uint16_t mask, imr; + uint16_t imr, mask = (unsigned long) _mask; imr = __get_IMR(); - mask = source->irqmask & ~imr & __get_IFR(); - if (mask) { - __set_IMR(imr | mask); - __clr_IFR(mask); - distribute_irqs(&frv_fpga_irqs, mask); - __set_IMR(imr); + mask = mask & ~imr & __get_IFR(); + + /* poll all the triggered IRQs */ + while (mask) { + int irq; + + asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask)); + irq = 31 - irq; + mask &= ~(1 << irq); + + generic_handle_irq(IRQ_BASE_FPGA + irq, regs); } + + return IRQ_HANDLED; } +/* + * define an interrupt action for each FPGA PIC output + * - use dev_id to indicate the FPGA PIC input to output mappings + */ +static struct irqaction fpga_irq[4] = { + [0] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .mask = CPU_MASK_NONE, + .name = "fpga.0", + .dev_id = (void *) 0x0028UL, + }, + [1] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .mask = CPU_MASK_NONE, + .name = "fpga.1", + .dev_id = (void *) 0x0050UL, + }, + [2] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .mask = CPU_MASK_NONE, + .name = "fpga.2", + .dev_id = (void *) 0x1c00UL, + }, + [3] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .mask = CPU_MASK_NONE, + .name = "fpga.3", + .dev_id = (void *) 0x6386UL, + } +}; + +/* + * initialise the motherboard FPGA's PIC + */ void __init fpga_init(void) { + int irq; + + /* all PIC inputs are all set to be low-level driven, apart from the + * NMI button (15) which is fixed at falling-edge + */ __set_IMR(0x7ffe); __clr_IFR(0x0000); - frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0); - frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1); - frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2); - frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3); - frv_irq_set_group(&frv_fpga_irqs); + for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++) + set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq); + + set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq); + + /* the FPGA drives the first four external IRQ inputs on the CPU PIC */ + setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]); + setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]); + setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]); + setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]); } diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c index 21ca2b298247..a43a22158956 100644 --- a/arch/frv/kernel/irq-mb93093.c +++ b/arch/frv/kernel/irq-mb93093.c @@ -1,6 +1,6 @@ /* irq-mb93093.c: MB93093 FPGA interrupt handling * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -25,7 +24,6 @@ #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR))) @@ -34,66 +32,102 @@ #define __get_IFR() ({ __reg16(0x02); }) #define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0) -static void frv_fpga_doirq(struct irq_source *source); -static void frv_fpga_control(struct irq_group *group, int irq, int on); - -/*****************************************************************************/ /* - * FPGA IRQ multiplexor + * off-CPU FPGA PIC operations */ -static struct irq_source frv_fpga[4] = { -#define __FPGA(X, M) \ - [X] = { \ - .muxname = "fpga."#X, \ - .irqmask = M, \ - .doirq = frv_fpga_doirq, \ - } +static void frv_fpga_mask(unsigned int irq) +{ + uint16_t imr = __get_IMR(); - __FPGA(0, 0x0700), -}; + imr |= 1 << (irq - IRQ_BASE_FPGA); + __set_IMR(imr); +} -static struct irq_group frv_fpga_irqs = { - .first_irq = IRQ_BASE_FPGA, - .control = frv_fpga_control, - .sources = { - [ 8] = &frv_fpga[0], - [ 9] = &frv_fpga[0], - [10] = &frv_fpga[0], - }, -}; +static void frv_fpga_ack(unsigned int irq) +{ + __clr_IFR(1 << (irq - IRQ_BASE_FPGA)); +} + +static void frv_fpga_mask_ack(unsigned int irq) +{ + uint16_t imr = __get_IMR(); + imr |= 1 << (irq - IRQ_BASE_FPGA); + __set_IMR(imr); + + __clr_IFR(1 << (irq - IRQ_BASE_FPGA)); +} -static void frv_fpga_control(struct irq_group *group, int index, int on) +static void frv_fpga_unmask(unsigned int irq) { uint16_t imr = __get_IMR(); - if (on) - imr &= ~(1 << index); - else - imr |= 1 << index; + imr &= ~(1 << (irq - IRQ_BASE_FPGA)); __set_IMR(imr); } -static void frv_fpga_doirq(struct irq_source *source) +static struct irq_chip frv_fpga_pic = { + .name = "mb93093", + .ack = frv_fpga_ack, + .mask = frv_fpga_mask, + .mask_ack = frv_fpga_mask_ack, + .unmask = frv_fpga_unmask, + .end = frv_fpga_end, +}; + +/* + * FPGA PIC interrupt handler + */ +static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs) { - uint16_t mask, imr; + uint16_t imr, mask = (unsigned long) _mask; imr = __get_IMR(); - mask = source->irqmask & ~imr & __get_IFR(); - if (mask) { - __set_IMR(imr | mask); - __clr_IFR(mask); - distribute_irqs(&frv_fpga_irqs, mask); - __set_IMR(imr); + mask = mask & ~imr & __get_IFR(); + + /* poll all the triggered IRQs */ + while (mask) { + int irq; + + asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask)); + irq = 31 - irq; + mask &= ~(1 << irq); + + generic_irq_handle(IRQ_BASE_FPGA + irq, regs); } + + return IRQ_HANDLED; } +/* + * define an interrupt action for each FPGA PIC output + * - use dev_id to indicate the FPGA PIC input to output mappings + */ +static struct irqaction fpga_irq[1] = { + [0] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "fpga.0", + .dev_id = (void *) 0x0700UL, + } +}; + +/* + * initialise the motherboard FPGA's PIC + */ void __init fpga_init(void) { + int irq; + + /* all PIC inputs are all set to be edge triggered */ __set_IMR(0x0700); __clr_IFR(0x0000); - frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2); - frv_irq_set_group(&frv_fpga_irqs); + for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++) + set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq); + + /* the FPGA drives external IRQ input #2 on the CPU PIC */ + setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]); } diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c index c003ae5e2b30..39c0188a3498 100644 --- a/arch/frv/kernel/irq-mb93493.c +++ b/arch/frv/kernel/irq-mb93493.c @@ -1,6 +1,6 @@ /* irq-mb93493.c: MB93493 companion chip interrupt handler * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -25,84 +24,126 @@ #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #include <asm/mb93493-irqs.h> +#include <asm/mb93493-regs.h> -static void frv_mb93493_doirq(struct irq_source *source); +#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493)) + +#define IRQ_ROUTING \ + (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN)) -/*****************************************************************************/ /* - * MB93493 companion chip IRQ multiplexor + * daughter board PIC operations + * - there is no way to ACK interrupts in the MB93493 chip */ -static struct irq_source frv_mb93493[2] = { - [0] = { - .muxname = "mb93493.0", - .muxdata = __region_CS3 + 0x3d0, - .doirq = frv_mb93493_doirq, - .irqmask = 0x0000, - }, - [1] = { - .muxname = "mb93493.1", - .muxdata = __region_CS3 + 0x3d4, - .doirq = frv_mb93493_doirq, - .irqmask = 0x0000, - }, -}; - -static void frv_mb93493_control(struct irq_group *group, int index, int on) +static void frv_mb93493_mask(unsigned int irq) { - struct irq_source *source; uint32_t iqsr; + volatile void *piqsr; - if ((frv_mb93493[0].irqmask & (1 << index))) - source = &frv_mb93493[0]; + if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493))) + piqsr = __addr_MB93493_IQSR(1); else - source = &frv_mb93493[1]; + piqsr = __addr_MB93493_IQSR(0); + + iqsr = readl(piqsr); + iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16)); + writel(iqsr, piqsr); +} - iqsr = readl(source->muxdata); - if (on) - iqsr |= 1 << (index + 16); +static void frv_mb93493_ack(unsigned int irq) +{ +} + +static void frv_mb93493_unmask(unsigned int irq) +{ + uint32_t iqsr; + volatile void *piqsr; + + if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493))) + piqsr = __addr_MB93493_IQSR(1); else - iqsr &= ~(1 << (index + 16)); + piqsr = __addr_MB93493_IQSR(0); - writel(iqsr, source->muxdata); + iqsr = readl(piqsr); + iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16); + writel(iqsr, piqsr); } -static struct irq_group frv_mb93493_irqs = { - .first_irq = IRQ_BASE_MB93493, - .control = frv_mb93493_control, +static struct irq_chip frv_mb93493_pic = { + .name = "mb93093", + .ack = frv_mb93493_ack, + .mask = frv_mb93493_mask, + .mask_ack = frv_mb93493_mask, + .unmask = frv_mb93493_unmask, }; -static void frv_mb93493_doirq(struct irq_source *source) +/* + * MB93493 PIC interrupt handler + */ +static irqreturn_t mb93493_interrupt(int irq, void *_piqsr, struct pt_regs *regs) { - uint32_t mask = readl(source->muxdata); - mask = mask & (mask >> 16) & 0xffff; + volatile void *piqsr = _piqsr; + uint32_t iqsr; - if (mask) - distribute_irqs(&frv_mb93493_irqs, mask); -} + iqsr = readl(piqsr); + iqsr = iqsr & (iqsr >> 16) & 0xffff; -static void __init mb93493_irq_route(int irq, int source) -{ - frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493); - frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source]; + /* poll all the triggered IRQs */ + while (iqsr) { + int irq; + + asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr)); + irq = 31 - irq; + iqsr &= ~(1 << irq); + + generic_handle_irq(IRQ_BASE_MB93493 + irq, regs); + } + + return IRQ_HANDLED; } -void __init route_mb93493_irqs(void) +/* + * define an interrupt action for each MB93493 PIC output + * - use dev_id to indicate the MB93493 PIC input to output mappings + */ +static struct irqaction mb93493_irq[2] = { + [0] = { + .handler = mb93493_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .mask = CPU_MASK_NONE, + .name = "mb93493.0", + .dev_id = (void *) __addr_MB93493_IQSR(0), + }, + [1] = { + .handler = mb93493_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .mask = CPU_MASK_NONE, + .name = "mb93493.1", + .dev_id = (void *) __addr_MB93493_IQSR(1), + } +}; + +/* + * initialise the motherboard MB93493's PIC + */ +void __init mb93493_init(void) { - frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0); - frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1); - - frv_irq_set_group(&frv_mb93493_irqs); - - mb93493_irq_route(IRQ_MB93493_VDC, IRQ_MB93493_VDC_ROUTE); - mb93493_irq_route(IRQ_MB93493_VCC, IRQ_MB93493_VCC_ROUTE); - mb93493_irq_route(IRQ_MB93493_AUDIO_IN, IRQ_MB93493_AUDIO_IN_ROUTE); - mb93493_irq_route(IRQ_MB93493_I2C_0, IRQ_MB93493_I2C_0_ROUTE); - mb93493_irq_route(IRQ_MB93493_I2C_1, IRQ_MB93493_I2C_1_ROUTE); - mb93493_irq_route(IRQ_MB93493_USB, IRQ_MB93493_USB_ROUTE); - mb93493_irq_route(IRQ_MB93493_LOCAL_BUS, IRQ_MB93493_LOCAL_BUS_ROUTE); - mb93493_irq_route(IRQ_MB93493_PCMCIA, IRQ_MB93493_PCMCIA_ROUTE); - mb93493_irq_route(IRQ_MB93493_GPIO, IRQ_MB93493_GPIO_ROUTE); - mb93493_irq_route(IRQ_MB93493_AUDIO_OUT, IRQ_MB93493_AUDIO_OUT_ROUTE); + int irq; + + for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++) + set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq); + + /* the MB93493 drives external IRQ inputs on the CPU PIC */ + setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]); + setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]); } diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c deleted file mode 100644 index b90b70a761d1..000000000000 --- a/arch/frv/kernel/irq-routing.c +++ /dev/null @@ -1,291 +0,0 @@ -/* irq-routing.c: IRQ routing - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/sched.h> -#include <linux/random.h> -#include <linux/init.h> -#include <linux/serial_reg.h> -#include <asm/io.h> -#include <asm/irq-routing.h> -#include <asm/irc-regs.h> -#include <asm/serial-regs.h> -#include <asm/dma.h> - -struct irq_level frv_irq_levels[16] = { - [0 ... 15] = { - .lock = SPIN_LOCK_UNLOCKED, - } -}; - -struct irq_group *irq_groups[NR_IRQ_GROUPS]; - -extern struct irq_group frv_cpu_irqs; - -void __init frv_irq_route(struct irq_source *source, int irqlevel) -{ - source->level = &frv_irq_levels[irqlevel]; - source->next = frv_irq_levels[irqlevel].sources; - frv_irq_levels[irqlevel].sources = source; -} - -void __init frv_irq_route_external(struct irq_source *source, int irq) -{ - int irqlevel = 0; - - switch (irq) { - case IRQ_CPU_EXTERNAL0: irqlevel = IRQ_XIRQ0_LEVEL; break; - case IRQ_CPU_EXTERNAL1: irqlevel = IRQ_XIRQ1_LEVEL; break; - case IRQ_CPU_EXTERNAL2: irqlevel = IRQ_XIRQ2_LEVEL; break; - case IRQ_CPU_EXTERNAL3: irqlevel = IRQ_XIRQ3_LEVEL; break; - case IRQ_CPU_EXTERNAL4: irqlevel = IRQ_XIRQ4_LEVEL; break; - case IRQ_CPU_EXTERNAL5: irqlevel = IRQ_XIRQ5_LEVEL; break; - case IRQ_CPU_EXTERNAL6: irqlevel = IRQ_XIRQ6_LEVEL; break; - case IRQ_CPU_EXTERNAL7: irqlevel = IRQ_XIRQ7_LEVEL; break; - default: BUG(); - } - - source->level = &frv_irq_levels[irqlevel]; - source->next = frv_irq_levels[irqlevel].sources; - frv_irq_levels[irqlevel].sources = source; -} - -void __init frv_irq_set_group(struct irq_group *group) -{ - irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group; -} - -void distribute_irqs(struct irq_group *group, unsigned long irqmask) -{ - struct irqaction *action; - int irq; - - while (irqmask) { - asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask)); - if (irq < 0 || irq > 31) - asm volatile("break"); - irq = 31 - irq; - - irqmask &= ~(1 << irq); - action = group->actions[irq]; - - irq += group->first_irq; - - if (action) { - int status = 0; - -// if (!(action->flags & SA_INTERRUPT)) -// local_irq_enable(); - - do { - status |= action->flags; - action->handler(irq, action->dev_id, __frame); - action = action->next; - } while (action); - - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - } - } -} - -/*****************************************************************************/ -/* - * CPU UART interrupts - */ -static void frv_cpuuart_doirq(struct irq_source *source) -{ -// uint8_t iir = readb(source->muxdata + UART_IIR * 8); -// if ((iir & 0x0f) != UART_IIR_NO_INT) - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cpuuart[2] = { -#define __CPUUART(X, A) \ - [X] = { \ - .muxname = "uart", \ - .muxdata = (volatile void __iomem *)(unsigned long)A,\ - .irqmask = 1 << IRQ_CPU_UART##X, \ - .doirq = frv_cpuuart_doirq, \ - } - - __CPUUART(0, UART0_BASE), - __CPUUART(1, UART1_BASE), -}; - -/*****************************************************************************/ -/* - * CPU DMA interrupts - */ -static void frv_cpudma_doirq(struct irq_source *source) -{ - uint32_t cstr = readl(source->muxdata + DMAC_CSTRx); - if (cstr & DMAC_CSTRx_INT) - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cpudma[8] = { -#define __CPUDMA(X, A) \ - [X] = { \ - .muxname = "dma", \ - .muxdata = (volatile void __iomem *)(unsigned long)A,\ - .irqmask = 1 << IRQ_CPU_DMA##X, \ - .doirq = frv_cpudma_doirq, \ - } - - __CPUDMA(0, 0xfe000900), - __CPUDMA(1, 0xfe000980), - __CPUDMA(2, 0xfe000a00), - __CPUDMA(3, 0xfe000a80), - __CPUDMA(4, 0xfe001000), - __CPUDMA(5, 0xfe001080), - __CPUDMA(6, 0xfe001100), - __CPUDMA(7, 0xfe001180), -}; - -/*****************************************************************************/ -/* - * CPU timer interrupts - can't tell whether they've generated an interrupt or not - */ -static void frv_cputimer_doirq(struct irq_source *source) -{ - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cputimer[3] = { -#define __CPUTIMER(X) \ - [X] = { \ - .muxname = "timer", \ - .muxdata = NULL, \ - .irqmask = 1 << IRQ_CPU_TIMER##X, \ - .doirq = frv_cputimer_doirq, \ - } - - __CPUTIMER(0), - __CPUTIMER(1), - __CPUTIMER(2), -}; - -/*****************************************************************************/ -/* - * external CPU interrupts - can't tell directly whether they've generated an interrupt or not - */ -static void frv_cpuexternal_doirq(struct irq_source *source) -{ - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cpuexternal[8] = { -#define __CPUEXTERNAL(X) \ - [X] = { \ - .muxname = "ext", \ - .muxdata = NULL, \ - .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \ - .doirq = frv_cpuexternal_doirq, \ - } - - __CPUEXTERNAL(0), - __CPUEXTERNAL(1), - __CPUEXTERNAL(2), - __CPUEXTERNAL(3), - __CPUEXTERNAL(4), - __CPUEXTERNAL(5), - __CPUEXTERNAL(6), - __CPUEXTERNAL(7), -}; - -#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16)) - -struct irq_group frv_cpu_irqs = { - .sources = { - [IRQ_CPU_UART0] = &frv_cpuuart[0], - [IRQ_CPU_UART1] = &frv_cpuuart[1], - [IRQ_CPU_TIMER0] = &frv_cputimer[0], - [IRQ_CPU_TIMER1] = &frv_cputimer[1], - [IRQ_CPU_TIMER2] = &frv_cputimer[2], - [IRQ_CPU_DMA0] = &frv_cpudma[0], - [IRQ_CPU_DMA1] = &frv_cpudma[1], - [IRQ_CPU_DMA2] = &frv_cpudma[2], - [IRQ_CPU_DMA3] = &frv_cpudma[3], - [IRQ_CPU_DMA4] = &frv_cpudma[4], - [IRQ_CPU_DMA5] = &frv_cpudma[5], - [IRQ_CPU_DMA6] = &frv_cpudma[6], - [IRQ_CPU_DMA7] = &frv_cpudma[7], - [IRQ_CPU_EXTERNAL0] = &frv_cpuexternal[0], - [IRQ_CPU_EXTERNAL1] = &frv_cpuexternal[1], - [IRQ_CPU_EXTERNAL2] = &frv_cpuexternal[2], - [IRQ_CPU_EXTERNAL3] = &frv_cpuexternal[3], - [IRQ_CPU_EXTERNAL4] = &frv_cpuexternal[4], - [IRQ_CPU_EXTERNAL5] = &frv_cpuexternal[5], - [IRQ_CPU_EXTERNAL6] = &frv_cpuexternal[6], - [IRQ_CPU_EXTERNAL7] = &frv_cpuexternal[7], - }, -}; - -/*****************************************************************************/ -/* - * route the CPU's interrupt sources - */ -void __init route_cpu_irqs(void) -{ - frv_irq_set_group(&frv_cpu_irqs); - - __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 IRQ detect levels */ - __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */ - - /* route UART and error interrupts */ - frv_irq_route(&frv_cpuuart[0], IRQ_UART0_LEVEL); - frv_irq_route(&frv_cpuuart[1], IRQ_UART1_LEVEL); - - set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL); - - /* route DMA channel interrupts */ - frv_irq_route(&frv_cpudma[0], IRQ_DMA0_LEVEL); - frv_irq_route(&frv_cpudma[1], IRQ_DMA1_LEVEL); - frv_irq_route(&frv_cpudma[2], IRQ_DMA2_LEVEL); - frv_irq_route(&frv_cpudma[3], IRQ_DMA3_LEVEL); - frv_irq_route(&frv_cpudma[4], IRQ_DMA4_LEVEL); - frv_irq_route(&frv_cpudma[5], IRQ_DMA5_LEVEL); - frv_irq_route(&frv_cpudma[6], IRQ_DMA6_LEVEL); - frv_irq_route(&frv_cpudma[7], IRQ_DMA7_LEVEL); - - set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL); - set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL); - - /* route timer interrupts */ - frv_irq_route(&frv_cputimer[0], IRQ_TIMER0_LEVEL); - frv_irq_route(&frv_cputimer[1], IRQ_TIMER1_LEVEL); - frv_irq_route(&frv_cputimer[2], IRQ_TIMER2_LEVEL); - - set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL); - - /* route external interrupts */ - frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL); - frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL); - frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL); - frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL); - frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL); - frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL); - frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL); - frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL); - - set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL); - set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL); - -#if defined(CONFIG_MB93091_VDK) - __set_TM1(0x55550000); /* XIRQ7-0 all active low */ -#elif defined(CONFIG_MB93093_PDK) - __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */ -#else -#error dont know external IRQ trigger levels for this setup -#endif - -} /* end route_cpu_irqs() */ diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 8b112b361914..5ac041c7c0a4 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -1,6 +1,6 @@ /* irq.c: FRV IRQ handling * - * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,14 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -/* - * (mostly architecture independent, will move to kernel/irq.c in 2.5.) - * - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -44,19 +36,16 @@ #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #include <asm/gdb-stub.h> -extern void __init fpga_init(void); -extern void __init route_mb93493_irqs(void); - -static void register_irq_proc (unsigned int irq); +#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16)) -/* - * Special irq handlers. - */ +extern void __init fpga_init(void); +#ifdef CONFIG_FUJITSU_MB93493 +extern void __init mb93493_init(void); +#endif -irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; } +#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) atomic_t irq_err_count; @@ -65,215 +54,86 @@ atomic_t irq_err_count; */ int show_interrupts(struct seq_file *p, void *v) { - struct irqaction *action; - struct irq_group *group; + int i = *(loff_t *) v, cpu; + struct irqaction * action; unsigned long flags; - int level, grp, ix, i, j; - - i = *(loff_t *) v; - - switch (i) { - case 0: - seq_printf(p, " "); - for_each_online_cpu(j) - seq_printf(p, "CPU%d ",j); - - seq_putc(p, '\n'); - break; - case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP: - local_irq_save(flags); - - grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP; - group = irq_groups[grp]; - if (!group) - goto skip; - - ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP; - action = group->actions[ix]; - if (!action) - goto skip; - - seq_printf(p, "%3d: ", i - 1); - -#ifndef CONFIG_SMP - seq_printf(p, "%10u ", kstat_irqs(i)); -#else - for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]); -#endif - - level = group->sources[ix]->level - frv_irq_levels; - - seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level); - seq_printf(p, " %s", action->name); - - for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); + if (i == 0) { + char cpuname[12]; + seq_printf(p, " "); + for_each_present_cpu(cpu) { + sprintf(cpuname, "CPU%d", cpu); + seq_printf(p, " %10s", cpuname); + } seq_putc(p, '\n'); -skip: - local_irq_restore(flags); - break; + } - case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1: - seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); - break; + if (i < NR_IRQS) { + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (action) { + seq_printf(p, "%3d: ", i); + for_each_present_cpu(cpu) + seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); + seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-"); + seq_printf(p, " %s", action->name); + for (action = action->next; + action; + action = action->next) + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); + } - default: - break; + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); } return 0; } - /* - * Generic enable/disable code: this just calls - * down into the PIC-specific version for the actual - * hardware disable after having gotten the irq - * controller lock. + * on-CPU PIC operations */ - -/** - * disable_irq_nosync - disable an irq without waiting - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables and Enables are - * nested. - * Unlike disable_irq(), this function does not ensure existing - * instances of the IRQ handler have completed before returning. - * - * This function may be called from IRQ context. - */ - -void disable_irq_nosync(unsigned int irq) +static void frv_cpupic_ack(unsigned int irqlevel) { - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - unsigned long flags; - int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1); - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[idx]; - if (!source) - BUG(); - - level = source->level; - - spin_lock_irqsave(&level->lock, flags); - - if (group->control) { - if (!group->disable_cnt[idx]++) - group->control(group, idx, 0); - } else if (!level->disable_count++) { - __set_MASK(level - frv_irq_levels); - } - - spin_unlock_irqrestore(&level->lock, flags); + __clr_RC(irqlevel); + __clr_IRL(); } -EXPORT_SYMBOL(disable_irq_nosync); - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and Disables are - * nested. - * This function waits for any pending IRQ handlers for this interrupt - * to complete before returning. If you use this function while - * holding a resource the IRQ handler may need you will deadlock. - * - * This function may be called - with care - from IRQ context. - */ - -void disable_irq(unsigned int irq) +static void frv_cpupic_mask(unsigned int irqlevel) { - disable_irq_nosync(irq); - -#ifdef CONFIG_SMP - if (!local_irq_count(smp_processor_id())) { - do { - barrier(); - } while (irq_desc[irq].status & IRQ_INPROGRESS); - } -#endif + __set_MASK(irqlevel); } -EXPORT_SYMBOL(disable_irq); - -/** - * enable_irq - enable handling of an irq - * @irq: Interrupt to enable - * - * Undoes the effect of one call to disable_irq(). If this - * matches the last disable, processing of interrupts on this - * IRQ line is re-enabled. - * - * This function may be called from IRQ context. - */ - -void enable_irq(unsigned int irq) +static void frv_cpupic_mask_ack(unsigned int irqlevel) { - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - unsigned long flags; - int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1); - int count; - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[idx]; - if (!source) - BUG(); - - level = source->level; - - spin_lock_irqsave(&level->lock, flags); - - if (group->control) - count = group->disable_cnt[idx]; - else - count = level->disable_count; - - switch (count) { - case 1: - if (group->control) { - if (group->actions[idx]) - group->control(group, idx, 1); - } else { - if (level->usage) - __clr_MASK(level - frv_irq_levels); - } - /* fall-through */ - - default: - count--; - break; - - case 0: - printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0)); - } + __set_MASK(irqlevel); + __clr_RC(irqlevel); + __clr_IRL(); +} - if (group->control) - group->disable_cnt[idx] = count; - else - level->disable_count = count; +static void frv_cpupic_unmask(unsigned int irqlevel) +{ + __clr_MASK(irqlevel); +} - spin_unlock_irqrestore(&level->lock, flags); +static void frv_cpupic_end(unsigned int irqlevel) +{ + __clr_MASK(irqlevel); } -EXPORT_SYMBOL(enable_irq); +static struct irq_chip frv_cpu_pic = { + .name = "cpu", + .ack = frv_cpupic_ack, + .mask = frv_cpupic_mask, + .mask_ack = frv_cpupic_mask_ack, + .unmask = frv_cpupic_unmask, + .end = frv_cpupic_end, +}; -/*****************************************************************************/ /* * handles all normal device IRQ's * - registers are referred to by the __frame variable (GR28) @@ -282,463 +142,65 @@ EXPORT_SYMBOL(enable_irq); */ asmlinkage void do_IRQ(void) { - struct irq_source *source; - int level, cpu; - irq_enter(); - - level = (__frame->tbr >> 4) & 0xf; - cpu = smp_processor_id(); - - if ((unsigned long) __frame - (unsigned long) (current + 1) < 512) - BUG(); - - __set_MASK(level); - __clr_RC(level); - __clr_IRL(); - - kstat_this_cpu.irqs[level]++; - - for (source = frv_irq_levels[level].sources; source; source = source->next) - source->doirq(source); - - __clr_MASK(level); - + generic_handle_irq(__get_IRL(), __frame); irq_exit(); +} -} /* end do_IRQ() */ - -/*****************************************************************************/ /* * handles all NMIs when not co-opted by the debugger * - registers are referred to by the __frame variable (GR28) */ asmlinkage void do_NMI(void) { -} /* end do_NMI() */ - -/*****************************************************************************/ -/** - * request_irq - allocate an interrupt line - * @irq: Interrupt line to allocate - * @handler: Function to be called when the IRQ occurs - * @irqflags: Interrupt type flags - * @devname: An ascii name for the claiming device - * @dev_id: A cookie passed back to the handler function - * - * This call allocates interrupt resources and enables the - * interrupt line and IRQ handling. From the point this - * call is made your handler function may be invoked. Since - * your handler function must clear any interrupt the board - * raises, you must take care both to initialise your hardware - * and to set up the interrupt handler in the right order. - * - * Dev_id must be globally unique. Normally the address of the - * device data structure is used as the cookie. Since the handler - * receives this value it makes sense to use it. - * - * If your interrupt is shared you must pass a non NULL dev_id - * as this is required when freeing the interrupt. - * - * Flags: - * - * SA_SHIRQ Interrupt is shared - * - * SA_INTERRUPT Disable local interrupts while processing - * - * SA_SAMPLE_RANDOM The interrupt can be used for entropy - * - */ - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction *action; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if (irqflags & SA_SHIRQ) { - if (!dev_id) - printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", - devname, (&irq)[-1]); - } -#endif - - if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = CPU_MASK_NONE; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. The function - * does not return until any executing interrupts for this IRQ - * have completed. - * - * This function may be called from interrupt context. - * - * Bugs: Attempting to free an irq in a handler for the same irq hangs - * the machine. - */ - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - struct irqaction **p, **pp; - unsigned long flags; - - if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS) - return; - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - if (!source) - BUG(); - - level = source->level; - p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - - spin_lock_irqsave(&level->lock, flags); - - for (pp = p; *pp; pp = &(*pp)->next) { - struct irqaction *action = *pp; - - if (action->dev_id != dev_id) - continue; - - /* found it - remove from the list of entries */ - *pp = action->next; - - level->usage--; - - if (p == pp && group->control) - group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0); - - if (level->usage == 0) - __set_MASK(level - frv_irq_levels); - - spin_unlock_irqrestore(&level->lock,flags); - -#ifdef CONFIG_SMP - /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - barrier(); -#endif - kfree(action); - return; - } -} - -EXPORT_SYMBOL(free_irq); - -/* - * IRQ autodetection code.. - * - * This depends on the fact that any interrupt that comes in on to an - * unassigned IRQ will cause GxICR_DETECT to be set - */ - -static DECLARE_MUTEX(probe_sem); - -/** - * probe_irq_on - begin an interrupt autodetect - * - * Commence probing for an interrupt. The interrupts are scanned - * and a mask of potential interrupt lines is returned. - * - */ - -unsigned long probe_irq_on(void) -{ - down(&probe_sem); - return 0; } -EXPORT_SYMBOL(probe_irq_on); - /* - * Return a mask of triggered interrupts (this - * can handle only legacy ISA interrupts). - */ - -/** - * probe_irq_mask - scan a bitmap of interrupt lines - * @val: mask of interrupts to consider - * - * Scan the ISA bus interrupt lines and return a bitmap of - * active interrupts. The interrupt probe logic state is then - * returned to its previous value. - * - * Note: we need to scan all the irq's even though we will - * only return ISA irq numbers - just so that we reset them - * all to a known state. - */ -unsigned int probe_irq_mask(unsigned long xmask) -{ - up(&probe_sem); - return 0; -} - -EXPORT_SYMBOL(probe_irq_mask); - -/* - * Return the one interrupt that triggered (this can - * handle any interrupt source). - */ - -/** - * probe_irq_off - end an interrupt autodetect - * @xmask: mask of potential interrupts (unused) - * - * Scans the unused interrupt lines and returns the line which - * appears to have triggered the interrupt. If no interrupt was - * found then zero is returned. If more than one interrupt is - * found then minus the first candidate is returned to indicate - * their is doubt. - * - * The interrupt probe logic state is returned to its previous - * value. - * - * BUGS: When used in a module (which arguably shouldnt happen) - * nothing prevents two IRQ probe callers from overlapping. The - * results of this are non-optimal. + * initialise the interrupt system */ - -int probe_irq_off(unsigned long xmask) -{ - up(&probe_sem); - return -1; -} - -EXPORT_SYMBOL(probe_irq_off); - -/* this was setup_x86_irq but it seems pretty generic */ -int setup_irq(unsigned int irq, struct irqaction *new) -{ - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - struct irqaction **p, **pp; - unsigned long flags; - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - if (!source) - BUG(); - - level = source->level; - - p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - /* must juggle the interrupt processing stuff with interrupts disabled */ - spin_lock_irqsave(&level->lock, flags); - - /* can't share interrupts unless all parties agree to */ - if (level->usage != 0 && !(level->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&level->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - pp = p; - while (*pp) - pp = &(*pp)->next; - - *pp = new; - - level->usage++; - level->flags = new->flags; - - /* turn the interrupts on */ - if (level->usage == 1) - __clr_MASK(level - frv_irq_levels); - - if (p == pp && group->control) - group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1); - - spin_unlock_irqrestore(&level->lock, flags); - register_irq_proc(irq); - return 0; -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; - -#define HEX_DIGITS 8 - -static unsigned int parse_hex_value (const char __user *buffer, - unsigned long count, unsigned long *ret) -{ - unsigned char hexnum [HEX_DIGITS]; - unsigned long value; - int i; - - if (!count) - return -EINVAL; - if (count > HEX_DIGITS) - count = HEX_DIGITS; - if (copy_from_user(hexnum, buffer, count)) - return -EFAULT; - - /* - * Parse the first 8 characters as a hex string, any non-hex char - * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. - */ - value = 0; - - for (i = 0; i < count; i++) { - unsigned int c = hexnum[i]; - - switch (c) { - case '0' ... '9': c -= '0'; break; - case 'a' ... 'f': c -= 'a'-10; break; - case 'A' ... 'F': c -= 'A'-10; break; - default: - goto out; - } - value = (value << 4) | c; - } -out: - *ret = value; - return 0; -} - - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - unsigned long *mask = (unsigned long *) data; - if (count < HEX_DIGITS+1) - return -EINVAL; - return sprintf (page, "%08lx\n", *mask); -} - -static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - unsigned long *mask = (unsigned long *) data, full_count = count, err; - unsigned long new_value; - - show_state(); - err = parse_hex_value(buffer, count, &new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); -} - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) +void __init init_IRQ(void) { - struct proc_dir_entry *entry; - int i; + int level; - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); + for (level = 1; level <= 14; level++) + set_irq_chip_and_handler(level, &frv_cpu_pic, + handle_level_irq); - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - if (!entry) - return; + set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq); - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. + /* set the trigger levels for internal interrupt sources + * - timers all falling-edge + * - ERR0 is rising-edge + * - all others are high-level */ - for (i = 0; i < NR_IRQS; i++) - register_irq_proc(i); -} + __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */ + __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */ + + /* route internal interrupts */ + set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, + IRQ_DMA0_LEVEL); + set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL); + set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, + IRQ_UART1_LEVEL, IRQ_UART0_LEVEL); + set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, + IRQ_DMA4_LEVEL); + + /* route external interrupts */ + set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, + IRQ_XIRQ4_LEVEL); + set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, + IRQ_XIRQ0_LEVEL); + +#if defined(CONFIG_MB93091_VDK) + __set_TM1(0x55550000); /* XIRQ7-0 all active low */ +#elif defined(CONFIG_MB93093_PDK) + __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */ +#else +#error dont know external IRQ trigger levels for this setup +#endif -/*****************************************************************************/ -/* - * initialise the interrupt system - */ -void __init init_IRQ(void) -{ - route_cpu_irqs(); fpga_init(); #ifdef CONFIG_FUJITSU_MB93493 - route_mb93493_irqs(); + mb93493_init(); #endif -} /* end init_IRQ() */ +} diff --git a/arch/frv/kernel/local.h b/arch/frv/kernel/local.h index e9471761d78b..76606d13b1aa 100644 --- a/arch/frv/kernel/local.h +++ b/arch/frv/kernel/local.h @@ -51,6 +51,9 @@ extern void (*__power_switch_wake_cleanup)(void); /* time.c */ extern void time_divisor_init(void); +/* cmode.S */ +extern asmlinkage void frv_change_cmode(int); + #endif /* __ASSEMBLY__ */ #endif /* _FRV_LOCAL_H */ diff --git a/arch/frv/kernel/pm-mb93093.c b/arch/frv/kernel/pm-mb93093.c index 34d01d7dcc3b..eaa7b582ef52 100644 --- a/arch/frv/kernel/pm-mb93093.c +++ b/arch/frv/kernel/pm-mb93093.c @@ -10,7 +10,6 @@ * */ -#include <linux/config.h> #include <linux/init.h> #include <linux/pm.h> #include <linux/sched.h> diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index 43ce28a13a5d..c1d9fc8f1a85 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -11,7 +11,6 @@ * */ -#include <linux/config.h> #include <linux/init.h> #include <linux/module.h> #include <linux/pm.h> @@ -27,11 +26,6 @@ #include "local.h" -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -extern void frv_change_cmode(int); - /* * Debug macros */ diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 489e6c489cbe..515a5cea5469 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/module.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -26,6 +26,7 @@ #include <linux/reboot.h> #include <linux/interrupt.h> +#include <asm/asm-offsets.h> #include <asm/uaccess.h> #include <asm/system.h> #include <asm/setup.h> @@ -39,6 +40,9 @@ asmlinkage void ret_from_fork(void); #include <asm/pgalloc.h> +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + struct task_struct *alloc_task_struct(void) { struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL); @@ -204,7 +208,7 @@ int copy_thread(int nr, unsigned long clone_flags, regs0 = __kernel_frame0_ptr; childregs0 = (struct pt_regs *) - (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE); + (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); childregs = childregs0; /* set up the userspace frame (the only place that the USP is stored) */ @@ -368,3 +372,11 @@ int elf_check_arch(const struct elf32_hdr *hdr) return 1; } + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) +{ + memcpy(fpregs, + ¤t->thread.user->f, + sizeof(current->thread.user->f)); + return 1; +} diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index f953484e7d59..fcff819b4340 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -18,7 +18,6 @@ #include <linux/errno.h> #include <linux/ptrace.h> #include <linux/user.h> -#include <linux/config.h> #include <linux/security.h> #include <linux/signal.h> diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c index 7971d680ae29..f278cdf3a72f 100644 --- a/arch/frv/kernel/semaphore.c +++ b/arch/frv/kernel/semaphore.c @@ -10,7 +10,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/module.h> #include <asm/semaphore.h> diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 1f7d65f29e78..d96a57e5f030 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -10,8 +10,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/delay.h> @@ -44,7 +43,6 @@ #include <asm/mb-regs.h> #include <asm/mb93493-regs.h> #include <asm/gdb-stub.h> -#include <asm/irq-routing.h> #include <asm/io.h> #ifdef CONFIG_BLK_DEV_INITRD diff --git a/arch/frv/kernel/sleep.S b/arch/frv/kernel/sleep.S index e6079b8cac60..c9b2d51ab9ad 100644 --- a/arch/frv/kernel/sleep.S +++ b/arch/frv/kernel/sleep.S @@ -11,7 +11,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/setup.h> #include <asm/segment.h> diff --git a/arch/frv/kernel/switch_to.S b/arch/frv/kernel/switch_to.S index 1703dc20174e..b5275fa9cd0d 100644 --- a/arch/frv/kernel/switch_to.S +++ b/arch/frv/kernel/switch_to.S @@ -11,7 +11,7 @@ # 2 of the License, or (at your option) any later version. # ############################################################################### -#include <linux/config.h> + #include <linux/linkage.h> #include <asm/thread_info.h> #include <asm/processor.h> @@ -31,7 +31,7 @@ # address of frame 0 (userspace) on current kernel stack .globl __kernel_frame0_ptr __kernel_frame0_ptr: - .long init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE + .long init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE # address of current task .globl __kernel_current_task diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c index b908863d6593..ce676803eb6f 100644 --- a/arch/frv/kernel/sysctl.c +++ b/arch/frv/kernel/sysctl.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/slab.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c index 24cf85f89e40..7e55884135ed 100644 --- a/arch/frv/kernel/time.c +++ b/arch/frv/kernel/time.c @@ -26,14 +26,11 @@ #include <asm/timer-regs.h> #include <asm/mb-regs.h> #include <asm/mb86943a.h> -#include <asm/irq-routing.h> #include <linux/timex.h> #define TICK_SIZE (tick_nsec / 1000) -extern unsigned long wall_jiffies; - unsigned long __nongprelbss __clkin_clock_speed_HZ; unsigned long __nongprelbss __ext_bus_clock_speed_HZ; unsigned long __nongprelbss __res_bus_clock_speed_HZ; @@ -47,7 +44,7 @@ unsigned long __delay_loops_MHz; static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs *regs); static struct irqaction timer_irq = { - timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL + timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL }; static inline int set_rtc_mmss(unsigned long nowtime) @@ -73,7 +70,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs) */ write_seqlock(&xtime_lock); - do_timer(regs); + do_timer(1); update_process_times(user_mode(regs)); profile_tick(CPU_PROFILING, regs); @@ -145,85 +142,6 @@ void time_init(void) } /* - * This version of gettimeofday has near microsecond resolution. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - unsigned long usec, sec; - unsigned long max_ntp_tick; - - do { - unsigned long lost; - - seq = read_seqbegin(&xtime_lock); - - usec = 0; - lost = jiffies - wall_jiffies; - - /* - * If time_adjust is negative then NTP is slowing the clock - * so make sure not to go into next possible interval. - * Better to lose some accuracy than have time go backwards.. - */ - if (unlikely(time_adjust < 0)) { - max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; - usec = min(usec, max_ntp_tick); - - if (lost) - usec += lost * max_ntp_tick; - } - else if (unlikely(lost)) - usec += lost * (USEC_PER_SEC / HZ); - - sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); - } while (read_seqretry(&xtime_lock, seq)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - nsec -= 0 * NSEC_PER_USEC; - nsec -= (jiffies - wall_jiffies) * TICK_NSEC; - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - -/* * Scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index 9eb84b2e6abc..2e6098c85578 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/kernel.h> @@ -21,6 +20,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <asm/asm-offsets.h> #include <asm/setup.h> #include <asm/fpu.h> #include <asm/system.h> @@ -280,20 +280,20 @@ static const char *regnames[] = { void show_regs(struct pt_regs *regs) { - uint32_t *reg; + unsigned long *reg; int loop; printk("\n"); - printk("Frame: @%08x [%s]\n", - (uint32_t) regs, + printk("Frame: @%08lx [%s]\n", + (unsigned long) regs, regs->psr & PSR_S ? "kernel" : "user"); - reg = (uint32_t *) regs; - for (loop = 0; loop < REG__END; loop++) { - printk("%s %08x", regnames[loop + 0], reg[loop + 0]); + reg = (unsigned long *) regs; + for (loop = 0; loop < NR_PT_REGS; loop++) { + printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); - if (loop == REG__END - 1 || loop % 5 == 4) + if (loop == NR_PT_REGS - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); @@ -329,7 +329,7 @@ void die_if_kernel(const char *str, ...) */ static void show_backtrace_regs(struct pt_regs *frame) { - uint32_t *reg; + unsigned long *reg; int loop; /* print the registers for this frame */ @@ -337,11 +337,11 @@ static void show_backtrace_regs(struct pt_regs *frame) frame->psr & PSR_S ? "Kernel Mode" : "User Mode", frame); - reg = (uint32_t *) frame; - for (loop = 0; loop < REG__END; loop++) { - printk("%s %08x", regnames[loop + 0], reg[loop + 0]); + reg = (unsigned long *) frame; + for (loop = 0; loop < NR_PT_REGS; loop++) { + printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); - if (loop == REG__END - 1 || loop % 5 == 4) + if (loop == NR_PT_REGS - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); |