aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 16:08:20 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 16:08:20 -0400
commitd84c4124c4b6611301b402e8611b7e36de3bd351 (patch)
treed83cfaabfb901755d85074815ad948028dc7b03f /arch/sh/kernel
parent932c37c375cca25175f9b6acee4c75d7a96d985f (diff)
parenta3cf4ea8729a5d448742fd5a0a003827c9f25cb6 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: sh: Fix stacktrace simplification fallout. sh: SH7760 DMABRG support. sh: clockevent/clocksource/hrtimers/nohz TMU support. sh: Truncate MAX_ACTIVE_REGIONS for the common case. rtc: rtc-sh: Fix rtc_dev pointer for rtc_update_irq(). sh: Convert to common die chain. sh: Wire up utimensat syscall. sh: landisk mv_nr_irqs definition. sh: Fixup ndelay() xloops calculation for alternate HZ. sh: Add 32-bit opcode feature CPU flag. sh: Fix PC adjustments for varying opcode length. sh: Support for SH-2A 32-bit opcodes. sh: Kill off redundant __div64_32 symbol export. sh: Share exception vector table for SH-3/4. sh: Always define TRAPA_BUG_OPCODE. sh: __GFP_REPEAT for pte allocations, too. rtc: rtc-sh: Fix up dev_dbg() warnings. sh: generic quicklist support.
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile5
-rw-r--r--arch/sh/kernel/cpu/sh2a/opcode_helper.c55
-rw-r--r--arch/sh/kernel/cpu/sh2a/probe.c1
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S13
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh4/ex.S62
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c3
-rw-r--r--arch/sh/kernel/process.c16
-rw-r--r--arch/sh/kernel/setup.c2
-rw-r--r--arch/sh/kernel/sh_ksyms.c2
-rw-r--r--arch/sh/kernel/signal.c13
-rw-r--r--arch/sh/kernel/stacktrace.c2
-rw-r--r--arch/sh/kernel/syscalls.S1
-rw-r--r--arch/sh/kernel/time.c172
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c182
-rw-r--r--arch/sh/kernel/traps.c20
16 files changed, 260 insertions, 295 deletions
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 350972ae9410..965fa2572b23 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -2,9 +2,8 @@
2# Makefile for the Linux/SuperH SH-2A backends. 2# Makefile for the Linux/SuperH SH-2A backends.
3# 3#
4 4
5obj-y := common.o probe.o 5obj-y := common.o probe.o opcode_helper.o
6 6
7common-y += $(addprefix ../sh2/, ex.o) 7common-y += $(addprefix ../sh2/, ex.o entry.o)
8common-y += $(addprefix ../sh2/, entry.o)
9 8
10obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o 9obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
new file mode 100644
index 000000000000..9704b7926d8b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
@@ -0,0 +1,55 @@
1/*
2 * arch/sh/kernel/cpu/sh2a/opcode_helper.c
3 *
4 * Helper for the SH-2A 32-bit opcodes.
5 *
6 * Copyright (C) 2007 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/kernel.h>
13#include <asm/system.h>
14
15/*
16 * Instructions on SH are generally fixed at 16-bits, however, SH-2A
17 * introduces some 32-bit instructions. Since there are no real
18 * constraints on their use (and they can be mixed and matched), we need
19 * to check the instruction encoding to work out if it's a true 32-bit
20 * instruction or not.
21 *
22 * Presently, 32-bit opcodes have only slight variations in what the
23 * actual encoding looks like in the first-half of the instruction, which
24 * makes it fairly straightforward to differentiate from the 16-bit ones.
25 *
26 * First 16-bits of encoding Used by
27 *
28 * 0011nnnnmmmm0001 mov.b, mov.w, mov.l, fmov.d,
29 * fmov.s, movu.b, movu.w
30 *
31 * 0011nnnn0iii1001 bclr.b, bld.b, bset.b, bst.b, band.b,
32 * bandnot.b, bldnot.b, bor.b, bornot.b,
33 * bxor.b
34 *
35 * 0000nnnniiii0000 movi20
36 * 0000nnnniiii0001 movi20s
37 */
38unsigned int instruction_size(unsigned int insn)
39{
40 /* Look for the common cases */
41 switch ((insn & 0xf00f)) {
42 case 0x0000: /* movi20 */
43 case 0x0001: /* movi20s */
44 case 0x3001: /* 32-bit mov/fmov/movu variants */
45 return 4;
46 }
47
48 /* And the special cases.. */
49 switch ((insn & 0xf08f)) {
50 case 0x3009: /* 32-bit b*.b bit operations */
51 return 4;
52 }
53
54 return 2;
55}
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
index 426f6db01fc6..f455c3509789 100644
--- a/arch/sh/kernel/cpu/sh2a/probe.c
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -18,6 +18,7 @@ int __init detect_cpu_and_cache_system(void)
18{ 18{
19 /* Just SH7206 for now .. */ 19 /* Just SH7206 for now .. */
20 current_cpu_data.type = CPU_SH7206; 20 current_cpu_data.type = CPU_SH7206;
21 current_cpu_data.flags |= CPU_HAS_OP32;
21 22
22 current_cpu_data.dcache.ways = 4; 23 current_cpu_data.dcache.ways = 4;
23 current_cpu_data.dcache.way_incr = (1 << 11); 24 current_cpu_data.dcache.way_incr = (1 << 11);
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index ba3082d640b5..2b2a9e02fb75 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/sh/kernel/cpu/sh3/ex.S 2 * arch/sh/kernel/cpu/sh3/ex.S
3 * 3 *
4 * The SH-3 exception vector table. 4 * The SH-3 and SH-4 exception vector table.
5 5
6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
7 * Copyright (C) 2003 - 2006 Paul Mundt 7 * Copyright (C) 2003 - 2006 Paul Mundt
@@ -9,7 +9,6 @@
9 * This file is subject to the terms and conditions of the GNU General Public 9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive 10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details. 11 * for more details.
12 *
13 */ 12 */
14#include <linux/linkage.h> 13#include <linux/linkage.h>
15 14
@@ -36,8 +35,12 @@ ENTRY(exception_handling_table)
36 .long exception_error ! address error load 35 .long exception_error ! address error load
37 .long exception_error ! address error store /* 100 */ 36 .long exception_error ! address error store /* 100 */
38#endif 37#endif
39 .long exception_error ! fpu_exception /* 120 */ 38#if defined(CONFIG_SH_FPU)
40 .long exception_error /* 140 */ 39 .long do_fpu_error /* 120 */
40#else
41 .long exception_error /* 120 */
42#endif
43 .long exception_error /* 140 */
41 .long system_call ! Unconditional Trap /* 160 */ 44 .long system_call ! Unconditional Trap /* 160 */
42 .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ 45 .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
43 .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ 46 .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
@@ -55,4 +58,4 @@ ENTRY(user_break_point_trap)
55 * away offsets can be manually inserted in to their appropriate 58 * away offsets can be manually inserted in to their appropriate
56 * location via set_exception_table_{evt,vec}(). 59 * location via set_exception_table_{evt,vec}().
57 */ 60 */
58 .balign 4096,0,4096 61 .balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 19ca68c71884..8add10bd8268 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -2,10 +2,10 @@
2# Makefile for the Linux/SuperH SH-4 backends. 2# Makefile for the Linux/SuperH SH-4 backends.
3# 3#
4 4
5obj-y := ex.o probe.o common.o 5obj-y := probe.o common.o
6common-y += $(addprefix ../sh3/, entry.o) 6common-y += $(addprefix ../sh3/, entry.o ex.o)
7 7
8obj-$(CONFIG_SH_FPU) += fpu.o 8obj-$(CONFIG_SH_FPU) += fpu.o
9obj-$(CONFIG_SH_STORE_QUEUES) += sq.o 9obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
10 10
11# CPU subtype setup 11# CPU subtype setup
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
deleted file mode 100644
index ac8ab57413cc..000000000000
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ /dev/null
@@ -1,62 +0,0 @@
1/*
2 * arch/sh/kernel/cpu/sh4/ex.S
3 *
4 * The SH-4 exception vector table.
5
6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
7 * Copyright (C) 2003 - 2006 Paul Mundt
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 *
13 */
14#include <linux/linkage.h>
15
16 .align 2
17 .data
18
19ENTRY(exception_handling_table)
20 .long exception_error /* 000 */
21 .long exception_error
22#if defined(CONFIG_MMU)
23 .long tlb_miss_load /* 040 */
24 .long tlb_miss_store
25 .long initial_page_write
26 .long tlb_protection_violation_load
27 .long tlb_protection_violation_store
28 .long address_error_load
29 .long address_error_store /* 100 */
30#else
31 .long exception_error ! tlb miss load /* 040 */
32 .long exception_error ! tlb miss store
33 .long exception_error ! initial page write
34 .long exception_error ! tlb prot violation load
35 .long exception_error ! tlb prot violation store
36 .long exception_error ! address error load
37 .long exception_error ! address error store /* 100 */
38#endif
39#if defined(CONFIG_SH_FPU)
40 .long do_fpu_error /* 120 */
41#else
42 .long exception_error /* 120 */
43#endif
44 .long exception_error /* 140 */
45 .long system_call ! Unconditional Trap /* 160 */
46 .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
47 .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
48ENTRY(nmi_slot)
49#if defined (CONFIG_KGDB_NMI)
50 .long debug_enter /* 1C0 */ ! Allow trap to debugger
51#else
52 .long exception_none /* 1C0 */ ! Not implemented yet
53#endif
54ENTRY(user_break_point_trap)
55 .long break_point_trap /* 1E0 */
56
57 /*
58 * Pad the remainder of the table out, exceptions residing in far
59 * away offsets can be manually inserted in to their appropriate
60 * location via set_exception_table_{evt,vec}().
61 */
62 .balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index 7624677f6628..d61dd599169f 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -16,6 +16,7 @@
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/signal.h> 17#include <linux/signal.h>
18#include <asm/processor.h> 18#include <asm/processor.h>
19#include <asm/system.h>
19#include <asm/io.h> 20#include <asm/io.h>
20 21
21/* The PR (precision) bit in the FP Status Register must be clear when 22/* The PR (precision) bit in the FP Status Register must be clear when
@@ -265,7 +266,7 @@ ieee_fpe_handler (struct pt_regs *regs)
265 nextpc = regs->pr; 266 nextpc = regs->pr;
266 finsn = *(unsigned short *) (regs->pc + 2); 267 finsn = *(unsigned short *) (regs->pc + 2);
267 } else { 268 } else {
268 nextpc = regs->pc + 2; 269 nextpc = regs->pc + instruction_size(insn);
269 finsn = insn; 270 finsn = insn;
270 } 271 }
271 272
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 329b3f3051de..6b4f5748d0be 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -15,9 +15,12 @@
15#include <linux/pm.h> 15#include <linux/pm.h>
16#include <linux/kallsyms.h> 16#include <linux/kallsyms.h>
17#include <linux/kexec.h> 17#include <linux/kexec.h>
18#include <asm/kdebug.h> 18#include <linux/kdebug.h>
19#include <linux/tick.h>
19#include <asm/uaccess.h> 20#include <asm/uaccess.h>
20#include <asm/mmu_context.h> 21#include <asm/mmu_context.h>
22#include <asm/pgalloc.h>
23#include <asm/system.h>
21#include <asm/ubc.h> 24#include <asm/ubc.h>
22 25
23static int hlt_counter; 26static int hlt_counter;
@@ -58,12 +61,15 @@ void cpu_idle(void)
58 if (!idle) 61 if (!idle)
59 idle = default_idle; 62 idle = default_idle;
60 63
64 tick_nohz_stop_sched_tick();
61 while (!need_resched()) 65 while (!need_resched())
62 idle(); 66 idle();
67 tick_nohz_restart_sched_tick();
63 68
64 preempt_enable_no_resched(); 69 preempt_enable_no_resched();
65 schedule(); 70 schedule();
66 preempt_disable(); 71 preempt_disable();
72 check_pgt_cache();
67 } 73 }
68} 74}
69 75
@@ -495,9 +501,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
495 struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 501 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
496 502
497 /* Rewind */ 503 /* Rewind */
498 regs->pc -= 2; 504 regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
499 505
500 if (notify_die(DIE_TRAP, regs, regs->tra & 0xff, 506 if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
501 SIGTRAP) == NOTIFY_STOP) 507 SIGTRAP) == NOTIFY_STOP)
502 return; 508 return;
503 509
@@ -514,9 +520,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
514 struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 520 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
515 521
516 /* Rewind */ 522 /* Rewind */
517 regs->pc -= 2; 523 regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
518 524
519 if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff, 525 if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
520 SIGTRAP) == NOTIFY_STOP) 526 SIGTRAP) == NOTIFY_STOP)
521 return; 527 return;
522 528
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 477d2a854fc4..c27729135935 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c)
431/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */ 431/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
432static const char *cpu_flags[] = { 432static const char *cpu_flags[] = {
433 "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", 433 "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
434 "ptea", "llsc", "l2", NULL 434 "ptea", "llsc", "l2", "op32", NULL
435}; 435};
436 436
437static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c) 437static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index fa91641c1f62..c1cfcb9f047c 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -58,8 +58,6 @@ EXPORT_SYMBOL(__udelay);
58EXPORT_SYMBOL(__ndelay); 58EXPORT_SYMBOL(__ndelay);
59EXPORT_SYMBOL(__const_udelay); 59EXPORT_SYMBOL(__const_udelay);
60 60
61EXPORT_SYMBOL(__div64_32);
62
63#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) 61#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
64 62
65/* These symbols are generated by the compiler itself */ 63/* These symbols are generated by the compiler itself */
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index eb0191c374b6..b32c35a7c0a3 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -23,7 +23,7 @@
23#include <linux/personality.h> 23#include <linux/personality.h>
24#include <linux/binfmts.h> 24#include <linux/binfmts.h>
25#include <linux/freezer.h> 25#include <linux/freezer.h>
26 26#include <asm/system.h>
27#include <asm/ucontext.h> 27#include <asm/ucontext.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/pgtable.h> 29#include <asm/pgtable.h>
@@ -500,7 +500,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
500 } 500 }
501 /* fallthrough */ 501 /* fallthrough */
502 case -ERESTARTNOINTR: 502 case -ERESTARTNOINTR:
503 regs->pc -= 2; 503 regs->pc -= instruction_size(
504 ctrl_inw(regs->pc - 4));
505 break;
504 } 506 }
505 } else { 507 } else {
506 /* gUSA handling */ 508 /* gUSA handling */
@@ -516,7 +518,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
516 regs->regs[15] = regs->regs[1]; 518 regs->regs[15] = regs->regs[1];
517 if (regs->pc < regs->regs[0]) 519 if (regs->pc < regs->regs[0])
518 /* Go to rewind point #1 */ 520 /* Go to rewind point #1 */
519 regs->pc = regs->regs[0] + offset - 2; 521 regs->pc = regs->regs[0] + offset -
522 instruction_size(ctrl_inw(regs->pc-4));
520 } 523 }
521#ifdef CONFIG_PREEMPT 524#ifdef CONFIG_PREEMPT
522 local_irq_restore(flags); 525 local_irq_restore(flags);
@@ -600,9 +603,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
600 regs->regs[0] == -ERESTARTSYS || 603 regs->regs[0] == -ERESTARTSYS ||
601 regs->regs[0] == -ERESTARTNOINTR) { 604 regs->regs[0] == -ERESTARTNOINTR) {
602 regs->regs[0] = save_r0; 605 regs->regs[0] = save_r0;
603 regs->pc -= 2; 606 regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
604 } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { 607 } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
605 regs->pc -= 2; 608 regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
606 regs->regs[3] = __NR_restart_syscall; 609 regs->regs[3] = __NR_restart_syscall;
607 } 610 }
608 } 611 }
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 4bdd2f83535d..d41e561be20e 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -17,7 +17,7 @@
17/* 17/*
18 * Save stack-backtrace addresses into a stack_trace buffer. 18 * Save stack-backtrace addresses into a stack_trace buffer.
19 */ 19 */
20void save_stack_trace(struct stack_trace *trace, struct task_struct *task) 20void save_stack_trace(struct stack_trace *trace)
21{ 21{
22 unsigned long *sp = (unsigned long *)current_stack_pointer; 22 unsigned long *sp = (unsigned long *)current_stack_pointer;
23 23
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 38fc8cd3ea3a..4357d1a6358f 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -354,3 +354,4 @@ ENTRY(sys_call_table)
354 .long sys_move_pages 354 .long sys_move_pages
355 .long sys_getcpu 355 .long sys_getcpu
356 .long sys_epoll_pwait 356 .long sys_epoll_pwait
357 .long sys_utimensat /* 320 */
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index d47e775962e9..a3a67d151e52 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka 4 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
6 * Copyright (C) 2002 - 2006 Paul Mundt 6 * Copyright (C) 2002 - 2007 Paul Mundt
7 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> 7 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
8 * 8 *
9 * Some code taken from i386 version. 9 * Some code taken from i386 version.
@@ -15,6 +15,7 @@
15#include <linux/profile.h> 15#include <linux/profile.h>
16#include <linux/timex.h> 16#include <linux/timex.h>
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/clockchips.h>
18#include <asm/clock.h> 19#include <asm/clock.h>
19#include <asm/rtc.h> 20#include <asm/rtc.h>
20#include <asm/timer.h> 21#include <asm/timer.h>
@@ -38,6 +39,14 @@ static int null_rtc_set_time(const time_t secs)
38 return 0; 39 return 0;
39} 40}
40 41
42/*
43 * Null high precision timer functions for systems lacking one.
44 */
45static cycle_t null_hpt_read(void)
46{
47 return 0;
48}
49
41void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; 50void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
42int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; 51int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
43 52
@@ -101,6 +110,7 @@ int do_settimeofday(struct timespec *tv)
101EXPORT_SYMBOL(do_settimeofday); 110EXPORT_SYMBOL(do_settimeofday);
102#endif /* !CONFIG_GENERIC_TIME */ 111#endif /* !CONFIG_GENERIC_TIME */
103 112
113#ifndef CONFIG_GENERIC_CLOCKEVENTS
104/* last time the RTC clock got updated */ 114/* last time the RTC clock got updated */
105static long last_rtc_update; 115static long last_rtc_update;
106 116
@@ -138,6 +148,7 @@ void handle_timer_tick(void)
138 last_rtc_update = xtime.tv_sec - 600; 148 last_rtc_update = xtime.tv_sec - 600;
139 } 149 }
140} 150}
151#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
141 152
142#ifdef CONFIG_PM 153#ifdef CONFIG_PM
143int timer_suspend(struct sys_device *dev, pm_message_t state) 154int timer_suspend(struct sys_device *dev, pm_message_t state)
@@ -168,136 +179,58 @@ static struct sysdev_class timer_sysclass = {
168 .resume = timer_resume, 179 .resume = timer_resume,
169}; 180};
170 181
171#ifdef CONFIG_NO_IDLE_HZ 182static int __init timer_init_sysfs(void)
172static int timer_dyn_tick_enable(void)
173{ 183{
174 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; 184 int ret = sysdev_class_register(&timer_sysclass);
175 unsigned long flags; 185 if (ret != 0)
176 int ret = -ENODEV; 186 return ret;
177
178 if (dyn_tick) {
179 spin_lock_irqsave(&dyn_tick->lock, flags);
180 ret = 0;
181 if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
182 ret = dyn_tick->enable();
183
184 if (ret == 0)
185 dyn_tick->state |= DYN_TICK_ENABLED;
186 }
187 spin_unlock_irqrestore(&dyn_tick->lock, flags);
188 }
189 187
190 return ret; 188 sys_timer->dev.cls = &timer_sysclass;
189 return sysdev_register(&sys_timer->dev);
191} 190}
191device_initcall(timer_init_sysfs);
192 192
193static int timer_dyn_tick_disable(void) 193void (*board_time_init)(void);
194{
195 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
196 unsigned long flags;
197 int ret = -ENODEV;
198
199 if (dyn_tick) {
200 spin_lock_irqsave(&dyn_tick->lock, flags);
201 ret = 0;
202 if (dyn_tick->state & DYN_TICK_ENABLED) {
203 ret = dyn_tick->disable();
204
205 if (ret == 0)
206 dyn_tick->state &= ~DYN_TICK_ENABLED;
207 }
208 spin_unlock_irqrestore(&dyn_tick->lock, flags);
209 }
210
211 return ret;
212}
213 194
214/* 195/*
215 * Reprogram the system timer for at least the calculated time interval. 196 * Shamelessly based on the MIPS and Sparc64 work.
216 * This function should be called from the idle thread with IRQs disabled,
217 * immediately before sleeping.
218 */ 197 */
219void timer_dyn_reprogram(void) 198static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
220{ 199unsigned long sh_hpt_frequency = 0;
221 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; 200
222 unsigned long next, seq, flags; 201#define NSEC_PER_CYC_SHIFT 10
223 202
224 if (!dyn_tick) 203struct clocksource clocksource_sh = {
225 return; 204 .name = "SuperH",
226 205 .rating = 200,
227 spin_lock_irqsave(&dyn_tick->lock, flags); 206 .mask = CLOCKSOURCE_MASK(32),
228 if (dyn_tick->state & DYN_TICK_ENABLED) { 207 .read = null_hpt_read,
229 next = next_timer_interrupt(); 208 .shift = 16,
230 do { 209 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
231 seq = read_seqbegin(&xtime_lock); 210};
232 dyn_tick->reprogram(next - jiffies);
233 } while (read_seqretry(&xtime_lock, seq));
234 }
235 spin_unlock_irqrestore(&dyn_tick->lock, flags);
236}
237 211
238static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) 212static void __init init_sh_clocksource(void)
239{ 213{
240 return sprintf(buf, "%i\n", 214 if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
241 (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); 215 return;
242}
243 216
244static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, 217 clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
245 size_t count) 218 clocksource_sh.shift);
246{
247 unsigned int enable = simple_strtoul(buf, NULL, 2);
248 219
249 if (enable) 220 timer_ticks_per_nsec_quotient =
250 timer_dyn_tick_enable(); 221 clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
251 else
252 timer_dyn_tick_disable();
253 222
254 return count; 223 clocksource_register(&clocksource_sh);
255} 224}
256static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
257 225
258/* 226#ifdef CONFIG_GENERIC_TIME
259 * dyntick=enable|disable 227unsigned long long sched_clock(void)
260 */
261static char dyntick_str[4] __initdata = "";
262
263static int __init dyntick_setup(char *str)
264{ 228{
265 if (str) 229 unsigned long long ticks = clocksource_sh.read();
266 strlcpy(dyntick_str, str, sizeof(dyntick_str)); 230 return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
267 return 1;
268} 231}
269
270__setup("dyntick=", dyntick_setup);
271#endif
272
273static int __init timer_init_sysfs(void)
274{
275 int ret = sysdev_class_register(&timer_sysclass);
276 if (ret != 0)
277 return ret;
278
279 sys_timer->dev.cls = &timer_sysclass;
280 ret = sysdev_register(&sys_timer->dev);
281
282#ifdef CONFIG_NO_IDLE_HZ
283 if (ret == 0 && sys_timer->dyn_tick) {
284 ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
285
286 /*
287 * Turn on dynamic tick after calibrate delay
288 * for correct bogomips
289 */
290 if (ret == 0 && dyntick_str[0] == 'e')
291 ret = timer_dyn_tick_enable();
292 }
293#endif 232#endif
294 233
295 return ret;
296}
297device_initcall(timer_init_sysfs);
298
299void (*board_time_init)(void);
300
301void __init time_init(void) 234void __init time_init(void)
302{ 235{
303 if (board_time_init) 236 if (board_time_init)
@@ -316,10 +249,15 @@ void __init time_init(void)
316 sys_timer = get_sys_timer(); 249 sys_timer = get_sys_timer();
317 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); 250 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
318 251
319#ifdef CONFIG_NO_IDLE_HZ 252 if (sys_timer->ops->read)
320 if (sys_timer->dyn_tick) 253 clocksource_sh.read = sys_timer->ops->read;
321 spin_lock_init(&sys_timer->dyn_tick->lock); 254
322#endif 255 init_sh_clocksource();
256
257 if (sh_hpt_frequency)
258 printk("Using %lu.%03lu MHz high precision timer.\n",
259 ((sh_hpt_frequency + 500) / 1000) / 1000,
260 ((sh_hpt_frequency + 500) / 1000) % 1000);
323 261
324#if defined(CONFIG_SH_KGDB) 262#if defined(CONFIG_SH_KGDB)
325 /* 263 /*
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index d9e3151c891e..2d997e2a5b6c 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support 2 * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
3 * 3 *
4 * Copyright (C) 2005 Paul Mundt 4 * Copyright (C) 2005 - 2007 Paul Mundt
5 * 5 *
6 * TMU handling code hacked out of arch/sh/kernel/time.c 6 * TMU handling code hacked out of arch/sh/kernel/time.c
7 * 7 *
@@ -18,6 +18,7 @@
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/seqlock.h> 20#include <linux/seqlock.h>
21#include <linux/clockchips.h>
21#include <asm/timer.h> 22#include <asm/timer.h>
22#include <asm/rtc.h> 23#include <asm/rtc.h>
23#include <asm/io.h> 24#include <asm/io.h>
@@ -25,56 +26,75 @@
25#include <asm/clock.h> 26#include <asm/clock.h>
26 27
27#define TMU_TOCR_INIT 0x00 28#define TMU_TOCR_INIT 0x00
28#define TMU0_TCR_INIT 0x0020 29#define TMU_TCR_INIT 0x0020
29#define TMU_TSTR_INIT 1
30 30
31#define TMU0_TCR_CALIB 0x0000 31static int tmu_timer_start(void)
32{
33 ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
34 return 0;
35}
32 36
33static unsigned long tmu_timer_get_offset(void) 37static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
34{ 38{
35 int count; 39 ctrl_outl(interval, TMU0_TCNT);
36 static int count_p = 0x7fffffff; /* for the first call after boot */
37 static unsigned long jiffies_p = 0;
38 40
39 /* 41 /*
40 * cache volatile jiffies temporarily; we have IRQs turned off. 42 * TCNT reloads from TCOR on underflow, clear it if we don't
43 * intend to auto-reload
41 */ 44 */
42 unsigned long jiffies_t; 45 if (reload)
46 ctrl_outl(interval, TMU0_TCOR);
47 else
48 ctrl_outl(0, TMU0_TCOR);
43 49
44 /* timer count may underflow right here */ 50 tmu_timer_start();
45 count = ctrl_inl(TMU0_TCNT); /* read the latched count */ 51}
46 52
47 jiffies_t = jiffies; 53static int tmu_timer_stop(void)
54{
55 ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
56 return 0;
57}
48 58
49 /* 59static cycle_t tmu_timer_read(void)
50 * avoiding timer inconsistencies (they are rare, but they happen)... 60{
51 * there is one kind of problem that must be avoided here: 61 return ~ctrl_inl(TMU1_TCNT);
52 * 1. the timer counter underflows 62}
53 */ 63
64static int tmu_set_next_event(unsigned long cycles,
65 struct clock_event_device *evt)
66{
67 tmu0_timer_set_interval(cycles, 1);
68 return 0;
69}
54 70
55 if (jiffies_t == jiffies_p) { 71static void tmu_set_mode(enum clock_event_mode mode,
56 if (count > count_p) { 72 struct clock_event_device *evt)
57 /* the nutcase */ 73{
58 if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ 74 switch (mode) {
59 count -= LATCH; 75 case CLOCK_EVT_MODE_PERIODIC:
60 } else { 76 ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
61 printk("%s (): hardware timer problem?\n", 77 break;
62 __FUNCTION__); 78 case CLOCK_EVT_MODE_ONESHOT:
63 } 79 ctrl_outl(0, TMU0_TCOR);
64 } 80 break;
65 } else 81 case CLOCK_EVT_MODE_UNUSED:
66 jiffies_p = jiffies_t; 82 case CLOCK_EVT_MODE_SHUTDOWN:
67 83 break;
68 count_p = count; 84 }
69
70 count = ((LATCH-1) - count) * TICK_SIZE;
71 count = (count + LATCH/2) / LATCH;
72
73 return count;
74} 85}
75 86
87static struct clock_event_device tmu0_clockevent = {
88 .name = "tmu0",
89 .shift = 32,
90 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
91 .set_mode = tmu_set_mode,
92 .set_next_event = tmu_set_next_event,
93};
94
76static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) 95static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
77{ 96{
97 struct clock_event_device *evt = &tmu0_clockevent;
78 unsigned long timer_status; 98 unsigned long timer_status;
79 99
80 /* Clear UNF bit */ 100 /* Clear UNF bit */
@@ -82,72 +102,76 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
82 timer_status &= ~0x100; 102 timer_status &= ~0x100;
83 ctrl_outw(timer_status, TMU0_TCR); 103 ctrl_outw(timer_status, TMU0_TCR);
84 104
85 /* 105 evt->event_handler(evt);
86 * Here we are in the timer irq handler. We just have irqs locally
87 * disabled but we don't know if the timer_bh is running on the other
88 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
89 * the irq version of write_lock because as just said we have irq
90 * locally disabled. -arca
91 */
92 write_seqlock(&xtime_lock);
93 handle_timer_tick();
94 write_sequnlock(&xtime_lock);
95 106
96 return IRQ_HANDLED; 107 return IRQ_HANDLED;
97} 108}
98 109
99static struct irqaction tmu_irq = { 110static struct irqaction tmu0_irq = {
100 .name = "timer", 111 .name = "periodic timer",
101 .handler = tmu_timer_interrupt, 112 .handler = tmu_timer_interrupt,
102 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 113 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
103 .mask = CPU_MASK_NONE, 114 .mask = CPU_MASK_NONE,
104}; 115};
105 116
106static void tmu_clk_init(struct clk *clk) 117static void tmu0_clk_init(struct clk *clk)
107{ 118{
108 u8 divisor = TMU0_TCR_INIT & 0x7; 119 u8 divisor = TMU_TCR_INIT & 0x7;
109 ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); 120 ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
110 clk->rate = clk->parent->rate / (4 << (divisor << 1)); 121 clk->rate = clk->parent->rate / (4 << (divisor << 1));
111} 122}
112 123
113static void tmu_clk_recalc(struct clk *clk) 124static void tmu0_clk_recalc(struct clk *clk)
114{ 125{
115 u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; 126 u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
116 clk->rate = clk->parent->rate / (4 << (divisor << 1)); 127 clk->rate = clk->parent->rate / (4 << (divisor << 1));
117} 128}
118 129
119static struct clk_ops tmu_clk_ops = { 130static struct clk_ops tmu0_clk_ops = {
120 .init = tmu_clk_init, 131 .init = tmu0_clk_init,
121 .recalc = tmu_clk_recalc, 132 .recalc = tmu0_clk_recalc,
122}; 133};
123 134
124static struct clk tmu0_clk = { 135static struct clk tmu0_clk = {
125 .name = "tmu0_clk", 136 .name = "tmu0_clk",
126 .ops = &tmu_clk_ops, 137 .ops = &tmu0_clk_ops,
127}; 138};
128 139
129static int tmu_timer_start(void) 140static void tmu1_clk_init(struct clk *clk)
130{ 141{
131 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); 142 u8 divisor = TMU_TCR_INIT & 0x7;
132 return 0; 143 ctrl_outw(divisor, TMU1_TCR);
144 clk->rate = clk->parent->rate / (4 << (divisor << 1));
133} 145}
134 146
135static int tmu_timer_stop(void) 147static void tmu1_clk_recalc(struct clk *clk)
136{ 148{
137 ctrl_outb(0, TMU_TSTR); 149 u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
138 return 0; 150 clk->rate = clk->parent->rate / (4 << (divisor << 1));
139} 151}
140 152
153static struct clk_ops tmu1_clk_ops = {
154 .init = tmu1_clk_init,
155 .recalc = tmu1_clk_recalc,
156};
157
158static struct clk tmu1_clk = {
159 .name = "tmu1_clk",
160 .ops = &tmu1_clk_ops,
161};
162
141static int tmu_timer_init(void) 163static int tmu_timer_init(void)
142{ 164{
143 unsigned long interval; 165 unsigned long interval;
166 unsigned long frequency;
144 167
145 setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); 168 setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
146 169
147 tmu0_clk.parent = clk_get(NULL, "module_clk"); 170 tmu0_clk.parent = clk_get(NULL, "module_clk");
171 tmu1_clk.parent = clk_get(NULL, "module_clk");
148 172
149 /* Start TMU0 */
150 tmu_timer_stop(); 173 tmu_timer_stop();
174
151#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ 175#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
152 !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ 176 !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
153 !defined(CONFIG_CPU_SUBTYPE_SH7785) 177 !defined(CONFIG_CPU_SUBTYPE_SH7785)
@@ -155,15 +179,29 @@ static int tmu_timer_init(void)
155#endif 179#endif
156 180
157 clk_register(&tmu0_clk); 181 clk_register(&tmu0_clk);
182 clk_register(&tmu1_clk);
158 clk_enable(&tmu0_clk); 183 clk_enable(&tmu0_clk);
184 clk_enable(&tmu1_clk);
159 185
160 interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; 186 frequency = clk_get_rate(&tmu0_clk);
161 printk(KERN_INFO "Interval = %ld\n", interval); 187 interval = (frequency + HZ / 2) / HZ;
162 188
163 ctrl_outl(interval, TMU0_TCOR); 189 sh_hpt_frequency = clk_get_rate(&tmu1_clk);
164 ctrl_outl(interval, TMU0_TCNT); 190 ctrl_outl(~0, TMU1_TCNT);
191 ctrl_outl(~0, TMU1_TCOR);
165 192
166 tmu_timer_start(); 193 tmu0_timer_set_interval(interval, 1);
194
195 tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
196 tmu0_clockevent.shift);
197 tmu0_clockevent.max_delta_ns =
198 clockevent_delta2ns(-1, &tmu0_clockevent);
199 tmu0_clockevent.min_delta_ns =
200 clockevent_delta2ns(1, &tmu0_clockevent);
201
202 tmu0_clockevent.cpumask = cpumask_of_cpu(0);
203
204 clockevents_register_device(&tmu0_clockevent);
167 205
168 return 0; 206 return 0;
169} 207}
@@ -172,9 +210,7 @@ struct sys_timer_ops tmu_timer_ops = {
172 .init = tmu_timer_init, 210 .init = tmu_timer_init,
173 .start = tmu_timer_start, 211 .start = tmu_timer_start,
174 .stop = tmu_timer_stop, 212 .stop = tmu_timer_stop,
175#ifndef CONFIG_GENERIC_TIME 213 .read = tmu_timer_read,
176 .get_offset = tmu_timer_get_offset,
177#endif
178}; 214};
179 215
180struct sys_timer tmu_timer = { 216struct sys_timer tmu_timer = {
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 7b40f0ff3dfc..3a197649cd83 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -20,10 +20,10 @@
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/bug.h> 21#include <linux/bug.h>
22#include <linux/debug_locks.h> 22#include <linux/debug_locks.h>
23#include <linux/kdebug.h>
23#include <linux/limits.h> 24#include <linux/limits.h>
24#include <asm/system.h> 25#include <asm/system.h>
25#include <asm/uaccess.h> 26#include <asm/uaccess.h>
26#include <asm/kdebug.h>
27 27
28#ifdef CONFIG_SH_KGDB 28#ifdef CONFIG_SH_KGDB
29#include <asm/kgdb.h> 29#include <asm/kgdb.h>
@@ -76,20 +76,6 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
76 } 76 }
77} 77}
78 78
79ATOMIC_NOTIFIER_HEAD(shdie_chain);
80
81int register_die_notifier(struct notifier_block *nb)
82{
83 return atomic_notifier_chain_register(&shdie_chain, nb);
84}
85EXPORT_SYMBOL(register_die_notifier);
86
87int unregister_die_notifier(struct notifier_block *nb)
88{
89 return atomic_notifier_chain_unregister(&shdie_chain, nb);
90}
91EXPORT_SYMBOL(unregister_die_notifier);
92
93static DEFINE_SPINLOCK(die_lock); 79static DEFINE_SPINLOCK(die_lock);
94 80
95void die(const char * str, struct pt_regs * regs, long err) 81void die(const char * str, struct pt_regs * regs, long err)
@@ -505,7 +491,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
505 simple: 491 simple:
506 ret = handle_unaligned_ins(instruction,regs); 492 ret = handle_unaligned_ins(instruction,regs);
507 if (ret==0) 493 if (ret==0)
508 regs->pc += 2; 494 regs->pc += instruction_size(instruction);
509 return ret; 495 return ret;
510} 496}
511#endif /* CONFIG_CPU_SH2A */ 497#endif /* CONFIG_CPU_SH2A */
@@ -682,7 +668,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
682 668
683 err = do_fpu_inst(inst, regs); 669 err = do_fpu_inst(inst, regs);
684 if (!err) { 670 if (!err) {
685 regs->pc += 2; 671 regs->pc += instruction_size(inst);
686 return; 672 return;
687 } 673 }
688 /* not a FPU inst. */ 674 /* not a FPU inst. */