Browse Source

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.
Linus Torvalds 18 years ago
parent
commit
d84c4124c4

+ 7 - 22
arch/sh/Kconfig

@@ -52,6 +52,9 @@ config GENERIC_IOMAP
 config GENERIC_TIME
 	def_bool n
 
+config GENERIC_CLOCKEVENTS
+	def_bool n
+
 config SYS_SUPPORTS_APM_EMULATION
 	bool
 
@@ -436,11 +439,11 @@ endmenu
 
 menu "Timer and clock configuration"
 
-if !GENERIC_TIME
-
 config SH_TMU
 	bool "TMU timer support"
 	depends on CPU_SH3 || CPU_SH4
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
 	default y
 	help
 	  This enables the use of the TMU as the system timer.
@@ -459,8 +462,6 @@ config SH_MTU2
 	help
 	  This enables the use of the MTU2 as the system timer.
 
-endif
-
 config SH_TIMER_IRQ
 	int
 	default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
@@ -468,24 +469,6 @@ config SH_TIMER_IRQ
 	default "140" if CPU_SUBTYPE_SH7206
 	default "16"
 
-config NO_IDLE_HZ
-	bool "Dynamic tick timer"
-	help
-	  Select this option if you want to disable continuous timer ticks
-	  and have them programmed to occur as required. This option saves
-	  power as the system can remain in idle state for longer.
-
-	  By default dynamic tick is disabled during the boot, and can be
-	  manually enabled with:
-
-	    echo 1 > /sys/devices/system/timer/timer0/dyn_tick
-
-	  Alternatively, if you want dynamic tick automatically enabled
-	  during boot, pass "dyntick=enable" via the kernel command string.
-
-	  Please note that dynamic tick may affect the accuracy of
-	  timekeeping on some platforms depending on the implementation.
-
 config SH_PCLK_FREQ
 	int "Peripheral clock frequency (in Hz)"
 	default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
@@ -509,6 +492,8 @@ config SH_CLK_MD
 	help
 	  MD2 - MD0 pin setting.
 
+source "kernel/time/Kconfig"
+
 endmenu
 
 menu "CPU Frequency scaling"

+ 1 - 0
arch/sh/boards/landisk/setup.c

@@ -93,6 +93,7 @@ static void __init landisk_setup(char **cmdline_p)
  */
 struct sh_machine_vector mv_landisk __initmv = {
 	.mv_name = "LANDISK",
+	.mv_nr_irqs = 72,
 	.mv_setup = landisk_setup,
 	.mv_init_irq = init_landisk_IRQ,
 };

+ 2 - 1
arch/sh/drivers/Makefile

@@ -2,8 +2,9 @@
 # Makefile for the Linux SuperH-specific device drivers.
 #
 
+obj-y		+= dma/
+
 obj-$(CONFIG_PCI)		+= pci/
-obj-$(CONFIG_SH_DMA)		+= dma/
 obj-$(CONFIG_SUPERHYWAY)	+= superhyway/
 obj-$(CONFIG_PUSH_SWITCH)	+= push-switch.o
 obj-$(CONFIG_HEARTBEAT)		+= heartbeat.o

+ 14 - 6
arch/sh/drivers/dma/Kconfig

@@ -1,12 +1,12 @@
 menu "DMA support"
 
-config SH_DMA
-	bool "DMA controller (DMAC) support"
-	help
-	  Selecting this option will provide same API as PC's Direct Memory
-	  Access Controller(8237A) for SuperH DMAC.
+config SH_DMA_API
+	bool
 
-	  If unsure, say N.
+config SH_DMA
+	bool "SuperH on-chip DMA controller (DMAC) support"
+	select SH_DMA_API
+	default n
 
 config NR_ONCHIP_DMA_CHANNELS
 	depends on SH_DMA
@@ -53,4 +53,12 @@ config DMA_PAGE_OPS_CHANNEL
 	  in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
 	  are dual-address capable.
 
+config SH_DMABRG
+	bool "SH7760 DMABRG support"
+	depends on CPU_SUBTYPE_SH7760
+	help
+	  The DMABRG does data transfers from main memory to Audio/USB units
+	  of the SH7760.
+	  Say Y if you want to use Audio/USB DMA on your SH7760 board.
+
 endmenu

+ 2 - 2
arch/sh/drivers/dma/Makefile

@@ -2,8 +2,8 @@
 # Makefile for the SuperH DMA specific kernel interface routines under Linux.
 #
 
-obj-y				+= dma-api.o
+obj-$(CONFIG_SH_DMA_API)	+= dma-api.o dma-sysfs.o
 obj-$(CONFIG_ISA_DMA_API)	+= dma-isa.o
-obj-$(CONFIG_SYSFS)		+= dma-sysfs.o
 obj-$(CONFIG_SH_DMA)		+= dma-sh.o
 obj-$(CONFIG_SH_DREAMCAST)	+= dma-pvr2.o dma-g2.o
+obj-$(CONFIG_SH_DMABRG)		+= dmabrg.o

+ 196 - 0
arch/sh/drivers/dma/dmabrg.c

@@ -0,0 +1,196 @@
+/*
+ * SH7760 DMABRG IRQ handling
+ *
+ * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
+ *  licensed under the GPLv2.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/dmabrg.h>
+#include <asm/io.h>
+
+/*
+ * The DMABRG is a special DMA unit within the SH7760. It does transfers
+ * from USB-SRAM/Audio units to main memory (and also the LCDC; but that
+ * part is sensibly placed  in the LCDC  registers and requires no irqs)
+ * It has 3 IRQ lines which trigger 10 events, and works independently
+ * from the traditional SH DMAC (although it blocks usage of DMAC 0)
+ *
+ * BRGIRQID   | component | dir | meaning      | source
+ * -----------------------------------------------------
+ *     0      | USB-DMA   | ... | xfer done    | DMABRGI1
+ *     1      | USB-UAE   | ... | USB addr err.| DMABRGI0
+ *     2      | HAC0/SSI0 | play| all done     | DMABRGI1
+ *     3      | HAC0/SSI0 | play| half done    | DMABRGI2
+ *     4      | HAC0/SSI0 | rec | all done     | DMABRGI1
+ *     5      | HAC0/SSI0 | rec | half done    | DMABRGI2
+ *     6      | HAC1/SSI1 | play| all done     | DMABRGI1
+ *     7      | HAC1/SSI1 | play| half done    | DMABRGI2
+ *     8      | HAC1/SSI1 | rec | all done     | DMABRGI1
+ *     9      | HAC1/SSI1 | rec | half done    | DMABRGI2
+ *
+ * all can be enabled/disabled in the DMABRGCR register,
+ * as well as checked if they occured.
+ *
+ * DMABRGI0 services  USB  DMA  Address  errors,  but it still must be
+ * enabled/acked in the DMABRGCR register.  USB-DMA complete indicator
+ * is grouped together with the audio buffer end indicators, too bad...
+ *
+ * DMABRGCR:	Bits 31-24: audio-dma ENABLE flags,
+ *		Bits 23-16: audio-dma STATUS flags,
+ *		Bits  9-8:  USB error/xfer ENABLE,
+ *		Bits  1-0:  USB error/xfer STATUS.
+ *	Ack an IRQ by writing 0 to the STATUS flag.
+ *	Mask IRQ by writing 0 to ENABLE flag.
+ *
+ * Usage is almost like with any other IRQ:
+ *  dmabrg_request_irq(BRGIRQID, handler, data)
+ *  dmabrg_free_irq(BRGIRQID)
+ *
+ * handler prototype:  void brgirqhandler(void *data)
+ */
+
+#define DMARSRA		0xfe090000
+#define DMAOR		0xffa00040
+#define DMACHCR0	0xffa0000c
+#define DMABRGCR	0xfe3c0000
+
+#define DMAOR_BRG	0x0000c000
+#define DMAOR_DMEN	0x00000001
+
+#define DMABRGI0	68
+#define DMABRGI1	69
+#define DMABRGI2	70
+
+struct dmabrg_handler {
+	void (*handler)(void *);
+	void *data;
+} *dmabrg_handlers;
+
+static inline void dmabrg_call_handler(int i)
+{
+	dmabrg_handlers[i].handler(dmabrg_handlers[i].data);
+}
+
+/*
+ * main DMABRG irq handler. It acks irqs and then
+ * handles every set and unmasked bit sequentially.
+ * No locking and no validity checks; it should be
+ * as fast as possible (audio!)
+ */
+static irqreturn_t dmabrg_irq(int irq, void *data)
+{
+	unsigned long dcr;
+	unsigned int i;
+
+	dcr = ctrl_inl(DMABRGCR);
+	ctrl_outl(dcr & ~0x00ff0003, DMABRGCR);	/* ack all */
+	dcr &= dcr >> 8;	/* ignore masked */
+
+	/* USB stuff, get it out of the way first */
+	if (dcr & 1)
+		dmabrg_call_handler(DMABRGIRQ_USBDMA);
+	if (dcr & 2)
+		dmabrg_call_handler(DMABRGIRQ_USBDMAERR);
+
+	/* Audio */
+	dcr >>= 16;
+	while (dcr) {
+		i = __ffs(dcr);
+		dcr &= dcr - 1;
+		dmabrg_call_handler(i + DMABRGIRQ_A0TXF);
+	}
+	return IRQ_HANDLED;
+}
+
+static void dmabrg_disable_irq(unsigned int dmairq)
+{
+	unsigned long dcr;
+	dcr = ctrl_inl(DMABRGCR);
+	dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+	ctrl_outl(dcr, DMABRGCR);
+}
+
+static void dmabrg_enable_irq(unsigned int dmairq)
+{
+	unsigned long dcr;
+	dcr = ctrl_inl(DMABRGCR);
+	dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+	ctrl_outl(dcr, DMABRGCR);
+}
+
+int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*),
+		       void *data)
+{
+	if ((dmairq > 9) || !handler)
+		return -ENOENT;
+	if (dmabrg_handlers[dmairq].handler)
+		return -EBUSY;
+
+	dmabrg_handlers[dmairq].handler = handler;
+	dmabrg_handlers[dmairq].data = data;
+	
+	dmabrg_enable_irq(dmairq);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dmabrg_request_irq);
+
+void dmabrg_free_irq(unsigned int dmairq)
+{
+	if (likely(dmairq < 10)) {
+		dmabrg_disable_irq(dmairq);
+		dmabrg_handlers[dmairq].handler = NULL;
+		dmabrg_handlers[dmairq].data = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(dmabrg_free_irq);
+
+static int __init dmabrg_init(void)
+{
+	unsigned long or;
+	int ret;
+
+	dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler),
+				  GFP_KERNEL);
+	if (!dmabrg_handlers)
+		return -ENOMEM;
+
+#ifdef CONFIG_SH_DMA
+	/* request DMAC channel 0 before anyone else can get it */
+	ret = request_dma(0, "DMAC 0 (DMABRG)");
+	if (ret < 0)
+		printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n");
+#endif
+
+	ctrl_outl(0, DMABRGCR);
+	ctrl_outl(0, DMACHCR0);
+	ctrl_outl(0x94000000, DMARSRA);	/* enable DMABRG in DMAC 0 */
+
+	/* enable DMABRG mode, enable the DMAC */
+	or = ctrl_inl(DMAOR);
+	ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
+
+	ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+			"DMABRG USB address error", NULL);
+	if (ret)
+		goto out0;
+
+	ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+			"DMABRG Transfer End", NULL);
+	if (ret)
+		goto out1;
+
+	ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+			"DMABRG Transfer Half", NULL);
+	if (ret == 0)
+		return ret;
+
+	free_irq(DMABRGI1, 0);
+out1:	free_irq(DMABRGI0, 0);
+out0:	kfree(dmabrg_handlers);
+	return ret;
+}
+subsys_initcall(dmabrg_init);

+ 2 - 3
arch/sh/kernel/cpu/sh2a/Makefile

@@ -2,9 +2,8 @@
 # Makefile for the Linux/SuperH SH-2A backends.
 #
 
-obj-y	:= common.o probe.o
+obj-y	:= common.o probe.o opcode_helper.o
 
-common-y	+= $(addprefix ../sh2/, ex.o)
-common-y	+= $(addprefix ../sh2/, entry.o)
+common-y	+= $(addprefix ../sh2/, ex.o entry.o)
 
 obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o

+ 55 - 0
arch/sh/kernel/cpu/sh2a/opcode_helper.c

@@ -0,0 +1,55 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/opcode_helper.c
+ *
+ * Helper for the SH-2A 32-bit opcodes.
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <asm/system.h>
+
+/*
+ * Instructions on SH are generally fixed at 16-bits, however, SH-2A
+ * introduces some 32-bit instructions. Since there are no real
+ * constraints on their use (and they can be mixed and matched), we need
+ * to check the instruction encoding to work out if it's a true 32-bit
+ * instruction or not.
+ *
+ * Presently, 32-bit opcodes have only slight variations in what the
+ * actual encoding looks like in the first-half of the instruction, which
+ * makes it fairly straightforward to differentiate from the 16-bit ones.
+ *
+ * First 16-bits of encoding		Used by
+ *
+ *	0011nnnnmmmm0001	mov.b, mov.w, mov.l, fmov.d,
+ *				fmov.s, movu.b, movu.w
+ *
+ *	0011nnnn0iii1001        bclr.b, bld.b, bset.b, bst.b, band.b,
+ *				bandnot.b, bldnot.b, bor.b, bornot.b,
+ *				bxor.b
+ *
+ *	0000nnnniiii0000        movi20
+ *	0000nnnniiii0001        movi20s
+ */
+unsigned int instruction_size(unsigned int insn)
+{
+	/* Look for the common cases */
+	switch ((insn & 0xf00f)) {
+	case 0x0000:	/* movi20 */
+	case 0x0001:	/* movi20s */
+	case 0x3001:	/* 32-bit mov/fmov/movu variants */
+		return 4;
+	}
+
+	/* And the special cases.. */
+	switch ((insn & 0xf08f)) {
+	case 0x3009:	/* 32-bit b*.b bit operations */
+		return 4;
+	}
+
+	return 2;
+}

+ 1 - 0
arch/sh/kernel/cpu/sh2a/probe.c

@@ -18,6 +18,7 @@ int __init detect_cpu_and_cache_system(void)
 {
 	/* Just SH7206 for now .. */
 	current_cpu_data.type			= CPU_SH7206;
+	current_cpu_data.flags			|= CPU_HAS_OP32;
 
 	current_cpu_data.dcache.ways		= 4;
 	current_cpu_data.dcache.way_incr	= (1 << 11);

+ 8 - 5
arch/sh/kernel/cpu/sh3/ex.S

@@ -1,7 +1,7 @@
 /*
  *  arch/sh/kernel/cpu/sh3/ex.S
  *
- *  The SH-3 exception vector table.
+ *  The SH-3 and SH-4 exception vector table.
 
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2006  Paul Mundt
@@ -9,7 +9,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
- *
  */
 #include <linux/linkage.h>
 
@@ -36,8 +35,12 @@ ENTRY(exception_handling_table)
 	.long	exception_error	! address error load
 	.long	exception_error	! address error store	/* 100 */
 #endif
-	.long	exception_error	! fpu_exception	/* 120 */
-	.long	exception_error			/* 140 */
+#if defined(CONFIG_SH_FPU)
+	.long	do_fpu_error		/* 120 */
+#else
+	.long	exception_error		/* 120 */
+#endif
+	.long	exception_error		/* 140 */
 	.long	system_call	! Unconditional Trap	 /* 160 */
 	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
 	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
@@ -55,4 +58,4 @@ ENTRY(user_break_point_trap)
 	 * away offsets can be manually inserted in to their appropriate
 	 * location via set_exception_table_{evt,vec}().
 	 */
-	.balign 4096,0,4096
+	.balign	4096,0,4096

+ 3 - 3
arch/sh/kernel/cpu/sh4/Makefile

@@ -2,10 +2,10 @@
 # Makefile for the Linux/SuperH SH-4 backends.
 #
 
-obj-y	:= ex.o probe.o common.o
-common-y	+= $(addprefix ../sh3/, entry.o)
+obj-y	:= probe.o common.o
+common-y	+= $(addprefix ../sh3/, entry.o ex.o)
 
-obj-$(CONFIG_SH_FPU)                    += fpu.o
+obj-$(CONFIG_SH_FPU)			+= fpu.o
 obj-$(CONFIG_SH_STORE_QUEUES)		+= sq.o
 
 # CPU subtype setup

+ 0 - 62
arch/sh/kernel/cpu/sh4/ex.S

@@ -1,62 +0,0 @@
-/*
- *  arch/sh/kernel/cpu/sh4/ex.S
- *
- *  The SH-4 exception vector table.
-
- *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003 - 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-#include <linux/linkage.h>
-
-	.align 2
-	.data
-
-ENTRY(exception_handling_table)
-	.long	exception_error		/* 000 */
-	.long	exception_error
-#if defined(CONFIG_MMU)
-	.long	tlb_miss_load		/* 040 */
-	.long	tlb_miss_store
-	.long	initial_page_write
-	.long	tlb_protection_violation_load
-	.long	tlb_protection_violation_store
-	.long	address_error_load
-	.long	address_error_store	/* 100 */
-#else
-	.long	exception_error	! tlb miss load		/* 040 */
-	.long	exception_error	! tlb miss store
-	.long	exception_error	! initial page write
-	.long	exception_error	! tlb prot violation load
-	.long	exception_error	! tlb prot violation store
-	.long	exception_error	! address error load
-	.long	exception_error	! address error store	/* 100 */
-#endif
-#if defined(CONFIG_SH_FPU)
-	.long	do_fpu_error		/* 120 */
-#else
-	.long	exception_error		/* 120 */
-#endif
-	.long	exception_error		/* 140 */
-	.long	system_call	! Unconditional Trap	 /* 160 */
-	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
-	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
-ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
-	.long	debug_enter	/* 1C0 */	! Allow trap to debugger
-#else
-	.long	exception_none	/* 1C0 */	! Not implemented yet
-#endif
-ENTRY(user_break_point_trap)
-	.long	break_point_trap	/* 1E0 */
-
-	/*
-	 * Pad the remainder of the table out, exceptions residing in far
-	 * away offsets can be manually inserted in to their appropriate
-	 * location via set_exception_table_{evt,vec}().
-	 */
-	.balign	4096,0,4096

+ 2 - 1
arch/sh/kernel/cpu/sh4/fpu.c

@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/processor.h>
+#include <asm/system.h>
 #include <asm/io.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
@@ -265,7 +266,7 @@ ieee_fpe_handler (struct pt_regs *regs)
 		nextpc = regs->pr;
 		finsn = *(unsigned short *) (regs->pc + 2);
 	} else {
-		nextpc = regs->pc + 2;
+		nextpc = regs->pc + instruction_size(insn);
 		finsn = insn;
 	}
 

+ 11 - 5
arch/sh/kernel/process.c

@@ -15,9 +15,12 @@
 #include <linux/pm.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
+#include <linux/tick.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
 #include <asm/ubc.h>
 
 static int hlt_counter;
@@ -58,12 +61,15 @@ void cpu_idle(void)
 		if (!idle)
 			idle = default_idle;
 
+		tick_nohz_stop_sched_tick();
 		while (!need_resched())
 			idle();
+		tick_nohz_restart_sched_tick();
 
 		preempt_enable_no_resched();
 		schedule();
 		preempt_disable();
+		check_pgt_cache();
 	}
 }
 
@@ -495,9 +501,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
 	/* Rewind */
-	regs->pc -= 2;
+	regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-	if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
+	if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
 		       SIGTRAP) == NOTIFY_STOP)
 		return;
 
@@ -514,9 +520,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
 	/* Rewind */
-	regs->pc -= 2;
+	regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-	if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
+	if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
 		       SIGTRAP) == NOTIFY_STOP)
 		return;
 

+ 1 - 1
arch/sh/kernel/setup.c

@@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c)
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
 	"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-	"ptea", "llsc", "l2", NULL
+	"ptea", "llsc", "l2", "op32", NULL
 };
 
 static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)

+ 0 - 2
arch/sh/kernel/sh_ksyms.c

@@ -58,8 +58,6 @@ EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL(__div64_32);
-
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 /* These symbols are generated by the compiler itself */

+ 8 - 5
arch/sh/kernel/signal.c

@@ -23,7 +23,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
-
+#include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -500,7 +500,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 				}
 			/* fallthrough */
 			case -ERESTARTNOINTR:
-				regs->pc -= 2;
+				regs->pc -= instruction_size(
+						ctrl_inw(regs->pc - 4));
+				break;
 		}
 	} else {
 		/* gUSA handling */
@@ -516,7 +518,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 			regs->regs[15] = regs->regs[1];
 			if (regs->pc < regs->regs[0])
 				/* Go to rewind point #1 */
-				regs->pc = regs->regs[0] + offset - 2;
+				regs->pc = regs->regs[0] + offset -
+					instruction_size(ctrl_inw(regs->pc-4));
 		}
 #ifdef CONFIG_PREEMPT
 		local_irq_restore(flags);
@@ -600,9 +603,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 		    regs->regs[0] == -ERESTARTSYS ||
 		    regs->regs[0] == -ERESTARTNOINTR) {
 			regs->regs[0] = save_r0;
-			regs->pc -= 2;
+			regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 		} else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
-			regs->pc -= 2;
+			regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 			regs->regs[3] = __NR_restart_syscall;
 		}
 	}

+ 1 - 1
arch/sh/kernel/stacktrace.c

@@ -17,7 +17,7 @@
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
 	unsigned long *sp = (unsigned long *)current_stack_pointer;
 

+ 1 - 0
arch/sh/kernel/syscalls.S

@@ -354,3 +354,4 @@ ENTRY(sys_call_table)
 	.long sys_move_pages
 	.long sys_getcpu
 	.long sys_epoll_pwait
+	.long sys_utimensat		/* 320 */

+ 55 - 117
arch/sh/kernel/time.c

@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002 - 2006  Paul Mundt
+ *  Copyright (C) 2002 - 2007  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
@@ -15,6 +15,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
+#include <linux/clockchips.h>
 #include <asm/clock.h>
 #include <asm/rtc.h>
 #include <asm/timer.h>
@@ -38,6 +39,14 @@ static int null_rtc_set_time(const time_t secs)
 	return 0;
 }
 
+/*
+ * Null high precision timer functions for systems lacking one.
+ */
+static cycle_t null_hpt_read(void)
+{
+	return 0;
+}
+
 void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
 int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
 
@@ -101,6 +110,7 @@ int do_settimeofday(struct timespec *tv)
 EXPORT_SYMBOL(do_settimeofday);
 #endif /* !CONFIG_GENERIC_TIME */
 
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
@@ -138,6 +148,7 @@ void handle_timer_tick(void)
 			last_rtc_update = xtime.tv_sec - 600;
 	}
 }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_PM
 int timer_suspend(struct sys_device *dev, pm_message_t state)
@@ -168,136 +179,58 @@ static struct sysdev_class timer_sysclass = {
 	.resume	 = timer_resume,
 };
 
-#ifdef CONFIG_NO_IDLE_HZ
-static int timer_dyn_tick_enable(void)
+static int __init timer_init_sysfs(void)
 {
-	struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-	unsigned long flags;
-	int ret = -ENODEV;
-
-	if (dyn_tick) {
-		spin_lock_irqsave(&dyn_tick->lock, flags);
-		ret = 0;
-		if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
-			ret = dyn_tick->enable();
-
-			if (ret == 0)
-				dyn_tick->state |= DYN_TICK_ENABLED;
-		}
-		spin_unlock_irqrestore(&dyn_tick->lock, flags);
-	}
+	int ret = sysdev_class_register(&timer_sysclass);
+	if (ret != 0)
+		return ret;
 
-	return ret;
+	sys_timer->dev.cls = &timer_sysclass;
+	return sysdev_register(&sys_timer->dev);
 }
+device_initcall(timer_init_sysfs);
 
-static int timer_dyn_tick_disable(void)
-{
-	struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-	unsigned long flags;
-	int ret = -ENODEV;
-
-	if (dyn_tick) {
-		spin_lock_irqsave(&dyn_tick->lock, flags);
-		ret = 0;
-		if (dyn_tick->state & DYN_TICK_ENABLED) {
-			ret = dyn_tick->disable();
-
-			if (ret == 0)
-				dyn_tick->state &= ~DYN_TICK_ENABLED;
-		}
-		spin_unlock_irqrestore(&dyn_tick->lock, flags);
-	}
-
-	return ret;
-}
+void (*board_time_init)(void);
 
 /*
- * Reprogram the system timer for at least the calculated time interval.
- * This function should be called from the idle thread with IRQs disabled,
- * immediately before sleeping.
+ * Shamelessly based on the MIPS and Sparc64 work.
  */
-void timer_dyn_reprogram(void)
-{
-	struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-	unsigned long next, seq, flags;
-
-	if (!dyn_tick)
-		return;
-
-	spin_lock_irqsave(&dyn_tick->lock, flags);
-	if (dyn_tick->state & DYN_TICK_ENABLED) {
-		next = next_timer_interrupt();
-		do {
-			seq = read_seqbegin(&xtime_lock);
-			dyn_tick->reprogram(next - jiffies);
-		} while (read_seqretry(&xtime_lock, seq));
-	}
-	spin_unlock_irqrestore(&dyn_tick->lock, flags);
-}
+static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
+unsigned long sh_hpt_frequency = 0;
+
+#define NSEC_PER_CYC_SHIFT	10
+
+struct clocksource clocksource_sh = {
+	.name		= "SuperH",
+	.rating		= 200,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.read		= null_hpt_read,
+	.shift		= 16,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
 
-static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+static void __init init_sh_clocksource(void)
 {
-	return sprintf(buf, "%i\n",
-		       (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
-}
+	if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
+		return;
 
-static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
-				  size_t count)
-{
-	unsigned int enable = simple_strtoul(buf, NULL, 2);
+	clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
+						  clocksource_sh.shift);
 
-	if (enable)
-		timer_dyn_tick_enable();
-	else
-		timer_dyn_tick_disable();
+	timer_ticks_per_nsec_quotient =
+		clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
 
-	return count;
+	clocksource_register(&clocksource_sh);
 }
-static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
 
-/*
- * dyntick=enable|disable
- */
-static char dyntick_str[4] __initdata = "";
-
-static int __init dyntick_setup(char *str)
+#ifdef CONFIG_GENERIC_TIME
+unsigned long long sched_clock(void)
 {
-	if (str)
-		strlcpy(dyntick_str, str, sizeof(dyntick_str));
-	return 1;
+	unsigned long long ticks = clocksource_sh.read();
+	return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
 }
-
-__setup("dyntick=", dyntick_setup);
-#endif
-
-static int __init timer_init_sysfs(void)
-{
-	int ret = sysdev_class_register(&timer_sysclass);
-	if (ret != 0)
-		return ret;
-
-	sys_timer->dev.cls = &timer_sysclass;
-	ret = sysdev_register(&sys_timer->dev);
-
-#ifdef CONFIG_NO_IDLE_HZ
-	if (ret == 0 && sys_timer->dyn_tick) {
-		ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
-
-		/*
-		 * Turn on dynamic tick after calibrate delay
-		 * for correct bogomips
-		 */
-		if (ret == 0 && dyntick_str[0] == 'e')
-			ret = timer_dyn_tick_enable();
-	}
 #endif
 
-	return ret;
-}
-device_initcall(timer_init_sysfs);
-
-void (*board_time_init)(void);
-
 void __init time_init(void)
 {
 	if (board_time_init)
@@ -316,10 +249,15 @@ void __init time_init(void)
 	sys_timer = get_sys_timer();
 	printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
 
-#ifdef CONFIG_NO_IDLE_HZ
-	if (sys_timer->dyn_tick)
-		spin_lock_init(&sys_timer->dyn_tick->lock);
-#endif
+	if (sys_timer->ops->read)
+		clocksource_sh.read = sys_timer->ops->read;
+
+	init_sh_clocksource();
+
+	if (sh_hpt_frequency)
+		printk("Using %lu.%03lu MHz high precision timer.\n",
+		       ((sh_hpt_frequency + 500) / 1000) / 1000,
+		       ((sh_hpt_frequency + 500) / 1000) % 1000);
 
 #if defined(CONFIG_SH_KGDB)
 	/*

+ 109 - 73
arch/sh/kernel/timers/timer-tmu.c

@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
  *
- *  Copyright (C) 2005  Paul Mundt
+ *  Copyright (C) 2005 - 2007  Paul Mundt
  *
  * TMU handling code hacked out of arch/sh/kernel/time.c
  *
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/seqlock.h>
+#include <linux/clockchips.h>
 #include <asm/timer.h>
 #include <asm/rtc.h>
 #include <asm/io.h>
@@ -25,56 +26,75 @@
 #include <asm/clock.h>
 
 #define TMU_TOCR_INIT	0x00
-#define TMU0_TCR_INIT	0x0020
-#define TMU_TSTR_INIT	1
+#define TMU_TCR_INIT	0x0020
 
-#define TMU0_TCR_CALIB	0x0000
+static int tmu_timer_start(void)
+{
+	ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+	return 0;
+}
 
-static unsigned long tmu_timer_get_offset(void)
+static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
 {
-	int count;
-	static int count_p = 0x7fffffff;    /* for the first call after boot */
-	static unsigned long jiffies_p = 0;
+	ctrl_outl(interval, TMU0_TCNT);
 
 	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off.
+	 * TCNT reloads from TCOR on underflow, clear it if we don't
+	 * intend to auto-reload
 	 */
-	unsigned long jiffies_t;
+	if (reload)
+		ctrl_outl(interval, TMU0_TCOR);
+	else
+		ctrl_outl(0, TMU0_TCOR);
 
-	/* timer count may underflow right here */
-	count = ctrl_inl(TMU0_TCNT);	/* read the latched count */
+	tmu_timer_start();
+}
 
-	jiffies_t = jiffies;
+static int tmu_timer_stop(void)
+{
+	ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+	return 0;
+}
 
-	/*
-	 * avoiding timer inconsistencies (they are rare, but they happen)...
-	 * there is one kind of problem that must be avoided here:
-	 *  1. the timer counter underflows
-	 */
+static cycle_t tmu_timer_read(void)
+{
+	return ~ctrl_inl(TMU1_TCNT);
+}
+
+static int tmu_set_next_event(unsigned long cycles,
+			      struct clock_event_device *evt)
+{
+	tmu0_timer_set_interval(cycles, 1);
+	return 0;
+}
 
-	if (jiffies_t == jiffies_p) {
-		if (count > count_p) {
-			/* the nutcase */
-			if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
-				count -= LATCH;
-			} else {
-				printk("%s (): hardware timer problem?\n",
-				       __FUNCTION__);
-			}
-		}
-	} else
-		jiffies_p = jiffies_t;
-
-	count_p = count;
-
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	count = (count + LATCH/2) / LATCH;
-
-	return count;
+static void tmu_set_mode(enum clock_event_mode mode,
+			 struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		ctrl_outl(0, TMU0_TCOR);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		break;
+	}
 }
 
+static struct clock_event_device tmu0_clockevent = {
+	.name		= "tmu0",
+	.shift		= 32,
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= tmu_set_mode,
+	.set_next_event	= tmu_set_next_event,
+};
+
 static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 {
+	struct clock_event_device *evt = &tmu0_clockevent;
 	unsigned long timer_status;
 
 	/* Clear UNF bit */
@@ -82,72 +102,76 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 	timer_status &= ~0x100;
 	ctrl_outw(timer_status, TMU0_TCR);
 
-	/*
-	 * Here we are in the timer irq handler. We just have irqs locally
-	 * disabled but we don't know if the timer_bh is running on the other
-	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-	 * the irq version of write_lock because as just said we have irq
-	 * locally disabled. -arca
-	 */
-	write_seqlock(&xtime_lock);
-	handle_timer_tick();
-	write_sequnlock(&xtime_lock);
+	evt->event_handler(evt);
 
 	return IRQ_HANDLED;
 }
 
-static struct irqaction tmu_irq = {
-	.name		= "timer",
+static struct irqaction tmu0_irq = {
+	.name		= "periodic timer",
 	.handler	= tmu_timer_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 	.mask		= CPU_MASK_NONE,
 };
 
-static void tmu_clk_init(struct clk *clk)
+static void tmu0_clk_init(struct clk *clk)
 {
-	u8 divisor = TMU0_TCR_INIT & 0x7;
-	ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
+	u8 divisor = TMU_TCR_INIT & 0x7;
+	ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
 	clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static void tmu_clk_recalc(struct clk *clk)
+static void tmu0_clk_recalc(struct clk *clk)
 {
 	u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
 	clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static struct clk_ops tmu_clk_ops = {
-	.init		= tmu_clk_init,
-	.recalc		= tmu_clk_recalc,
+static struct clk_ops tmu0_clk_ops = {
+	.init		= tmu0_clk_init,
+	.recalc		= tmu0_clk_recalc,
 };
 
 static struct clk tmu0_clk = {
 	.name		= "tmu0_clk",
-	.ops		= &tmu_clk_ops,
+	.ops		= &tmu0_clk_ops,
 };
 
-static int tmu_timer_start(void)
+static void tmu1_clk_init(struct clk *clk)
 {
-	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-	return 0;
+	u8 divisor = TMU_TCR_INIT & 0x7;
+	ctrl_outw(divisor, TMU1_TCR);
+	clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static int tmu_timer_stop(void)
+static void tmu1_clk_recalc(struct clk *clk)
 {
-	ctrl_outb(0, TMU_TSTR);
-	return 0;
+	u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
+	clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
+static struct clk_ops tmu1_clk_ops = {
+	.init		= tmu1_clk_init,
+	.recalc		= tmu1_clk_recalc,
+};
+
+static struct clk tmu1_clk = {
+	.name		= "tmu1_clk",
+	.ops		= &tmu1_clk_ops,
+};
+
 static int tmu_timer_init(void)
 {
 	unsigned long interval;
+	unsigned long frequency;
 
-	setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
+	setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
 
 	tmu0_clk.parent = clk_get(NULL, "module_clk");
+	tmu1_clk.parent = clk_get(NULL, "module_clk");
 
-	/* Start TMU0 */
 	tmu_timer_stop();
+
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7785)
@@ -155,15 +179,29 @@ static int tmu_timer_init(void)
 #endif
 
 	clk_register(&tmu0_clk);
+	clk_register(&tmu1_clk);
 	clk_enable(&tmu0_clk);
+	clk_enable(&tmu1_clk);
 
-	interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
-	printk(KERN_INFO "Interval = %ld\n", interval);
+	frequency = clk_get_rate(&tmu0_clk);
+	interval = (frequency + HZ / 2) / HZ;
 
-	ctrl_outl(interval, TMU0_TCOR);
-	ctrl_outl(interval, TMU0_TCNT);
+	sh_hpt_frequency = clk_get_rate(&tmu1_clk);
+	ctrl_outl(~0, TMU1_TCNT);
+	ctrl_outl(~0, TMU1_TCOR);
 
-	tmu_timer_start();
+	tmu0_timer_set_interval(interval, 1);
+
+	tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
+				      tmu0_clockevent.shift);
+	tmu0_clockevent.max_delta_ns =
+			clockevent_delta2ns(-1, &tmu0_clockevent);
+	tmu0_clockevent.min_delta_ns =
+			clockevent_delta2ns(1, &tmu0_clockevent);
+
+	tmu0_clockevent.cpumask = cpumask_of_cpu(0);
+
+	clockevents_register_device(&tmu0_clockevent);
 
 	return 0;
 }
@@ -172,9 +210,7 @@ struct sys_timer_ops tmu_timer_ops = {
 	.init		= tmu_timer_init,
 	.start		= tmu_timer_start,
 	.stop		= tmu_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
-	.get_offset	= tmu_timer_get_offset,
-#endif
+	.read		= tmu_timer_read,
 };
 
 struct sys_timer tmu_timer = {

+ 3 - 17
arch/sh/kernel/traps.c

@@ -20,10 +20,10 @@
 #include <linux/io.h>
 #include <linux/bug.h>
 #include <linux/debug_locks.h>
+#include <linux/kdebug.h>
 #include <linux/limits.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/kdebug.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -76,20 +76,6 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
 	}
 }
 
-ATOMIC_NOTIFIER_HEAD(shdie_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_unregister(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
 static DEFINE_SPINLOCK(die_lock);
 
 void 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)
  simple:
 	ret = handle_unaligned_ins(instruction,regs);
 	if (ret==0)
-		regs->pc += 2;
+		regs->pc += instruction_size(instruction);
 	return ret;
 }
 #endif /* CONFIG_CPU_SH2A */
@@ -682,7 +668,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
 
 	err = do_fpu_inst(inst, regs);
 	if (!err) {
-		regs->pc += 2;
+		regs->pc += instruction_size(inst);
 		return;
 	}
 	/* not a FPU inst. */

+ 3 - 2
arch/sh/lib/delay.c

@@ -24,9 +24,10 @@ inline void __const_udelay(unsigned long xloops)
 	__asm__("dmulu.l	%0, %2\n\t"
 		"sts	mach, %0"
 		: "=r" (xloops)
-		: "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
+		: "0" (xloops),
+		  "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy)
 		: "macl", "mach");
-	__delay(xloops * HZ);
+	__delay(xloops);
 }
 
 void __udelay(unsigned long usecs)

+ 7 - 0
arch/sh/mm/Kconfig

@@ -218,6 +218,9 @@ endmenu
 
 menu "Memory management options"
 
+config QUICKLIST
+	def_bool y
+
 config MMU
         bool "Support for memory management hardware"
 	depends on !CPU_SH2
@@ -300,6 +303,10 @@ config NODES_SHIFT
 config ARCH_FLATMEM_ENABLE
 	def_bool y
 
+config MAX_ACTIVE_REGIONS
+	int
+	default "1"
+
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
 

+ 1 - 1
arch/sh/mm/fault.c

@@ -15,7 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>

+ 2 - 0
arch/sh/mm/init.c

@@ -67,6 +67,8 @@ void show_mem(void)
 	printk("%d slab pages\n", slab);
 	printk("%d pages shared\n", shared);
 	printk("%d pages swap cached\n", cached);
+	printk(KERN_INFO "Total of %ld pages in page table cache\n",
+	       quicklist_total_size());
 }
 
 #ifdef CONFIG_MMU

+ 4 - 4
drivers/rtc/rtc-sh.c

@@ -104,7 +104,7 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
 
 	writeb(tmp, rtc->regbase + RCR1);
 
-	rtc_update_irq(&rtc->rtc_dev, 1, events);
+	rtc_update_irq(rtc->rtc_dev, 1, events);
 
 	spin_unlock(&rtc->lock);
 
@@ -139,7 +139,7 @@ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
 
 		rtc->rearm_aie = 1;
 
-		rtc_update_irq(&rtc->rtc_dev, 1, events);
+		rtc_update_irq(rtc->rtc_dev, 1, events);
 	}
 
 	spin_unlock(&rtc->lock);
@@ -153,7 +153,7 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
 
 	spin_lock(&rtc->lock);
 
-	rtc_update_irq(&rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+	rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
 
 	spin_unlock(&rtc->lock);
 
@@ -341,7 +341,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
 		tm->tm_sec--;
 #endif
 
-	dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
 		__FUNCTION__,
 		tm->tm_sec, tm->tm_min, tm->tm_hour,

+ 2 - 2
include/asm-sh/bug.h

@@ -1,12 +1,12 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
+#define TRAPA_BUG_OPCODE	0xc33e	/* trapa #0x3e */
+
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_WARN_ON
 
-#define TRAPA_BUG_OPCODE	0xc33e	/* trapa #0x3e */
-
 /**
  * _EMIT_BUG_ENTRY
  * %1 - __FILE__

+ 1 - 0
include/asm-sh/cpu-features.h

@@ -20,5 +20,6 @@
 #define CPU_HAS_PTEA		0x0020	/* PTEA register */
 #define CPU_HAS_LLSC		0x0040	/* movli.l/movco.l */
 #define CPU_HAS_L2_CACHE	0x0080	/* Secondary cache / URAM */
+#define CPU_HAS_OP32		0x0100	/* 32-bit instruction support */
 
 #endif /* __ASM_SH_CPU_FEATURES_H */

+ 23 - 0
include/asm-sh/dmabrg.h

@@ -0,0 +1,23 @@
+/*
+ * SH7760 DMABRG (USB/Audio) support
+ */
+
+#ifndef _DMABRG_H_
+#define _DMABRG_H_
+
+/* IRQ sources */
+#define DMABRGIRQ_USBDMA	0
+#define DMABRGIRQ_USBDMAERR	1
+#define DMABRGIRQ_A0TXF		2
+#define DMABRGIRQ_A0TXH		3
+#define DMABRGIRQ_A0RXF		4
+#define DMABRGIRQ_A0RXH		5
+#define DMABRGIRQ_A1TXF		6
+#define DMABRGIRQ_A1TXH		7
+#define DMABRGIRQ_A1RXF		8
+#define DMABRGIRQ_A1RXH		9
+
+extern int dmabrg_request_irq(unsigned int, void(*)(void *), void *);
+extern void dmabrg_free_irq(unsigned int);
+
+#endif

+ 2 - 23
include/asm-sh/kdebug.h

@@ -2,20 +2,6 @@
 #define __ASM_SH_KDEBUG_H
 
 #include <linux/notifier.h>
-#include <asm-generic/kdebug.h>
-
-struct pt_regs;
-
-struct die_args {
-	struct pt_regs *regs;
-	int trapnr;
-};
-
-int register_die_notifier(struct notifier_block *nb);
-int unregister_die_notifier(struct notifier_block *nb);
-int register_page_fault_notifier(struct notifier_block *nb);
-int unregister_page_fault_notifier(struct notifier_block *nb);
-extern struct atomic_notifier_head shdie_chain;
 
 /* Grossly misnamed. */
 enum die_val {
@@ -23,14 +9,7 @@ enum die_val {
 	DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val, struct pt_regs *regs,
-			     int trap, int sig)
-{
-	struct die_args args = {
-		.regs = regs,
-		.trapnr = trap,
-	};
+int register_page_fault_notifier(struct notifier_block *nb);
+int unregister_page_fault_notifier(struct notifier_block *nb);
 
-	return atomic_notifier_call_chain(&shdie_chain, val, &args);
-}
 #endif /* __ASM_SH_KDEBUG_H */

+ 28 - 16
include/asm-sh/pgalloc.h

@@ -1,6 +1,12 @@
 #ifndef __ASM_SH_PGALLOC_H
 #define __ASM_SH_PGALLOC_H
 
+#include <linux/quicklist.h>
+#include <asm/page.h>
+
+#define QUICK_PGD 0	/* We preserve special mappings over free */
+#define QUICK_PT 1	/* Other page table pages that are zero on free */
+
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
 				       pte_t *pte)
 {
@@ -13,48 +19,49 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 	set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
 }
 
+static inline void pgd_ctor(void *x)
+{
+	pgd_t *pgd = x;
+
+	memcpy(pgd + USER_PTRS_PER_PGD,
+	       swapper_pg_dir + USER_PTRS_PER_PGD,
+	       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+}
+
 /*
  * Allocate and free page tables.
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
-
-	if (pgd) {
-		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-		memcpy(pgd + USER_PTRS_PER_PGD,
-		       swapper_pg_dir + USER_PTRS_PER_PGD,
-		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-	}
-
-	return pgd;
+	return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
-	free_page((unsigned long)pgd);
+	quicklist_free(QUICK_PGD, NULL, pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+	return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
 					 unsigned long address)
 {
-	return alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+	void *pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+	return pg ? virt_to_page(pg) : NULL;
 }
 
 static inline void pte_free_kernel(pte_t *pte)
 {
-	free_page((unsigned long)pte);
+	quicklist_free(QUICK_PT, NULL, pte);
 }
 
 static inline void pte_free(struct page *pte)
 {
-	__free_page(pte);
+	quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
 #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
@@ -66,6 +73,11 @@ static inline void pte_free(struct page *pte)
 
 #define pmd_free(x)			do { } while (0)
 #define __pmd_free_tlb(tlb,x)		do { } while (0)
-#define check_pgt_cache()		do { } while (0)
+
+static inline void check_pgt_cache(void)
+{
+	quicklist_trim(QUICK_PGD, NULL, 25, 16);
+	quicklist_trim(QUICK_PT, NULL, 25, 16);
+}
 
 #endif /* __ASM_SH_PGALLOC_H */

+ 9 - 0
include/asm-sh/system.h

@@ -255,6 +255,15 @@ static inline void *set_exception_table_evt(unsigned int evt, void *handler)
 	return set_exception_table_vec(evt >> 5, handler);
 }
 
+/*
+ * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
+ */
+#ifdef CONFIG_CPU_SH2A
+extern unsigned int instruction_size(unsigned int insn);
+#else
+#define instruction_size(insn)	(2)
+#endif
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */

+ 4 - 21
include/asm-sh/timer.h

@@ -2,12 +2,14 @@
 #define __ASM_SH_TIMER_H
 
 #include <linux/sysdev.h>
+#include <linux/clocksource.h>
 #include <asm/cpu/timer.h>
 
 struct sys_timer_ops {
 	int (*init)(void);
 	int (*start)(void);
 	int (*stop)(void);
+	cycle_t (*read)(void);
 #ifndef CONFIG_GENERIC_TIME
 	unsigned long (*get_offset)(void);
 #endif
@@ -18,29 +20,8 @@ struct sys_timer {
 
 	struct sys_device	dev;
 	struct sys_timer_ops	*ops;
-
-#ifdef CONFIG_NO_IDLE_HZ
-	struct dyn_tick_timer	*dyn_tick;
-#endif
 };
 
-#ifdef CONFIG_NO_IDLE_HZ
-#define DYN_TICK_ENABLED	(1 << 1)
-
-struct dyn_tick_timer {
-	spinlock_t	lock;
-	unsigned int	state;			/* Current state */
-	int		(*enable)(void);	/* Enables dynamic tick */
-	int		(*disable)(void);	/* Disables dynamic tick */
-	void		(*reprogram)(unsigned long); /* Reprograms the timer */
-	int		(*handler)(int, void *);
-};
-
-void timer_dyn_reprogram(void);
-#else
-#define timer_dyn_reprogram()	do { } while (0)
-#endif
-
 #define TICK_SIZE (tick_nsec / 1000)
 
 extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
@@ -58,5 +39,7 @@ struct sys_timer *get_sys_timer(void);
 
 /* arch/sh/kernel/time.c */
 void handle_timer_tick(void);
+extern unsigned long sh_hpt_frequency;
+extern struct clocksource clocksource_sh;
 
 #endif /* __ASM_SH_TIMER_H */

+ 3 - 2
include/asm-sh/unistd.h

@@ -85,7 +85,7 @@
 #define __NR_sigpending		 73
 #define __NR_sethostname	 74
 #define __NR_setrlimit		 75
-#define __NR_getrlimit	 	 76	/* Back compatible 2Gig limited rlimit */
+#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
 #define __NR_getrusage		 77
 #define __NR_gettimeofday	 78
 #define __NR_settimeofday	 79
@@ -328,8 +328,9 @@
 #define __NR_move_pages		317
 #define __NR_getcpu		318
 #define __NR_epoll_pwait	319
+#define __NR_utimensat		320
 
-#define NR_syscalls 320
+#define NR_syscalls 321
 
 #ifdef __KERNEL__
 

+ 1 - 1
mm/Kconfig

@@ -166,5 +166,5 @@ config ZONE_DMA_FLAG
 config NR_QUICK
 	int
 	depends on QUICKLIST
+	default "2" if SUPERH
 	default "1"
-