summaryrefslogtreecommitdiffstats
path: root/arch/frv/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/frv/kernel')
-rw-r--r--arch/frv/kernel/Makefile5
-rw-r--r--arch/frv/kernel/asm-offsets.c116
-rw-r--r--arch/frv/kernel/break.S35
-rw-r--r--arch/frv/kernel/cmode.S1
-rw-r--r--arch/frv/kernel/debug-stub.c13
-rw-r--r--arch/frv/kernel/entry-table.S1
-rw-r--r--arch/frv/kernel/entry.S2
-rw-r--r--arch/frv/kernel/frv_ksyms.c1
-rw-r--r--arch/frv/kernel/gdb-stub.c159
-rw-r--r--arch/frv/kernel/head-mmu-fr451.S1
-rw-r--r--arch/frv/kernel/head-uc-fr401.S1
-rw-r--r--arch/frv/kernel/head-uc-fr451.S1
-rw-r--r--arch/frv/kernel/head-uc-fr555.S1
-rw-r--r--arch/frv/kernel/head.S2
-rw-r--r--arch/frv/kernel/irq-mb93091.c158
-rw-r--r--arch/frv/kernel/irq-mb93093.c116
-rw-r--r--arch/frv/kernel/irq-mb93493.c161
-rw-r--r--arch/frv/kernel/irq-routing.c291
-rw-r--r--arch/frv/kernel/irq.c742
-rw-r--r--arch/frv/kernel/local.h3
-rw-r--r--arch/frv/kernel/pm-mb93093.c1
-rw-r--r--arch/frv/kernel/pm.c6
-rw-r--r--arch/frv/kernel/process.c16
-rw-r--r--arch/frv/kernel/ptrace.c1
-rw-r--r--arch/frv/kernel/semaphore.c1
-rw-r--r--arch/frv/kernel/setup.c4
-rw-r--r--arch/frv/kernel/sleep.S1
-rw-r--r--arch/frv/kernel/switch_to.S4
-rw-r--r--arch/frv/kernel/sysctl.c1
-rw-r--r--arch/frv/kernel/time.c86
-rw-r--r--arch/frv/kernel/traps.c26
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,
+ &current->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(" | ");
OpenPOWER on IntegriCloud