diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d74eb120a9c6b2255deb2812e8069b635f9b9a32..038179ecf6a904dd03fe65f9ab1d0654d4e2427a 100644
--- a/arch/sh/Kconfig
+++ b/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"
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index a83a5d9587bb3532abd3c33ba4ee39f11f818e43..4058b4f50d44eda199717a64d09fc2e2169545ba 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/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,
 };
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index 6cb92676c5fc4a51178a72524a61ee6d93ac7f11..e13f06bebd9221c9247d27754b0fcd396eb11e57 100644
--- a/arch/sh/drivers/Makefile
+++ b/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
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index defc13c37d483c3d4b064f1035609546ba3d4633..99935f9daf4b89b53825eefdf7df3ae2546e4d10 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/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
diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile
index db1295d32268b51fdd393227bac89a0347004696..1ac812d2448837dd02ae30a784ab91d69554f349 100644
--- a/arch/sh/drivers/dma/Makefile
+++ b/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
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d0a29370f2177fef290e2598d8e3cd764c65c7c
--- /dev/null
+++ b/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);
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 350972ae9410df1e11b37658e6ce993817b6cc33..965fa2572b2368230bffb56ee00be7d8714eebdf 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/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
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 0000000000000000000000000000000000000000..9704b7926d8bd30706c19dbb54952d554b708a93
--- /dev/null
+++ b/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;
+}
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
index 426f6db01fc69d117621398e5be60f29a09f261a..f455c3509789b8ba5b4943e758b31b27d9626695 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)
 {
 	/* 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);
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index ba3082d640b5f1d06191a7cc9671ee62a4bb111e..2b2a9e02fb752d1e358f41787369cb8731412501 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/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
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 19ca68c71884176ed9f7f2230ab4618660842a47..8add10bd82683d5efd5064faee11b0746e146c61 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/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
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
deleted file mode 100644
index ac8ab57413cced9e802c5f77485be6e4b844d299..0000000000000000000000000000000000000000
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ /dev/null
@@ -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
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index 7624677f66281e7ef31b99d9b48caf1bc7534b5d..d61dd599169f97b0acb1f42fc9b19acc2dd26835 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/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;
 	}
 
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 329b3f3051de9d53bb5b58b7418e595d11d74e09..6b4f5748d0be682a2b6334ca7d6f5ccc406be271 100644
--- a/arch/sh/kernel/process.c
+++ b/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;
 
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 477d2a854fc4e4a59d0f83cec2341b8648b10fd1..c27729135935d77a8a4387fdb562e3bb86158357 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)
 /* 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)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index fa91641c1f62c34a4eb0e478bc9654fec48ae585..c1cfcb9f047c1803f3e5564079bdba127f6509e4 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/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 */
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index eb0191c374b6839caffd65099899e7166c0d30e2..b32c35a7c0a3e42512765962e8b71c0c1096a5c8 100644
--- a/arch/sh/kernel/signal.c
+++ b/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;
 		}
 	}
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 4bdd2f83535da137635e7507b19f608592f0fd7a..d41e561be20eafacbacf9c99fd08a84d1f1e2321 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/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;
 
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 38fc8cd3ea3a12fbe35dc6a014d12b651eab6795..4357d1a6358f61ba39a2ab7094fdfd968daec8aa 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/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 */
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index d47e775962e955054f8e0296f4f3a5fdd65377e5..a3a67d151e520285b08c7fd58cc93d618e079fe6 100644
--- a/arch/sh/kernel/time.c
+++ b/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)
 	/*
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index d9e3151c891e9cd197aaa87e4f6efe2d7f81e73c..2d997e2a5b6cc6a0961810c8b02beb49df44efac 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/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 = {
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 7b40f0ff3dfc8701a8121dfddaaf3f9044db97c0..3a197649cd83c6c57227156fbcdd6d06e86ef7a2 100644
--- a/arch/sh/kernel/traps.c
+++ b/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. */
diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c
index 351714694d6d4b9b6f81d183e774f1fc47e0e215..f3ddd2133e6f4edffb5a7fc7958350d9d1c2f680 100644
--- a/arch/sh/lib/delay.c
+++ b/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)
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 12f3d394dc28e97df806d7884cb92b890f681e92..253346d7b316fc1bd3a934f6e37c8b038c18a303 100644
--- a/arch/sh/mm/Kconfig
+++ b/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
 
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 0ecc117cade4525042e98b8240e1a0ebcda9b882..9207da67ff8a669841170bc73b600f9782d3037d 100644
--- a/arch/sh/mm/fault.c
+++ b/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>
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 4d030988b3681b3102e859d1f4464afbd23cdef8..8fe223a890ed4aaedf8947493f947041e4bed535 100644
--- a/arch/sh/mm/init.c
+++ b/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
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 6abf4811958c3969270fb09e3f8fffd23b656013..e0f91dfce0f56bcb8f340058d208557e613a44dd 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/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,
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index 794c36daf06da9e3530ee167a87958cc1672048a..46f925c815aca9918823e4b23607b1e50e833cd4 100644
--- a/include/asm-sh/bug.h
+++ b/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__
diff --git a/include/asm-sh/cpu-features.h b/include/asm-sh/cpu-features.h
index 4bccd7c032f9c3d2320c8c7735b7fb5a0d02937b..86308aa3973180867a7b30a2f95e43f6137e54c2 100644
--- a/include/asm-sh/cpu-features.h
+++ b/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 */
diff --git a/include/asm-sh/dmabrg.h b/include/asm-sh/dmabrg.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5edba216cf19c2393decc822c5bf744c5a86039
--- /dev/null
+++ b/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
diff --git a/include/asm-sh/kdebug.h b/include/asm-sh/kdebug.h
index 493c206297479adb4ffdb7f14457c0e8b8338c13..16578b7c9da12cf3ac7a2100ebaeea7e287fce73 100644
--- a/include/asm-sh/kdebug.h
+++ b/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 */
diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h
index 888e4529e6fe3c4bb2108f134b8b7674435836c3..18b613c57cf5118a8ea6fc452d0a0230ff4d50bf 100644
--- a/include/asm-sh/pgalloc.h
+++ b/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 */
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index e7e96ee0c8a5470e39f044e6067dcf8de8dea7a4..82f3e229e62135c2e944e1fbbe5e316744e2c4c1 100644
--- a/include/asm-sh/system.h
+++ b/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
  */
diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h
index 17b5e76a4c3131471599b52bb3aea12ce78aad43..701ba84c7049305dd1e763efe671bfbf15ed9439 100644
--- a/include/asm-sh/timer.h
+++ b/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 */
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index 49be50a36b77dc3dc02dad61892100051f030377..af71e379a5eea94097e029e44e555ab5b3c4cd40 100644
--- a/include/asm-sh/unistd.h
+++ b/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__
 
diff --git a/mm/Kconfig b/mm/Kconfig
index 1ac718f636ec6f5842217bd6b06c7ef0bff0dd21..a17da8bafe62758b6f0d86816d9d6c64b464e687 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -166,5 +166,5 @@ config ZONE_DMA_FLAG
 config NR_QUICK
 	int
 	depends on QUICKLIST
+	default "2" if SUPERH
 	default "1"
-